# MediaWiki install & usage
cache
+docs/js
images/[0-9a-f]
images/archive
images/deleted
== Developers ==
* Aaron Schulz
* Alex Z.
+* Alexander Monk
* Alexandre Emsenhuber
* Andrew Garrett
* Arthur Richards
* Derk-Jan Hartman
* Domas Mituzas
* Emufarmers
-* Fran McCrory
+* Fran Rogers
* Greg Sabino Mullane
* Guy Van den Broeck
* Happy-melon
* Agbad
* Ahmad Sherif
* Alejandro Mery
-* Alexander Monk
* Amalthea
* Amir E. Aharoni
* Andrew Dunbar
* (bug 11142) Improve file extension blacklist error reporting in API upload.
* (bug 39665) List of query generators is now not built using reflection, instead it is
defined in code.
+* (bug 35993) Deprecated gettoken parameter - support will be removed in 1.22.
=== Languages updated in 1.20 ===
in MW 1.20 (saving preferences using Special:Preferences cleared any
additional fields) and which has been disabled in 1.20.1 as a part of
a security fix (bug 42202).
+* Added option to specify "others" as author in extension credits using
+ "..." as author name.
* Added the ability to limit the wall clock time used by shell processes,
as well as the CPU time. Configurable with $wgMaxShellWallClockTime.
* Allow memory of shell subprocesses to be limited using Linux cgroups
* (bug 43915) New maintenance script deleteEqualMessages.php.
* New collation uppercase-sv, which is like uppercase, but adapted
to Swedish sort order.
+* WikiText now permits the use of WAI-ARIA's role="presentation" inside of
+ html elements and tables. This allows presentational markup, especially
+ tables. To be marked up as such.
+* maintenance/sql.php learned the --cluster option. Let you run the script
+ on some external cluster instead of the primary cluster for a given wiki.
+* (bug 20281) test the parsing of inline URLs.
+* Added Special:PagesWithProp, which lists pages using a particular page property.
=== Bug fixes in 1.21 ===
* (bug 40353) SpecialDoubleRedirect should support interwiki redirects.
* (bug 43964) Invalid value of "link" parameter in <gallery> no longer produces
a fatal error.
* (bug 44775) The username field is not pre-filled when creating an account.
+* (bug 45069) wfParseUrl() no longer produces a PHP notice if passed a "mailto:"
+ URL without address
+* (bug 45012) Creating an account by e-mail can no longer show a
+ "password mismatch" error.
+* (bug 44599) On Special:Version, HEADs for submodule checkouts (e.g. for
+ extensions) performed using Git 1.7.8+ should now appear.
=== API changes in 1.21 ===
* prop=revisions can now report the contentmodel and contentformat.
iicontinue).
* Add supports for all pageset capabilities - generators, redirects, converttitles to
action=purge and action=setnotificationtimestamp.
+* (bug 43251) prop=pageprops&ppprop= now accepts multiple props to query.
+* ApiQueryImageInfo will now limit the number of calls to File::transform made
+ in any one query. If there are too many, iicontinue will be returned.
+* action=query&meta=siteinfo&siprop=general will now return the regexes used for
+ link trails and link prefices. Added for Parsoid support.
+* Added an API query module list=pageswithprop, which lists pages using a
+ particular page property.
+* Added an API query module list=pagepropnames, which lists all page prop names
+ currently in use on the wiki.
=== API internal changes in 1.21 ===
* For debugging only, a new global $wgDebugAPI removes many API restrictions when true.
first one keeping its meaning. ApiPageSet is now derived from ApiBase.
* BREAKING CHANGE: ApiQuery::newGenerator() and executeGeneratorModule() were deleted.
* ApiQueryGeneratorBase::setGeneratorMode() now requires a pageset param.
+* $wgAPIGeneratorModules is now obsolete and will be ignored.
+* Added flags ApiResult::OVERRIDE and ADD_ON_TOP to setElement() and addValue()
=== Languages updated in 1.21 ===
as separators for thousands and decimals respectively.
=== Other changes in 1.21 ===
+* BREAKING CHANGE: (bug 44385) Removed the jquery.collapsibleTabs module and
+ moved it to the Vector extension. It was entirely Vector-extension-specific,
+ deeply interconnected with the extension, and this functionality really
+ belongs to the extension instead of the skin anyway. In the unlikely case you
+ were using it, you have to either copy it to your extension, or install the
+ Vector extension (and possibly disable its features using config settings if
+ you don't want them).
== Compatibility ==
*
* Configuration of the profiler output can be done in LocalSettings.php
*/
-
-
header( $_SERVER['SERVER_PROTOCOL'] . ' 500 MediaWiki configuration Error', true, 500 );
echo( 'MediaWiki API is not enabled for this site. Add the following line to your LocalSettings.php'
. '<pre><b>$wgEnableAPI=true;</b></pre>' );
- die(1);
+ die( 1 );
}
// Set a dummy $wgTitle, because $wgTitle == null breaks various things
// Log the request
if ( $wgAPIRequestLog ) {
$items = array(
- wfTimestamp( TS_MW ),
- $endtime - $starttime,
- $wgRequest->getIP(),
- $_SERVER['HTTP_USER_AGENT']
+ wfTimestamp( TS_MW ),
+ $endtime - $starttime,
+ $wgRequest->getIP(),
+ $_SERVER['HTTP_USER_AGENT']
);
$items[] = $wgRequest->wasPosted() ? 'POST' : 'GET';
$module = $processor->getModule();
// See if this is a public Wiki (no protections).
if ( $wgImgAuthPublicTest
- && in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) )
- {
+ && in_array( 'read', User::getGroupPermissions( array( '*' ) ), true )
+ ) {
// This is a public wiki, so disable this script (for private wikis only)
wfForbidden( 'img-auth-accessdenied', 'img-auth-public' );
return;
}
// Stream the requested file
- wfDebugLog( 'img_auth', "Streaming `".$filename."`." );
+ wfDebugLog( 'img_auth', "Streaming `" . $filename . "`." );
$repo->streamFile( $filename, array( 'Cache-Control: private', 'Vary: Cookie' ) );
}
$detailMsg = wfMessage( $detailMsgKey, $args )->escaped();
wfDebugLog( 'img_auth',
- "wfForbidden Hdr:" . wfMessage( $msg1 )->inLanguage( 'en' )->text() . " Msg: ".
- wfMessage( $msg2, $args )->inLanguage( 'en' )->text()
+ "wfForbidden Hdr: " . wfMessage( $msg1 )->inLanguage( 'en' )->text() . " Msg: " .
+ wfMessage( $msg2, $args )->inLanguage( 'en' )->text()
);
header( 'HTTP/1.0 403 Forbidden' );
/**
* Page on which we're performing the action
- * @var Page $page
+ * @var WikiPage|Article|ImagePage|CategoryPage|Page $page
*/
protected $page;
public function showMissingArticle() {
global $wgSend404Code;
$outputPage = $this->getContext()->getOutput();
+ $validUserPage = false;
# Show info in user (talk) namespace. Does the user exist? Is he blocked?
if ( $this->getTitle()->getNamespace() == NS_USER || $this->getTitle()->getNamespace() == NS_USER_TALK ) {
)
)
);
+ $validUserPage = true;
+ } else {
+ $validUserPage = true;
}
}
'msgKey' => array( 'moveddeleted-notice' ) )
);
- if ( !$this->mPage->hasViewableContent() && $wgSend404Code ) {
+ if ( !$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage ) {
// If there's no backing content, send a 404 Not Found
// for better machine handling of broken links.
$this->getContext()->getRequest()->response()->header( "HTTP/1.1 404 Not Found" );
'ApiQueryLogEvents' => 'includes/api/ApiQueryLogEvents.php',
'ApiQueryORM' => 'includes/api/ApiQueryORM.php',
'ApiQueryPageProps' => 'includes/api/ApiQueryPageProps.php',
+ 'ApiQueryPagesWithProp' => 'includes/api/ApiQueryPagesWithProp.php',
+ 'ApiQueryPagePropNames' => 'includes/api/ApiQueryPagePropNames.php',
'ApiQueryProtectedTitles' => 'includes/api/ApiQueryProtectedTitles.php',
'ApiQueryQueryPage' => 'includes/api/ApiQueryQueryPage.php',
'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php',
'MemcLockManager' => 'includes/filebackend/lockmanager/MemcLockManager.php',
'QuorumLockManager' => 'includes/filebackend/lockmanager/QuorumLockManager.php',
'MySqlLockManager'=> 'includes/filebackend/lockmanager/DBLockManager.php',
+ 'PostgreSqlLockManager'=> 'includes/filebackend/lockmanager/DBLockManager.php',
'NullLockManager' => 'includes/filebackend/lockmanager/LockManager.php',
'FileOp' => 'includes/filebackend/FileOp.php',
'FileOpBatch' => 'includes/filebackend/FileOpBatch.php',
# includes/job
'Job' => 'includes/job/Job.php',
'JobQueue' => 'includes/job/JobQueue.php',
+ 'JobQueueAggregator' => 'includes/job/JobQueueAggregator.php',
+ 'JobQueueAggregatorMemc' => 'includes/job/JobQueueAggregatorMemc.php',
+ 'JobQueueAggregatorRedis' => 'includes/job/JobQueueAggregatorRedis.php',
'JobQueueDB' => 'includes/job/JobQueueDB.php',
'JobQueueGroup' => 'includes/job/JobQueueGroup.php',
'JobQueueRedis' => 'includes/job/JobQueueRedis.php',
'SpecialNewFiles' => 'includes/specials/SpecialNewimages.php',
'SpecialNewpages' => 'includes/specials/SpecialNewpages.php',
'SpecialPasswordReset' => 'includes/specials/SpecialPasswordReset.php',
+ 'SpecialPagesWithProp' => 'includes/specials/SpecialPagesWithProp.php',
'SpecialPermanentLink' => 'includes/SpecialPage.php',
'SpecialPreferences' => 'includes/specials/SpecialPreferences.php',
'SpecialPrefixindex' => 'includes/specials/SpecialPrefixindex.php',
* Each backend configuration has the following parameters:
* - 'name' : A unique name for the lock manager
* - 'class' : The lock manger class to use
- * Additional parameters are specific to the class used.
+ *
+ * See LockManager::__construct() for more details.
+ * Additional parameters are specific to the lock manager class used.
* These settings should be global to all wikis.
*/
$wgLockManagers = array();
* Where $type is 'specialpage', 'parserhook', 'variable', 'media' or 'other'.
* Where 'descriptionmsg' can be an array with message key and parameters:
* 'descriptionmsg' => array( 'exampleextension-desc', param1, param2, ... ),
+ *
+ * author can be a string or an array of strings. Authors can be linked using
+ * the regular wikitext link syntax. To have an internationalized version of
+ * "and others" show, add an element "...". This element can also be linked,
+ * for instance "[http://example ...]".
*/
$wgExtensionCredits = array();
'default' => array( 'class' => 'JobQueueDB', 'order' => 'random' ),
);
+/**
+ * Which aggregator to use for tracking which queues have jobs.
+ * These settings should be global to all wikis.
+ */
+$wgJobQueueAggregator = array(
+ 'class' => 'JobQueueAggregatorMemc'
+);
+
/**
* Additional functions to be performed with updateSpecialPages.
* Expensive Querypages are already updated.
'Listredirects' => 'pages',
'Categories' => 'pages',
'Disambiguations' => 'pages',
+ 'PagesWithProp' => 'pages',
'Randompage' => 'redirects',
'Randomredirect' => 'redirects',
$wgAPIMetaModules = array();
$wgAPIPropModules = array();
$wgAPIListModules = array();
+
+/**
+ * This variable is ignored. To add your module to the API, please add it to $wgAPI*Modules
+ * @deprecated since 1.21
+ */
$wgAPIGeneratorModules = array();
/**
$wgMaxShellWallClockTime = 180;
/**
- * Under Linux: a cgroup directory used to constrain memory usage of shell
+ * Under Linux: a cgroup directory used to constrain memory usage of shell
* commands. The directory must be writable by the user which runs MediaWiki.
*
* If specified, this is used instead of ulimit, which is inaccurate, and
* them segfault or deadlock.
*
* A wrapper script will create a cgroup for each shell command that runs, as
- * a subgroup of the specified cgroup. If the memory limit is exceeded, the
+ * a subgroup of the specified cgroup. If the memory limit is exceeded, the
* kernel will send a SIGKILL signal to a process in the subgroup.
*
* @par Example:
* echo '$wgShellCgroup = "/sys/fs/cgroup/memory/mediawiki/job";' >> LocalSettings.php
* @endcode
*
- * The reliability of cgroup cleanup can be improved by installing a
+ * The reliability of cgroup cleanup can be improved by installing a
* notify_on_release script in the root cgroup, see e.g.
* https://gerrit.wikimedia.org/r/#/c/40784
*/
wfProfileOut( get_class( $this ) . "::importContentFormData" );
}
- # Trim spaces on user supplied text
- $summary = trim( $request->getText( 'wpSummary' ) );
-
# Truncate for whole multibyte characters
- $this->summary = $wgContLang->truncate( $summary, 255 );
+ $this->summary = $wgContLang->truncate( $request->getText( 'wpSummary' ), 255 );
# If the summary consists of a heading, e.g. '==Foobar==', extract the title from the
# header syntax, e.g. 'Foobar'. This is mainly an issue when we are using wpSummary for
* @return String
*/
protected function getSummaryPreview( $isSubjectPreview, $summary = "" ) {
+ // avoid spaces in preview, gets always trimmed on save
+ $summary = trim( $summary );
if ( !$summary || ( !$this->preview && !$this->diff ) ) {
return "";
}
* @param $dir string The root directory of the repo where the .git dir can be found
*/
public function __construct( $dir ) {
- $this->basedir = "{$dir}/.git/";
+ $this->basedir = "{$dir}/.git";
+ if ( is_readable( $this->basedir ) ) {
+ $GITfile = file_get_contents( $this->basedir );
+ if ( strlen( $GITfile ) > 8 && substr( $GITfile, 0, 8 ) === 'gitdir: ' ) {
+ $path = rtrim( substr( $GITfile, 8 ), "\r\n" );
+ $isAbsolute = $path[0] === '/' || substr( $path, 1, 1 ) === ':';
+ $this->basedir = $isAbsolute ? $path : "{$dir}/{$path}";
+ }
+ }
}
/**
}
// If not a SHA1 it may be a ref:
- $REFfile = "{$this->basedir}{$HEAD}";
+ $REFfile = "{$this->basedir}/{$HEAD}";
if ( !is_readable( $REFfile ) ) {
return false;
}
if ( !isset( $bits['host'] ) ) {
$bits['host'] = '';
- /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
- if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
- $bits['path'] = '/' . $bits['path'];
+ // bug 45069
+ if ( isset( $bits['path'] ) ) {
+ /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
+ if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
+ $bits['path'] = '/' . $bits['path'];
+ }
+ } else {
+ $bits['path'] = '';
}
}
}
/**
- * This is the new function for getting translated interface messages.
- * See the Message class for documentation how to use them.
- * The intention is that this function replaces all old wfMsg* functions.
+ * This is the function for getting translated interface messages.
+ *
+ * @see Message class for documentation how to use them.
+ * @see https://www.mediawiki.org/wiki/Manual:Messages_API
+ *
+ * This function replaces all old wfMsg* functions.
+ *
* @param $key \string Message key.
* Varargs: normal message parameters.
* @return Message
* @return string|bool The output number as a string, or false on error
*/
function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = true, $engine = 'auto' ) {
+ $input = (string)$input;
if(
$sourceBase < 2 ||
$sourceBase > 36 ||
* Make an HTML list of templates, and then add a "More..." link at
* the bottom. If $more is null, do not add a "More..." link. If $more
* is a Title, make a link to that title and use it. If $more is a string,
- * directly paste it in as the link.
+ * directly paste it in as the link (escaping needs to be done manually).
+ * Finally, if $more is a Message, call toString().
*
- * @param $templates Array of templates from Article::getUsedTemplate
- * or similar
+ * @param array $templates Array of templates from Article::getUsedTemplate or similar
* @param bool $preview Whether this is for a preview
* @param bool $section Whether this is for a section edit
- * @param Title|string|null $more A link for "More..." of the templates
+ * @param Title|Message|string|null $more An escaped link for "More..." of the templates
* @return String: HTML output
*/
public static function formatTemplates( $templates, $preview = false, $section = false, $more = null ) {
$this->language = $wgLang;
}
+ /**
+ * Returns the message key
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getKey() {
+ return $this->key;
+ }
+
+ /**
+ * Returns the message parameters
+ *
+ * @since 1.21
+ *
+ * @return string[]
+ */
+ public function getParams() {
+ return $this->parameters;
+ }
+
+ /**
+ * Returns the message format
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getFormat() {
+ return $this->format;
+ }
+
/**
* Factory function that is just wrapper for the real constructor. It is
* intented to be used instead of the real constructor, because it allows
*/
private $mRedirectedFrom = null;
+ /**
+ * Additional key => value data
+ */
+ private $mProperties = array();
+
/**
* Constructor for OutputPage. This should not be called directly.
* Instead a new RequestContext should be created and it will implicitly create
return $this->mArticleBodyOnly;
}
+ /**
+ * Set an additional output property
+ * @since 1.21
+ *
+ * @param string $name
+ * @param mixed $value
+ */
+ public function setProperty( $name, $value ) {
+ $this->mProperties[$name] = $value;
+ }
+
+ /**
+ * Get an additional output property
+ * @since 1.21
+ *
+ * @param $name
+ * @return mixed: Property value or null if not found
+ */
+ public function getProperty( $name ) {
+ if ( isset( $this->mProperties[$name] ) ) {
+ return $this->mProperties[$name];
+ } else {
+ return null;
+ }
+ }
+
/**
* checkLastModified tells the client to use the client-cached page if
* possible. If successful, the OutputPage is disabled so that
* DO NOT CALL THIS FROM OUTSIDE OF THIS CLASS OR Skin::makeGlobalVariablesScript().
* This is only public until that function is removed. You have been warned.
*
- * Do not add things here which can be evaluated in ResourceLoaderStartupScript
+ * Do not add things here which can be evaluated in ResourceLoaderStartUpModule
* - in other words, page-independent/site-wide variables (without state).
* You will only be adding bloat to the html page and causing page caches to
* have to be purged on configuration changes.
*
* @param $params
* @param $element
+ * @return bool
*/
static function validateTag( $params, $element ) {
$params = Sanitizer::decodeTagAttributes( $params );
$value = Sanitizer::escapeId( $value, 'noninitial' );
}
+ # WAI-ARIA
+ # http://www.w3.org/TR/wai-aria/
+ # http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#wai-aria
+ # For now we only support role="presentation" until we work out what roles should be
+ # usable by content and we ensure that our code explicitly rejects patterns that
+ # violate HTML5's ARIA restrictions.
+ if ( $attribute === 'role' && $value !== 'presentation' ) {
+ continue;
+ }
+
//RDFa and microdata properties allow URLs, URIs and/or CURIs. check them for sanity
if ( $attribute === 'rel' || $attribute === 'rev' ||
$attribute === 'about' || $attribute === 'property' || $attribute === 'resource' || #RDFa
return $whitelist;
}
- $common = array( 'id', 'class', 'lang', 'dir', 'title', 'style' );
+ $common = array(
+ # HTML
+ 'id',
+ 'class',
+ 'style',
+ 'lang',
+ 'dir',
+ 'title',
+
+ # WAI-ARIA
+ 'role',
+ );
if ( $wgAllowRdfaAttributes ) {
#RDFa attributes as specified in section 9 of http://www.w3.org/TR/2008/REC-rdfa-syntax-20081014
}
# Blacklisted file extensions shouldn't appear on the "allowed" list
-$wgFileExtensions = array_diff ( $wgFileExtensions, $wgFileBlacklist );
+$wgFileExtensions = array_values( array_diff ( $wgFileExtensions, $wgFileBlacklist ) );
if ( $wgArticleCountMethod === null ) {
$wgArticleCountMethod = $wgUseCommaCount ? 'comma' : 'link';
*/
public $siteParamsCallback = null;
+ /**
+ * Configuration cache for getConfig()
+ * @var array
+ */
+ protected $cfgCache = array();
+
/**
* Retrieves a configuration setting for a given wiki.
* @param $settingName String ID of the setting name to retrieve
return array( $site, $lang );
}
+ /**
+ * Get the resolved (post-setup) configuration of a potentially foreign wiki.
+ * For foreign wikis, this is expensive, and only works if maintenance
+ * scripts are setup to handle the --wiki parameter such as in wiki farms.
+ *
+ * @param string $wiki
+ * @param array|string $settings A setting name or array of setting names
+ * @return Array|mixed Array if $settings is an array, otherwise the value
+ * @throws MWException
+ * @since 1.21
+ */
+ public function getConfig( $wiki, $settings ) {
+ global $IP;
+
+ $multi = is_array( $settings );
+ $settings = (array)$settings;
+ if ( $wiki === wfWikiID() ) { // $wiki is this wiki
+ $res = array();
+ foreach ( $settings as $name ) {
+ if ( !preg_match( '/^wg[A-Z]/', $name ) ) {
+ throw new MWException( "Variable '$name' does start with 'wg'." );
+ } elseif ( !isset( $GLOBALS[$name] ) ) {
+ throw new MWException( "Variable '$name' is not set." );
+ }
+ $res[$name] = $GLOBALS[$name];
+ }
+ } else { // $wiki is a foreign wiki
+ if ( isset( $this->cfgCache[$wiki] ) ) {
+ $res = array_intersect_key( $this->cfgCache[$wiki], array_flip( $settings ) );
+ if ( count( $res ) == count( $settings ) ) {
+ return $res; // cache hit
+ }
+ } elseif ( !in_array( $wiki, $this->wikis ) ) {
+ throw new MWException( "No such wiki '$wiki'." );
+ } else {
+ $this->cfgCache[$wiki] = array();
+ }
+ $retVal = 1;
+ $cmd = wfShellWikiCmd(
+ "$IP/maintenance/getConfiguration.php",
+ array(
+ '--wiki', $wiki,
+ '--settings', implode( ' ', $settings ),
+ '--format', 'PHP'
+ )
+ );
+ // ulimit5.sh breaks this call
+ $data = trim( wfShellExec( $cmd, $retVal, array(), array( 'memory' => 0 ) ) );
+ if ( $retVal != 0 || !strlen( $data ) ) {
+ throw new MWException( "Failed to run getConfiguration.php." );
+ }
+ $res = unserialize( $data );
+ if ( !is_array( $res ) ) {
+ throw new MWException( "Failed to unserialize configuration array." );
+ }
+ $this->cfgCache[$wiki] = $this->cfgCache[$wiki] + $res;
+ }
+
+ return $multi ? $res : current( $res );
+ }
+
/**
* Returns true if the given vhost is handled locally.
* @param $vhost String
'Categories' => 'SpecialCategories',
'Disambiguations' => 'DisambiguationsPage',
'Listredirects' => 'ListredirectsPage',
+ 'PagesWithProp' => 'SpecialPagesWithProp',
// Login/create account
'Userlogin' => 'LoginForm',
/**
* Get the error message as HTML. This is done by parsing the wikitext error
* message.
+ *
+ * @note: this does not perform a full wikitext to HTML conversion, it merely applies
+ * a message transformation.
+ * @todo: figure out whether that is actually The Right Thing.
*/
public function getHTML( $shortContext = false, $longContext = false ) {
$text = $this->getWikiText( $shortContext, $longContext );
public function getContentModel() {
if ( !$this->mContentModel ) {
$linkCache = LinkCache::singleton();
+ $linkCache->addLinkObj( $this );
$this->mContentModel = $linkCache->getGoodLinkFieldObj( $this, 'model' );
}
*/
private function checkQuickPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
if ( $action == 'create' ) {
- if ( ( $this->isTalkPage() && !$user->isAllowed( 'createtalk' ) ) ||
- ( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) ) ) {
+ if (
+ ( $this->isTalkPage() && !$user->isAllowed( 'createtalk' ) ) ||
+ ( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) )
+ ) {
$errors[] = $user->isAnon() ? array( 'nocreatetext' ) : array( 'nocreate-loggedin' );
}
} elseif ( $action == 'move' ) {
$errors = $this->resultToError( $errors, $result );
}
// Check getUserPermissionsErrorsExpensive hook
- if ( $doExpensiveQueries && !( $short && count( $errors ) > 0 ) &&
- !wfRunHooks( 'getUserPermissionsErrorsExpensive', array( &$this, &$user, $action, &$result ) ) ) {
+ if (
+ $doExpensiveQueries
+ && !( $short && count( $errors ) > 0 )
+ && !wfRunHooks( 'getUserPermissionsErrorsExpensive', array( &$this, &$user, $action, &$result ) )
+ ) {
$errors = $this->resultToError( $errors, $result );
}
# If it's a special page, ditch the subpage bit and check again
$name = $this->getDBkey();
list( $name, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $name );
- if ( $name !== false ) {
+ if ( $name ) {
$pure = SpecialPage::getTitleFor( $name )->getPrefixedText();
if ( in_array( $pure, $wgWhitelistRead, true ) ) {
$whitelisted = true;
public function userCanEditJsSubpage() {
global $wgUser;
wfDeprecated( __METHOD__, '1.19' );
- return ( ( $wgUser->isAllowedAll( 'editusercssjs', 'edituserjs' ) )
- || preg_match( '/^' . preg_quote( $wgUser->getName(), '/' ) . '\//', $this->mTextform ) );
+ return (
+ ( $wgUser->isAllowedAll( 'editusercssjs', 'edituserjs' ) )
+ || preg_match( '/^' . preg_quote( $wgUser->getName(), '/' ) . '\//', $this->mTextform )
+ );
}
/**
if ( $getPages ) {
$cols = array( 'pr_page', 'page_namespace', 'page_title',
- 'pr_expiry', 'pr_type', 'pr_level' );
+ 'pr_expiry', 'pr_type', 'pr_level' );
$where_clauses[] = 'page_id=pr_page';
$tables[] = 'page';
} else {
$pagerestrictions[$row->pr_type] = array();
}
- if ( isset( $pagerestrictions[$row->pr_type] ) &&
- !in_array( $row->pr_level, $pagerestrictions[$row->pr_type] ) ) {
+ if (
+ isset( $pagerestrictions[$row->pr_type] )
+ && !in_array( $row->pr_level, $pagerestrictions[$row->pr_type] )
+ ) {
$pagerestrictions[$row->pr_type][] = $row->pr_level;
}
} else {
* @return Bool
*/
public function isRedirect( $flags = 0 ) {
- if ( !is_null( $this->mRedirect ) ) {
+ if ( !( $flags & Title::GAID_FOR_UPDATE ) && !is_null( $this->mRedirect ) ) {
return $this->mRedirect;
}
- # Calling getArticleID() loads the field from cache as needed
+
if ( !$this->getArticleID( $flags ) ) {
return $this->mRedirect = false;
}
$linkCache = LinkCache::singleton();
+ $linkCache->addLinkObj( $this );
$cached = $linkCache->getGoodLinkFieldObj( $this, 'redirect' );
+
if ( $cached === null ) {
- // TODO: check the assumption that the cache actually knows about this title
- // and handle this, such as get the title from the database.
- // See https://bugzilla.wikimedia.org/show_bug.cgi?id=37209
- wfDebug( "LinkCache doesn't currently know about this title: " . $this->getPrefixedDBkey() );
- wfDebug( wfBacktrace() );
+ // Should not happen
+ throw new MWException( "LinkCache doesn't know redirect status of this title: " . $this->getPrefixedDBkey() );
}
$this->mRedirect = (bool)$cached;
* @return Int
*/
public function getLength( $flags = 0 ) {
- if ( $this->mLength != -1 ) {
+ if ( !( $flags & Title::GAID_FOR_UPDATE ) && $this->mLength != -1 ) {
return $this->mLength;
}
- # Calling getArticleID() loads the field from cache as needed
+
if ( !$this->getArticleID( $flags ) ) {
return $this->mLength = 0;
}
+
$linkCache = LinkCache::singleton();
+ $linkCache->addLinkObj( $this );
$cached = $linkCache->getGoodLinkFieldObj( $this, 'length' );
- if ( $cached === null ) { # check the assumption that the cache actually knows about this title
- # XXX: this does apparently happen, see https://bugzilla.wikimedia.org/show_bug.cgi?id=37209
- # as a stop gap, perhaps log this, but don't throw an exception?
- wfDebug( "LinkCache doesn't currently know about this title: " . $this->getPrefixedDBkey() );
- wfDebug( wfBacktrace() );
+
+ if ( $cached === null ) {
+ // Should not happen
+ throw new MWException( "LinkCache doesn't know redirect status of this title: " . $this->getPrefixedDBkey() );
}
$this->mLength = intval( $cached );
if ( !( $flags & Title::GAID_FOR_UPDATE ) && $this->mLatestID !== false ) {
return intval( $this->mLatestID );
}
- # Calling getArticleID() loads the field from cache as needed
+
if ( !$this->getArticleID( $flags ) ) {
return $this->mLatestID = 0;
}
+
$linkCache = LinkCache::singleton();
$linkCache->addLinkObj( $this );
$cached = $linkCache->getGoodLinkFieldObj( $this, 'revision' );
- if ( $cached === null ) { # check the assumption that the cache actually knows about this title
- # XXX: this does apparently happen, see https://bugzilla.wikimedia.org/show_bug.cgi?id=37209
- # as a stop gap, perhaps log this, but don't throw an exception?
- throw new MWException( "LinkCache doesn't currently know about this title: " . $this->getPrefixedDBkey() );
+
+ if ( $cached === null ) {
+ // Should not happen
+ throw new MWException( "LinkCache doesn't know latest revision ID of this title: " . $this->getPrefixedDBkey() );
}
$this->mLatestID = intval( $cached );
# Pages with "/./" or "/../" appearing in the URLs will often be un-
# reachable due to the way web browsers deal with 'relative' URLs.
# Also, they conflict with subpage syntax. Forbid them explicitly.
- if ( strpos( $dbkey, '.' ) !== false &&
- ( $dbkey === '.' || $dbkey === '..' ||
- strpos( $dbkey, './' ) === 0 ||
- strpos( $dbkey, '../' ) === 0 ||
- strpos( $dbkey, '/./' ) !== false ||
- strpos( $dbkey, '/../' ) !== false ||
- substr( $dbkey, -2 ) == '/.' ||
- substr( $dbkey, -3 ) == '/..' ) )
- {
+ if (
+ strpos( $dbkey, '.' ) !== false &&
+ (
+ $dbkey === '.' || $dbkey === '..' ||
+ strpos( $dbkey, './' ) === 0 ||
+ strpos( $dbkey, '../' ) === 0 ||
+ strpos( $dbkey, '/./' ) !== false ||
+ strpos( $dbkey, '/../' ) !== false ||
+ substr( $dbkey, -2 ) == '/.' ||
+ substr( $dbkey, -3 ) == '/..'
+ )
+ ) {
return false;
}
# underlying database field. We make an exception for special pages, which
# don't need to be stored in the database, and may edge over 255 bytes due
# to subpage syntax for long titles, e.g. [[Special:Block/Long name]]
- if ( ( $this->mNamespace != NS_SPECIAL && strlen( $dbkey ) > 255 ) ||
- strlen( $dbkey ) > 512 )
- {
+ if (
+ ( $this->mNamespace != NS_SPECIAL && strlen( $dbkey ) > 255 )
+ || strlen( $dbkey ) > 512
+ ) {
return false;
}
if ( strlen( $nt->getDBkey() ) < 1 ) {
$errors[] = array( 'articleexists' );
}
- if ( ( $this->getDBkey() == '' ) ||
- ( !$oldid ) ||
- ( $nt->getDBkey() == '' ) ) {
+ if (
+ ( $this->getDBkey() == '' ) ||
+ ( !$oldid ) ||
+ ( $nt->getDBkey() == '' )
+ ) {
$errors[] = array( 'badarticleerror' );
}
}
$old_cmp = '>';
$new_cmp = '<';
- $options = (array) $options;
+ $options = (array)$options;
if ( in_array( 'include_old', $options ) ) {
$old_cmp = '>=';
}
/**
* Set the password and reset the random token unconditionally.
*
- * @param $str String New password to set
+ * @param $str string|null New password to set or null to set an invalid
+ * password hash meaning that the user will not be able to log in
+ * through the web interface.
*/
public function setInternalPassword( $str ) {
$this->load();
* Set the browser cookie
* @param $name String: name of cookie
* @param $value String: value to give cookie
- * @param $expire Int: number of seconds til cookie expires
+ * @param $expire Int: Unix timestamp (in seconds) when the cookie should expire.
+ * 0 (the default) causes it to expire $wgCookieExpiration seconds from now.
* @param $prefix String: Prefix to use, if not $wgCookiePrefix (use '' for no prefix)
* @param $domain String: Cookie domain to use, if not $wgCookieDomain
* @param $forceSecure Bool:
$secureCookie = $forceSecure;
}
- $httpOnlySafe = wfHttpOnlySafe() && $wgCookieHttpOnly;
+ // Mark the cookie as httpOnly if $wgCookieHttpOnly is true,
+ // unless the requesting user-agent is known to have trouble with
+ // httpOnly cookies.
+ $httpOnlySafe = $wgCookieHttpOnly && wfHttpOnlySafe();
+
wfDebugLog( 'cookie',
'setcookie: "' . implode( '", "',
array(
// Hide "This page is a member of # hidden categories" explanation
$content .= Html::element( 'style', array(),
- '.mw-hiddenCategoriesExplanation { display: none; }' );
+ '.mw-hiddenCategoriesExplanation { display: none; }' ) . "\n";
// Hide "Templates used on this page" explanation
$content .= Html::element( 'style', array(),
- '.mw-templatesUsedExplanation { display: none; }' );
+ '.mw-templatesUsedExplanation { display: none; }' ) . "\n";
// Get page information
$pageInfo = $this->pageInfo();
// Render page information
foreach ( $pageInfo as $header => $infoTable ) {
- $content .= $this->makeHeader( $this->msg( "pageinfo-${header}" )->escaped() );
- $table = '';
+ $content .= $this->makeHeader( $this->msg( "pageinfo-${header}" )->escaped() ) . "\n";
+ $table = "\n";
foreach ( $infoTable as $infoRow ) {
$name = ( $infoRow[0] instanceof Message ) ? $infoRow[0]->escaped() : $infoRow[0];
$value = ( $infoRow[1] instanceof Message ) ? $infoRow[1]->escaped() : $infoRow[1];
- $table = $this->addRow( $table, $name, $value );
+ $table = $this->addRow( $table, $name, $value ) . "\n";
}
- $content = $this->addTable( $content, $table );
+ $content = $this->addTable( $content, $table ) . "\n";
}
// Page footer
* @return string The HTML.
*/
protected function makeHeader( $header ) {
- global $wgParser;
- $spanAttribs = array( 'class' => 'mw-headline', 'id' => $wgParser->guessSectionNameFromWikiText( $header ) );
+ $spanAttribs = array( 'class' => 'mw-headline', 'id' => Sanitizer::escapeId( $header ) );
return Html::rawElement( 'h2', array(), Html::element( 'span', $spanAttribs, $header ) );
}
public function setWarning( $warning ) {
$result = $this->getResult();
$data = $result->getData();
- if ( isset( $data['warnings'][$this->getModuleName()] ) ) {
+ $moduleName = $this->getModuleName();
+ if ( isset( $data['warnings'][$moduleName] ) ) {
// Don't add duplicate warnings
- $warn_regex = preg_quote( $warning, '/' );
- if ( preg_match( "/{$warn_regex}(\\n|$)/", $data['warnings'][$this->getModuleName()]['*'] ) ) {
- return;
+ $oldWarning = $data['warnings'][$moduleName]['*'];
+ $warnPos = strpos( $oldWarning, $warning );
+ // If $warning was found in $oldWarning, check if it starts at 0 or after "\n"
+ if ( $warnPos !== false && ( $warnPos === 0 || $oldWarning[$warnPos - 1] === "\n" ) ) {
+ // Check if $warning is followed by "\n" or the end of the $oldWarning
+ $warnPos += strlen( $warning );
+ if ( strlen( $oldWarning ) <= $warnPos || $oldWarning[$warnPos] === "\n" ) {
+ return;
+ }
}
- $oldwarning = $data['warnings'][$this->getModuleName()]['*'];
// If there is a warning already, append it to the existing one
- $warning = "$oldwarning\n$warning";
- $result->unsetValue( 'warnings', $this->getModuleName() );
+ $warning = "$oldWarning\n$warning";
}
$msg = array();
ApiResult::setContent( $msg, $warning );
$result->disableSizeCheck();
- $result->addValue( 'warnings', $this->getModuleName(), $msg );
+ $result->addValue( 'warnings', $moduleName,
+ $msg, ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
$result->enableSizeCheck();
}
public function getParamDescription() {
$p = $this->getModulePrefix();
return array(
- 'name' => 'User Name',
+ 'name' => 'Username',
'password' => "Password (ignored if {$p}mailpassword is set)",
- 'domain' => 'Domain (optional)',
+ 'domain' => 'Domain for external authentication (optional)',
'token' => 'Account creation token obtained in first request',
- 'email' => 'Email address of user',
- 'realname' => 'Real Name of user',
- 'mailpassword' => 'Whether to generate and mail a random password to the user',
- 'reason' => "Optional reason for creating the account (used when {$p}mailpassword is set)",
- 'language' => 'Language code to set for the user.'
+ 'email' => 'E-mail address of user (optional)',
+ 'realname' => 'Real name of user (optional)',
+ 'mailpassword' => 'If set to any value, a random password will be e-mailed to the user',
+ 'reason' => 'Optional reason for creating the account to be put in the logs',
+ 'language' => 'Language code to set as default for the user (optional, defaults to content language)'
);
}
}
public function getHelpUrls() {
- return 'https://www.mediawiki.org/wiki/API:Account creation';
+ return 'https://www.mediawiki.org/wiki/API:Account_creation';
}
}
// TODO: Make them not or check if they still do
$wgTitle = $titleObj;
- $articleObject = new Article( $titleObj );
+ $articleContext = new RequestContext;
+ $articleContext->setRequest( $req );
+ $articleContext->setWikiPage( $pageObj );
+ $articleContext->setUser( $this->getUser() );
+
+ $articleObject = Article::newFromWikiPage( $pageObj, $articleContext );
+
$ep = new EditPage( $articleObject );
// allow editing of non-textual content.
} else {
$r['oldrevid'] = intval( $oldRevId );
$r['newrevid'] = intval( $newRevId );
- $pageObj->clear();
$r['newtimestamp'] = wfTimestamp( TS_ISO_8601,
$pageObj->getTimestamp() );
}
/**
* Initialize the printer function and prepare the output headers, etc.
- * This method must be the first outputing method during execution.
- * A help screen's header is printed for the HTML-based output
- * @param $isError bool Whether an error message is printed
+ * This method must be the first outputting method during execution.
+ * A human-targeted notice about available formats is printed for the HTML-based output,
+ * except for help screens (caused by either an error in the API parameters,
+ * the calling of action=help, or requesting the root script api.php).
+ * @param $isHelpScreen bool Whether a help screen is going to be shown
*/
- function initPrinter( $isError ) {
+ function initPrinter( $isHelpScreen ) {
if ( $this->mDisabled ) {
return;
}
<?php
- if ( !$isError ) {
+ if ( !$isHelpScreen ) {
?>
<br />
<small>
See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>, or
<a href='<?php echo( $script ); ?>'>API help</a> for more information.
</small>
+<pre style='white-space: pre-wrap;'>
<?php
- }
+ } else { // don't wrap the contents of the <pre> for help screens
+ // because these are actually formatted to rely on
+ // the monospaced font for layout purposes
?>
<pre>
<?php
-
+ }
}
}
}
/**
- * Sets whether the pretty-printer should format *bold* and $italics$
+ * Sets whether the pretty-printer should format *bold*
* @param $help bool
*/
public function setHelp( $help = true ) {
protected function formatHTML( $text ) {
// Escape everything first for full coverage
$text = htmlspecialchars( $text );
-
// encode all comments or tags as safe blue strings
$text = str_replace( '<', '<span style="color:blue;"><', $text );
$text = str_replace( '>', '></span>', $text );
- // identify URLs
- $protos = wfUrlProtocolsWithoutProtRel();
- // This regex hacks around bug 13218 (" included in the URL)
- $text = preg_replace( "#(((?i)$protos).*?)(")?([ \\'\"<>\n]|<|>|")#", '<a href="\\1">\\1</a>\\3\\4', $text );
// identify requests to api.php
$text = preg_replace( "#api\\.php\\?[^ <\n\t]+#", '<a href="\\0">\\0</a>', $text );
if ( $this->mHelp ) {
// make strings inside * bold
$text = preg_replace( "#\\*[^<>\n]+\\*#", '<b>\\0</b>', $text );
- // make strings inside $ italic
- $text = preg_replace( "#\\$[^<>\n]+\\$#", '<b><i>\\0</i></b>', $text );
}
+ // identify URLs
+ $protos = wfUrlProtocolsWithoutProtRel();
+ // This regex hacks around bug 13218 (" included in the URL)
+ $text = preg_replace( "#(((?i)$protos).*?)(")?([ \\'\"<>\n]|<|>|")#", '<a href="\\1">\\1</a>\\3\\4', $text );
/**
* Temporary fix for bad links in help messages. As a special case,
$paramsUsed = $this->getParamsUsed();
$allParams = $this->getRequest()->getValueNames();
- $unusedParams = array_diff( $allParams, $paramsUsed );
+ // Printer has not yet executed; don't warn that its parameters are unused
+ $printerParams = array_map(
+ array( $this->mPrinter, 'encodeParamName' ),
+ array_keys( $this->mPrinter->getFinalParams() ?: array() )
+ );
+
+ $unusedParams = array_diff( $allParams, $paramsUsed, $printerParams );
if( count( $unusedParams ) ) {
$s = count( $unusedParams ) > 1 ? 's' : '';
$this->setWarning( "Unrecognized parameter$s: '" . implode( $unusedParams, "', '" ) . "'" );
* tell the printer not to escape ampersands so that our links do
* not break.
*/
- $printer->setUnescapeAmps( ( $this->mAction == 'help' || $isError )
- && $printer->getFormat() == 'XML' && $printer->getIsHtml() );
+ $isHelp = $isError || $this->mAction == 'help';
+ $printer->setUnescapeAmps( $isHelp && $printer->getFormat() == 'XML' && $printer->getIsHtml() );
- $printer->initPrinter( $isError );
+ $printer->initPrinter( $isHelp );
$printer->execute();
$printer->closePrinter();
'converttitles' => false,
);
if ( $this->mAllowGenerator ) {
- $result['generator'] = array(
- ApiBase::PARAM_TYPE => $this->getGenerators() );
+ if ( $flags & ApiBase::GET_VALUES_FOR_HELP ) {
+ $result['generator'] = array(
+ ApiBase::PARAM_TYPE => $this->getGenerators()
+ );
+ } else {
+ $result['generator'] = null;
+ }
}
return $result;
}
// we must create it to get module manager
$query = $this->getMain()->getModuleManager()->getModule( 'query' );
}
- $gens = array_keys( $query->getGenerators() );
+ $gens = array();
+ $mgr = $query->getModuleManager();
+ foreach ( $mgr->getNamesWithClasses() as $name => $class ) {
+ if ( is_subclass_of( $class, 'ApiQueryGeneratorBase' ) ) {
+ $gens[] = $name;
+ }
+ }
sort( $gens );
self::$generators = $gens;
}
'iwbacklinks' => 'ApiQueryIWBacklinks',
'langbacklinks' => 'ApiQueryLangBacklinks',
'logevents' => 'ApiQueryLogEvents',
+ 'pageswithprop' => 'ApiQueryPagesWithProp',
+ 'pagepropnames' => 'ApiQueryPagePropNames',
'protectedtitles' => 'ApiQueryProtectedTitles',
'querypage' => 'ApiQueryQueryPage',
'random' => 'ApiQueryRandom',
'userinfo' => 'ApiQueryUserInfo',
);
- /**
- * List of Api Query generator modules
- * Defined in code, rather than being derived at runtime,
- * due to performance reasons
- * @var array
- */
- private $mQueryGenerators = array(
- 'allcategories' => 'ApiQueryAllCategories',
- 'allimages' => 'ApiQueryAllImages',
- 'alllinks' => 'ApiQueryAllLinks',
- 'allpages' => 'ApiQueryAllPages',
- 'alltransclusions' => 'ApiQueryAllLinks',
- 'backlinks' => 'ApiQueryBacklinks',
- 'categories' => 'ApiQueryCategories',
- 'categorymembers' => 'ApiQueryCategoryMembers',
- 'duplicatefiles' => 'ApiQueryDuplicateFiles',
- 'embeddedin' => 'ApiQueryBacklinks',
- 'exturlusage' => 'ApiQueryExtLinksUsage',
- 'images' => 'ApiQueryImages',
- 'imageusage' => 'ApiQueryBacklinks',
- 'iwbacklinks' => 'ApiQueryIWBacklinks',
- 'langbacklinks' => 'ApiQueryLangBacklinks',
- 'links' => 'ApiQueryLinks',
- 'protectedtitles' => 'ApiQueryProtectedTitles',
- 'querypage' => 'ApiQueryQueryPage',
- 'random' => 'ApiQueryRandom',
- 'recentchanges' => 'ApiQueryRecentChanges',
- 'search' => 'ApiQuerySearch',
- 'templates' => 'ApiQueryLinks',
- 'watchlist' => 'ApiQueryWatchlist',
- 'watchlistraw' => 'ApiQueryWatchlistRaw',
- );
-
/**
* @var ApiPageSet
*/
$this->mModuleMgr->addModules( self::$QueryMetaModules, 'meta' );
$this->mModuleMgr->addModules( $wgAPIMetaModules, 'meta' );
- global $wgAPIGeneratorModules;
- if ( is_array( $wgAPIGeneratorModules ) ) {
- foreach ( $wgAPIGeneratorModules as $moduleName => $moduleClass ) {
- $this->mQueryGenerators[$moduleName] = $moduleClass;
- }
- }
-
// Create PageSet that will process titles/pageids/revids/generator
$this->mPageSet = new ApiPageSet( $this );
}
/**
* Get the generators array mapping module names to class names
+ * @deprecated since 1.21, list of generators is maintained by ApiPageSet
* @return array array(modulename => classname)
*/
public function getGenerators() {
- return $this->mQueryGenerators;
+ wfDeprecated( __METHOD__, '1.21' );
+ $gens = array();
+ foreach ( $this->mModuleMgr->getNamesWithClasses() as $name => $class ) {
+ if ( is_subclass_of( $class, 'ApiQueryGeneratorBase' ) ) {
+ $gens[$name] = $class;
+ }
+ }
+ return $gens;
}
/**
// object by adding extra fields from the page table.
// This function will gather all the extra request fields from the modules.
foreach ( $modules as $module ) {
+ if ( !$this->getRequest()->wasPosted() && $module->mustBePosted() ) {
+ $this->dieUsageMsgOrDebug( array( 'mustbeposted', $module->getModuleName() ) );
+ }
+
$module->requestExtraData( $this->mPageSet );
}
'exportnowrap' => false,
'iwurl' => false,
);
- if( $flags ) {
+ if ( $flags ) {
$result += $this->getPageSet()->getFinalParams( $flags );
}
return $result;
$msg = array( $paramName => $paramValue );
$result = $this->getResult();
$result->disableSizeCheck();
- $result->addValue( 'query-continue', $this->getModuleName(), $msg );
+ $result->addValue( 'query-continue', $this->getModuleName(), $msg, ApiResult::ADD_ON_TOP );
$result->enableSizeCheck();
}
* @ingroup API
*/
class ApiQueryImageInfo extends ApiQueryBase {
+ const TRANSFORM_LIMIT = 50;
+ private static $transformCount = 0;
public function __construct( $query, $moduleName, $prefix = 'ii' ) {
// We allow a subclass to override the prefix, to create a related API module.
$img = $images[$title];
+ if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) {
+ if ( count( $pageIds[NS_FILE] ) == 1 ) {
+ // See the 'the user is screwed' comment below
+ $this->setContinueEnumParameter( 'start',
+ $start !== null ? $start : wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
+ );
+ } else {
+ $this->setContinueEnumParameter( 'continue',
+ $this->getContinueStr( $img, $start ) );
+ }
+ break;
+ }
+
$fit = $result->addValue(
array( 'query', 'pages', intval( $pageId ) ),
'imagerepository', $img->getRepoName()
if ( $url ) {
if ( !is_null( $thumbParams ) ) {
$mto = $file->transform( $thumbParams );
+ self::$transformCount++;
if ( $mto && !$mto->isError() ) {
$vals['thumburl'] = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT );
return $vals;
}
+ /**
+ * Get the count of image transformations performed
+ *
+ * If this is >= TRANSFORM_LIMIT, you should probably stop processing images.
+ *
+ * @return integer count
+ */
+ static function getTransformCount() {
+ return self::$transformCount;
+ }
+
/**
*
* @param $metadata Array
--- /dev/null
+<?php
+/**
+ * Created on January 21, 2013
+ *
+ * Copyright © 2013 Brad Jorsch <bjorsch@wikimedia.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.21
+ * @author Brad Jorsch
+ */
+
+/**
+ * A query module to list used page props
+ *
+ * @ingroup API
+ * @since 1.21
+ */
+class ApiQueryPagePropNames extends ApiQueryBase {
+
+ public function __construct( $query, $moduleName ) {
+ parent::__construct( $query, $moduleName, 'ppn' );
+ }
+
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
+ public function execute() {
+ $params = $this->extractRequestParams();
+
+ $this->addTables( 'page_props' );
+ $this->addFields( 'pp_propname' );
+ $this->addOption( 'DISTINCT' );
+ $this->addOption( 'ORDER BY', 'pp_propname' );
+
+ if ( $params['continue'] ) {
+ $cont = explode( '|', $params['continue'] );
+ $this->dieContinueUsageIf( count( $cont ) != 1 );
+
+ // Add a WHERE clause
+ $this->addWhereRange( 'pp_propname', 'newer', $cont[0], null );
+ }
+
+ $limit = $params['limit'];
+ $this->addOption( 'LIMIT', $limit + 1 );
+
+ $result = $this->getResult();
+ $count = 0;
+ foreach ( $this->select( __METHOD__ ) as $row ) {
+ if ( ++$count > $limit ) {
+ // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+ $this->setContinueEnumParameter( 'continue', $row->pp_propname );
+ break;
+ }
+
+ $vals = array();
+ $vals['propname'] = $row->pp_propname;
+ $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
+ if ( !$fit ) {
+ $this->setContinueEnumParameter( 'continue', $row->pp_propname );
+ break;
+ }
+ }
+
+ $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'p' );
+ }
+
+ public function getAllowedParams() {
+ return array(
+ 'continue' => null,
+ 'limit' => array(
+ ApiBase::PARAM_TYPE => 'limit',
+ ApiBase::PARAM_DFLT => 10,
+ ApiBase::PARAM_MIN => 1,
+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+ ),
+ );
+ }
+
+ public function getParamDescription() {
+ return array(
+ 'continue' => 'When more results are available, use this to continue',
+ 'limit' => 'The maximum number of pages to return',
+ );
+ }
+
+ public function getDescription() {
+ return 'List all page prop names in use on the wiki';
+ }
+
+ public function getExamples() {
+ return array(
+ 'api.php?action=query&list=pagepropnames' => 'Get first 10 prop names',
+ );
+ }
+
+ public function getHelpUrls() {
+ return 'https://www.mediawiki.org/wiki/API:Pagepropnames';
+ }
+}
}
# Force a sort order to ensure that properties are grouped by page
- $this->addOption( 'ORDER BY', 'pp_page' );
+ # But only if pp_page is not constant in the WHERE clause.
+ if ( count( $pages ) > 1 ) {
+ $this->addOption( 'ORDER BY', 'pp_page' );
+ }
$res = $this->select( __METHOD__ );
$currentPage = 0; # Id of the page currently processed
public function getAllowedParams() {
return array(
'continue' => null,
- 'prop' => null,
+ 'prop' => array(
+ ApiBase::PARAM_ISMULTI => true,
+ ),
);
}
public function getParamDescription() {
return array(
'continue' => 'When more results are available, use this to continue',
- 'prop' => 'Page prop to look on the page for. Useful for checking whether a certain page uses a certain page prop.'
+ 'prop' => 'Only list these props. Useful for checking whether a certain page uses a certain page prop',
);
}
--- /dev/null
+<?php
+/**
+ * Created on December 31, 2012
+ *
+ * Copyright © 2012 Brad Jorsch <bjorsch@wikimedia.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.21
+ * @author Brad Jorsch
+ */
+
+/**
+ * A query module to enumerate pages that use a particular prop
+ *
+ * @ingroup API
+ * @since 1.21
+ */
+class ApiQueryPagesWithProp extends ApiQueryGeneratorBase {
+
+ public function __construct( $query, $moduleName ) {
+ parent::__construct( $query, $moduleName, 'pwp' );
+ }
+
+ public function execute() {
+ $this->run();
+ }
+
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
+ public function executeGenerator( $resultPageSet ) {
+ $this->run( $resultPageSet );
+ }
+
+ /**
+ * @param $resultPageSet ApiPageSet
+ * @return void
+ */
+ private function run( $resultPageSet = null ) {
+ $params = $this->extractRequestParams();
+
+ $prop = array_flip( $params['prop'] );
+ $fld_ids = isset( $prop['ids'] );
+ $fld_title = isset( $prop['title'] );
+ $fld_value = isset( $prop['value'] );
+
+ if ( $resultPageSet === null ) {
+ $this->addFields( array( 'page_id' ) );
+ $this->addFieldsIf( array( 'page_title', 'page_namespace' ), $fld_title );
+ $this->addFieldsIf( 'pp_value', $fld_value );
+ } else {
+ $this->addFields( $resultPageSet->getPageTableFields() );
+ }
+ $this->addTables( array( 'page_props', 'page' ) );
+ $this->addWhere( 'pp_page=page_id' );
+ $this->addWhereFld( 'pp_propname', $params['propname'] );
+
+ $dir = ( $params['dir'] == 'ascending' ) ? 'newer' : 'older';
+
+ if ( $params['continue'] ) {
+ $cont = explode( '|', $params['continue'] );
+ $this->dieContinueUsageIf( count( $cont ) != 1 );
+
+ // Add a WHERE clause
+ $from = (int)$cont[0];
+ $this->addWhereRange( 'pp_page', $dir, $from, null );
+ }
+
+ $sort = ( $params['dir'] === 'descending' ? ' DESC' : '' );
+ $this->addOption( 'ORDER BY', 'pp_page' . $sort );
+
+ $limit = $params['limit'];
+ $this->addOption( 'LIMIT', $limit + 1 );
+
+ $result = $this->getResult();
+ $count = 0;
+ foreach ( $this->select( __METHOD__ ) as $row ) {
+ if ( ++$count > $limit ) {
+ // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+ $this->setContinueEnumParameter( 'continue', $row->page_id );
+ break;
+ }
+
+ if ( $resultPageSet === null ) {
+ $vals = array();
+ if ( $fld_ids ) {
+ $vals['pageid'] = (int)$row->page_id;
+ }
+ if ( $fld_title ) {
+ $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+ ApiQueryBase::addTitleInfo( $vals, $title );
+ }
+ if ( $fld_value ) {
+ $vals['value'] = $row->pp_value;
+ }
+ $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
+ if ( !$fit ) {
+ $this->setContinueEnumParameter( 'continue', $row->page_id );
+ break;
+ }
+ } else {
+ $resultPageSet->processDbRow( $row );
+ }
+ }
+
+ if ( $resultPageSet === null ) {
+ $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'page' );
+ }
+ }
+
+ public function getAllowedParams() {
+ return array(
+ 'propname' => array(
+ ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_REQUIRED => true,
+ ),
+ 'prop' => array(
+ ApiBase::PARAM_DFLT => 'ids|title',
+ ApiBase::PARAM_ISMULTI => true,
+ ApiBase::PARAM_TYPE => array (
+ 'ids',
+ 'title',
+ 'value',
+ )
+ ),
+ 'continue' => null,
+ 'limit' => array(
+ ApiBase::PARAM_TYPE => 'limit',
+ ApiBase::PARAM_DFLT => 10,
+ ApiBase::PARAM_MIN => 1,
+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+ ),
+ 'dir' => array(
+ ApiBase::PARAM_DFLT => 'ascending',
+ ApiBase::PARAM_TYPE => array(
+ 'ascending',
+ 'descending',
+ )
+ ),
+ );
+ }
+
+ public function getParamDescription() {
+ return array(
+ 'propname' => 'Page prop for which to enumerate pages',
+ 'prop' => array(
+ 'What pieces of information to include',
+ ' ids - Adds the page ID',
+ ' title - Adds the title and namespace ID of the page',
+ ' value - Adds the value of the page prop',
+ ),
+ 'dir' => 'In which direction to sort',
+ 'continue' => 'When more results are available, use this to continue',
+ 'limit' => 'The maximum number of pages to return',
+ );
+ }
+
+ public function getDescription() {
+ return 'List all pages using a given page prop';
+ }
+
+ public function getExamples() {
+ return array(
+ 'api.php?action=query&list=pageswithprop&pwppropname=displaytitle&pwpprop=ids|title|value' => 'Get first 10 pages using {{DISPLAYTITLE:}}',
+ 'api.php?action=query&generator=pageswithprop&gpwppropname=notoc&prop=info' => 'Get page info about first 10 pages using __NOTOC__',
+ );
+ }
+
+ public function getHelpUrls() {
+ return 'https://www.mediawiki.org/wiki/API:Pageswithprop';
+ }
+}
case 'variables':
$fit = $this->appendVariables( $p );
break;
+ case 'protocols':
+ $fit = $this->appendProtocols( $p );
+ break;
default:
ApiBase::dieDebug( __METHOD__, "Unknown prop=$p" );
}
}
protected function appendGeneralInfo( $property ) {
- global $wgContLang;
+ global $wgContLang,
+ $wgDisableLangConversion,
+ $wgDisableTitleConversion;
$data = array();
$mainPage = Title::newMainPage();
$data['dbtype'] = $GLOBALS['wgDBtype'];
$data['dbversion'] = $this->getDB()->getServerVersion();
+ if ( !$wgDisableLangConversion ) {
+ $data['langconversion'] = '';
+ }
+
+ if ( !$wgDisableTitleConversion ) {
+ $data['titleconversion'] = '';
+ }
+
+ if ( $wgContLang->linkPrefixExtension() ) {
+ $data['linkprefix'] = wfMessage( 'linkprefix' )->inContentLanguage()->text();
+ }
+
+ $linktrail = $wgContLang->linkTrail();
+ if ( $linktrail ) {
+ $data['linktrail'] = $linktrail;
+ }
+
$git = SpecialVersion::getGitHeadSha1( $GLOBALS['IP'] );
if ( $git ) {
$data['git-hash'] = $git;
return $this->getResult()->addValue( 'query', $property, $variables );
}
+ public function appendProtocols( $property ) {
+ global $wgUrlProtocols;
+ // Make a copy of the global so we don't try to set the _element key of it - bug 45130
+ $protocols = array_values( $wgUrlProtocols );
+ $this->getResult()->setIndexedTagName( $protocols, 'p' );
+ return $this->getResult()->addValue( 'query', $property, $protocols );
+ }
+
private function formatParserTags( $item ) {
return "<{$item}>";
}
'functionhooks',
'showhooks',
'variables',
+ 'protocols',
)
),
'filteriw' => array(
' functionhooks - Returns a list of parser function hooks',
' showhooks - Returns a list of all subscribed hooks (contents of $wgHooks)',
' variables - Returns a list of variable IDs',
+ ' protocols - Returns a list of protocols that are allowed in external links.',
),
'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
'showalldb' => 'List all database servers, not just the one lagging the most',
*/
class ApiResult extends ApiBase {
+ /**
+ * override existing value in addValue() and setElement()
+ * @since 1.21
+ */
+ const OVERRIDE = 1;
+
+ /**
+ * For addValue() and setElement(), if the value does not exist, add it as the first element.
+ * In case the new value has no name (numerical index), all indexes will be renumbered.
+ * @since 1.21
+ */
+ const ADD_ON_TOP = 2;
+
private $mData, $mIsRawMode, $mSize, $mCheckingSize;
/**
* @param $arr array to add $value to
* @param $name string Index of $arr to add $value at
* @param $value mixed
- * @param $overwrite bool Whether overwriting an existing element is allowed
+ * @param $flags int Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP. This parameter used to be
+ * boolean, and the value of OVERRIDE=1 was specifically chosen so that it would be backwards
+ * compatible with the new method signature.
+ *
+ * @since 1.21 int $flags replaced boolean $override
*/
- public static function setElement( &$arr, $name, $value, $overwrite = false ) {
+ public static function setElement( &$arr, $name, $value, $flags = 0 ) {
if ( $arr === null || $name === null || $value === null || !is_array( $arr ) || is_array( $name ) ) {
ApiBase::dieDebug( __METHOD__, 'Bad parameter' );
}
- if ( !isset ( $arr[$name] ) || $overwrite ) {
- $arr[$name] = $value;
+ $exists = isset( $arr[$name] );
+ if ( !$exists || ( $flags & ApiResult::OVERRIDE ) ) {
+ if ( !$exists && ( $flags & ApiResult::ADD_ON_TOP ) ) {
+ $arr = array( $name => $value ) + $arr;
+ } else {
+ $arr[$name] = $value;
+ }
} elseif ( is_array( $arr[$name] ) && is_array( $value ) ) {
$merged = array_intersect_key( $arr[$name], $value );
if ( !count( $merged ) ) {
* @param $path array|string|null
* @param $name string
* @param $value mixed
- * @param $overwrite bool
- *
+ * @param $flags int Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP. This parameter used to be
+ * boolean, and the value of OVERRIDE=1 was specifically chosen so that it would be backwards
+ * compatible with the new method signature.
* @return bool True if $value fits in the result, false if not
+ *
+ * @since 1.21 int $flags replaced boolean $override
*/
- public function addValue( $path, $name, $value, $overwrite = false ) {
+ public function addValue( $path, $name, $value, $flags = 0 ) {
global $wgAPIMaxResultSize;
$data = &$this->mData;
$this->mSize = $newsize;
}
- if ( !is_null( $path ) ) {
- if ( is_array( $path ) ) {
- foreach ( $path as $p ) {
- if ( !isset( $data[$p] ) ) {
+ $addOnTop = $flags & ApiResult::ADD_ON_TOP;
+ if ( $path !== null ) {
+ foreach ( (array) $path as $p ) {
+ if ( !isset( $data[$p] ) ) {
+ if ( $addOnTop ) {
+ $data = array( $p => array() ) + $data;
+ $addOnTop = false;
+ } else {
$data[$p] = array();
}
- $data = &$data[$p];
}
- } else {
- if ( !isset( $data[$path] ) ) {
- $data[$path] = array();
- }
- $data = &$data[$path];
+ $data = &$data[$p];
}
}
if ( !$name ) {
- $data[] = $value; // Add list element
+ // Add list element
+ if ( $addOnTop ) {
+ // This element needs to be inserted in the beginning
+ // Numerical indexes will be renumbered
+ array_unshift( $data, $value );
+ } else {
+ // Add new value at the end
+ $data[] = $value;
+ }
} else {
- self::setElement( $data, $name, $value, $overwrite ); // Add named element
+ // Add named element
+ self::setElement( $data, $name, $value, $flags );
}
return true;
}
*/
public function setParsedLimit( $moduleName, $limit ) {
// Add value, allowing overwriting
- $this->addValue( 'limits', $moduleName, $limit, true );
+ $this->addValue( 'limits', $moduleName, $limit, ApiResult::OVERRIDE );
}
/**
"{$prefix}_namespace" => $this->title->getNamespace(),
"{$prefix}_title" => $this->title->getDBkey(),
$this->getDb()->makeList( array(
- "{$prefix}_interwiki = ''",
- "{$prefix}_interwiki is null",
+ "{$prefix}_interwiki" => '',
+ "{$prefix}_interwiki IS NULL",
), LIST_OR ),
"page_id={$prefix}_from"
);
* Fetch the next row from the given result object, in object form.
* Fields can be retrieved with $row->fieldname, with fields acting like
* member variables.
+ * If no more rows are available, false is returned.
*
* @param $res ResultWrapper|object as returned from DatabaseBase::query(), etc.
- * @return Row object
+ * @return object|bool
* @throws DBUnexpectedError Thrown if the database returns an error
*/
function fetchObject( $res );
/**
* Fetch the next row from the given result object, in associative array
* form. Fields are retrieved with $row['fieldname'].
+ * If no more rows are available, false is returned.
*
* @param $res ResultWrapper result object as returned from DatabaseBase::query(), etc.
- * @return Row object
+ * @return array|bool
* @throws DBUnexpectedError Thrown if the database returns an error
*/
function fetchRow( $res );
* Fetch the next row from the given result object, in object form.
* Fields can be retrieved with $row->fieldname, with fields acting like
* member variables.
+ * If no more rows are available, false is returned.
*
* @param $res array|ResultWrapper SQL result object as returned from Database::query(), etc.
- * @return DB2 row object
+ * @return object|bool
* @throws DBUnexpectedError Thrown if the database returns an error
*/
public function fetchObject( $res ) {
/**
* Fetch the next row from the given result object, in associative array
* form. Fields are retrieved with $row['fieldname'].
+ * If no more rows are available, false is returned.
*
* @param $res array|ResultWrapper SQL result object as returned from Database::query(), etc.
- * @return ResultWrapper row object
+ * @return array|bool
* @throws DBUnexpectedError Thrown if the database returns an error
*/
public function fetchRow( $res ) {
/**
* @param $res ResultWrapper
- * @return object|stdClass
+ * @return object|bool
* @throws DBUnexpectedError
*/
function fetchObject( $res ) {
/**
* @param $res ResultWrapper
- * @return array
+ * @return array|bool
* @throws DBUnexpectedError
*/
function fetchRow( $res ) {
* @param $write array
* @param $method string
* @param $lowPriority bool
+ * @return bool
*/
public function lockTables( $read, $write, $method, $lowPriority = true ) {
$items = array();
}
$sql = "LOCK TABLES " . implode( ',', $items );
$this->query( $sql, $method );
+ return true;
}
/**
* @param $method string
+ * @return bool
*/
public function unlockTables( $method ) {
$this->query( "UNLOCK TABLES", $method );
+ return true;
}
/**
$this->query( "SET datestyle = 'ISO, YMD'", __METHOD__ );
$this->query( "SET timezone = 'GMT'", __METHOD__ );
$this->query( "SET standard_conforming_strings = on", __METHOD__ );
+ if ( $this->getServerVersion() >= 9.0 ) {
+ $this->query( "SET bytea_output = 'escape'", __METHOD__ ); // PHP bug 53127
+ }
global $wgDBmwschema;
$this->determineCoreSchema( $wgDBmwschema );
}
return parent::streamStatementEnd( $sql, $newLine );
}
+
+ /**
+ * Check to see if a named lock is available. This is non-blocking.
+ * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
+ *
+ * @param $lockName String: name of lock to poll
+ * @param $method String: name of method calling us
+ * @return Boolean
+ * @since 1.20
+ */
+ public function lockIsFree( $lockName, $method ) {
+ $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
+ $result = $this->query( "SELECT (CASE(pg_try_advisory_lock($key))
+ WHEN 'f' THEN 'f' ELSE pg_advisory_unlock($key) END) AS lockstatus", $method );
+ $row = $this->fetchObject( $result );
+ return ( $row->lockstatus === 't' );
+ }
+
+ /**
+ * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
+ * @param $lockName string
+ * @param $method string
+ * @param $timeout int
+ * @return bool
+ */
+ public function lock( $lockName, $method, $timeout = 5 ) {
+ $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
+ for ( $attempts=1; $attempts <= $timeout; ++$attempts ) {
+ $result = $this->query(
+ "SELECT pg_try_advisory_lock($key) AS lockstatus", $method );
+ $row = $this->fetchObject( $result );
+ if ( $row->lockstatus === 't' ) {
+ return true;
+ } else {
+ sleep( 1 );
+ }
+ }
+ wfDebug( __METHOD__." failed to acquire lock\n" );
+ return false;
+ }
+
+ /**
+ * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKSFROM PG DOCS: http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
+ * @param $lockName string
+ * @param $method string
+ * @return bool
+ */
+ public function unlock( $lockName, $method ) {
+ $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
+ $result = $this->query( "SELECT pg_advisory_unlock($key) as lockstatus", $method );
+ $row = $this->fetchObject( $result );
+ return ( $row->lockstatus === 't' );
+ }
+
+ /**
+ * @param string $lockName
+ * @return string Integer
+ */
+ private function bigintFromLockName( $lockName ) {
+ return wfBaseConvert( substr( sha1( $lockName ), 0, 15 ), 16, 10 );
+ }
} // end DatabasePostgres class
# set error codes only, don't raise exceptions
if ( $this->mOpened ) {
$this->mConn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
- # Enforce LIKE to be case sensitive, just like MySQL\r
+ # Enforce LIKE to be case sensitive, just like MySQL
$this->query( 'PRAGMA case_sensitive_like = 1' );
return true;
}
/**
* @param $res ResultWrapper
- * @return
+ * @return object|bool
*/
function fetchObject( $res ) {
if ( $res instanceof ResultWrapper ) {
/**
* @param $res ResultWrapper
- * @return bool|mixed
+ * @return array|bool
*/
function fetchRow( $res ) {
if ( $res instanceof ResultWrapper ) {
/**
* @param $conn
+ * @return bool
* @throws DBConnectionError
*/
function reportConnectionError( &$conn ) {
* @param $old Content: old content
* @param $new Content: new content
*
+ * @return bool|string
* @since 1.21
* @throws MWException if $old or $new are not instances of TextContent.
*/
*
* @param $otext String: old text, must be already segmented
* @param $ntext String: new text, must be already segmented
+ * @return bool|string
* @deprecated since 1.21, use generateContentDiffBody() instead!
*/
function generateDiffBody( $otext, $ntext ) {
* @return string|bool The text stored or false on error
* @throws MWException
*/
- public abstract function fetchFromURL( $url );
+ abstract public function fetchFromURL( $url );
/**
* Insert a data item into a given location
* @return string|bool The URL of the stored data item, or false on error
* @throws MWException
*/
- public abstract function store( $location, $data );
+ abstract public function store( $location, $data );
}
* $opts is an associative of boolean flags, including:
* - force : Operation precondition errors no longer trigger an abort.
* Any remaining operations are still attempted. Unexpected
- * failures may still cause remaning operations to be aborted.
+ * failures may still cause remaining operations to be aborted.
* - nonLocking : No locks are acquired for the operations.
* This can increase performance for non-critical writes.
* This has no effect unless the 'force' flag is set.
*/
/**
- * Version of LockManager based on using DB table row locks.
+ * Version of LockManager based on using named/row DB locks.
*
* This is meant for multi-wiki systems that may share files.
- * All locks are blocking, so it might be useful to set a small
- * lock-wait timeout via server config to curtail deadlocks.
*
* All lock requests for a resource, identified by a hash string, will map
* to one bucket. Each bucket maps to one or several peer DBs, each on their
* @ingroup LockManager
* @since 1.19
*/
-class DBLockManager extends QuorumLockManager {
+abstract class DBLockManager extends QuorumLockManager {
/** @var Array Map of DB names to server config */
protected $dbServers; // (DB name => server config array)
/** @var BagOStuff */
$this->session = wfRandomString( 31 );
}
- /**
- * Get a connection to a lock DB and acquire locks on $paths.
- * This does not use GET_LOCK() per http://bugs.mysql.com/bug.php?id=1118.
- *
- * @see QuorumLockManager::getLocksOnServer()
- * @return Status
- */
- protected function getLocksOnServer( $lockSrv, array $paths, $type ) {
- $status = Status::newGood();
-
- if ( $type == self::LOCK_EX ) { // writer locks
- try {
- $keys = array_unique( array_map( array( $this, 'sha1Base36Absolute' ), $paths ) );
- # Build up values for INSERT clause
- $data = array();
- foreach ( $keys as $key ) {
- $data[] = array( 'fle_key' => $key );
- }
- # Wait on any existing writers and block new ones if we get in
- $db = $this->getConnection( $lockSrv ); // checked in isServerUp()
- $db->insert( 'filelocks_exclusive', $data, __METHOD__ );
- } catch ( DBError $e ) {
- foreach ( $paths as $path ) {
- $status->fatal( 'lockmanager-fail-acquirelock', $path );
- }
- }
- }
-
- return $status;
- }
-
- /**
- * @see QuorumLockManager::freeLocksOnServer()
- * @return Status
- */
- protected function freeLocksOnServer( $lockSrv, array $paths, $type ) {
- return Status::newGood(); // not supported
- }
-
- /**
- * @see QuorumLockManager::releaseAllLocks()
- * @return Status
- */
- protected function releaseAllLocks() {
- $status = Status::newGood();
-
- foreach ( $this->conns as $lockDb => $db ) {
- if ( $db->trxLevel() ) { // in transaction
- try {
- $db->rollback( __METHOD__ ); // finish transaction and kill any rows
- } catch ( DBError $e ) {
- $status->fatal( 'lockmanager-fail-db-release', $lockDb );
- }
- }
- }
-
- return $status;
- }
-
/**
* @see QuorumLockManager::isServerUp()
* @return bool
* Make sure remaining locks get cleared for sanity
*/
function __destruct() {
+ $this->releaseAllLocks();
foreach ( $this->conns as $db ) {
- if ( $db->trxLevel() ) { // in transaction
- try {
- $db->rollback( __METHOD__ ); // finish transaction and kill any rows
- } catch ( DBError $e ) {
- // oh well
- }
- }
$db->close();
}
}
return $status;
}
+
+ /**
+ * @see QuorumLockManager::freeLocksOnServer()
+ * @return Status
+ */
+ protected function freeLocksOnServer( $lockSrv, array $paths, $type ) {
+ return Status::newGood(); // not supported
+ }
+
+ /**
+ * @see QuorumLockManager::releaseAllLocks()
+ * @return Status
+ */
+ protected function releaseAllLocks() {
+ $status = Status::newGood();
+
+ foreach ( $this->conns as $lockDb => $db ) {
+ if ( $db->trxLevel() ) { // in transaction
+ try {
+ $db->rollback( __METHOD__ ); // finish transaction and kill any rows
+ } catch ( DBError $e ) {
+ $status->fatal( 'lockmanager-fail-db-release', $lockDb );
+ }
+ }
+ }
+
+ return $status;
+ }
+}
+
+/**
+ * PostgreSQL version of DBLockManager that supports shared locks.
+ * All locks are non-blocking, which avoids deadlocks.
+ *
+ * @ingroup LockManager
+ */
+class PostgreSqlLockManager extends DBLockManager {
+ /** @var Array Mapping of lock types to the type actually used */
+ protected $lockTypeMap = array(
+ self::LOCK_SH => self::LOCK_SH,
+ self::LOCK_UW => self::LOCK_SH,
+ self::LOCK_EX => self::LOCK_EX
+ );
+
+ protected function getLocksOnServer( $lockSrv, array $paths, $type ) {
+ $status = Status::newGood();
+ if ( !count( $paths ) ) {
+ return $status; // nothing to lock
+ }
+
+ $db = $this->getConnection( $lockSrv ); // checked in isServerUp()
+ $bigints = array_unique( array_map(
+ function( $key ) { return wfBaseConvert( substr( $key, 0, 15 ), 16, 10 ); },
+ array_map( array( $this, 'sha1Base16Absolute' ), $paths )
+ ) );
+
+ // Try to acquire all the locks...
+ $fields = array();
+ foreach ( $bigints as $bigint ) {
+ $fields[] = ( $type == self::LOCK_SH )
+ ? "pg_try_advisory_lock_shared({$db->addQuotes( $bigint )}) AS K$bigint"
+ : "pg_try_advisory_lock({$db->addQuotes( $bigint )}) AS K$bigint";
+ }
+ $res = $db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__ );
+ $row = (array)$res->fetchObject();
+
+ if ( in_array( 'f', $row ) ) {
+ // Release any acquired locks if some could not be acquired...
+ $fields = array();
+ foreach ( $row as $kbigint => $ok ) {
+ if ( $ok === 't' ) { // locked
+ $bigint = substr( $kbigint, 1 ); // strip off the "K"
+ $fields[] = ( $type == self::LOCK_SH )
+ ? "pg_advisory_unlock_shared({$db->addQuotes( $bigint )})"
+ : "pg_advisory_unlock({$db->addQuotes( $bigint )})";
+ }
+ }
+ if ( count( $fields ) ) {
+ $db->query( 'SELECT ' . implode( ', ', $fields ), __METHOD__ );
+ }
+ foreach ( $paths as $path ) {
+ $status->fatal( 'lockmanager-fail-acquirelock', $path );
+ }
+ }
+
+ return $status;
+ }
+
+ /**
+ * @see QuorumLockManager::freeLocksOnServer()
+ * @return Status
+ */
+ protected function freeLocksOnServer( $lockSrv, array $paths, $type ) {
+ return Status::newGood(); // not supported
+ }
+
+ /**
+ * @see QuorumLockManager::releaseAllLocks()
+ * @return Status
+ */
+ protected function releaseAllLocks() {
+ $status = Status::newGood();
+
+ foreach ( $this->conns as $lockDb => $db ) {
+ try {
+ $db->query( "SELECT pg_advisory_unlock_all()", __METHOD__ );
+ } catch ( DBError $e ) {
+ $status->fatal( 'lockmanager-fail-db-release', $lockDb );
+ }
+ }
+
+ return $status;
+ }
}
return wfBaseConvert( sha1( "{$this->domain}:{$path}" ), 16, 36, 31 );
}
+ /**
+ * Get the base 16 SHA-1 of a string, padded to 31 digits.
+ * Before hashing, the path will be prefixed with the domain ID.
+ * This should be used interally for lock key or file names.
+ *
+ * @param $path string
+ * @return string
+ */
+ final protected function sha1Base16Absolute( $path ) {
+ return sha1( "{$this->domain}:{$path}" );
+ }
+
/**
* Lock resources with the given keys and lock type
*
* @param $copyStatus string
* @param $source string
* @param $watch bool
+ * @param $timestamp string|bool
+ * @param $user User object or null to use $wgUser
+ * @return bool
+ * @throws MWException
*/
- function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '', $watch = false ) {
+ function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '', $watch = false, $timestamp = false, User $user = null ) {
$this->readOnlyError();
}
* @param $srcPath String
* @param $flags int
* @param $options Array
+ * @return \FileRepoStatus
* @throws MWException
*/
function publish( $srcPath, $flags = 0, array $options = array() ) {
* @param $source string
* @param $watch bool
* @param $timestamp bool|string
+ * @param $user User object or null to use $wgUser
+ * @return bool
* @throws MWException
*/
function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '',
- $watch = false, $timestamp = false ) {
+ $watch = false, $timestamp = false, User $user = null ) {
$this->readOnlyError();
}
/**
* @param $versions array
* @param $unsuppress bool
+ * @return \FileRepoStatus
* @throws MWException
*/
function restore( $versions = array(), $unsuppress = false ) {
/**
* @param $reason string
* @param $suppress bool
+ * @return \FileRepoStatus
* @throws MWException
*/
function delete( $reason, $suppress = false ) {
/**
* @param $target Title
+ * @return \FileRepoStatus
* @throws MWException
*/
function move( $target ) {
$extraDataLoaded, # Whether or not lazy-loaded data has been loaded from the database
$upgraded, # Whether the row was upgraded on load
$locked, # True if the image row is locked
+ $lockedOwnTrx, # True if the image row is locked with a lock initiated transaction
$missing, # True if file is not present in file system. Not to be cached in memcached
$deleted; # Bitfield akin to rev_deleted
* @param $source string
* @param $watch bool
* @param $timestamp string|bool
+ * @param $user User object or null to use $wgUser
* @return bool
*/
function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '',
- $watch = false, $timestamp = false )
+ $watch = false, $timestamp = false, User $user = null )
{
+ if ( !$user ) {
+ global $wgUser;
+ $user = $wgUser;
+ }
+
$pageText = SpecialUpload::getInitialPageText( $desc, $license, $copyStatus, $source );
- if ( !$this->recordUpload2( $oldver, $desc, $pageText, false, $timestamp ) ) {
+ if ( !$this->recordUpload2( $oldver, $desc, $pageText, false, $timestamp, $user ) ) {
return false;
}
if ( $watch ) {
- global $wgUser;
- $wgUser->addWatch( $this->getTitle() );
+ $user->addWatch( $this->getTitle() );
}
return true;
}
$dbw = $this->repo->getMasterDB();
if ( !$this->locked ) {
- $dbw->begin( __METHOD__ );
+ if ( !$dbw->trxLevel() ) {
+ $dbw->begin( __METHOD__ );
+ $this->lockedOwnTrx = true;
+ }
$this->locked++;
}
function unlock() {
if ( $this->locked ) {
--$this->locked;
- if ( !$this->locked ) {
+ if ( !$this->locked && $this->lockedOwnTrx ) {
$dbw = $this->repo->getMasterDB();
$dbw->commit( __METHOD__ );
+ $this->lockedOwnTrx = false;
}
}
}
$this->locked = false;
$dbw = $this->repo->getMasterDB();
$dbw->rollback( __METHOD__ );
+ $this->lockedOwnTrx = false;
}
/**
/**
* Delete unused files in the deleted zone.
* This should be called from outside the transaction in which execute() was called.
- * @return FileRepoStatus|void
+ * @return FileRepoStatus
*/
function cleanup() {
if ( !$this->cleanupBatch ) {
'config-admin-password' => '{{Identical|Password}}',
'config-admin-email' => '{{Identical|E-mail address}}',
'config-subscribe' => 'Used as label for the installer checkbox',
+ 'config-subscribe-help' => '"Low-volume" in this context means that there will be few e-mails to that mailing list per time period.',
'config-profile-help' => 'Messages referenced:
* {{msg-mw|config-profile-wiki}}
* {{msg-mw|config-profile-no-anon}}
);
/** Asturian (asturianu)
+ * @author Xuacu
*/
$messages['ast'] = array(
+ 'config-desc' => "L'instalador pa MediaWiki",
+ 'config-title' => 'Instalación de MediaWiki $1',
+ 'config-information' => 'Información',
+ 'config-localsettings-upgrade' => "Detectose un ficheru <code>LocalSettings.php</code>.
+P'anovar esta instalación, escriba'l valor de
+<code>\$wgUpgradeKey</code> nel cuadru d'abaxo.
+Alcontraralu en <code>LocalSettings.php</code>.",
+ 'config-localsettings-cli-upgrade' => "Deteutose un ficheru <code>LocalSettings.php</code>.
+P'anovar esta instalación, execute <code>update.php</code>",
+ 'config-localsettings-key' => "Clave d'anovamientu:",
+ 'config-localsettings-badkey' => 'La clave que dio ye incorreuta.',
+ 'config-upgrade-key-missing' => "Deteutose una instalación esistente de MediaWiki.
+P'anovar esta instalación, ponga la llinia siguiente al final del ficheru <code>LocalSettings.php</code>:
+
+$1",
+ 'config-localsettings-incomplete' => 'Paez que\'l ficheru <code>LocalSettings.php</code> esistente ta incompletu.
+La variable $1 nun ta definida.
+Camude\'l ficheru <code>LocalSettings.php</code> pa qu\'esta variable quede definida y calque "{{int:Config-continue}}".',
+ 'config-localsettings-connection-error' => 'Alcontrose un error al conectar cola base de datos usando la configuración especificada en <code>LocalSettings.php</code> o <code>AdminSettings.php</code>. Corrixa esta configuración y vuelva a intentalo.
+
+$1',
+ 'config-your-language' => 'La so llingua:',
+ 'config-your-language-help' => "Seleicione la llingua a emplegar nel procesu d'instalación.",
+ 'config-wiki-language' => 'Llingua de la wiki:',
+ 'config-wiki-language-help' => "Seleicione la llingua que s'usará preferentemente na wiki.",
+ 'config-back' => '← Atrás',
+ 'config-continue' => 'Siguir →',
+ 'config-page-language' => 'Llingua',
+ 'config-page-welcome' => '¡Bienveníu a MediaWiki!',
+ 'config-page-dbconnect' => 'Conectar cola base de datos',
+ 'config-page-upgrade' => 'Anovar instalación esistente',
+ 'config-page-dbsettings' => 'Configuración de la base de datos',
+ 'config-page-name' => 'Nome',
+ 'config-page-options' => 'Opciones',
+ 'config-page-install' => 'Instalar',
+ 'config-page-complete' => '¡Completo!',
+ 'config-page-restart' => 'Reaniciar la instalación',
+ 'config-page-readme' => 'Llei-me',
+ 'config-page-releasenotes' => 'Notes de la versión',
+ 'config-page-copying' => 'Copiar',
+ 'config-page-upgradedoc' => 'Anovando',
+ 'config-page-existingwiki' => 'Wiki esistente',
+ 'config-download-localsettings' => 'Descargar <code>LocalSettings.php</code>',
+ 'config-help' => 'Ayuda',
+ 'config-nofile' => 'Nun pudo atopase\'l ficheru "$1". ¿Desaniciose?',
'mainpagetext' => "'''MediaWiki instalóse correchamente.'''",
- 'mainpagedocfooter' => "Visita la [//meta.wikimedia.org/wiki/Help:Contents Guía d'usuariu] pa saber cómo usar esti software wiki.
+ 'mainpagedocfooter' => 'Visita la [//meta.wikimedia.org/wiki/Help:Contents Guía del usuariu] pa saber cómo usar esti software wiki.
== Empecipiando ==
* [//www.mediawiki.org/wiki/Manual:Configuration_settings Llista de les opciones de configuración]
* [//www.mediawiki.org/wiki/Manual:FAQ FAQ de MediaWiki]
-* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de corréu de les ediciones de MediaWiki]",
+* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de corréu de les ediciones de MediaWiki]
+* [//www.mediawiki.org/wiki/Localisation#Translation_resources Llocaliza MediaWiki na to llingua]',
);
/** Kotava (Kotava)
* @author Rillke
* @author The Evil IP address
* @author Umherirrender
+ * @author Wikinaut
* @author 아라
*/
$messages['de'] = array(
'config-page-copying' => 'Kopie der Lizenz',
'config-page-upgradedoc' => 'Aktualisiere',
'config-page-existingwiki' => 'Vorhandenes Wiki',
- 'config-help-restart' => 'Sollen alle bereits eingegebene Daten gelöscht und der Installationsvorgang erneut gestartet werden?',
+ 'config-help-restart' => 'Sollen alle bereits eingegebenen Daten gelöscht und der Installationsvorgang erneut gestartet werden?',
'config-restart' => 'Ja, erneut starten',
'config-welcome' => '=== Prüfung der Installationsumgebung ===
Die Basisprüfungen werden durchgeführt, um festzustellen, ob die Installationsumgebung für die Installation von MediaWiki geeignet ist.
'config-support-mysql' => '* $1 je primarny cil za MediaWiki a podpěruje so najlěpje ([http://www.php.net/manual/en/mysql.installation.php Nawod ke kompilowanju PHP z MySQL-podpěru])',
'config-support-postgres' => '* $1 je popularny system datoweje banki zjawneho žórła jako alternatiwa k MySQL ([http://www.php.net/manual/en/pgsql.installation.php nawod za kompilowanje PHP z podpěru PostgreSQL]). Móhło hišće někotre zmylki eksistować, a njeporuča so jón w produktiwnej wokolinje wužiwać.',
'config-support-oracle' => '* $1 je komercielna předewzaćelska datowa banka. ([http://www.php.net/manual/en/oci8.installation.php Nawod za kompilowanje PHP z OCI8-podpěru])',
- 'config-support-ibm_db2' => '* $1 je komercielna předewzaćelska datowa banka.', # Fuzzy
+ 'config-support-ibm_db2' => '* $1 je komercielna předewzaćelska datowa banka. ([http://www.php.net/manual/en/ibm-db2.installation.php How to compile PHP with IBM DB2 support])',
'config-header-mysql' => 'Nastajenja MySQL',
'config-header-postgres' => 'Nastajenja PostgreSQL',
'config-header-sqlite' => 'Nastajenja SQLite',
'config-optional-continue' => 'Dalše prašenja?',
'config-optional-skip' => 'Instaluj nětko wiki.',
'config-profile' => 'Profil wužiwarskich prawow:',
- 'config-profile-wiki' => 'Tradicionelny wiki', # Fuzzy
+ 'config-profile-wiki' => 'Zjawny wiki',
'config-profile-no-anon' => 'Załoženje konto je trěbne',
'config-profile-fishbowl' => 'Jenož awtorizowani wobdźěłarjo',
'config-profile-private' => 'Priwatny wiki',
'config-install-alreadydone' => "'''Warnowanje:''' Zda so, zo sy hižo MediaWiki instalował a pospytuješ jón znowa instalować.
Prošu pokročuj z přichodnej stronu.",
'config-install-begin' => 'Přez kliknjenje na "{{int:config-continue}}" budźe so instalacija MediaWiki startować.
-Jeli hišće chceš něšto změnić, klikń na "Wróćo".', # Fuzzy
+Jeli hišće chceš něšto změnić, klikń na "{{int:config-back}}".',
'config-install-step-done' => 'dokónčene',
'config-install-step-failed' => 'njeporadźiło',
'config-install-extensions' => 'Inkluziwnje rozšěrjenja',
* [//www.mediawiki.org/wiki/Manual:Configuration_settings Wo nastajenjach]
* [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ]
-* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]', # Fuzzy
+* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]
+* [//www.mediawiki.org/wiki/Localisation#Translation_resources Localise MediaWiki for your language]',
);
/** Haitian (Kreyòl ayisyen)
'config-copyright' => '=== 著作権および規約 ===
$1
-この作品はフリーソフトウェアです。あなたは、フリーソフトウェア財団の発行するGNU一般公衆利用許諾書 (GNU General Public License)(バージョン2、またはそれ以降のライセンス)の規約に基づき、このライブラリを再配布および改変できます。
+この作品はフリーソフトウェアです。あなたは、フリーソフトウェア財団の発行するGNU一般公衆利用許諾書 (GNU General Public License) (バージョン2、またはそれ以降のライセンス) の規約に基づき、このライブラリを再配布および改変できます。
この作品は、有用であることを期待して配布されていますが、商用あるいは特定の目的に適するかどうかも含めて、暗黙的にも、一切保証されません。
詳しくは、GNU一般公衆利用許諾書をご覧ください。
-あなたはこのプログラムと共に、<doclink href=Copying>GNU一般公衆利用許諾契約書の複製</doclink>を一部受け取ったはずです。もし受け取っていなければ、フリーソフトウェア財団(宛先は the Free Software Foundation, Inc., 59Temple Place, Suite 330, Boston, MA 02111-1307 USA)まで請求してください。',
+あなたはこのプログラムと共に、<doclink href=Copying>GNU一般公衆利用許諾契約書の複製</doclink>を一部受け取ったはずです。受け取っていない場合は、フリーソフトウェア財団 (宛先は the Free Software Foundation, Inc., 59Temple Place, Suite 330, Boston, MA 02111-1307 USA) まで請求してください。',
'config-sidebar' => '* [//www.mediawiki.org MediaWikiのホーム]
* [//www.mediawiki.org/wiki/Help:Contents 利用者向け案内]
* [//www.mediawiki.org/wiki/Manual:Contents 管理者向け案内]
'config-no-cache' => "'''警告:''' [http://www.php.net/apc APC]、[http://xcache.lighttpd.net/ XCache]、[http://www.iis.net/download/WinCacheForPhp WinCache] のいずれも見つかりませんでした。
オブジェクトのキャッシュは有効化されません。",
'config-diff3-bad' => 'GNU diff3 が見つかりません。',
- 'config-imagemagick' => 'ImageMagickが見つかりました:<code>$1</code>。
-ã\82¢ã\83\83ã\83\97ã\83ã\83¼ã\83\89ã\81\8cæ\9c\89å\8a¹ã\81ªã\82\89ã\80\81ç\94»å\83\8fã\81®ã\82µã\83 ã\83\8dã\82¤ã\83«ã\81\8c利用できます。',
+ 'config-imagemagick' => 'ImageMagickが見つかりました: <code>$1</code>。
+ã\82¢ã\83\83ã\83\97ã\83ã\83¼ã\83\89ã\81\8cæ\9c\89å\8a¹ã\81§ã\81\82ã\82\8cã\81°ã\80\81ç\94»å\83\8fã\81®ã\82µã\83 ã\83\8dã\82¤ã\83«ã\82\92利用できます。',
'config-gd' => 'GD画像ライブラリが内蔵されていることが確認されました。
アップロードが有効なら、画像のサムネイルが利用できます。',
'config-no-scaling' => 'GDライブラリもImageMagickも見つかりませんでした。
'config-admin-error-user' => '"<nowiki>$1</nowiki>"という名前の管理者を作成する際に内部エラーが発生しました。',
'config-admin-error-password' => '管理者"<nowiki>$1</nowiki>"のパスワードを設定する際に内部エラーが発生しました: <pre>$2</pre>',
'config-subscribe' => '[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce リリース告知のメーリングリスト]を購読する。',
- 'config-subscribe-help' => 'これは、リリースの告知(重要なセキュリティに関する案内を含む)に使われる、低容量のメーリングリストです。
+ 'config-subscribe-help' => 'これは、リリースの告知 (重要なセキュリティに関する案内を含む) に使用される、流量が少ないメーリングリストです。
このメーリングリストを購読して、新しいバージョンが出た場合にMediaWikiを更新してください。',
'config-almost-done' => 'これでほぼ終わりました!
残りの設定を飛ばして、ウィキを今すぐインストールできます。',
array( 'addField', 'uploadstash', 'us_props', 'patch-uploadstash-us_props.sql' ),
array( 'modifyField', 'user_groups', 'ug_group', 'patch-ug_group-length-increase-255.sql' ),
array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ufg_group-length-increase-255.sql' ),
+ array( 'addIndex', 'page_props', 'pp_propname_page', 'patch-page_props-propname-page-index.sql' ),
);
}
array( 'addPgIndex', 'oldimage', 'oi_sha1', '(oi_sha1)' ),
array( 'addPgIndex', 'page', 'page_mediawiki_title', '(page_title) WHERE page_namespace = 8' ),
array( 'addPgIndex', 'pagelinks', 'pagelinks_title', '(pl_title)' ),
+ array( 'addPgIndex', 'page_props', 'pp_propname_page', '(pp_propname, pp_page)' ),
array( 'addPgIndex', 'revision', 'rev_text_id_idx', '(rev_text_id)' ),
array( 'addPgIndex', 'recentchanges', 'rc_timestamp_bot', '(rc_timestamp) WHERE rc_bot = 0' ),
array( 'addPgIndex', 'templatelinks', 'templatelinks_from', '(tl_from)' ),
array( 'addField', 'uploadstash', 'us_props', 'patch-uploadstash-us_props.sql' ),
array( 'modifyField', 'user_groups', 'ug_group', 'patch-ug_group-length-increase-255.sql' ),
array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ufg_group-length-increase-255.sql' ),
+ array( 'addIndex', 'page_props', 'pp_propname_page', 'patch-page_props-propname-page-index.sql' ),
);
}
* removed later on, when the first one is popped.
*
* @param $jobs array of Job objects
+ * @return bool
* @deprecated 1.21
*/
public static function batchInsert( $jobs ) {
* large batches of jobs can cause slave lag.
*
* @param $jobs array of Job objects
+ * @return bool
* @deprecated 1.21
*/
public static function safeBatchInsert( $jobs ) {
}
/**
- * @return bool
+ * @return bool Whether only one of each identical set of jobs should be run
*/
public function ignoreDuplicates() {
return $this->removeDuplicates;
}
+ /**
+ * @return bool Whether this job can be retried on failure by job runners
+ */
+ public function allowRetries() {
+ return true;
+ }
+
/**
* Subclasses may need to override this to make duplication detection work
*
if ( $paramString != '' ) {
$paramString .= ' ';
}
-
if ( is_array( $value ) ) {
$value = "array(" . count( $value ) . ")";
- } else if ( is_object( $value ) && !method_exists( $value, '__toString' ) ) {
+ } elseif ( is_object( $value ) && !method_exists( $value, '__toString' ) ) {
$value = "object(" . get_class( $value ) . ")";
}
+ $value = (string)$value;
+ if ( mb_strlen( $value ) > 1024 ) {
+ $value = "string(" . mb_strlen( $value ) . ")";
+ }
$paramString .= "$key=$value";
}
protected $type; // string; job type
protected $order; // string; job priority for pop()
protected $claimTTL; // integer; seconds
+ protected $maxTries; // integer; maximum number of times to try a job
const QoS_Atomic = 1; // integer; "all-or-nothing" job insertions
- const MAX_ATTEMPTS = 3; // integer; number of times to try a job
-
/**
* @param $params array
*/
$this->type = $params['type'];
$this->order = isset( $params['order'] ) ? $params['order'] : 'random';
$this->claimTTL = isset( $params['claimTTL'] ) ? $params['claimTTL'] : 0;
+ $this->maxTries = isset( $params['maxTries'] ) ? $params['maxTries'] : 3;
}
/**
* by timestamp, allowing for some jobs to be popped off out of order.
* If "random" is used, pop() will pick jobs in random order. This might be
* useful for improving concurrency depending on the queue storage medium.
+ * Note that "random" really means "don't care", so it may actually be FIFO
+ * or only weakly random (e.g. pop() takes one of the first X jobs randomly).
* - claimTTL : If supported, the queue will recycle jobs that have been popped
* but not acknowledged as completed after this many seconds. Recycling
* of jobs simple means re-inserting them into the queue. Jobs can be
/**
* Push a single jobs into the queue.
* This does not require $wgJobClasses to be set for the given job type.
+ * Outside callers should use JobQueueGroup::push() instead of this function.
*
* @param $jobs Job|Array
* @param $flags integer Bitfield (supports JobQueue::QoS_Atomic)
* @throws MWException
*/
final public function push( $jobs, $flags = 0 ) {
- $jobs = is_array( $jobs ) ? $jobs : array( $jobs );
-
- return $this->batchPush( $jobs, $flags );
+ return $this->batchPush( is_array( $jobs ) ? $jobs : array( $jobs ), $flags );
}
/**
* Push a batch of jobs into the queue.
* This does not require $wgJobClasses to be set for the given job type.
+ * Outside callers should use JobQueueGroup::push() instead of this function.
*
* @param $jobs array List of Jobs
* @param $flags integer Bitfield (supports JobQueue::QoS_Atomic)
* @throws MWException
*/
final public function batchPush( array $jobs, $flags = 0 ) {
+ if ( !count( $jobs ) ) {
+ return true; // nothing to do
+ }
foreach ( $jobs as $job ) {
if ( $job->getType() !== $this->type ) {
throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
}
}
+
wfProfileIn( __METHOD__ );
$ok = $this->doBatchPush( $jobs, $flags );
wfProfileOut( __METHOD__ );
/**
* Pop a job off of the queue.
* This requires $wgJobClasses to be set for the given job type.
+ * Outside callers should use JobQueueGroup::pop() instead of this function.
*
- * @return Job|bool Returns false on failure
+ * @return Job|bool Returns false if there are no jobs
* @throws MWException
*/
final public function pop() {
* Acknowledge that a job was completed.
*
* This does nothing for certain queue classes or if "claimTTL" is not set.
+ * Outside callers should use JobQueueGroup::ack() instead of this function.
*
* @param $job Job
* @return bool
* @return void
*/
protected function doFlushCaches() {}
+
+ /**
+ * Namespace the queue with a key to isolate it for testing
+ *
+ * @param $key string
+ * @return void
+ * @throws MWException
+ */
+ public function setTestingPrefix( $key ) {
+ throw new MWException( "Queue namespacing not supported for this queue type." );
+ }
}
--- /dev/null
+<?php
+/**
+ * Job queue aggregator code.
+ *
+ * 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
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle tracking information about all queues
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+abstract class JobQueueAggregator {
+ /** @var JobQueueAggregator */
+ protected static $instance = null;
+
+ /**
+ * @param array $params
+ */
+ protected function __construct( array $params ) {}
+
+ /**
+ * @return JobQueueAggregator
+ */
+ final public static function singleton() {
+ global $wgJobQueueAggregator;
+
+ if ( !isset( self::$instance ) ) {
+ $class = $wgJobQueueAggregator['class'];
+ $obj = new $class( $wgJobQueueAggregator );
+ if ( !( $obj instanceof JobQueueAggregator ) ) {
+ throw new MWException( "Class '$class' is not a JobQueueAggregator class." );
+ }
+ self::$instance = $obj;
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Destroy the singleton instance
+ *
+ * @return void
+ */
+ final public static function destroySingleton() {
+ self::$instance = null;
+ }
+
+ /**
+ * Mark a queue as being empty
+ *
+ * @param string $wiki
+ * @param string $type
+ * @return bool Success
+ */
+ final public function notifyQueueEmpty( $wiki, $type ) {
+ wfProfileIn( __METHOD__ );
+ $ok = $this->doNotifyQueueEmpty( $wiki, $type );
+ wfProfileOut( __METHOD__ );
+ return $ok;
+ }
+
+ /**
+ * @see JobQueueAggregator::notifyQueueEmpty()
+ */
+ abstract protected function doNotifyQueueEmpty( $wiki, $type );
+
+ /**
+ * Mark a queue as being non-empty
+ *
+ * @param string $wiki
+ * @param string $type
+ * @return bool Success
+ */
+ final public function notifyQueueNonEmpty( $wiki, $type ) {
+ wfProfileIn( __METHOD__ );
+ $ok = $this->doNotifyQueueNonEmpty( $wiki, $type );
+ wfProfileOut( __METHOD__ );
+ return $ok;
+ }
+
+ /**
+ * @see JobQueueAggregator::notifyQueueNonEmpty()
+ */
+ abstract protected function doNotifyQueueNonEmpty( $wiki, $type );
+
+ /**
+ * Get the list of all of the queues with jobs
+ *
+ * @return Array (job type => (list of wiki IDs))
+ */
+ final public function getAllReadyWikiQueues() {
+ wfProfileIn( __METHOD__ );
+ $res = $this->doGetAllReadyWikiQueues();
+ wfProfileOut( __METHOD__ );
+ return $res;
+ }
+
+ /**
+ * @see JobQueueAggregator::getAllReadyWikiQueues()
+ */
+ abstract protected function doGetAllReadyWikiQueues();
+
+ /**
+ * Get all databases that have a pending job.
+ * This poll all the queues and is this expensive.
+ *
+ * @return Array (job type => (list of wiki IDs))
+ */
+ protected function findPendingWikiQueues() {
+ global $wgLocalDatabases;
+
+ $pendingDBs = array(); // (job type => (db list))
+ foreach ( $wgLocalDatabases as $db ) {
+ foreach ( JobQueueGroup::singleton( $db )->getQueuesWithJobs() as $type ) {
+ $pendingDBs[$type][] = $db;
+ }
+ }
+
+ return $pendingDBs;
+ }
+}
--- /dev/null
+<?php
+/**
+ * Job queue aggregator code that uses BagOStuff.
+ *
+ * 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
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle tracking information about all queues using BagOStuff
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+class JobQueueAggregatorMemc extends JobQueueAggregator {
+ /** @var BagOStuff */
+ protected $cache;
+
+ protected $cacheTTL; // integer; seconds
+
+ /**
+ * @params include:
+ * - objectCache : Name of an object cache registered in $wgObjectCaches.
+ * This defaults to the one specified by $wgMainCacheType.
+ * - cacheTTL : Seconds to cache the aggregate data before regenerating.
+ * @param array $params
+ */
+ protected function __construct( array $params ) {
+ parent::__construct( $params );
+ $this->cache = isset( $params['objectCache'] )
+ ? wfGetCache( $params['objectCache'] )
+ : wfGetMainCache();
+ $this->cacheTTL = isset( $params['cacheTTL'] ) ? $params['cacheTTL'] : 180; // 3 min
+ }
+
+ /**
+ * @see JobQueueAggregator::doNotifyQueueEmpty()
+ */
+ protected function doNotifyQueueEmpty( $wiki, $type ) {
+ $key = $this->getReadyQueueCacheKey();
+ // Delist the queue from the "ready queue" list
+ if ( $this->cache->add( "$key:lock", 1, 60 ) ) { // lock
+ $curInfo = $this->cache->get( $key );
+ if ( is_array( $curInfo ) && isset( $curInfo['pendingDBs'][$type] ) ) {
+ if ( in_array( $wiki, $curInfo['pendingDBs'][$type] ) ) {
+ $curInfo['pendingDBs'][$type] = array_diff(
+ $curInfo['pendingDBs'][$type], array( $wiki ) );
+ $this->cache->set( $key, $curInfo );
+ }
+ }
+ $this->cache->delete( "$key:lock" ); // unlock
+ }
+ return true;
+ }
+
+ /**
+ * @see JobQueueAggregator::doNotifyQueueNonEmpty()
+ */
+ protected function doNotifyQueueNonEmpty( $wiki, $type ) {
+ return true; // updated periodically
+ }
+
+ /**
+ * @see JobQueueAggregator::doAllGetReadyWikiQueues()
+ */
+ protected function doGetAllReadyWikiQueues() {
+ $key = $this->getReadyQueueCacheKey();
+ // If the cache entry wasn't present, is stale, or in .1% of cases otherwise,
+ // regenerate the cache. Use any available stale cache if another process is
+ // currently regenerating the pending DB information.
+ $pendingDbInfo = $this->cache->get( $key );
+ if ( !is_array( $pendingDbInfo )
+ || ( time() - $pendingDbInfo['timestamp'] ) > $this->cacheTTL
+ || mt_rand( 0, 999 ) == 0
+ ) {
+ if ( $this->cache->add( "$key:rebuild", 1, 1800 ) ) { // lock
+ $pendingDbInfo = array(
+ 'pendingDBs' => $this->findPendingWikiQueues(),
+ 'timestamp' => time()
+ );
+ for ( $attempts=1; $attempts <= 25; ++$attempts ) {
+ if ( $this->cache->add( "$key:lock", 1, 60 ) ) { // lock
+ $this->cache->set( $key, $pendingDbInfo );
+ $this->cache->delete( "$key:lock" ); // unlock
+ break;
+ }
+ }
+ $this->cache->delete( "$key:rebuild" ); // unlock
+ }
+ }
+ return is_array( $pendingDbInfo )
+ ? $pendingDbInfo['pendingDBs']
+ : array(); // cache is both empty and locked
+ }
+
+ /**
+ * @return string
+ */
+ private function getReadyQueueCacheKey() {
+ return "jobqueue:aggregator:ready-queues:v1"; // global
+ }
+}
--- /dev/null
+<?php
+/**
+ * Job queue aggregator code that uses PhpRedis.
+ *
+ * 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
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle tracking information about all queues using PhpRedis
+ *
+ * @ingroup JobQueue
+ * @since 1.21
+ */
+class JobQueueAggregatorRedis extends JobQueueAggregator {
+ /** @var RedisConnectionPool */
+ protected $redisPool;
+
+ /**
+ * @params include:
+ * - redisConfig : An array of parameters to RedisConnectionPool::__construct().
+ * - redisServer : A hostname/port combination or the absolute path of a UNIX socket.
+ * If a hostname is specified but no port, the standard port number
+ * 6379 will be used. Required.
+ * @param array $params
+ */
+ protected function __construct( array $params ) {
+ parent::__construct( $params );
+ $this->server = $params['redisServer'];
+ $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
+ }
+
+ /**
+ * @see JobQueueAggregator::doNotifyQueueEmpty()
+ */
+ protected function doNotifyQueueEmpty( $wiki, $type ) {
+ $conn = $this->getConnection();
+ if ( !$conn ) {
+ return false;
+ }
+ try {
+ $conn->hDel( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ) );
+ return true;
+ } catch ( RedisException $e ) {
+ $this->handleException( $conn, $e );
+ return false;
+ }
+ }
+
+ /**
+ * @see JobQueueAggregator::doNotifyQueueNonEmpty()
+ */
+ protected function doNotifyQueueNonEmpty( $wiki, $type ) {
+ $conn = $this->getConnection();
+ if ( !$conn ) {
+ return false;
+ }
+ try {
+ $conn->hSet( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ), time() );
+ return true;
+ } catch ( RedisException $e ) {
+ $this->handleException( $conn, $e );
+ return false;
+ }
+ }
+
+ /**
+ * @see JobQueueAggregator::doAllGetReadyWikiQueues()
+ */
+ protected function doGetAllReadyWikiQueues() {
+ $conn = $this->getConnection();
+ if ( !$conn ) {
+ return array();
+ }
+ try {
+ $conn->multi( Redis::PIPELINE );
+ $conn->exists( $this->getReadyQueueKey() );
+ $conn->hGetAll( $this->getReadyQueueKey() );
+ list( $exists, $map ) = $conn->exec();
+
+ if ( $exists ) { // cache hit
+ $pendingDBs = array(); // (type => list of wikis)
+ foreach ( $map as $key => $time ) {
+ list( $type, $wiki ) = $this->dencQueueName( $key );
+ $pendingDBs[$type][] = $wiki;
+ }
+ } else { // cache miss
+ $pendingDBs = $this->findPendingWikiQueues(); // (type => list of wikis)
+
+ $now = time();
+ $map = array();
+ foreach ( $pendingDBs as $type => $wikis ) {
+ foreach ( $wikis as $wiki ) {
+ $map[$this->encQueueName( $type, $wiki )] = $now;
+ }
+ }
+ $conn->hMSet( $this->getReadyQueueKey(), $map );
+ }
+
+ return $pendingDBs;
+ } catch ( RedisException $e ) {
+ $this->handleException( $conn, $e );
+ return array();
+ }
+ }
+
+ /**
+ * Get a connection to the server that handles all sub-queues for this queue
+ *
+ * @return Array (server name, Redis instance)
+ * @throws MWException
+ */
+ protected function getConnection() {
+ return $this->redisPool->getConnection( $this->server );
+ }
+
+ /**
+ * @param RedisConnRef $conn
+ * @param RedisException $e
+ * @return void
+ */
+ protected function handleException( RedisConnRef $conn, $e ) {
+ $this->redisPool->handleException( $this->server, $conn, $e );
+ }
+
+ /**
+ * @return string
+ */
+ private function getReadyQueueKey() {
+ return "jobqueue:aggregator:h-ready-queues:v1"; // global
+ }
+
+ /**
+ * @param string $type
+ * @param string $wiki
+ * @return string
+ */
+ private function encQueueName( $type, $wiki ) {
+ return rawurlencode( $type ) . '/' . rawurlencode( $wiki );
+ }
+
+ /**
+ * @param string $name
+ * @return string
+ */
+ private function dencQueueName( $name ) {
+ list( $type, $wiki ) = explode( '/', $name, 2 );
+ return array( rawurldecode( $type ), rawurldecode( $wiki ) );
+ }
+}
}
}
+ $key = $this->getCacheKey( 'empty' );
$atomic = ( $flags & self::QoS_Atomic );
- $key = $this->getCacheKey( 'empty' );
- $ttl = self::CACHE_TTL_LONG;
$dbw->onTransactionIdle(
- function() use ( $dbw, $rowSet, $rowList, $atomic, $key, $ttl, $scope
+ function() use ( $dbw, $rowSet, $rowList, $atomic, $key, $scope
) {
global $wgMemc;
$dbw->commit( __METHOD__ );
}
- $wgMemc->set( $key, 'false', $ttl ); // queue is not empty
+ $wgMemc->set( $key, 'false', JobQueueDB::CACHE_TTL_LONG );
} );
}
'job_cmd' => $this->type,
"job_token != {$dbw->addQuotes( '' )}", // was acquired
"job_token_timestamp < {$dbw->addQuotes( $claimCutoff )}", // stale
- "job_attempts < {$dbw->addQuotes( self::MAX_ATTEMPTS )}" ), // retries left
+ "job_attempts < {$dbw->addQuotes( $this->maxTries )}" ), // retries left
__METHOD__
);
$ids = array_map( function( $o ) { return $o->job_id; }, iterator_to_array( $res ) );
"job_token_timestamp < {$dbw->addQuotes( $pruneCutoff )}" // stale
);
if ( $this->claimTTL > 0 ) { // only prune jobs attempted too many times...
- $conds[] = "job_attempts >= {$dbw->addQuotes( self::MAX_ATTEMPTS )}";
+ $conds[] = "job_attempts >= {$dbw->addQuotes( $this->maxTries )}";
}
// Get the IDs of jobs that are considered stale and should be removed. Selecting
// the IDs first means that the UPDATE can be done by primary key (less deadlocks).
const TYPE_DEFAULT = 1; // integer; jobs popped by default
const TYPE_ANY = 2; // integer; any job
- const USE_CACHE = 1; // integer; use process cache
+ const USE_CACHE = 1; // integer; use process or persistent cache
const PROC_CACHE_TTL = 15; // integer; seconds
+ const CACHE_VERSION = 1; // integer; cache version
+
/**
* @param $wiki string Wiki ID
*/
protected function __construct( $wiki ) {
$this->wiki = $wiki;
- $this->cache = new ProcessCacheLRU( 1 );
+ $this->cache = new ProcessCacheLRU( 10 );
}
/**
}
/**
+ * Get the job queue object for a given queue type
+ *
* @param $type string
- * @return JobQueue Job queue object for a given queue type
+ * @return JobQueue
*/
public function get( $type ) {
global $wgJobTypeConf;
/**
* Insert jobs into the respective queues of with the belong.
- * This inserts the jobs into the queue specified by $wgJobTypeConf.
+ *
+ * This inserts the jobs into the queue specified by $wgJobTypeConf
+ * and updates the aggregate job queue information cache as needed.
*
* @param $jobs Job|array A single Job or a list of Jobs
* @throws MWException
$ok = true;
foreach ( $jobsByType as $type => $jobs ) {
- if ( !$this->get( $type )->push( $jobs ) ) {
+ if ( $this->get( $type )->push( $jobs ) ) {
+ JobQueueAggregator::singleton()->notifyQueueNonEmpty( $this->wiki, $type );
+ } else {
$ok = false;
}
}
/**
* Pop a job off one of the job queues
*
- * @param $queueType integer JobQueueGroup::TYPE_* constant
+ * This pops a job off a queue as specified by $wgJobTypeConf and
+ * updates the aggregate job queue information cache as needed.
+ *
+ * @param $qtype integer|string JobQueueGroup::TYPE_DEFAULT or type string
* @param $flags integer Bitfield of JobQueueGroup::USE_* constants
* @return Job|bool Returns false on failure
*/
- public function pop( $queueType = self::TYPE_DEFAULT, $flags = 0 ) {
- if ( $flags & self::USE_CACHE ) {
- if ( !$this->cache->has( 'queues-ready', 'list', self::PROC_CACHE_TTL ) ) {
- $this->cache->set( 'queues-ready', 'list', $this->getQueuesWithJobs() );
+ public function pop( $qtype = self::TYPE_DEFAULT, $flags = 0 ) {
+ if ( is_string( $qtype ) ) { // specific job type
+ $job = $this->get( $qtype )->pop();
+ if ( !$job ) {
+ JobQueueAggregator::singleton()->notifyQueueEmpty( $this->wiki, $qtype );
+ }
+ return $job;
+ } else { // any job in the "default" jobs types
+ if ( $flags & self::USE_CACHE ) {
+ if ( !$this->cache->has( 'queues-ready', 'list', self::PROC_CACHE_TTL ) ) {
+ $this->cache->set( 'queues-ready', 'list', $this->getQueuesWithJobs() );
+ }
+ $types = $this->cache->get( 'queues-ready', 'list' );
+ } else {
+ $types = $this->getQueuesWithJobs();
}
- $types = $this->cache->get( 'queues-ready', 'list' );
- } else {
- $types = $this->getQueuesWithJobs();
- }
-
- if ( $queueType == self::TYPE_DEFAULT ) {
- $types = array_intersect( $types, $this->getDefaultQueueTypes() );
- }
- shuffle( $types ); // avoid starvation
- foreach ( $types as $type ) { // for each queue...
- $job = $this->get( $type )->pop();
- if ( $job ) { // found
- return $job;
- } else { // not found
- $this->cache->clear( 'queues-ready' );
+ if ( $qtype == self::TYPE_DEFAULT ) {
+ $types = array_intersect( $types, $this->getDefaultQueueTypes() );
+ }
+ shuffle( $types ); // avoid starvation
+
+ foreach ( $types as $type ) { // for each queue...
+ $job = $this->get( $type )->pop();
+ if ( $job ) { // found
+ return $job;
+ } else { // not found
+ JobQueueAggregator::singleton()->notifyQueueEmpty( $this->wiki, $type );
+ $this->cache->clear( 'queues-ready' );
+ }
}
- }
- return false; // no jobs found
+ return false; // no jobs found
+ }
}
/**
* @return array List of strings
*/
public function getQueueTypes() {
- global $wgJobClasses;
-
- return array_keys( $wgJobClasses );
+ return array_keys( $this->getCachedConfigVar( 'wgJobClasses' ) );
}
/**
}
/**
+ * Get the list of job types that have non-empty queues
+ *
* @return Array List of job types that have non-empty queues
*/
public function getQueuesWithJobs() {
return $types;
}
- /**
- * @return Array List of default job types that have non-empty queues
- */
- public function getDefaultQueuesWithJobs() {
- $types = array();
- foreach ( $this->getDefaultQueueTypes() as $type ) {
- if ( !$this->get( $type )->isEmpty() ) {
- $types[] = $type;
- }
- }
- return $types;
- }
-
/**
* Execute any due periodic queue maintenance tasks for all queues.
*
return $count;
}
+
+ /**
+ * @param $name string
+ * @return mixed
+ */
+ private function getCachedConfigVar( $name ) {
+ global $wgConf, $wgMemc;
+
+ if ( $this->wiki === wfWikiID() ) {
+ return $GLOBALS[$name]; // common case
+ } else {
+ list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+ $key = wfForeignMemcKey( $db, $prefix, 'configvalue', $name );
+ $value = $wgMemc->get( $key ); // ('v' => ...) or false
+ if ( is_array( $value ) ) {
+ return $value['v'];
+ } else {
+ $value = $wgConf->getConfig( $this->wiki, $name );
+ $wgMemc->set( $key, array( 'v' => $value ), 86400 + mt_rand( 0, 86400 ) );
+ return $value;
+ }
+ }
+ }
}
const ROOTJOB_TTL = 1209600; // integer; seconds to remember root jobs (14 days)
const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed (7 days)
+ protected $key; // string; key to prefix the queue keys with (used for testing)
+
/**
* @params include:
- * - redisConf : An array of parameters to RedisConnectionPool::__construct().
- * - server : A hostname/port combination or the absolute path of a UNIX socket.
- * If a hostname is specified but no port, the standard port number
- * 6379 will be used. Required.
+ * - redisConfig : An array of parameters to RedisConnectionPool::__construct().
+ * - redisServer : A hostname/port combination or the absolute path of a UNIX socket.
+ * If a hostname is specified but no port, the standard port number
+ * 6379 will be used. Required.
* @param array $params
*/
public function __construct( array $params ) {
parent::__construct( $params );
- $this->server = $params['redisConf']['server'];
- $this->redisPool = RedisConnectionPool::singleton( $params['redisConf'] );
+ $this->server = $params['redisServer'];
+ $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
}
/**
* @throws MWException
*/
protected function doIsEmpty() {
- if ( mt_rand( 0, 99 ) == 0 ) {
- $this->doInternalMaintenance();
- }
-
$conn = $this->getConnection();
try {
return ( $conn->lSize( $this->getQueueKey( 'l-unclaimed' ) ) == 0 );
* @throws MWException
*/
protected function doGetSize() {
- if ( mt_rand( 0, 99 ) == 0 ) {
- $this->doInternalMaintenance();
- }
-
$conn = $this->getConnection();
try {
return $conn->lSize( $this->getQueueKey( 'l-unclaimed' ) );
* @throws MWException
*/
protected function doGetAcquiredCount() {
- if ( mt_rand( 0, 99 ) == 0 ) {
- $this->doInternalMaintenance();
+ if ( $this->claimTTL <= 0 ) {
+ return 0; // no acknowledgements
}
-
$conn = $this->getConnection();
try {
- if ( $this->claimTTL > 0 ) {
- return $conn->lSize( $this->getQueueKey( 'l-claimed' ) );
- } else {
- return 0;
- }
+ return $conn->lSize( $this->getQueueKey( 'l-claimed' ) );
} catch ( RedisException $e ) {
$this->throwRedisException( $this->server, $conn, $e );
}
protected function doPop() {
$job = false;
- if ( mt_rand( 0, 99 ) == 0 ) {
- $this->doInternalMaintenance();
+ if ( $this->claimTTL <= 0 && mt_rand( 0, 99 ) == 0 ) {
+ $this->cleanupClaimedJobs(); // prune jobs and IDs from the "garbage" list
}
$conn = $this->getConnection();
return ( $timestamp && $timestamp > $params['rootJobTimestamp'] );
}
- /**
- * Do any job recycling or queue cleanup as needed
- *
- * @return void
- * @return integer Number of jobs recycled/deleted
- * @throws MWException
- */
- protected function doInternalMaintenance() {
- return ( $this->claimTTL > 0 ) ?
- $this->recycleAndDeleteStaleJobs() : $this->cleanupClaimedJobs();
- }
-
/**
* Recycle or destroy any jobs that have been claimed for too long
*
* @return integer Number of jobs recycled/deleted
* @throws MWException
*/
- protected function recycleAndDeleteStaleJobs() {
+ public function recycleAndDeleteStaleJobs() {
+ if ( $this->claimTTL <= 0 ) { // sanity
+ throw new MWException( "Cannot recycle jobs since acknowledgements are disabled." );
+ }
$count = 0;
// For each job item that can be retried, we need to add it back to the
// main queue and remove it from the list of currenty claimed job items.
if ( $ctime < $claimCutoff ) {
// Get the number of failed attempts
$attempts = isset( $info['attempts'] ) ? $info['attempts'] : 0;
- if ( $attempts < self::MAX_ATTEMPTS ) {
+ if ( $attempts < $this->maxTries ) {
$uidsPush[] = $uid; // retry it
} elseif ( $ctime < $pruneCutoff ) {
$uidsRemove[] = $uid; // just remove it
return $count;
}
+ /**
+ * @return Array
+ */
+ protected function doGetPeriodicTasks() {
+ if ( $this->claimTTL > 0 ) {
+ return array(
+ 'recycleAndDeleteStaleJobs' => array(
+ 'callback' => array( $this, 'recycleAndDeleteStaleJobs' ),
+ 'period' => ceil( $this->claimTTL / 2 )
+ )
+ );
+ } else {
+ return array();
+ }
+ }
+
/**
* @param $job Job
* @return array
*/
private function getQueueKey( $prop ) {
list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
- return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, $prop );
+ if ( strlen( $this->key ) ) { // namespaced queue (for testing)
+ return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, $this->key, $prop );
+ } else {
+ return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, $prop );
+ }
}
/**
}
return $res;
}
+
+ /**
+ * @param $key string
+ * @return void
+ */
+ public function setTestingPrefix( $key ) {
+ $this->key = $key;
+ }
}
return false;
}
+ $user = $this->getUser();
+ if ( !$user ) {
+ $this->setLastError( 'Invalid user' );
+ return false;
+ }
+
# Save it
global $wgUser;
$oldUser = $wgUser;
- $wgUser = $this->getUser();
+ $wgUser = $user;
$article = WikiPage::factory( $this->title );
$reason = wfMessage( 'double-redirect-fixed-' . $this->reason,
$this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText()
)->inContentLanguage()->text();
- $article->doEditContent( $newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $this->getUser() );
+ $article->doEditContent( $newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $user );
$wgUser = $oldUser;
return true;
/**
* Get a user object for doing edits, from a request-lifetime cache
- * @return User
+ * False will be returned if the user name specified in the
+ * 'double-redirect-fixer' message is invalid.
+ *
+ * @return User|bool
*/
function getUser() {
if ( !self::$user ) {
- self::$user = User::newFromName( wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text(), false );
- # FIXME: newFromName could return false on a badly configured wiki.
- if ( !self::$user->isLoggedIn() ) {
+ self::$user = User::newFromName( wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text() );
+ # User::newFromName() can return false on a badly configured wiki.
+ if ( self::$user && !self::$user->isLoggedIn() ) {
self::$user->addToDatabase();
}
}
}
function run() {
- UserMailer::send(
+ $status = UserMailer::send(
$this->params['to'],
$this->params['from'],
$this->params['subj'],
$this->params['body'],
$this->params['replyto']
);
- return true;
+
+ return $status->isOK();
}
}
/** */
+if ( PHP_SAPI != 'cli' ) {
+ die( "Run me from the command line please.\n" );
+}
+
require_once 'UtfNormalDefines.php';
require_once 'UtfNormalUtil.php';
require_once 'UtfNormal.php';
$verbose = false;
#$verbose = true;
-if( PHP_SAPI != 'cli' ) {
- die( "Run me from the command line please.\n" );
-}
$in = fopen( "UTF-8-test.txt", "rt" );
if( !$in ) {
* @ingroup UtfNormal
*/
+if( PHP_SAPI != 'cli' ) {
+ die( "Run me from the command line please.\n" );
+}
+
if( isset( $_SERVER['argv'] ) && in_array( '--icu', $_SERVER['argv'] ) ) {
dl( 'php_utfnormal.so' );
}
define( 'BENCH_CYCLES', 5 );
-if( PHP_SAPI != 'cli' ) {
- die( "Run me from the command line please.\n" );
-}
-
$testfiles = array(
'testdata/washington.txt' => 'English text',
'testdata/berlin.txt' => 'German text',
* @ingroup UtfNormal
*/
+if( PHP_SAPI != 'cli' ) {
+ die( "Run me from the command line please.\n" );
+}
+
if( isset( $_SERVER['argv'] ) && in_array( '--icu', $_SERVER['argv'] ) ) {
dl( 'php_utfnormal.so' );
}
define( 'BIGSIZE', 1024 * 1024 * 10); // 10m
ini_set('memory_limit', BIGSIZE + 120 * 1024 * 1024);
-if( PHP_SAPI != 'cli' ) {
- die( "Run me from the command line please.\n" );
-}
-
$testfiles = array(
'testdata/washington.txt' => 'English text',
'testdata/berlin.txt' => 'German text',
* @ingroup UtfNormal
*/
+if( PHP_SAPI != 'cli' ) {
+ die( "Run me from the command line please.\n" );
+}
+
$verbose = true;
#define( 'PRETTY_UTF8', true );
require_once 'UtfNormalUtil.php';
require_once 'UtfNormal.php';
-if( PHP_SAPI != 'cli' ) {
- die( "Run me from the command line please.\n" );
-}
-
$in = fopen("NormalizationTest.txt", "rt");
if( !$in ) {
print "Couldn't open NormalizationTest.txt -- can't run tests.\n";
* @return bool
*/
public function cas( $casToken, $key, $value, $exptime = 0 ) {
- $db = $this->getDB();
- $exptime = intval( $exptime );
-
- if ( $exptime < 0 ) {
- $exptime = 0;
- }
+ list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
+ try {
+ $db = $this->getDB( $serverIndex );
+ $exptime = intval( $exptime );
- if ( $exptime == 0 ) {
- $encExpiry = $this->getMaxDateTime();
- } else {
- if ( $exptime < 3.16e8 ) { # ~10 years
- $exptime += time();
+ if ( $exptime < 0 ) {
+ $exptime = 0;
}
- $encExpiry = $db->timestamp( $exptime );
- }
- try {
+ if ( $exptime == 0 ) {
+ $encExpiry = $this->getMaxDateTime( $db );
+ } else {
+ if ( $exptime < 3.16e8 ) { # ~10 years
+ $exptime += time();
+ }
+ $encExpiry = $db->timestamp( $exptime );
+ }
$db->begin( __METHOD__ );
// (bug 24425) use a replace if the db supports it instead of
// delete/insert to avoid clashes with conflicting keynames
$db->update(
- $this->getTableByKey( $key ),
+ $tableName,
array(
'keyname' => $key,
'value' => $db->encodeBlob( $this->serialize( $value ) ),
array(
'keyname' => $key,
'value' => $db->encodeBlob( $this->serialize( $casToken ) )
- ), __METHOD__ );
+ ),
+ __METHOD__
+ );
$db->commit( __METHOD__ );
} catch ( DBQueryError $e ) {
$this->handleWriteError( $e );
/**
* @param $parser Parser
* @param string $num
- * @param null $raw
- * @return
+ * @param string $arg
+ * @return string
*/
- static function formatnum( $parser, $num = '', $raw = null) {
- if ( self::isRaw( $raw ) ) {
+ static function formatnum( $parser, $num = '', $arg = null ) {
+ if ( self::matchAgainstMagicword( 'rawsuffix', $arg ) ) {
$func = array( $parser->getFunctionLang(), 'parseFormattedNumber' );
+ } elseif ( self::matchAgainstMagicword( 'nocommafysuffix', $arg ) ) {
+ $func = array( $parser->getFunctionLang(), 'formatNumNoSeparators' );
} else {
$func = array( $parser->getFunctionLang(), 'formatNum' );
}
return '';
}
- static function isRaw( $param ) {
- static $mwRaw;
- if ( !$mwRaw ) {
- $mwRaw =& MagicWord::get( 'rawsuffix' );
- }
- if ( is_null( $param ) ) {
+ /**
+ * Matches the given value against the value of given magic word
+ *
+ * @param string $magicword magic word key
+ * @param mixed $value value to match
+ * @return boolean true on successful match
+ */
+ static private function matchAgainstMagicword( $magicword, $value ) {
+ if ( strval( $value ) === '' ) {
return false;
- } else {
- return $mwRaw->match( $param );
}
+ $mwObject = MagicWord::get( $magicword );
+ return $mwObject->match( $value );
}
static function formatRaw( $num, $raw ) {
- if( self::isRaw( $raw ) ) {
+ if( self::matchAgainstMagicword( 'rawsuffix', $raw ) ) {
return $num;
} else {
global $wgContLang;
static $cache = array();
// split the given option to its variable
- if( self::isRaw( $arg1 ) ) {
+ if( self::matchAgainstMagicword( 'rawsuffix', $arg1 ) ) {
//{{pagesincategory:|raw[|type]}}
$raw = $arg1;
$type = $magicWords->matchStartToEnd( $arg2 );
return $this->language->getPluralRules();
}
+ /**
+ * Get the digit groupin Pattern for the site content language.
+ *
+ * @return array
+ */
+ protected function getDigitGroupingPattern() {
+ return $this->language->digitGroupingPattern();
+ }
+
/**
* Get the digit transform table for the content language
- * Seperator transform table also required here to convert
- * the . and , sign to appropriate forms in content language.
*
* @return array
*/
protected function getDigitTransformTable() {
- $digitTransformTable = $this->language->digitTransformTable();
- $separatorTransformTable = $this->language->separatorTransformTable();
- if ( $digitTransformTable ) {
- array_merge( $digitTransformTable, (array)$separatorTransformTable );
- } else {
- return $separatorTransformTable;
- }
- return $digitTransformTable;
+ return $this->language->digitTransformTable();
}
+ /**
+ * Get seperator transform table required for converting
+ * the . and , sign to appropriate forms in site content language.
+ *
+ * @return array
+ */
+ protected function getSeparatorTransformTable() {
+ return $this->language->separatorTransformTable();
+ }
+
+
/**
* Get all the dynamic data for the content language to an array
*
protected function getData() {
return array(
'digitTransformTable' => $this->getDigitTransformTable(),
+ 'separatorTransformTable' => $this->getSeparatorTransformTable(),
'grammarForms' => $this->getSiteLangGrammarForms(),
'pluralRules' => $this->getPluralRules(),
+ 'digitGroupingPattern' => $this->getDigitGroupingPattern(),
);
}
function execute( $code ) {
$this->setHeaders();
- if ( wfReadOnly() ) {
- throw new ReadOnlyError;
- }
+ $this->checkReadOnly();
$this->attemptInvalidate( $code );
}
$opts->add( 'username', '' );
$opts->add( 'feed', '' );
$opts->add( 'tagfilter', '' );
+ $opts->add( 'invert', false );
$this->customFilters = array();
wfRunHooks( 'SpecialNewPagesFilters', array( $this, &$this->customFilters ) );
$namespace = $this->opts->consumeValue( 'namespace' );
$username = $this->opts->consumeValue( 'username' );
$tagFilterVal = $this->opts->consumeValue( 'tagfilter' );
+ $nsinvert = $this->opts->consumeValue( 'invert' );
// Check username input validity
$ut = Title::makeTitleSafe( NS_USER, $username );
'id' => 'namespace',
'class' => 'namespaceselector',
)
+ ) . ' ' .
+ Xml::checkLabel(
+ $this->msg( 'invert' )->text(),
+ 'invert',
+ 'nsinvert',
+ $nsinvert,
+ array( 'title' => $this->msg( 'tooltip-invert' )->text() )
) .
'</td>
</tr>' . ( $tagFilter ? (
$user = Title::makeTitleSafe( NS_USER, $username );
if( $namespace !== false ) {
- $conds['rc_namespace'] = $namespace;
+ if ( $this->opts->getValue( 'invert' ) ) {
+ $conds[] = 'rc_namespace != ' . $this->mDb->addQuotes( $namespace );
+ } else {
+ $conds['rc_namespace'] = $namespace;
+ }
$rcIndexes = array( 'new_name_timestamp' );
} else {
$rcIndexes = array( 'rc_timestamp' );
--- /dev/null
+<?php
+/**
+ * Implements Special:PagesWithProp
+ *
+ * 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
+ *
+ * @since 1.21
+ * @file
+ * @ingroup SpecialPage
+ * @author Brad Jorsch
+ */
+
+
+/**
+ * Special:PagesWithProp to search the page_props table
+ * @ingroup SpecialPage
+ * @since 1.21
+ */
+class SpecialPagesWithProp extends QueryPage {
+ private $propName = null;
+
+ function __construct( $name = 'PagesWithProp' ) {
+ parent::__construct( $name );
+ }
+
+ function isCacheable() {
+ return false;
+ }
+
+ function execute( $par ) {
+ $this->setHeaders();
+ $this->outputHeader();
+
+ $request = $this->getRequest();
+ $propname = $request->getVal( 'propname', $par );
+
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select(
+ 'page_props',
+ 'pp_propname',
+ '',
+ __METHOD__,
+ array( 'DISTINCT', 'ORDER BY' => 'pp_propname' )
+ );
+ foreach ( $res as $row ) {
+ $propnames[$row->pp_propname] = $row->pp_propname;
+ }
+
+ $form = new HTMLForm( array(
+ 'propname' => array(
+ 'type' => 'selectorother',
+ 'name' => 'propname',
+ 'options' => $propnames,
+ 'default' => $propname,
+ 'label-message' => 'pageswithprop-prop',
+ 'required' => true,
+ ),
+ ), $this->getContext() );
+ $form->setMethod( 'get' );
+ $form->setAction( $this->getTitle()->getFullUrl() );
+ $form->setSubmitCallback( array( $this, 'onSubmit' ) );
+ $form->setWrapperLegend( $this->msg( 'pageswithprop-legend' ) );
+ $form->addHeaderText( $this->msg( 'pageswithprop-text' )->parseAsBlock() );
+ $form->setSubmitTextMsg( 'pageswithprop-submit' );
+
+ $form->prepareForm();
+ $form->displayForm( false );
+ if ( $propname !== '' && $propname !== null ) {
+ $form->trySubmit();
+ }
+ }
+
+ public function onSubmit( $data, $form ) {
+ $this->propName = $data['propname'];
+ parent::execute( $data['propname'] );
+ }
+
+ /**
+ * Disable RSS/Atom feeds
+ * @return bool
+ */
+ function isSyndicated() {
+ return false;
+ }
+
+ function getQueryInfo() {
+ return array(
+ 'tables' => array( 'page_props', 'page' ),
+ 'fields' => array(
+ 'page_id' => 'pp_page',
+ 'page_namespace',
+ 'page_title',
+ 'page_len',
+ 'page_is_redirect',
+ 'page_latest',
+ 'pp_value',
+ ),
+ 'conds' => array(
+ 'page_id = pp_page',
+ 'pp_propname' => $this->propName,
+ ),
+ 'options' => array()
+ );
+ }
+
+ function getOrderFields() {
+ return array( 'page_id' );
+ }
+
+ function formatResult( $skin, $result ) {
+ $title = Title::newFromRow( $result );
+ $ret = Linker::link( $title, null, array(), array(), array( 'known' ) );
+ if ( $result->pp_value !== '' ) {
+ $value = $this->msg( 'parentheses' )
+ ->rawParams( Xml::span( $result->pp_value, 'prop-value' ) )
+ ->escaped();
+ $ret .= " $value";
+ }
+ return $ret;
+ }
+}
return Status::newFatal( 'noname' );
} elseif ( 0 != $u->idForName() ) {
return Status::newFatal( 'userexists' );
- } elseif ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) {
- return Status::newFatal( 'badretype' );
}
- # check for minimal password length
- $valid = $u->getPasswordValidity( $this->mPassword );
- if ( $valid !== true ) {
- if ( !$this->mCreateaccountMail ) {
+ if ( $this->mCreateaccountMail ) {
+ # do not force a password for account creation by email
+ # set invalid password, it will be replaced later by a random generated password
+ $this->mPassword = null;
+ } else {
+ if ( $this->mPassword !== $this->mRetype ) {
+ return Status::newFatal( 'badretype' );
+ }
+
+ # check for minimal password length
+ $valid = $u->getPasswordValidity( $this->mPassword );
+ if ( $valid !== true ) {
if ( !is_array( $valid ) ) {
$valid = array( $valid, $wgMinimalPasswordLength );
}
return call_user_func_array( 'Status::newFatal', $valid );
- } else {
- # do not force a password for account creation by email
- # set invalid password, it will be replaced later by a random generated password
- $this->mPassword = null;
}
}
*/
private function IPInfo() {
$ip = str_replace( '--', ' - ', htmlspecialchars( $this->getRequest()->getIP() ) );
- return "<!-- visited from $ip -->\n" .
- "<span style='display:none'>visited from $ip</span>";
+ return "<!-- visited from $ip -->\n<span style='display:none'>visited from $ip</span>";
}
/**
function listAuthors( $authors ) {
$list = array();
foreach( (array)$authors as $item ) {
- if( $item == '...' ) {
+ if ( $item == '...' ) {
$list[] = $this->msg( 'version-poweredby-others' )->text();
+ } elseif ( substr( $item, -5 ) == ' ...]' ) {
+ $list[] = substr( $item, 0, -4 ) . $this->msg( 'version-poweredby-others' )->text() . "]";
} else {
$list[] = $item;
}
/* bool */ 'hideLiu' => (int)$user->getBoolOption( 'watchlisthideliu' ),
/* bool */ 'hidePatrolled' => (int)$user->getBoolOption( 'watchlisthidepatrolled' ),
/* bool */ 'hideOwn' => (int)$user->getBoolOption( 'watchlisthideown' ),
- /* ? */ 'namespace' => 'all',
+ /* bool */ 'extended' => (int)$user->getBoolOption( 'extendwatchlist' ),
+ /* ? */ 'namespace' => '', //means all
/* ? */ 'invert' => false,
/* bool */ 'associated' => false,
);
# Extract variables from the request, falling back to user preferences or
# other default values if these don't exist
- $prefs['days'] = floatval( $user->getOption( 'watchlistdays' ) );
- $prefs['hideminor'] = $user->getBoolOption( 'watchlisthideminor' );
- $prefs['hidebots'] = $user->getBoolOption( 'watchlisthidebots' );
- $prefs['hideanons'] = $user->getBoolOption( 'watchlisthideanons' );
- $prefs['hideliu'] = $user->getBoolOption( 'watchlisthideliu' );
- $prefs['hideown'] = $user->getBoolOption( 'watchlisthideown' );
- $prefs['hidepatrolled'] = $user->getBoolOption( 'watchlisthidepatrolled' );
-
- # Get query variables
$values = array();
- $values['days'] = $request->getVal( 'days', $prefs['days'] );
- $values['hideMinor'] = (int)$request->getBool( 'hideMinor', $prefs['hideminor'] );
- $values['hideBots'] = (int)$request->getBool( 'hideBots', $prefs['hidebots'] );
- $values['hideAnons'] = (int)$request->getBool( 'hideAnons', $prefs['hideanons'] );
- $values['hideLiu'] = (int)$request->getBool( 'hideLiu', $prefs['hideliu'] );
- $values['hideOwn'] = (int)$request->getBool( 'hideOwn', $prefs['hideown'] );
- $values['hidePatrolled'] = (int)$request->getBool( 'hidePatrolled', $prefs['hidepatrolled'] );
+ $values['days'] = $request->getVal( 'days', $defaults['days'] );
+ $values['hideMinor'] = (int)$request->getBool( 'hideMinor', $defaults['hideMinor'] );
+ $values['hideBots'] = (int)$request->getBool( 'hideBots', $defaults['hideBots'] );
+ $values['hideAnons'] = (int)$request->getBool( 'hideAnons', $defaults['hideAnons'] );
+ $values['hideLiu'] = (int)$request->getBool( 'hideLiu', $defaults['hideLiu'] );
+ $values['hideOwn'] = (int)$request->getBool( 'hideOwn', $defaults['hideOwn'] );
+ $values['hidePatrolled'] = (int)$request->getBool( 'hidePatrolled', $defaults['hidePatrolled'] );
+ $values['extended'] = (int)$request->getBool( 'extended', $defaults['extended'] );
foreach( $this->customFilters as $key => $params ) {
$values[$key] = (int)$request->getBool( $key );
}
}
# Toggle watchlist content (all recent edits or just the latest)
- if( $user->getOption( 'extendwatchlist' ) ) {
+ if( $values['extended'] ) {
$limitWatchlist = intval( $user->getOption( 'wllimit' ) );
$usePage = false;
} else {
$form = Xml::fieldset( $this->msg( 'watchlist-options' )->text(), false, array( 'id' => 'mw-watchlist-options' ) );
# Show watchlist header
- $form .= $this->msg( 'watchlist-details' )->numParams( $nitems )->parse();
+ $form .= $this->msg( 'watchlist-details' )->numParams( $nitems )->parse() . "\n";
if( $user->getOption( 'enotifwatchlistpages' ) && $wgEnotifWatchlist) {
$form .= $this->msg( 'wlheader-enotif' )->parseAsBlock() . "\n";
if( $wgShowUpdatedMarker ) {
$form .= Xml::openElement( 'form', array( 'method' => 'post',
'action' => $this->getTitle()->getLocalUrl(),
- 'id' => 'mw-watchlist-resetbutton' ) ) .
- $this->msg( 'wlheader-showupdated' )->parse() . ' ' .
- Xml::submitButton( $this->msg( 'enotif_reset' )->text(), array( 'name' => 'dummy' ) ) .
- Html::hidden( 'reset', 'all' );
+ 'id' => 'mw-watchlist-resetbutton' ) ) . "\n" .
+ $this->msg( 'wlheader-showupdated' )->parse() .
+ Xml::submitButton( $this->msg( 'enotif_reset' )->text(), array( 'name' => 'dummy' ) ) . "\n" .
+ Html::hidden( 'reset', 'all' ) . "\n";
foreach ( $nondefaults as $key => $value ) {
- $form .= Html::hidden( $key, $value );
+ $form .= Html::hidden( $key, $value ) . "\n";
}
- $form .= Xml::closeElement( 'form' );
+ $form .= Xml::closeElement( 'form' ) . "\n";
}
- $form .= '<hr />';
+ $form .= "<hr />\n";
$tables = array( 'recentchanges', 'watchlist' );
$fields = RecentChange::selectFields();
if( $values['days'] > 0 ) {
$timestamp = wfTimestampNow();
$wlInfo = $this->msg( 'wlnote' )->numParams( $numRows, round( $values['days'] * 24 ) )->params(
- $lang->userDate( $timestamp, $user ), $lang->userTime( $timestamp, $user ) )->parse() . '<br />';
+ $lang->userDate( $timestamp, $user ), $lang->userTime( $timestamp, $user ) )->parse() . "<br />\n";
}
- $cutofflinks = "\n" . $this->cutoffLinks( $values['days'], $nondefaults ) . "<br />\n";
+ $cutofflinks = $this->cutoffLinks( $values['days'], $nondefaults ) . "<br />\n";
# Spit out some control panel links
$filters = array(
$links[] = $this->showHideLink( $nondefaults, $msg, $name, $values[$name] );
}
+ $hiddenFields = $nondefaults;
+ unset( $hiddenFields['namespace'] );
+ unset( $hiddenFields['invert'] );
+ unset( $hiddenFields['associated'] );
+
# Namespace filter and put the whole form together.
$form .= $wlInfo;
$form .= $cutofflinks;
- $form .= $lang->pipeList( $links );
- $form .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-watchlist-form-namespaceselector' ) );
- $form .= '<hr /><p>';
+ $form .= $lang->pipeList( $links ) . "\n";
+ $form .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-watchlist-form-namespaceselector' ) ) . "\n";
+ $form .= "<hr />\n<p>";
$form .= Html::namespaceSelector(
array(
'selected' => $nameSpace,
$associated,
array( 'title' => $this->msg( 'tooltip-namespace_association' )->text() )
) . ' ';
- $form .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . '</p>';
- $form .= Html::hidden( 'days', $values['days'] );
- foreach ( $filters as $key => $msg ) {
- if ( $values[$key] ) {
- $form .= Html::hidden( $key, 1 );
- }
+ $form .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "</p>\n";
+ foreach ( $hiddenFields as $key => $value ) {
+ $form .= Html::hidden( $key, $value ) . "\n";
}
- $form .= Xml::closeElement( 'form' );
- $form .= Xml::closeElement( 'fieldset' );
+ $form .= Xml::closeElement( 'form' ) . "\n";
+ $form .= Xml::closeElement( 'fieldset' ) . "\n";
$output->addHTML( $form );
# If there's nothing to show, stop here
return $number;
}
+ /**
+ * Front-end for non-commafied formatNum
+ *
+ * @param mixed $number the string to be formatted, should be an integer
+ * or a floating point number.
+ * @since 1.21
+ * @return string
+ */
+ public function formatNumNoSeparators( $number ) {
+ return $this->formatNum( $number, true );
+ }
+
/**
* @param $number string
* @return string
return '';
}
- // Handle explicit 0= and 1= forms
+ // Handle explicit n=pluralform cases
foreach ( $forms as $index => $form ) {
- if ( isset( $form[1] ) && $form[1] === '=' ) {
- if ( $form[0] === (string) $count ) {
- return substr( $form, 2 );
+ if ( preg_match( '/\d+=/i', $form ) ) {
+ $pos = strpos( $form, '=' );
+ if ( substr( $form, 0, $pos ) === (string) $count ) {
+ return substr( $form, $pos + 1 );
}
unset( $forms[$index] );
}
<pluralRule count="two">n mod 10 is 2</pluralRule>
<pluralRule count="few">n mod 10 in 3..4</pluralRule>
</pluralRules>
- <!-- Plural form transformations
- Based on this discussion: http://translatewiki.net/wiki/Thread:Support/New_plural_rules_for_Scots_Gaelic_(gd)
- $forms[0] - 1
- $forms[1] - 2
- $forms[2] - 11
- $forms[3] - 12
- $forms[4] - 3-10, 13-19
- $forms[5] - 0, 20, rest -->
- <pluralRules locales="gd">
- <pluralRule count="one">n is 1</pluralRule>
- <pluralRule count="two">n is 2</pluralRule>
- <pluralRule count="elevan">n is 11</pluralRule>
- <pluralRule count="twelve">n is 12</pluralRule>
- <pluralRule count="few">n in 3..10 or n in 13..19</pluralRule>
- </pluralRules>
- <!-- Hopefully temporary overrides for bug 40251 -->
- <pluralRules locales="fa hu ja vi">
- <pluralRule count="one">n is 1</pluralRule>
- </pluralRules>
<!-- Copied from "bh" -->
<pluralRules locales="bho">
<pluralRule count="one">n in 0..1</pluralRule>
'search-interwiki-default' => '$1 نتيجة:',
'search-interwiki-more' => '(المزيد)',
'search-relatedarticle' => 'مرتبطة',
-'mwsuggest-disable' => 'عطÙ\84 اÙ\82تراØات أجاÙ\83س',
+'mwsuggest-disable' => 'تعطÙ\8aÙ\84 اÙ\82تراØات AJAX',
'searcheverything-enable' => 'ابحث في جميع النطاقات',
'searchrelated' => 'مرتبطة',
'searchall' => 'الكل',
'viewsourcetext' => 'ܡܨܐ ܐܢܬ ܕܬܚܙܐ ܘܬܢܣܚ ܠܡܒܘ̈ܥܐ ܕܗܕܐ ܦܐܬܐ:',
'protectedinterface' => 'ܗܕܐ ܦܐܬܐ ܡܘܬܪܐ ܟܬܝܒܬܐ ܕܦܐܬܐ ܠܚܘܪܙܐ ܒܗܢܐ ܘܝܩܝ, ܘܐܝܬܝܗܝ ܢܛܪܬܐ ܠܡܘܢܥ ܚܘܒܠܐ.
ܠܡܘܣܦ ܐܘ ܫܘܚܠܦ ܬܘܪ̈ܓܡܐ ܕܟܠܗܘܢ ܘܝܩܝ، ܐܦܠܚ [//translatewiki.net/ translatewiki.net]، ܬܪܡܝܬܐ ܕܬܘܪܓܡܐ ܕܡܝܕܝܐܘܝܩܝ.',
-'editinginterface' => "'''Ü\99Ü\98Ü\97ܪÜ\90:''' Ü\90ܢܬ Ü«Ü\9aÜ Ü¦Ü¬ ܦܐܬܐ ܕܡܬܦܠܚܬ ܒܚܙܝܐ ܟܬܝܒܝܐ ܕܬܚܪܙܬܐ.
+'editinginterface' => "'''Ü\99Ü\98Ü\97ܪÜ\90:''' Ü\90ܢܬ ܬܫÜ\9aÜ Ü¦ ܦܐܬܐ ܕܡܬܦܠܚܬ ܒܚܙܝܐ ܟܬܝܒܝܐ ܕܬܚܪܙܬܐ.
ܟܠ ܫܘܚܠܦܐ ܒܦܐܬܐ ܗܕܐ ܢܗܘܐ ܠܗ ܡܥܒܕܢܘܬܐ ܥܠ ܐܣܟܡܐ ܕܦܐܬܐ ܕܡܦܠܚܢܐ ܕܡܦܠܚܢ̈ܐ ܐܚܪ̈ܢܐ ܒܘܝܩܝ ܗܢܐ.
ܠܡܘܣܦ ܐܘ ܫܘܚܠܦ ܬܘܪ̈ܓܡܐ ܕܟܠܗܘܢ ܘܝܩܝ، ܐܦܠܚ [//translatewiki.net/ translatewiki.net]، ܬܪܡܝܬܐ ܕܬܘܪܓܡܐ ܕܡܝܕܝܐܘܝܩܝ.",
'sqlhidden' => '(ܒܘܬܬܐ SQL ܛܫܝܐ)',
'revdelete-selected' => "'''{{PLURAL:$2|ܬܢܝܬܐ ܓܒܝܬܐ|ܬܢܝܬ̈ܐ ܓܒܝܬܐ}} ܕ [[:$1]]:'''",
'revdelete-hide-text' => 'ܛܫܝ ܟܬܒܬܐ ܕܬܢܝܬܐ',
'revdelete-hide-image' => 'ܛܫܝ ܚܒܝܫܬ̈ܐ ܕܠܦܦܐ',
+'revdelete-hide-name' => 'ܛܫܝ ܥܒܕܐ ܘܢܘܦܐ',
'revdelete-hide-comment' => 'ܛܫܝ ܟܪܝܘܬܐ ܕܫܘܚܠܦܐ',
'revdelete-hide-user' => 'ܛܫܝ ܫܡܐ/ܐܝ ܦܝ (IP) ܕܡܦܠܚܢܐ',
+'revdelete-radio-same' => '(ܠܐ ܬܫܚܠܦ)',
'revdelete-radio-set' => 'ܐܝܢ',
'revdelete-radio-unset' => 'ܠܐ',
'revdelete-log' => 'ܥܠܬܐ:',
'search-result-size' => '$1 ({{PLURAL:$2|1 ܡܠܬܐ|$2 ܡܠ̈ܐ}})',
'search-redirect' => '(ܨܝܒ $1)',
'search-section' => '(ܡܢܬܐ $1)',
-'search-suggest' => 'ܐܪܐ ܣܟܠ ܗܘܐ ܐܢܬ: $1',
+'search-suggest' => 'ܐܪܐ ܣܟܠܬ ܗܘܐ: $1',
'search-interwiki-caption' => 'ܬܪ̈ܡܝܬܐ ܐܚܘܬ̈ܐ',
'search-interwiki-default' => 'ܦܠܛ̈ܐ ܕ $1:',
'search-interwiki-more' => '(ܝܬܝܪ)',
'search-relatedarticle' => 'ܐܚܝܢܝ̈ܐ',
+'mwsuggest-disable' => 'ܒܛܘܠ ܬܘܦܥܠܐ ܕܡܚܫܚܬ̈ܐ ܕܒܨܝܐ',
'searcheverything-enable' => 'ܒܨܝ ܒܟܠ ܚܩܠܬ̈ܐ',
'searchrelated' => 'ܐܚܝܢܝ̈ܐ',
'searchall' => 'ܟܠ',
# User rights log
'rightslog' => 'ܣܓܠܐ ܕܙܕ̈ܩܐ ܕܡܦܠܚܢܐ',
+'rightslogtext' => 'ܗܢܘ ܣܓܠܐ ܕܫܘܚܠܦ̈ܐ ܕܙܕ̈ܩܐ ܕܡܦܠܚܢܐ.',
# Associated actions - in the sentence "You do not have permission to X"
'action-read' => 'ܩܪܝ ܦܐܬܐ ܗܕܐ',
'actioncomplete' => 'ܥܡܠܝܬܐ ܓܡܪܬ',
'actionfailed' => 'ܥܡܠܝܬܐ ܠܐ ܢܨܚܬ',
'dellogpage' => 'ܣܓܠܐ ܕܫܝܦܐ',
+'dellogpagetext' => 'ܠܬܚܬ ܡܟܬܒܘܬܐ ܕܦܐܬܬ̈ܐ ܫܝܦܬ̈ܐ ܚܕ̈ܬܬܐ.',
'deletionlog' => 'ܣܓܠܐ ܕܫܝܦܐ',
'deletecomment' => 'ܥܠܬܐ:',
'deleteotherreason' => 'ܥܠܬܐ ܐܚܪܬܐ/ܝܬܝܪܬܐ:',
# Namespace 8 related
'allmessages' => 'ܐܓܪ̈ܬܐ ܕܛܟܣܐ',
'allmessagesname' => 'ܫܡܐ',
+'allmessagesdefault' => 'ܐܓܪܬܐ ܕܟܬܒܬܐ ܡܬܚܫܒܢܝܬܐ',
'allmessagescurrent' => 'ܟܬܒܬܐ ܗܫܝܬܐ ܕܐܓܪܬܐ',
'allmessages-filter-legend' => 'ܡܨܦܝܢܝܬܐ',
+'allmessages-filter' => 'ܨܦܝ ܐܝܟ ܐܝܟܢܝܘܬܐ ܕܡܬܕܝܠܢܘܬܐ:',
+'allmessages-filter-unmodified' => 'ܠܐ ܫܘܓܢܝܐ',
'allmessages-filter-all' => 'ܟܠ',
+'allmessages-filter-modified' => 'ܫܘܓܢܝܐ',
'allmessages-prefix' => 'ܡܨܦܝܢܝܬܐ ܐܝܟ ܫܘܪܝܐ',
'allmessages-language' => 'ܠܫܢܐ:',
'allmessages-filter-submit' => 'ܙܠ',
'specialpages-group-highuse' => 'ܦܐܬܬ̈ܐ ܕܡܬܚܫܚܢܘܬܐ ܥܠܝܬܐ',
'specialpages-group-pages' => 'ܡܟܬܒܘܬ̈ܐ ܕܦܐܬܬ̈ܐ',
'specialpages-group-pagetools' => 'ܡܐܢ̈ܐ ܕܦܐܬܐ',
-'specialpages-group-wiki' => 'ܠܝܬ̈ܐ ܘܡܐܢ̈ܐ',
+'specialpages-group-wiki' => 'Ü\93Ü Ü\9dܬÌ\88Ü\90 Ü\98Ü¡Ü\90Ü¢Ì\88Ü\90',
'specialpages-group-redirects' => 'ܨܘܝܒܐ ܕܦܐܬܐ ܕܝܠܢܝܬܐ',
# Special:BlankPage
'undo-success' => 'Рэдагаваньне можа быць адмененае. Калі ласка, параўнайце адрозьненьні паміж вэрсіямі, каб упэўніцца, што гэта адпаведныя зьмены, а потым запішыце зьмены для сканчэньня рэдагаваньня.',
'undo-failure' => 'Рэдагаваньне ня можа быць скасаванае праз канфлікт паміж папярэднімі рэдагаваньнямі.',
'undo-norev' => 'Рэдагаваньне ня можа быць адмененае, таму што яно не існуе альбо было выдаленае.',
-'undo-summary' => 'Скасаваньне праўкі $1 удзельніка [[Special:Contributions/$2|$2]] ([[User talk:$2|гутаркі]])',
+'undo-summary' => 'Скасаваньне праўкі $1 {{GENDER:$2|удзельніка|удзельніцы}} [[Special:Contributions/$2|$2]] ([[User talk:$2|гутаркі]])',
# Account creation failure
'cantcreateaccounttitle' => 'Немагчыма стварыць рахунак',
'qbsettings-none' => 'Не паказваць',
'qbsettings-fixedleft' => 'Замацаваная зьлева',
'qbsettings-fixedright' => 'Замацаваная справа',
-'qbsettings-floatingleft' => 'Ð Ñ\83Ñ\85омаÑ\8f зьлева',
+'qbsettings-floatingleft' => 'Ð\9fлавае зьлева',
'qbsettings-floatingright' => 'Плавае справа',
'qbsettings-directionality' => 'Замацаваная, у залежнасьці ад накірунку напісаньня ў Вашай мове',
'action-userrights' => 'рэдагаваньне правоў усіх удзельнікаў',
'action-userrights-interwiki' => 'рэдагаваньне правоў удзельнікаў у іншых вікі',
'action-siteadmin' => 'блякаваньне і разблякаваньне базы зьвестак',
-'action-sendemail' => 'адпÑ\80аÑ\9eкÑ\83 Ñ\8dлекÑ\82Ñ\80оннÑ\8bÑ\85 лÑ\96Ñ\81Ñ\82оÑ\9e іншым удзельнікам',
+'action-sendemail' => 'адпÑ\80аÑ\9eлÑ\8fÑ\86Ñ\8c лÑ\96Ñ\81Ñ\82Ñ\8b іншым удзельнікам',
# Recent changes
'nchanges' => '$1 {{PLURAL:$1|зьмена|зьмены|зьменаў}}',
'largefileserver' => 'Памер гэтага файла перавышае максымальна дазволены.',
'emptyfile' => 'Загружаны файл, здаецца, пусты. Магчыма гэты адбылося з-за памылкі ў назьве файла.
Удакладніце, ці Вы сапраўды жадаеце загрузіць гэты файл.',
-'windows-nonascii-filename' => '{{SITENAME}} не падтрымлівае назвы файлаў з спэцыяльнымі сымбалямі.',
-'fileexists' => 'Файл з такой назвай ужо існуе.
-Калі ласка, праверце <strong>[[:$1]]</strong>, калі Вы ня ўпэўненыя, што жадаеце яго замяніць.
-[[$1|thumb]]',
+'windows-nonascii-filename' => 'Гэтая вікі не падтрымлівае назвы файлаў з спэцыяльнымі сымбалямі.',
+'fileexists' => 'Файл з такой назвай ужо існуе. Калі ласка, праверце <strong>[[:$1]]</strong>, калі Вы ня ўпэўненыя, што жадаеце яго замяніць. [[$1|thumb]]',
'filepageexists' => 'Старонка апісаньня для гэтага файла ўжо існуе як <strong>[[:$1]]</strong>, але файла з такой назвай няма.
Апісаньне якое Вы дадалі ня зьявіцца на старонцы апісаньня.
Каб яно там зьявілася, Вам трэба рэдагаваць яе самастойна.
'listusers-editsonly' => 'Паказаць толькі ўдзельнікаў, якія маюць рэдагаваньні',
'listusers-creationsort' => 'Адсартаваць па даце стварэньня',
'usereditcount' => '$1 {{PLURAL:$1|рэдагаваньне|рэдагаваньні|рэдагаваньняў}}',
-'usercreated' => '{{GENDER:$3|}}Створаны $1 у $2',
+'usercreated' => '{{GENDER:$3|Створаны|Створаная}} $1 у $2',
'newpages' => 'Новыя старонкі',
-'newpages-username' => 'Імя ўдзельніка/ўдзельніцы:',
+'newpages-username' => 'Імя ўдзельніка:',
'ancientpages' => 'Найстарэйшыя старонкі',
'move' => 'Перанесьці',
'movethispage' => 'Перанесьці гэтую старонку',
'emailccsubject' => 'Копія Вашага ліста да $1: $2',
'emailsent' => 'Ліст адасланы',
'emailsenttext' => 'Ваш ліст быў адасланы.',
-'emailuserfooter' => 'Гэты ліст быў дасланы ўдзельнікам $1 да ўдзельніка $2 з дапамогай функцыі «Даслаць ліст» праекту {{SITENAME}}.',
+'emailuserfooter' => 'Гэты ліст быў дасланы ўдзельнікам $1 да {{GENDER:$2|ўдзельніка|ўдзельніцы}} $2 з дапамогай функцыі «Даслаць ліст» {{GRAMMAR:родны|{{SITENAME}}}}.',
# User Messenger
'usermessage-summary' => 'Паведамленьне пра выхад з сыстэмы.',
'sqlite-no-fts' => '$1 без падтрымкі поўнатэкстнага пошуку',
# New logging system
-'logentry-delete-delete' => '$1 выдаліў старонку $3',
+'logentry-delete-delete' => '$1 {{GENDER:$2|выдаліў|выдаліла}} старонку $3',
'logentry-delete-restore' => '$1 аднавіў старонку $3',
'logentry-delete-event' => '$1 зьмяніў бачнасьць $5 {{PLURAL:$5|падзеі ў журнале|падзеяў у журнале|падзеяў у журнале}} на $3: $4',
'logentry-delete-revision' => '$1 зьмяніў бачнасьць $5 {{PLURAL:$5|вэрсіі|вэрсіяў|вэрсіяў}} старонкі $3: $4',
'revdelete-uname-unhid' => 'імя ўдзельніка адкрытае',
'revdelete-restricted' => 'ужыць абмежаваньні для адміністратараў',
'revdelete-unrestricted' => 'зьнятыя абмежаваньні для адміністратараў',
-'logentry-move-move' => '$1 перанёс старонку $3 у $4',
+'logentry-move-move' => '$1 {{GENDER:$2|перанёс|перанесла}} старонку $3 у $4',
'logentry-move-move-noredirect' => '$1 перанёс старонку $3 у $4 без пакінутага перанакіраваньня',
'logentry-move-move_redir' => '$1 перанёс старонку $3 у $4 паўзьверх перанакіраваньня',
'logentry-move-move_redir-noredirect' => '$1 перанёс старонку $3 у $4 паўзьверх перанакіраваньня без пакінутага перанакіраваньня',
'gotaccount' => "Имате ли вече сметка? '''$1'''.",
'gotaccountlink' => 'Влизане',
'userlogin-resetlink' => 'Забравени данни за влизане в системата?',
-'createaccountmail' => 'с писмо по електронната поща',
+'createaccountmail' => 'Използване на временна парола, която се изпраща по електронната поща, посочена по-долу',
'createaccountreason' => 'Причина:',
'badretype' => 'Въведените пароли не съвпадат.',
'userexists' => 'Въведеното потребителско име вече се използва.
'userinvalidcssjstitle' => "'''Внимание:''' Не съществува облик „$1“. Необходимо е да се знае, че имената на потребителските ви страници за CSS и Джаваскрипт трябва да се състоят от малки букви, например: „{{ns:user}}:Иван/vector.css“ (а не „{{ns:user}}:Иван/Vector.css“).",
'updated' => '(обновена)',
'note' => "'''Забележка:'''",
-'previewnote' => "'''Това е само предварителен преглед. Промените все още не са съхранени!'''",
-'continue-editing' => 'Ð\9fÑ\80одÑ\8aлжаване на Ñ\80едакÑ\82иÑ\80анеÑ\82о',
+'previewnote' => "'''Ð\92ажно е да Ñ\81е помни, Ñ\87е Ñ\82ова е само предварителен преглед. Промените все още не са съхранени!'''",
+'continue-editing' => 'Ð\9fÑ\80одÑ\8aлжаване кÑ\8aм полеÑ\82о за Ñ\80едакÑ\82иÑ\80ане',
'previewconflict' => 'Този предварителен преглед отразява текста в горната текстова кутия така, както би се показал, ако съхраните.',
'session_fail_preview' => "'''За съжаление редакцията ви не успя да бъде обработена поради загуба на данните за текущата сесия. Опитайте отново. Ако все още не работи, опитайте да [[Special:UserLogout|излезете]] и да влезете отново.'''",
'session_fail_preview_html' => "'''За съжаление редакцията ви не беше записана поради изтичането на сесията ви.'''
'prot_1movedto2' => '„[[$1]]“ преместена като „[[$2]]“',
'protect-badnamespace-title' => 'Незащитимо именно пространство',
'protect-badnamespace-text' => 'Страниците в това именно пространство не могат да бъдат защитени.',
+'protect-norestrictiontypes-title' => 'Незащитима страница',
'protect-legend' => 'Потвърждение на защитата',
'protectcomment' => 'Причина:',
'protectexpiry' => 'Изтича на:',
'thumbnail_error' => 'Грешка при създаване на миникартинка: $1',
'djvu_page_error' => 'Номерът на DjVu-страницата е извън обхвата',
'djvu_no_xml' => 'Не е възможно вземането на XML за DjVu-файла',
+'thumbnail-temp-create' => 'Временния файл с миникартинка не може да бъде създаден.',
'thumbnail_invalid_params' => 'Параметрите за миникартинка са невалидни',
'thumbnail_dest_directory' => 'Целевата директория не може да бъде създадена',
'thumbnail_image-type' => 'Типът картинка не се поддържа',
# JavaScriptTest
'javascripttest-pagetext-noframework' => 'Тази страница е запазена за изпълнение на Джаваскрипт тестове.',
+'javascripttest-pagetext-skins' => 'Избор на облик за тестванията:',
'javascripttest-qunit-intro' => 'Вижте [$1 тестовата документация] на mediawiki.org.',
# Tooltip help for the actions
'pageinfo-article-id' => 'Номер на страницата',
'pageinfo-views' => 'Брой прегледи',
'pageinfo-watchers' => 'Брой наблюдаващи страницата',
+'pageinfo-few-watchers' => 'Под $1 {{PLURAL:$1|наблюдаващ|наблюдаващи}}',
'pageinfo-redirects-name' => 'Пренасочвания към тази страница',
'pageinfo-subpages-name' => 'Подстраници на тази страница',
+'pageinfo-firsttime' => 'Дата на създаване на страницата',
'pageinfo-lastuser' => 'Последeн редактор',
'pageinfo-lasttime' => 'Дата на последнoто редактиране',
'pageinfo-edits' => 'Общ брой редакции',
'pageinfo-toolboxlink' => 'Информация за страницата',
'pageinfo-contentpage-yes' => 'Да',
'pageinfo-protect-cascading-yes' => 'Да',
+'pageinfo-category-pages' => 'Брой страници',
+'pageinfo-category-subcats' => 'Брой подкатегории',
+'pageinfo-category-files' => 'Брой файлове',
# Skin names
'skinname-standard' => 'Класика',
'file-info-png-looped' => 'зациклен',
'file-info-png-repeat' => 'изпълнено $1 {{PLURAL:$1|път|пъти}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|кадър|кадъра}}',
+'file-no-thumb-animation' => "'''Забележка: По технически причини миниатюрите на този файл няма да бъдат анимирани.'''",
+'file-no-thumb-animation-gif' => "'''Забележка: По технически причини миниатюрите на GIF файловете с висока резолюция като този няма да бъдат анимирани.'''",
# Special:NewFiles
'newimages' => 'Галерия на новите файлове',
'exif-gpsdifferential' => 'Диференциална корекция на GPS',
'exif-jpegfilecomment' => 'Kоментар на JPEG файл',
'exif-keywords' => 'Ключови думи',
+'exif-worldregioncreated' => 'Регион на света, където е направена снимката',
+'exif-countrycreated' => 'Държава, в която е направена снимката',
+'exif-countrycodecreated' => 'Код на държавата, където е направена снимката',
+'exif-provinceorstatecreated' => 'Област или щат, където е направена снимката',
+'exif-citycreated' => 'Град, в който е направена снимката',
'exif-objectname' => 'Кратко заглавие',
'exif-specialinstructions' => 'Специални инструкции',
+'exif-source' => 'Източник',
'exif-contact' => 'Информация за контакти',
'exif-languagecode' => 'Език',
'exif-iimversion' => 'IIM версия',
'logentry-newusers-newusers' => 'Потребителската сметка $1 беше създадена',
'logentry-newusers-create' => 'Потребителската сметка $1 беше създадена',
'logentry-newusers-create2' => '$1 създаде потребителска сметка $3',
+'logentry-newusers-byemail' => '$1 създаде потребителската сметка $3, паролата беше изпратена по електронна поща',
'logentry-newusers-autocreate' => 'Сметката $1 беше създадена автоматично',
+'logentry-rights-rights' => '$1 промени потребителската група на $3 от $4 на $5',
+'logentry-rights-rights-legacy' => '$1 промени потребителската група на $3',
'logentry-rights-autopromote' => '
$1 е автоматично повишен от $4 до $5',
'rightsnone' => '(никакви)',
# Categories related messages
'pagecategories' => '{{PLURAL:$1|श्रेणी|श्रेणी}}',
+'hidden-categories' => '{{PLURAL:$1|छुपावल गईल श्रेणी|छुपावल गईल श्रेणी}}',
'about' => 'बारे में',
'article' => 'सामग्री पन्ना',
'vector-view-history' => 'इतिहास देखीं',
'vector-view-view' => 'पढ़ीं',
'vector-view-viewsource' => 'स्त्रोत देखीं',
+'actions' => 'क्रिया',
+'namespaces' => 'नामस्थान',
+'variants' => 'संस्करण',
'errorpagetitle' => 'त्रुटी',
'returnto' => 'जाईं $1 पर।',
'yourname' => 'प्रयोगकर्ता नाम',
'yourpassword' => 'गुप्त शब्द',
'yourpasswordagain' => 'गुप्त-शब्द पुन:डालीं:',
+'remembermypassword' => 'इ ब्राउजर पर हमार प्रवेश जारी रहे (अधिकतम $1 {{PLURAL:$1|दिन|दिन}})',
'login' => 'खाता में प्रवेश',
'nav-login-createaccount' => 'खाता प्रवेश / खाता बनाईं',
'loginprompt' => '{{SITENAME}} में प्रवेश खातिर राउर कुकिज चालू होवे के चाहीं',
'italic_sample' => 'इटालिक पाठ्य',
'italic_tip' => 'इटालिक पाठ्य',
'headline_sample' => 'शिर्षक पाठ्य',
+'headline_tip' => 'द्वितीय-श्रेणी के शीर्षक',
'image_sample' => 'उदाहरण.jpg',
'media_sample' => 'उदाहरण.ogg',
'media_tip' => 'फाईल लिंक',
'newarticletext' => "रउआ एगो अइसन लिंक के पन्ना के अनुसरण कइले बानी जउन अभी तक उपलब्ध नइखे।
पन्ना बनावे खातिर, नीचे के बाकस में टाईप करे के शुरु करीं (ज्यादा जानकारी खातिर देखीं [[{{MediaWiki:Helppage}}|मदद पन्ना]])।
यदि रउआ अहिजा गलती से आ गईल बानी त, आपन ब्राउजर के '''back''' (बैक) बटन दबाईं",
+'noarticletext' => 'ई पन्ना मे अभी कउनो सामग्री नईखे बा ।
+रउआ अन्य पन्ना में [[Special:Search/{{PAGENAME}}|ई शीर्षक के खोज]] कर सकत बानीं',
'yourdiff' => 'अंतर',
'template-protected' => '(संरक्षित)',
+# Parser/template warnings
+'post-expand-template-inclusion-category' => 'अइसन पृष्ठ जे पर साँचा जोडे के सीमा पार हो गइल बा',
+
# History pages
'revisionasof' => '$1 के रुप में संशोधन',
'revision-info' => '$2 में से $1 के रुप में संशोधन',
'searchprofile-project-tooltip' => '$1 में खोजीं',
'searchprofile-images-tooltip' => 'फाईल खातिर खोज',
'searchprofile-everything-tooltip' => 'सभन सामग्री में खोजीं (वार्ता पन्ना सहित)',
+'searchprofile-advanced-tooltip' => 'विशेष नामस्थान में खोजीं',
'search-result-size' => '$1 ({{PLURAL:$2|1 शब्द|$2 शब्द}})',
'search-result-score' => 'प्रासंगिकता: $1%',
'search-redirect' => '(पुन: निर्देशण $1)',
'searchall' => 'सब',
'showingresults' => "नीचे देखावल जा रहल बा {{PLURAL:$1|'''1''' परिणाम|'''$1''' परिणाम}} #'''$2''' से शुरु होवे वाला।",
'showingresultsnum' => "नीचे देखावल जा रहल बा {{PLURAL:$3|'''1''' परिणाम|'''$3''' परिणाम}} #'''$2''' से शुरु होवे वाला।",
+'search-nonefound' => 'राउर खोज मे से मेल खात कउनो परिणाम नईखे बा',
'powersearch' => 'उन्नत खोज',
'powersearch-legend' => 'उन्नत खोज',
'powersearch-ns' => 'सन्दर्भ में खोजीं',
# Recent changes
'recentchanges' => 'तुरंत भईल परिवर्तन',
+'recentchanges-legend' => 'हाल के परिवर्तन संबंधी विकल्प',
+'recentchanges-label-newpage' => 'ई सम्पादन से एगो नवका पृष्ठ तैयार हो गइल बा',
+'recentchanges-label-minor' => 'ई एगो छोटा सम्पाद बा',
'rcshowhideminor' => '$1 छोट सम्पादन',
'diff' => 'अन्तर',
'hist' => 'इति',
'upload' => 'फाईल लादीं',
# File description page
+'file-anchor-link' => 'फ़ाइल',
'filehist' => 'पन्ना के इतिहास',
'filehist-deleteall' => 'सब मिटाईं',
'filehist-deleteone' => 'मिटाईं',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|बाईट|बाईट्स}}',
+'newpages' => 'नवका पन्ना',
'move' => 'स्थान्तरण',
'movethispage' => 'ई पन्ना के स्थांतरण करीं',
'booksources' => 'किताबी स्त्रोत',
# Special:AllPages
+'alphaindexline' => '$1 से $2',
+'allarticles' => 'सभी पन्ना',
'allpagessubmit' => 'जाईं',
'allpagesprefix' => 'उपसर्ग के साथे पन्ना प्रदर्शन:',
'created' => 'बनावल गईल',
+# Rollback
+'rollbacklink' => 'वापिस लीं',
+
# Undelete
'undeletelink' => 'देखीं/बहाल करीं',
'movepagebtn' => 'पन्ना स्थांतरण करीं',
'revertmove' => 'पिछलका स्थिति',
+# Export
+'export' => 'पन्ना निर्यात करीं',
+
# Thumbnails
'thumbnail-more' => 'बढ़ाईं',
'filemissing' => 'फाईल गायब',
'tooltip-pt-userpage' => 'राउर प्रयोगकर्ता पन्ना',
'tooltip-pt-mytalk' => 'राउर वार्ता पन्ना',
'tooltip-pt-preferences' => 'राउर पसन्द',
+'tooltip-pt-watchlist' => 'राउर ध्यान दियल पन्ना के सूची',
'tooltip-pt-mycontris' => 'राउर योगदान के सूची',
'tooltip-pt-login' => 'रउआ के खाता प्रवेश खातिर प्रोत्साहित करल जा रहल बा, बाकि ई अनिवार्य नईखे',
'tooltip-pt-anonlogin' => 'रउआ के खाता प्रवेश खातिर प्रोत्साहित करल जा रहल बा, बाँकि ई अनिवार्य नईखे',
'tooltip-t-permalink' => 'ई पन्ना के संसोधन खातिर स्थायी लिंक।',
'tooltip-ca-nstab-main' => 'सामग्री पन्ना देखीं',
'tooltip-ca-nstab-special' => 'ई एगो ख़ाश पन्ना ह, रउआ ई पन्ना के सम्पादन नईखीं कर सकत',
+'tooltip-ca-nstab-image' => 'संचिका के पन्ना देखीं',
+'tooltip-ca-nstab-template' => 'टेम्प्लेट देखीं',
+'tooltip-ca-nstab-category' => 'श्रेणी के पन्ना देखीं',
'tooltip-save' => 'आपन बदलाव के सुरक्षित करीं',
+'tooltip-preview' => 'आपन द्वारा कियल गइल बदलाव के देखीं, संजोये से पहले ईका इस्तेमाल करीं!',
+'tooltip-rollback' => '"वापिस लीं" ई पन्ना के पिछ्ला योगदाता के बदलाव एकही चटके मे गायब कर देवेला',
+'tooltip-summary' => 'एगो संक्षिप्त सारांश दर्ज करीं',
# Media information
'file-nohires' => ' उच्च गुणवत्ता उपलब्ध नईखे।',
'newwindow' => '(digeriñ en ur prenestr nevez)',
'cancel' => 'Nullañ',
'moredotdotdot' => "Ha muioc'h c'hoazh...",
+'morenotlisted' => "Ha muioc'h c'hoazh n'int ket rollet...",
'mypage' => 'Ma zammig pajenn',
'mytalk' => "Ma c'haozeadennoù",
'anontalk' => "Kaozeal gant ar chomlec'h IP-mañ",
Gallout a rit kenderc'hel da implijout {{SITENAME}} en un doare dizanv, pe <span class='plainlinks'>[$1 kevreañ en-dro]</span> gant an hevelep anv pe un anv all mar fell deoc'h.
Notit mat e c'hallo pajennoù zo kenderc'hel da vezañ diskwelet evel pa vefec'h kevreet c'hoazh, betek ma vo riñset krubuilh ho merdeer ganeoc'h.",
'welcomeuser' => 'Degemer mat $1 !',
+'welcomecreation-msg' => 'Krouet eo bet ho kont implijer.
+Na zisoñjit ket resisaat ho [[Special:Preferences|penndibaboù evit {{SITENAME}}]].',
'yourname' => 'Anv implijer :',
'yourpassword' => 'Ger-tremen :',
'yourpasswordagain' => 'Skrivit ho ker-tremen en-dro',
'changeemail-oldemail' => "Chomlec'h postel a-vremañ :",
'changeemail-newemail' => "Chomlec'h postel nevez :",
'changeemail-none' => '(hini ebet)',
+'changeemail-password' => 'Ho ker-tremen war {{SITENAME}}:',
'changeemail-submit' => "Cheñch chomlec'h postel",
'changeemail-cancel' => 'Nullañ',
'converter-manual-rule-error' => 'Fazi dinodet er reolenn cheñch yezh dre zorn',
# "Undo" feature
-'undo-success' => "Gallout a reer disteurel ar c'hemmoù-mañ. Gwiriit, mar plij, gant ar geñveriadenn a-is evit bezañ sur eo an dra-se a fell deoc'h ober; goude-se enrollit ar c'hemmoù a-is a-benn echuiñ disteurel ar c'hemmoù.",
+'undo-success' => "Gallout a reer dizober ar c'hemmoù-mañ. Gwiriit, mar plij, gant ar geñveriadenn a-is evit bezañ sur eo an dra-se a fell deoc'h ober; goude-se enrollit ar c'hemmoù a-is a-benn echuiñ disteurel ar c'hemmoù.",
'undo-failure' => "N'eus ket bet tu da zisteuler ar c'hemm-mañ abalamour d'un tabut gant kemmoù degaset e-keit-se.",
'undo-norev' => "N'eus ket bet gallet degas ar c'hemmoù-mañ rak pe n'eus ket anezho pe int bet diverket.",
-'undo-summary' => 'Disteurel kemmoù $1 a-berzh [[Special:Contributions/$2|$2]] ([[User talk:$2|kaozeal]])',
+'undo-summary' => 'Dizober kemmoù $1 a-berzh [[Special:Contributions/$2|$2]] ([[User talk:$2|kaozeal]])',
# Account creation failure
'cantcreateaccounttitle' => 'Dibosupl krouiñ ar gont',
'search-interwiki-default' => "$1 disoc'h :",
'search-interwiki-more' => "(muioc'h)",
'search-relatedarticle' => "Disoc'hoù kar",
-'mwsuggest-disable' => 'Diweredekaat kinnigoù AJAX',
+'mwsuggest-disable' => "Diweredekaat ar c'hinnigoù klask",
'searcheverything-enable' => 'Klask en holl esaouennoù anv',
'searchrelated' => "disoc'hoù kar",
'searchall' => 'An holl',
'backend-fail-notsame' => "Ur restr disheñvel zo e $1 c'hoazh.",
'backend-fail-invalidpath' => "$1 n'eo ket un hent stokañ reizh.",
'backend-fail-delete' => 'Dibosupl eo diverkañ ar restr $1.',
+'backend-fail-describe' => 'N\'eus ket bet gallet cheñch ar metaroadennoù evit ar restr "$1".',
'backend-fail-alreadyexists' => 'Ar restr "$1" zo anezhi c\'hoazh.',
'backend-fail-store' => 'Dibosupl stokañ ar restr $1 e $2.',
'backend-fail-copy' => 'Dibosupl eilañ ar restr "$1" war-du "$2".',
'linksearch-ok' => 'Klask',
'linksearch-text' => 'Gallout a reer implijout arouezennoù "joker" evel, da skouer, "*.wikipedia.org".
Rekis eo dezho un domani a-us da nebeutañ evel, da skouer, "*.org".<br />
-Protokoloù skoret : <code>$1</code> (defaults to http:// na lakait hini ebet eus ar re-se en ho klask)',
+{{PLURAL:$2|Protokol|Protokoloù}} skoret : <code>$1</code> (defaults to http:// na lakait hini ebet eus ar re-se en ho klask).',
'linksearch-line' => '$1 gant ul liamm adal $2',
'linksearch-error' => "N'hall an arouezennoù joker bezañ implijet nemet e deroù anv domani an ostiz.",
# Special:ActiveUsers
'activeusers' => 'Roll an implijerien oberiant',
'activeusers-intro' => 'Setu aze ur roll eus an implijerien zo bet oberiant mui pe vui e-pad an $1 {{PLURAL:$1|deiz|deiz}} diwezhañ.',
-'activeusers-count' => '$1 {{PLURAL:$1|degasadenn}} abaoe an {{PLURAL:$3|deiz|$3 deiz}} diwezhañ',
+'activeusers-count' => '$1 {{PLURAL:$1|oberiadenn}} abaoe an {{PLURAL:$3|deiz|$3 deiz}} diwezhañ',
'activeusers-from' => 'Diskouez an implijerien adal :',
'activeusers-hidebots' => 'Kuzhat ar robotoù',
'activeusers-hidesysops' => 'Kuzhat ar verourien',
a-benn gellout kemmañ ho roll evezhiañ.",
'addwatch' => "Ouzhpennañ d'ar roll evezhiañ",
'addedwatchtext' => 'Ouzh ho [[Special:Watchlist|rollad evezhiañ]] eo bet ouzhpennet ar bajenn "[[:$1]]".
-Kemmoù da zont ar bajenn-mañ ha re ar bajenn gaozeal stag outi a vo rollet amañ hag e teuio ar bajenn <b>e tev</b> er [[Special:RecentChanges|roll kemmoù diwezhañ]] evit bezañ gwelet aesoc\'h ganeoc\'h.
-
-Evit tennañ ar bajenn-mañ a-ziwar ho rollad evezhiañ, klikit war "Paouez da evezhiañ" er framm merdeiñ.',
+Amañ e vo rollet ar c\'hemmoù da zont evit ar bajenn-mañ hag ar bajenn gaozeal stag outi.',
'removewatch' => 'Lemel a-ziwar ar roll evezhiañ',
'removedwatchtext' => 'Lamet eo bet ar bajenn "[[:$1]]" a-ziwar ho [[Special:Watchlist|roll evezhiañ]].',
'watch' => 'Evezhiañ',
'rollback' => "disteuler ar c'hemmoù",
'rollback_short' => 'Disteuler',
'rollbacklink' => 'disteuler',
-'rollbacklinkcount' => 'terriñ $1 {{PLURAL:$1|kemm|kemmañ}}',
-'rollbacklinkcount-morethan' => 'terriñ ouzhpenn $1 {{PLURAL:$1|kemm|kemmoù}}',
+'rollbacklinkcount' => 'disteurel $1 {{PLURAL:$1|kemm}}',
+'rollbacklinkcount-morethan' => 'disteurel ouzhpenn $1 {{PLURAL:$1|kemm}}',
'rollbackfailed' => "C'hwitet eo bet an distaoladenn",
'cantrollback' => 'Dibosupl da zisteuler: an aozer diwezhañ eo an hini nemetañ da vezañ kemmet ar pennad-mañ',
'alreadyrolled' => "Dibosupl eo disteuler ar c'hemm diwezhañ graet d'ar bajenn [[:$1]] gant [[User:$2|$2]] ([[User talk:$2|Kaozeal]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);
Setu an doare a-vremañ evit ar bajenn-mañ '''$1''':",
'protect-cascadeon' => "Gwarezet eo ar bajenn-mañ peogwir he c'haver er {{PLURAL:$1|bajenn|pajennoù}} da-heul zo gweredekaet enno ar gwareziñ dre skalierad. Gallout a rit kemmañ al live gwareziñ met ne cheñcho ket ar gwareziñ dre skalierad.",
'protect-default' => 'Aotren an holl implijerien',
-'protect-fallback' => 'Ezhomm zo aotre "$1"',
-'protect-level-autoconfirmed' => "Stankañ an implijerien nevez hag ar re n'int ket enrollet",
+'protect-fallback' => 'Degemer hepken an implijerien gant an aotre "$1"',
+'protect-level-autoconfirmed' => 'Degemer hepken an implijerien emgadarnaet',
'protect-level-sysop' => 'Aotren ar verourien hepken',
'protect-summary-cascade' => 'Gwareziñ dre skalierad',
'protect-expiring' => "a zeu d'e dermen d'an $1",
# Move page
'move-page' => "Dilec'hiañ $1",
'move-page-legend' => 'Adenvel ur pennad',
-'movepagetext' => "Grit gant ar furmskrid a-is evit adenvel ur pennad hag adkas an holl stummoù kent anezhañ war-du an anv nevez.
-Dont a raio an titl kentañ da vezañ ur bajenn adkas war-du an titl nevez.
+'movepagetext' => "Grit gant ar furmskrid a-is evit adenvel ur pennad hag adkas an holl stummoù kent anezhañ war-zu an anv nevez.
+Dont a raio an titl kozh da vezañ ur bajenn adkas war-zu an titl nevez.
+Gallout a rit nevesaat ent emgefre an adkasoù a-vremañ a gas d'an titl orin.
Ne vo ket kemmet liammoù an titl kozh ha ne vo ket dilec'hiet ar bajenn gaozeal, ma'z eus anezhi.
+Ma rit ho soñj chom hep en ober, gwiriit mat an holl [[Special:DoubleRedirects|adkasoù doubl]] pe [[Special:BrokenRedirects|adkasoù torret]].
+C'hwi eo zo karget da wiriañ e kas mat al liammoù d'al lec'h int sañset kas.
+
+Notit mat '''ne vo ket''' dilec'hiet ma'z eus dija ur bajenn ganti an anv nevez, nemet e vefe un adkas ha ne vefe tamm istor ebet stag outi.
+Dre se e c'haller adkas ur bajenn war-zu he lec'h orin ma oa kamm an adkas.
+
'''DIWALLIT!'''
Gallout a ra kement-se bezañ ur c'hemm bras ha dic'hortoz evit ur pennad a vez sellet outi alies;
bezit sur e komprenit mat an heuliadoù a-raok kenderc'hel ganti.",
'pageinfo-redirectsto-info' => 'Titouroù',
'pageinfo-contentpage-yes' => 'Ya',
'pageinfo-protect-cascading-yes' => 'Ya',
+'pageinfo-category-info' => 'Titouroù ar rummad',
+'pageinfo-category-pages' => 'Niver a bajennoù',
+'pageinfo-category-subcats' => 'Niver a isrummadoù',
+'pageinfo-category-files' => 'Niver a restroù',
# Skin names
'skinname-standard' => 'Standard',
'minutes' => '{{PLURAL:$1|$1 vunutenn|$1 munutenn}}',
'hours' => '{{PLURAL:$1|$1 eurvezh|$1 eurvezh}}',
'days' => '{{PLURAL:$1|$1 deiz|$1 deiz}}',
+'months' => '{{PLURAL: $1|$1 miz|$1 miz}}',
+'years' => '{{PLURAL: $1|$1 bloaz|$1 bloaz}}',
'ago' => '$1 zo',
+'just-now' => 'bremañ diouzhtu',
# Bad image list
'bad_image_list' => "Setu doare ar furmad :
# Scary transclusion
'scarytranscludedisabled' => '[Diweredekaet eo an treuzkludañ etrewiki]',
'scarytranscludefailed' => "[N'eus ket bet gallet tapout ar patrom evit $1]",
+'scarytranscludefailed-httpstatus' => "[c'hwitet adtapout ar patrom evit $1: HTTP $2]",
'scarytranscludetoolong' => '[URL re hir]',
# Delete conflict
'ns-specialprotected' => 'Specijalne stranice se ne mogu uređivati.',
'titleprotected' => 'Naslov stranice je zaštićen od postavljanja od strane korisnika [[User:$1|$1]].
Iz razloga "\'\'$2\'\'".',
+'invalidtitle-knownnamespace' => 'Neispravan naslov s imenskim prostorom "$2" i tekstom "$3"',
'exception-nologin' => 'Niste prijavljeni',
'exception-nologin-text' => 'Ova stranica ili aktivnost zahtijeva da budete prijavljeni na ovom wikiju.',
'changeemail-oldemail' => 'Trenutna e-mail adresa:',
'changeemail-newemail' => 'Nova e-mail adresa:',
'changeemail-none' => '(ništa)',
+'changeemail-password' => 'Tvoja šifra/lozinka za {{SITENAME}}:',
'changeemail-submit' => 'Promijeni e-mail',
'changeemail-cancel' => 'Otkaži',
'youremail' => 'E-mail:',
'username' => '{{GENDER:$1|Korisničko}} ime:',
'uid' => '{{GENDER:$1|Korisnički}} ID:',
-'prefs-memberingroups' => 'Član {{PLURAL:$1|grupe|grupa}}:',
+'prefs-memberingroups' => '{{GENDER:$2|Korisnik|Korisnica}} je član {{PLURAL:$1|grupe|grupâ}}:',
'prefs-registration' => 'Vrijeme registracije:',
'yourrealname' => 'Vaše pravo ime:',
'yourlanguage' => 'Jezik:',
'backend-fail-store' => 'Ne može se spremiti datoteka $1 na $2.',
'backend-fail-copy' => 'Nije uspjelo kopiranje datoteke "$1" u "$2".',
'backend-fail-move' => 'Nije uspjelo premještanje datoteke "$1" u "$2".',
+'backend-fail-opentemp' => 'Ne mogu otvoriti privremenu datoteku.',
+'backend-fail-writetemp' => 'Ne mogu pisati u privremenu datoteku.',
+'backend-fail-closetemp' => 'Ne mogu zatvoriti privremenu datoteku.',
'backend-fail-read' => 'Ne mogu čitati datoteku $1.',
'backend-fail-create' => 'Ne mogu napraviti datoteku $1.',
+'backend-fail-contenttype' => 'Ne mogu da utvrdim kakav sadržaj ima datoteka koju treba da smjestim u "$1".',
# Lock manager
+'lockmanager-notlocked' => 'Ne mogu otključati "$1"; nije zaključan.',
+'lockmanager-fail-closelock' => 'Ne mogu zatvoriti "lock"-datoteku za "$1".',
+'lockmanager-fail-deletelock' => 'Ne mogu obrisati "lock"-datoteku za "$1".',
+'lockmanager-fail-acquirelock' => 'Ne mogu dobiti "lock"-datoteku za "$1".',
+'lockmanager-fail-openlock' => 'Ne mogu otvoriti "lock"-datoteku za "$1".',
+'lockmanager-fail-releaselock' => 'Ne mogu osloboditi katanac za „$1“.',
+'lockmanager-fail-db-bucket' => 'Ne mogu da kontaktiram s dovoljno "lock"-baza u kanti $1.',
+'lockmanager-fail-db-release' => 'Ne mogu osloboditi katance u bazi $1.',
'lockmanager-fail-svr-release' => 'Ne mogu se otključati katanci na serveru file $1.',
# ZipDirectoryReader
'uploadstash-badtoken' => 'Izvršavanje ove akcije je bilo neuspješno, možda zato što su vaša uređivačka odobrenja istekla. Pokušajte ponovo.',
'uploadstash-errclear' => 'Brisanje sakrivenih datoteka je bilo neuspješno.',
'uploadstash-refresh' => 'Osvježi spisak datoteka',
+'invalid-chunk-offset' => 'Neispravna polazna tačka',
# img_auth script messages
'img-auth-accessdenied' => 'Pristup onemogućen',
'wantedpages' => 'Tražene stranice',
'wantedpages-badtitle' => 'Nevaljan naslov u setu rezultata: $1',
'wantedfiles' => 'Tražene datoteke',
+'wantedfiletext-cat' => 'Sljedeće datoteke se koriste, ali ne postoje. Datoteke iz drugih baza mogu biti navedene iako ne postoje. Takve datoteke će biti <del>izbrisane</del> sa spiska. Pored toga, stranice koje sadrže nepostojeće datoteke se nalaze u [[:$1]].',
+'wantedfiletext-nocat' => 'Sljedeće datoteke se koriste, ali ne postoje. Datoteke iz drugih baza mogu biti navedene iako ne postoje. Takve datoteke će biti <del>izbrisane</del> sa spiska.',
'wantedtemplates' => 'Potrebni šabloni',
'mostlinked' => 'Članci sa najviše linkova',
'mostlinkedcategories' => 'Kategorije sa najviše linkova',
'enotif_mailer' => '{{SITENAME}} obaviještenje o pošti',
'enotif_reset' => 'Označi sve strane kao posjećene',
'enotif_impersonal_salutation' => '{{SITENAME}} korisnik',
+'enotif_subject_deleted' => '{{gender:$2|Korisnik|Korisnica}} $2 je {{gender:$2|obrisao|obrisala}} stranicu $1 projekta {{SITENAME}}',
+'enotif_subject_created' => '{{gender:$2|Korisnik|Korisnica}} $2 je {{gender:$2|napravio|napravila}} stranicu $1 projekta {{SITENAME}}',
+'enotif_subject_moved' => '{{gender:$2|Korisnik|Korisnica}} $2 je {{gender:$2|premjestio|premjestila}} stranicu $1 projekta {{SITENAME}}',
+'enotif_subject_restored' => '{{gender:$2|Korisnik|Korisnica}} $2 je {{gender:$2|vratio|vratila}} stranicu $1 projekta {{SITENAME}}',
+'enotif_subject_changed' => '{{gender:$2|Korisnik|Korisnica}} $2 je {{gender:$2|promijenio|promijenila}} stranicu $1 projekta {{SITENAME}}',
+'enotif_body_intro_deleted' => 'Stranicu $1 projekta {{SITENAME}} {{GENDER:$2|obrisao|obrisala}} je dana $PAGEEDITDATE {{GENDER:$2|korisnik|korisnica}} $2, pogledajte $3.',
+'enotif_body_intro_created' => 'Stranicu $1 projekta {{SITENAME}} {{GENDER:$2|napravio|napravila}} je dana $PAGEEDITDATE {{GENDER:$2|korisnik|korisnica}} $2, pogledajte $3 za trenutnu verziju.',
+'enotif_body_intro_moved' => 'Stranicu $1 projekta {{SITENAME}} {{GENDER:$2|premjestio|premjestila}} je dana $PAGEEDITDATE {{GENDER:$2|korisnik|korisnica}} $2, pogledajte $3 za trenutnu verziju.',
+'enotif_body_intro_restored' => 'Stranicu $1 projekta {{SITENAME}} {{GENDER:$2|vratio|vratila}} je dana $PAGEEDITDATE {{GENDER:$2|korisnik|korisnica}} $2, pogledajte $3 za trenutnu verziju.',
+'enotif_body_intro_changed' => 'Stranicu $1 projekta {{SITENAME}} {{GENDER:$2|promijenio|promijenila}} je dana $PAGEEDITDATE {{GENDER:$2|korisnik|korisnica}} $2, pogledajte $3 za trenutnu verziju.',
'enotif_lastvisited' => 'Pogledajte $1 za sve izmjene od vaše posljednje posjete.',
'enotif_lastdiff' => 'Vidi $1 da pregledate ovu promjenu.',
'enotif_anon_editor' => 'anonimni korisnik $1',
'enotif_body' => 'Poštovani $WATCHINGUSERNAME,
-
-Stranica {{SITENAME}} sa naslovom $PAGETITLE je bila $CHANGEDORCREATED dana $PAGEEDITDATE od strane $PAGEEDITOR, pogledajte $PAGETITLE_URL za trenutnu reviziju.
-
-$NEWPAGE
+$PAGEINTRO $NEWPAGE
Sažetak urednika: $PAGESUMMARY $PAGEMINOREDIT
Kontaktirajte urednika:
-mail: $PAGEEDITOR_EMAIL
+e-pošta: $PAGEEDITOR_EMAIL
wiki: $PAGEEDITOR_WIKI
-Neće biti drugih obavještenja u slučaju daljnjih izmjena osima ako posjetite stranicu.
-Također možete poništiti oznake obavijesti za sve praćene stranice koje imate na vašem spisku praćenja.
+Neće biti drugih obavještenja u slučaju daljnjih izmjena osima ako posjetite stranicu. Također možete poništiti oznake obavijesti za sve praćene stranice koje imate na vašem spisku praćenja.
- Vaš prijateljski {{SITENAME}} sistem obavještavanja
+Vaš prijateljski {{SITENAME}} sistem obavještavanja
--
Za promjenu vaših postavki e-mail obavijesti, posjetite
'protect-title' => 'Zaštićuje se "$1"',
'protect-title-notallowed' => 'Pregled stepena zaštite za "$1"',
'prot_1movedto2' => 'članak [[$1]] premješten na [[$2]]',
+'protect-badnamespace-title' => 'Nezaštitljiv imenski prostor',
+'protect-badnamespace-text' => 'Stranice u ovom imenskom prostoru se ne mogu zaštititi.',
'protect-legend' => 'Potvrdite zaštitu',
'protectcomment' => 'Razlog:',
'protectexpiry' => 'Ističe:',
'protect-default' => 'Dopusti svim korisnicima',
'protect-fallback' => 'Potrebno je imati "$1" ovlasti',
'protect-level-autoconfirmed' => 'Blokiraj nove i neregistrovane korisnike',
-'protect-level-sysop' => 'Samo administratori',
+'protect-level-sysop' => 'Dozvoli samo administratorima',
'protect-summary-cascade' => 'prenosna zaštita',
'protect-expiring' => 'ističe $1 (UTC)',
'protect-expiring-local' => 'ističe $1',
'blocklist-userblocks' => 'Sakrij blokade računa',
'blocklist-tempblocks' => 'Sakrij privremene blokade',
'blocklist-addressblocks' => 'Sakrij pojedinačne IP blokade',
+'blocklist-rangeblocks' => 'Sakrij blokiranja opsega',
'blocklist-timestamp' => 'Vremenska oznaka',
'blocklist-target' => 'Cilj',
'blocklist-expiry' => 'Ističe',
# Move page
'move-page' => 'Pomjeranje $1',
'move-page-legend' => 'Premjestite stranicu',
-'movepagetext' => "Korištenjem ovog formulara možete preusmjeriti članak
-zajedno sa stranicom za diskusiju tog članka.
+'movepagetext' => "Korištenjem ovog formulara možete preimenovati stranicu, premještajući cijelu historiju na novo ime.
+Članak pod starim imenom će postati stranica koja preusmjerava na članak pod novim imenom.
+Možete automatski izmjeniti preusmjerenje do izvornog naslova.
+Ako se ne odlučite na to, provjerite [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|neispravna preusmjeravanja]].
+Dužni ste provjeriti da svi linkovi i dalje nastave voditi na prave stranice.
-Članak pod starim imenom će postati stranica koja preusmjerava
-na članak pod novim imenom. Linkovi koji vode na članak sa
-starim imenom neće biti preusmjereni. Vaša je dužnost da se
-pobrinete da svi linkovi koji vode na članak sa starim imenom
-budu adekvatno preusmjereni (stranica posebne namjene za
-održavanje je korisna za obavještenje o [[Special:BrokenRedirects|mrtvim]] i [[Special:DoubleRedirects|duplim]] preusmjerenjima).
-
-Imajte na umu da članak '''neće''' biti preusmjeren ukoliko
-već postoji članak pod imenom na koje namjeravate da
-preusmjerite.
+Imajte na umu da članak '''neće''' biti preusmjeren ukoliko već postoji članak pod imenom na koje namjeravate da preusmjerite osim u slučaju stranice za preusmjeravanje koja nema nikakvih starih izmjena.
+To znači da možete vratiti stranicu na prethodno mjesto ako pogriješite, ali ne možete zamijeniti postojeću stranicu.
'''Pažnja!'''
-Imajte na umu da preusmjeravanje popularnog članka može biti
-drastična i neočekivana promjena za korisnike.",
+Ovo može biti drastična i neočekivana promjena kad su u pitanju popularne stranice;
+Molimo dobro razmislite prije nego što preimenujete stranicu.",
'movepagetext-noredirectfixer' => "Koristeći obrazac ispod ćete preimenovati stranicu i premjestiti cijelu njenu historiju na novi naziv.
Stari naziv će postati preusmjerenje na novi naziv.
Molimo provjerite da li postoje [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|nedovršena preusmjerenja]].
'djvu_page_error' => 'DjVu stranica je van opsega',
'djvu_no_xml' => 'Za XML-datoteku se ne može pozvati DjVu datoteka',
'thumbnail-temp-create' => 'Ne mogu da napravim privremenu smanjenu sliku',
+'thumbnail-dest-create' => 'Ne mogu da sačuvam smanjenu sliku ("thumbnail") na destinaciju',
'thumbnail_invalid_params' => 'Pogrešne postavke smanjenog prikaza',
'thumbnail_dest_directory' => 'Ne može se napraviti odredišni folder',
'thumbnail_image-type' => 'Tip slike nije podržan',
'import-upload' => 'Postavljanje XML podataka',
'import-token-mismatch' => 'Izgubljeni podaci sesije. Molimo pokušajte ponovno.',
'import-invalid-interwiki' => 'Ne može se uvesti iz navedenog wikija.',
+'import-error-edit' => 'Stranica "$1" nije uvezena jer vam nije dopušteno da je uređujete.',
+'import-error-create' => 'Stranica "$1" nije uvezena jer vam nije dozvoljeno da je napravite.',
+'import-error-interwiki' => 'Stranica "$1" nije uvezena jer je njen naziv rezerviran za vanjsko povezivanje (interwiki).',
+'import-error-special' => 'Stranica "$1" nije uvezena jer pripada posebnom imenskom prostoru koje ne prihvata stranice.',
+'import-error-invalid' => 'Stranica "$1" nije uvezena jer je njen naziv neispravan.',
'import-options-wrong' => '{{PLURAL:$2|Pogrešna opcija|Pogrešne opcije}}: <nowiki>$1</nowiki>',
# Import log
'pageinfo-article-id' => 'ID stranice',
'pageinfo-language' => 'Jezik sadržaja stranice',
'pageinfo-views' => 'Broj pogleda',
-'pageinfo-watchers' => 'Broj onih koji pregledaju',
+'pageinfo-watchers' => 'Broj pratitelja stranice',
'pageinfo-redirects-name' => 'Preusmjeravanja na ovu stranicu',
'pageinfo-subpages-name' => 'Podstranice ove stranice',
'pageinfo-firstuser' => 'Korisnik koji je napravio stranicu',
'specialpages-group-highuse' => 'Najčešće korištene stranice',
'specialpages-group-pages' => 'Spiskovi stranica',
'specialpages-group-pagetools' => 'Alati stranice',
-'specialpages-group-wiki' => 'Wiki podaci i alati',
+'specialpages-group-wiki' => 'Podaci i alati',
'specialpages-group-redirects' => 'Preusmjeravanje posebnih stranica',
'specialpages-group-spam' => 'Alati za spam',
'compare-submit' => 'Usporedi',
'compare-invalid-title' => 'Naslov koji ste unijeli je nevaljan.',
'compare-title-not-exists' => 'Naslov koji ste naveli ne postoji.',
+'compare-revision-not-exists' => 'Izmjena koji ste naveli ne postoji.',
# Database error messages
'dberr-header' => 'Ovaj wiki ima problem',
# New logging system
'logentry-delete-delete' => '$1 je obrisao stranicu $3',
'logentry-delete-restore' => '$1 je vratio stranicu $3',
+'logentry-delete-event' => '$1 je {{GENDER:|promijenio|promijenila}} vidljivost {{PLURAL:$5|događaja|$5 događaja}} u evidenciji na $3: $4',
+'logentry-delete-revision' => '$1 je {{GENDER:|promijenio|promijenila}} vidljivost {{PLURAL:$5|izmjene|$5 izmjene|$5 izmjena}} na stranici $3: $4',
+'logentry-delete-event-legacy' => '$1 je {{GENDER:|promijenio|promijenila}} vidljivost događaja u evidenciji na $3',
+'logentry-delete-revision-legacy' => '$1 je {{GENDER:|promijenio|promijenila}} vidljivost izmjena na stranici $3',
+'logentry-suppress-delete' => '$1 {{GENDER:|je potisnuo|je potisnula}} stranicu $3',
+'logentry-suppress-event' => '$1 je tajno {{GENDER:|promijenio|promijenila}} vidljivost {{PLURAL:$5|događaja|$5 događaja}} u evidenciji na $3: $4',
+'logentry-suppress-revision' => '$1 je tajno {{GENDER:|promijenio|promijenila}} vidljivost {{PLURAL:$5|izmjene|$5 izmjene|$5 izmjena}} na stranici $3: $4',
+'logentry-suppress-event-legacy' => '$1 je tajno {{GENDER:|promijenio|promijenila}} vidljivost događaja u evidenciji na $3',
+'logentry-suppress-revision-legacy' => '$1 je tajno {{GENDER:|promijenio|promijenila}} vidljivost izmjena na stranici $3',
'revdelete-content-hid' => 'skriveni sadržaj',
'revdelete-summary-hid' => 'sažetak izmjene je sakriven',
'revdelete-uname-hid' => 'sažetak izmjene je sakriven',
'logentry-newusers-newusers' => 'Korisnički račun $1 je napravljen',
'logentry-newusers-create' => 'Korisnički račun $1 je napravljen',
'logentry-newusers-create2' => '$3 je {{GENDER:$2|napravio|napravila}} korisnički račun $1',
+'logentry-newusers-byemail' => 'Korisnički račun $3 je napravio $1 i lozinka/šifra je poslana putem e-maila',
'logentry-newusers-autocreate' => 'Korisnički račun $1 je automatski napravljen',
'logentry-rights-rights' => '$1 {{GENDER:$1|je promijenio|je promijenila|je promijenio}} članstvo grupe za $3 iz $4 u $5',
'logentry-rights-rights-legacy' => '$1 je {{GENDER:$2|promijenio|promijenila|promijenio}} članstvo grupe za $3',
'api-error-emptypage' => 'Stvaranje novih praznih stranica nije dozvoljeno.',
'api-error-fetchfileerror' => 'Unutrašnja greška: pojavio se neki problem pri dobijanju podataka o datoteci.',
'api-error-fileexists-forbidden' => 'Datoteka s imenom "$1" već postoji, i ne može biti zamijenjena.',
+'api-error-fileexists-shared-forbidden' => 'Datoteka s imenom "$1" već postoji u zajedničkom spremištu i ne može biti prepisana.',
'api-error-file-too-large' => 'Datoteka koju ste poslali je bila prevelika.',
'api-error-filename-tooshort' => 'Ime datoteke je prekratko.',
'api-error-filetype-banned' => 'Ova vrsta datoteke je zabranjena.',
-'api-error-filetype-banned-type' => '$1 nije dopuštena vrsta datoteke. {{PLURAL:$3|Dopuštena vrsta datoteke je|Dopuštene vrste datoteka su}} $2.',
+'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|nije dopušteni vrsta datoteke|su nedopušteni vrste datoteke|su nedopušteni vrste datoteka}}. {{PLURAL:$3|Dopuštena vrsta datoteke je|Dopuštene vrste datoteka su}} $2.',
'api-error-filetype-missing' => 'Datoteci nedostaje nastavak.',
'api-error-hookaborted' => 'Izmjena koji ste pokušali načiniti je obustavljena preko kuke proširenja.',
'api-error-http' => 'Unutrašnja greška: ne može se spojiti na server.',
'api-error-ok-but-empty' => 'Unutrašnja greška: nema odgovora od servera.',
'api-error-overwrite' => 'Pisanje preko postojeće datoteke nije dopušteno.',
'api-error-stashfailed' => 'Unutrašnja greška: server nije mogao da spremi privremenu datoteku.',
+'api-error-publishfailed' => 'Unutrašnja greška: Server nije uspio objaviti privremenu datoteku.',
'api-error-timeout' => 'Server nije odgovorio unutar očekivanog vremena.',
'api-error-unclassified' => 'Desila se nepoznata greška',
'api-error-unknown-code' => 'Nepoznata greška: "$1"',
# Durations
'duration-seconds' => '$1 {{PLURAL:$1|sekunda|sekunde}}',
-'duration-minutes' => '$1 {{PLURAL:$1|minut|minuta|minuta}}',
+'duration-minutes' => '$1 {{PLURAL:$1|minut|minute|minuta}}',
'duration-hours' => '$1 {{PLURAL:$1|sat|sata|sati}}',
'duration-days' => '$1 {{PLURAL:$1|dan|dana}}',
'duration-weeks' => '$1 {{PLURAL:$1|sedmica|sedmice|sedmica}}',
'tog-externaldiff' => "Utilitza per defecte un altre visualitzador de diferències (opció per a experts, requereix la configuració adient de l'ordinador, [//www.mediawiki.org/wiki/Manual:External_editors consulteu-ho al manual])",
'tog-showjumplinks' => "Habilita els enllaços de dreceres d'accessibilitat",
'tog-uselivepreview' => 'Utilitza la previsualització automàtica (cal JavaScript) (experimental)',
-'tog-forceeditsummary' => "Avisa'm en introduir un camp de resum en blanc",
+'tog-forceeditsummary' => "Avisa'm en deixar el resum de la modificació en blanc",
'tog-watchlisthideown' => 'Amaga les meues edicions de la llista de seguiment',
'tog-watchlisthidebots' => 'Amaga de la llista de seguiment les edicions fetes per usuaris bots',
'tog-watchlisthideminor' => 'Amaga les edicions menors de la llista de seguiment',
'userrights-lookup-user' => "Gestiona els grups d'usuari",
'userrights-user-editname' => "Introduïu un nom d'usuari:",
'editusergroup' => "Edita els grups d'usuaris",
-'editinguser' => "S'està canviant els permisos de l'usuari '''[[User:$1|$1]]''' $2",
+'editinguser' => "Modificació dels permisos de {{GENDER:$1|l’usuari|la usuària}} '''[[User:$1|$1]]''' $2",
'userrights-editusergroup' => "Edita els grups d'usuaris",
'saveusergroups' => "Desa els grups d'usuari",
'userrights-groupsmember' => 'Membre de:',
'userrights-groupsmember-auto' => 'Membre implícit de:',
-'userrights-groups-help' => "Podeu modificar els grups als quals pertany aquest usuari.
-* Els requadres marcats indiquen que l'usuari és dins del grup.
-* Els requadres sense marcar indiquen que l'usuari no hi pertany.
-* Un asterisc (*) indica que no el podreu treure del grup una vegada l'hàgiu afegit o viceversa.",
+'userrights-groups-help' => "Podeu modificar els grups als quals pertany {{GENDER:$1|aquest usuari|aquesta usuària}}.
+* Una casella marcada significa que {{GENDER:$1|l’usuari|la usuària}} pertany a aquest grup.
+* Una casella no marcada significa que {{GENDER:$1|l’usuari|la usuària}} no pertany a aquest grup.
+* Un asterisc (*) indica que no {{GENDER:$1|el|la}} podreu treure del grup una vegada l'hàgiu afegit o viceversa.",
'userrights-reason' => 'Motiu:',
'userrights-no-interwiki' => "No teniu permisos per a editar els permisos d'usuari d'altres wikis.",
'userrights-nodatabase' => 'La base de dades $1 no existeix o no és local.',
per enviar un correu electrònic a altres usuaris.",
'emailuser' => 'Envia un missatge de correu electrònic a aquest usuari',
'emailuser-title-target' => 'Enviar un correu electrònic a {{GENDER:$1|aquest usuari|aquesta usuària}}',
-'emailuser-title-notarget' => "Enviar un correu electrònic a l'usuari",
+'emailuser-title-notarget' => 'Enviar un correu electrònic a un usuari',
'emailpage' => 'Correu electrònic a usuari',
'emailpagetext' => "Podeu usar el següent formulari per a enviar un missatge de correu electrònic a {{GENDER:$1|aquest usuari|aquesta usuària}}.
L'adreça electrònica que vau indicar a [[Special:Preferences|les vostres preferències d'usuari]] apareixerà com a remitent del correu electrònic, de manera que el destinatari us podrà respondre directament.",
** Abús de comptes d'usuari múltiples
** Nom d'usuari no acceptable",
'ipb-hardblock' => "Impedeix que els usuaris registrats puguin editar des d'aquesta adreça IP",
-'ipbcreateaccount' => 'Evita la creació de comptes',
-'ipbemailban' => "Evita que l'usuari enviï correu electrònic",
+'ipbcreateaccount' => 'Impedeix la creació de comptes',
+'ipbemailban' => "Impedeix que l'usuari enviï correus electrònics",
'ipbenableautoblock' => "Bloca l'adreça IP d'aquest usuari, i totes les subseqüents adreces des de les quals intenti registrar-se",
'ipbsubmit' => 'Bloqueja aquesta adreça',
'ipbother' => 'Un altre termini',
'thumbnail_image-missing' => 'Sembla que falta el fitxer: $1',
# Special:Import
-'import' => 'Importa les pàgines',
+'import' => 'Importació de pàgines',
'importinterwiki' => 'Importa interwiki',
'import-interwiki-text' => "Trieu un web basat en wiki i un títol de pàgina per a importar.
Es conservaran les dates de les versions i els noms dels editors.
'importcantopen' => "No ha estat possible d'obrir el fitxer a importar",
'importbadinterwiki' => "Enllaç d'interwiki incorrecte",
'importnotext' => 'Buit o sense text',
-'importsuccess' => "S'ha acabat d'importar.",
+'importsuccess' => 'Importació completada!',
'importhistoryconflict' => "Hi ha un conflicte de versions en l'historial (la pàgina podria haver sigut importada abans)",
'importnosources' => "No s'ha definit cap font d'origen interwiki i s'ha inhabilitat la càrrega directa d'una còpia de l'historial",
'importnofile' => "No s'ha pujat cap fitxer d'importació.",
'tooltip-t-print' => "Versió per a impressió d'aquesta pàgina",
'tooltip-t-permalink' => 'Enllaç permanent a aquesta versió de la pàgina',
'tooltip-ca-nstab-main' => 'Vegeu el contingut de la pàgina.',
-'tooltip-ca-nstab-user' => "Vegeu la pàgina de l'usuari.",
+'tooltip-ca-nstab-user' => "Vegeu la pàgina d'usuari",
'tooltip-ca-nstab-media' => "Vegeu la pàgina de l'element multimèdia",
'tooltip-ca-nstab-special' => 'Aquesta és una pàgina especial, no podeu modificar-la',
'tooltip-ca-nstab-project' => 'Vegeu la pàgina del projecte',
'creating' => 'دروستکردنی $1',
'editingsection' => 'دەستکاریکردنی: $1 (بەش)',
'editingcomment' => 'دەستکاریکردنی $1 (بەشی نوێ)',
-'editconflict' => 'دەستکاری کێشە : $1',
+'editconflict' => 'کێشەی دەستکاری: $1',
'explainconflict' => "کەسێکی تر ئەم پەڕەیە گۆڕیوە لەو کاتەوە تۆ دەستکاریکردنیت دەستپێکردووە.
بەشی سەرەوەی دەق، شێوازی ئێستای پەڕەکە لە خۆ ئەگرێت.
گۆڕانکاریەکانی تۆش لە بەشی خوارەوەی دەق نیشاندراوە.
# Rights
'right-read' => 'خوێندنەوەی پەڕەکان',
'right-edit' => 'دەستکاری کردنی پەڕەکان',
-'right-createpage' => 'دروست کردنی پەڕەکان (کە پەڕەی لێدوان نین)',
+'right-createpage' => 'دروستکردنی پەڕەکان (کە پەڕەی وتووێژ نین)',
'right-createtalk' => 'دروست کردنی پەڕەکانی لێدوان',
'right-createaccount' => 'دروست کردنی ھەژماری بەکارھێنەریی نوێ',
'right-minoredit' => 'بچووک دیاری کردنی گۆڕانکارییەکان',
# General errors
'error' => 'Chyba',
-'databaseerror' => 'Databázová chyba',
+'databaseerror' => 'Chyba databáze',
'dberrortext' => 'Při dotazu do databáze došlo k syntaktické chybě.
Příčinou může být chyba v programu.
Poslední dotaz byl:
'notloggedin' => 'Nejste přihlášen(a)',
'nologin' => "Dosud nemáte účet? '''$1'''.",
'nologinlink' => 'Zaregistrujte se',
-'createaccount' => 'Vytvořit nový účet',
+'createaccount' => 'Vytvořit účet',
'gotaccount' => "Už jste registrováni? '''$1'''.",
'gotaccountlink' => 'Přihlaste se',
'userlogin-resetlink' => 'Zapomněli jste přihlašovací údaje?',
'tog-enotifminoredits' => 'Gyrru e-bost ataf hefyd ar gyfer golygiadau bychain i dudalennau a ffeiliau',
'tog-enotifrevealaddr' => 'Datguddio fy nghyfeiriad e-bost mewn e-byst hysbysu',
'tog-shownumberswatching' => "Dangos y nifer o ddefnyddwyr sy'n gwylio",
-'tog-oldsig' => 'Llofnod cyfredol:',
+'tog-oldsig' => 'Y llofnod cyfredol:',
'tog-fancysig' => 'Trin y llofnod fel testun wici (heb gyswllt wici awtomatig)',
'tog-externaleditor' => 'Defnyddio golygydd allanol trwy ragosodiad (ar gyfer arbenigwyr yn unig; mae arno angen gosodiadau arbennig ar eich cyfrifiadur. [//www.mediawiki.org/wiki/Manual:External_editors Rhagor o wybodaeth.])',
'tog-externaldiff' => 'Defnyddio "external diff" trwy ragosodiad (ar gyfer arbenigwyr yn unig; mae arno angen gosodiadau arbennig ar eich cyfrifiadur. [//www.mediawiki.org/wiki/Manual:External_editors Rhagor o wybodaeth.])',
'prot_1movedto2' => 'wedi symud [[$1]] i [[$2]]',
'protect-badnamespace-title' => 'Parth na ellir ei ddiogelu',
'protect-badnamespace-text' => 'Ni ellir diogelu tudalennau yn y parth hwn.',
+'protect-norestrictiontypes-text' => 'Ni ellir gwarchod y dudalen hon gan nad oes mathau o gyfyngiadau ar gael iddi.',
+'protect-norestrictiontypes-title' => 'Tudalen na ellir ei gwarchod',
'protect-legend' => "Cadarnháu'r diogelu",
'protectcomment' => 'Rheswm:',
'protectexpiry' => 'Yn dod i ben:',
'immobile-target-namespace-iw' => 'Nid yw cyswllt rhyngwici yn nod dilys wrth symud tudalen.',
'immobile-source-page' => 'Ni ellir symud y dudalen hon.',
'immobile-target-page' => "Ddim yn gallu symud i'r teitl newydd hwn.",
+'bad-target-model' => "Mae'r cyrchfan dewisedig yn defnyddio model gwahanol i'w chynnwys. Ni ellir trawsnewid o $1 i $2.",
'imagenocrossnamespace' => 'Ni ellir symud ffeil i barth arall',
'nonfile-cannot-move-to-file' => 'Ni ellir symud unrhywbeth heblaw ffeil i barth y ffeiliau',
'imagetypemismatch' => "Nid yw'r estyniad ffeil newydd yn cyfateb i'r math o ffeil",
'pageinfo-magic-words' => '{{PLURAL:$1|Gair|Gair|Geiriau}} hud ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Categori|Categori|Categorïau}} cudd ($1)',
'pageinfo-templates' => '{{PLURAL:$1|Nodyn|Nodyn|Nodiadau}} a drawsgynhwyswyd ($1)',
+'pageinfo-transclusions' => '{{PLURAL:$1|Tudalen|Tudalen|Tudalennau}} y trawsgynhwyswyd y dudalen hon arnynt ($1)',
'pageinfo-toolboxlink' => 'Gwybodaeth am y dudalen',
'pageinfo-redirectsto' => 'Yn ailgyfeirio i',
+'pageinfo-redirectsto-info' => 'manylion',
+'pageinfo-contentpage' => 'Ymhlith tudalennau pwnc y wici',
+'pageinfo-contentpage-yes' => 'Ydi',
+'pageinfo-protect-cascading' => "Mae diogelu sgydol yn deillio o'r dudalen hon",
+'pageinfo-protect-cascading-yes' => 'Oes',
+'pageinfo-protect-cascading-from' => "Mae'r diogelu sgydol yn dechrau ar",
'pageinfo-category-info' => 'Gwybodaeth am y categori',
'pageinfo-category-pages' => 'Nifer y tudalennau',
'pageinfo-category-subcats' => 'Nifer yr is-gategorïau',
'markedaspatrollederror' => 'Ni ellir gosod marc ymweliad patrôl',
'markedaspatrollederrortext' => "Rhaid nodi'r union olygiad sydd angen marc ymweliad patrôl.",
'markedaspatrollederror-noautopatrol' => "Ni chaniateir i chi farcio'ch newidiadau eich hunan fel rhai derbyniol.",
+'markedaspatrollednotify' => 'Nodwyd bod y newid hwn i $1 wedi derbyn ymweliad patrôl.',
+'markedaspatrollederrornotify' => 'Methwyd rhoi marc ymweliad patrôl arni.',
# Patrol log
'patrol-log-page' => 'Lòg patrolio',
'exif-pixelydimension' => 'Lled y ddelwedd',
'exif-pixelxdimension' => 'Uchder y ddelwedd',
'exif-usercomment' => "Sylwadau'r defnyddiwr",
-'exif-relatedsoundfile' => 'Ffeil sain cysylltiedig',
+'exif-relatedsoundfile' => 'Ffeil sain gysylltiedig',
'exif-datetimeoriginal' => 'Dyddiad ac amser y cynhyrchwyd y data',
'exif-datetimedigitized' => 'Dyddiad ac amser y digiteiddiwyd',
'exif-subsectime' => 'Manylyn iseiliad amser newid y ffeil',
'exif-originaldocumentid' => 'ID unigryw y ddogfen wreiddiol',
'exif-licenseurl' => 'URL y drwydded hawlfraint',
'exif-morepermissionsurl' => 'Gwybodaeth trwyddedu amgen',
-'exif-attributionurl' => "Wrth ail-ddefnyddio'r gwaith yma, darparwch ddolen at",
-'exif-preferredattributionname' => "Wrth ail-ddefnyddio'r gwaith yma, cydnabyddwch",
+'exif-attributionurl' => "Wrth ailddefnyddio'r gwaith yma, darparwch ddolen at",
+'exif-preferredattributionname' => "Wrth ailddefnyddio'r gwaith yma, cydnabyddwch",
'exif-pngfilecomment' => 'Sylwadau ar y ffeil PNG',
'exif-disclaimer' => 'Ymwadiad',
'exif-contentwarning' => 'Rhybudd am y cynnwys',
# Scary transclusion
'scarytranscludedisabled' => '[Analluogwyd cynhwysiad rhyng-wici]',
-'scarytranscludefailed' => '[Methwyd â nôl y nodyn ar gyfer $1]',
+'scarytranscludefailed' => '[Methwyd nôl y nodyn ar gyfer $1]',
+'scarytranscludefailed-httpstatus' => '[Methwyd nôl y nodyn ar gyfer $1: HTTP $2]',
'scarytranscludetoolong' => "[Mae'r URL yn rhy hir]",
# Delete conflict
'logentry-newusers-newusers' => 'Dechreuwyd y cyfrif defnyddiwr $1',
'logentry-newusers-create' => 'Dechreuwyd y cyfrif defnyddiwr $1',
'logentry-newusers-create2' => 'Dechreuwyd y cyfrif defnyddiwr $3 gan $1',
+'logentry-newusers-byemail' => 'Dechreuodd $1 y cyfrif defnyddiwr $3 ac anfonodd gyfrinair drwy e-bost',
'logentry-newusers-autocreate' => 'Crëwyd y cyfrif $1 yn awtomatig',
+'logentry-rights-rights' => 'Newidiodd $1 y grwpiau y mae $3 yn aelod ohonynt o $4 i $5',
+'logentry-rights-rights-legacy' => 'Newidiodd $1 y grwpiau y mae $3 yn aelod ohonynt',
+'logentry-rights-autopromote' => 'Dyrchafwyd $1 yn awtomatig o $4 i $5',
'rightsnone' => '(dim)',
# Feedback
'api-error-ok-but-empty' => 'Gwall mewnol: dim ymateb gan y gweinydd.',
'api-error-overwrite' => 'Ni chaniateir trosysgrifo ffeil sydd eisoes yn bod.',
'api-error-stashfailed' => "Gwall mewnol: methodd y gweinydd â rhoi'r ffeil dros dro ar gadw.",
+'api-error-publishfailed' => "Gwall mewnol: methodd y gweinydd â chyhoeddi'r ffeil dros dro.",
'api-error-timeout' => 'Ni chafwyd ymateb gan y gweinydd mewn da bryd.',
'api-error-unclassified' => 'Cafwyd gwall anhysbys',
'api-error-unknown-code' => 'Gwall anhysbys: "$1"',
'columns' => 'Spalten:',
'searchresultshead' => 'Suche',
'resultsperpage' => 'Treffer pro Seite:',
-'stub-threshold' => 'Linkformatierung <a href="#" class="stub">kleiner Seiten</a> (in Byte):',
+'stub-threshold' => 'Linkformatierung <a href="#" class="stub">kleiner Seiten</a> (in Bytes):',
'stub-threshold-disabled' => 'Deaktiviert',
'recentchangesdays' => 'Anzahl der standardmäßig einbezogenen Tage:',
'recentchangesdays-max' => 'Maximal $1 {{PLURAL:$1|Tag|Tage}}',
'rc_categories' => 'Nur Seiten aus den Kategorien (getrennt mit „|“):',
'rc_categories_any' => 'Alle',
'rc-change-size' => '$1 {{PLURAL:$1|Byte|Bytes}}',
-'rc-change-size-new' => '$1 {{PLURAL:$1|Byte|Byte}} nach der Änderung',
+'rc-change-size-new' => '$1 {{PLURAL:$1|Byte|Bytes}} nach der Änderung',
'newsectionsummary' => 'Neuer Abschnitt /* $1 */',
'rc-enhanced-expand' => 'Details anzeigen (benötigt JavaScript)',
'rc-enhanced-hide' => 'Details verstecken',
'ignorewarnings' => 'Warnungen ignorieren',
'minlength1' => 'Dateinamen müssen mindestens einen Buchstaben lang sein.',
'illegalfilename' => 'Der Dateiname „$1“ enthält mindestens ein nicht erlaubtes Zeichen. Bitte benenne die Datei um und versuche, sie erneut hochzuladen.',
-'filename-toolong' => 'Dateinamen dürfen nicht größer als 240 Byte sein.',
+'filename-toolong' => 'Dateinamen dürfen nicht größer als 240 Bytes sein.',
'badfilename' => 'Der Dateiname wurde in „$1“ geändert.',
'filetype-mime-mismatch' => 'Dateierweiterung „.$1“ stimmt nicht mit dem MIME-Typ ($2) überein.',
'filetype-badmime' => 'Dateien mit dem MIME-Typ „$1“ dürfen nicht hochgeladen werden.',
'backend-fail-closetemp' => 'Die temporäre Datei konnte nicht geschlossen werden.',
'backend-fail-read' => 'Die Datei $1 konnte nicht gelesen werden.',
'backend-fail-create' => 'Die Datei $1 konnte nicht gespeichert werden.',
-'backend-fail-maxsize' => 'Die Datei $1 konnte nicht gespeichert werden, da sie größer als {{PLURAL:$2|ein Byte|$2 Byte}} ist.',
+'backend-fail-maxsize' => 'Die Datei $1 konnte nicht gespeichert werden, da sie größer als {{PLURAL:$2|ein Byte|$2 Bytes}} ist.',
'backend-fail-readonly' => 'Das Speicher-Backend „$1“ befindet sich derzeit im Lesemodus. Der angegebene Grund lautet: „$2“',
'backend-fail-synced' => 'Die Datei „$1“ befindet sich, innerhalb des internen Speicher-Backends, in einem inkonsistenten Zustand.',
'backend-fail-connect' => 'Es konnte keine Verbindung zum Speicher-Backend „$1“ hergestellt werden.',
'fewestrevisions' => 'Seiten mit den wenigsten Versionen',
# Miscellaneous special pages
-'nbytes' => '$1 {{PLURAL:$1|Byte|Byte}}',
+'nbytes' => '$1 {{PLURAL:$1|Byte|Bytes}}',
'ncategories' => '$1 {{PLURAL:$1|Kategorie|Kategorien}}',
'ninterwikis' => '{{PLURAL:$1|Ein Interwikilink|$1 Interwikilinks}}',
'nlinks' => '{{PLURAL:$1|1 Link|$1 Links}}',
'pageinfo-header-restrictions' => 'Seitenschutz',
'pageinfo-header-properties' => 'Seiteneigenschaften',
'pageinfo-display-title' => 'Anzeigetitel',
-'pageinfo-default-sort' => 'Standardsortierkriterium',
-'pageinfo-length' => 'Seitenlänge (in Byte)',
+'pageinfo-default-sort' => 'Standard-Sortierschlüssel',
+'pageinfo-length' => 'Seitenlänge (in Bytes)',
'pageinfo-article-id' => 'Seitenkennnummer',
'pageinfo-language' => 'Seiteninhaltssprache',
'pageinfo-robot-policy' => 'Suchmaschinenstatus',
'version-antispam' => 'Spamschutzerweiterungen',
'version-skins' => 'Benutzeroberflächen',
'version-api' => 'API-Erweiterungen',
-'version-other' => 'Andere Erweiterungen',
+'version-other' => 'Sonstige Erweiterungen',
'version-mediahandlers' => 'Mediennutzungserweiterungen',
'version-hooks' => "Schnittstellen ''(Hooks)''",
'version-extension-functions' => 'Funktionsaufrufe',
* @author George Animal
* @author Kaganer
* @author Mirzali
+ * @author Nemo bis
* @author Olvörg
* @author Reedy
* @author Sahim
'tooltip-summary' => 'Yew xulasaya kilm binuse',
# Scripts
-'common.js' => "/**
- * Keep code in MediaWiki:Common.js to a minimum as it is unconditionally
- * loaded for all users on every wiki page. If possible create a gadget that is
- * enabled by default instead of adding it here (since gadgets are fully
- * optimized ResourceLoader modules with possibility to add dependencies etc.)
- *
- * Since common.js isn't a gadget, there is no place to declare its
- * dependencies, so we have to lazy load them with mw.loader.using on demand and
- * then execute the rest in the callback. In most cases these dependencies will
- * be loaded (or loading) already and the callback will not be delayed. In case a
- * dependency hasn't arrived yet it'll make sure those are loaded before this.
- */
-mw.loader.using( 'mediawiki.util', function() {
-/* Begin of mw.loader.using callback */
-
-/**
- * Redirect User:Name/skin.js and skin.css to the current skin's pages
- * (unless the 'skin' page really exists)
- * @source: http://www.mediawiki.org/wiki/Snippets/Redirect_skin.js
- * @rev: 2
- */
-if ( mw.config.get( 'wgArticleId' ) === 0 && mw.config.get( 'wgNamespaceNumber' ) == 2 ) {
- var titleParts = mw.config.get( 'wgPageName' ).split( '/' );
- // Make sure there was a part before and after the slash
- // And that the latter is 'skin.js' or 'skin.css'
- if ( titleParts.length == 2 ) {
- var userSkinPage = titleParts.shift() + '/' + mw.config.get( 'skin' );
- if ( titleParts.slice(-1) == 'skin.js' ) {
- window.location.href = mw.util.wikiGetlink( userSkinPage + '.js' );
- } else if ( titleParts.slice(-1) == 'skin.css' ) {
- window.location.href = mw.util.wikiGetlink( userSkinPage + '.css' );
- }
- }
-}
-
-/** Map addPortletLink to mw.util
- */
-window.addPortletLink = function() {
- return mw.util.addPortletLink.apply( mw.util, arguments );
-};
-
-/** extract a URL parameter from the current URL **********
- *
- * @deprecated: Use mw.util.getParamValue with proper escaping
- */
-window.getURLParamValue = function() {
- return mw.util.getParamValue.apply( mw.util, arguments );
-};
-
-/** &withCSS= and &withJS= URL parameters *******
- * Allow to try custom scripts from MediaWiki space
- * without editing personal .css or .js files
- */
-var extraCSS = mw.util.getParamValue(\"withCSS\");
-if ( extraCSS && extraCSS.match(/^MediaWiki:[^&<>=%]*\\.css\$/) ) {
- importStylesheet(extraCSS);
-}
-var extraJS = mw.util.getParamValue(\"withJS\");
-if ( extraJS && extraJS.match(/^MediaWiki:[^&<>=%]*\\.js\$/) ) {
- importScript(extraJS);
-}
-
-
-/* Import more specific scripts if necessary */
-if (wgAction == 'edit' || wgAction == 'submit' || wgPageName == 'Special:Upload') { //scripts specific to editing pages
- importScript('MediaWiki:Common.js/edit.js');
-}
-else if (mw.config.get('wgPageName') == 'Special:Watchlist') { //watchlist scripts
- mw.loader.load(mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=MediaWiki:Common.js/watchlist.js&action=raw&ctype=text/javascript&smaxage=21600&maxage=86400');
-}
-
-if ( wgNamespaceNumber == 6 ) {
- importScript('MediaWiki:Common.js/file.js');
-}
-
-/**
- * WikiMiniAtlas
- *
- * Description: WikiMiniAtlas is a popup click and drag world map.
- * This script causes all of our coordinate links to display the WikiMiniAtlas popup button.
- * The script itself is located on meta because it is used by many projects.
- * See [[Meta:WikiMiniAtlas]] for more information.
- * Maintainers: [[User:Dschwen]]
- */
-
-mw.loader.load('//meta.wikimedia.org/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript&smaxage=21600&maxage=86400');
-
-/* Scripts specific to Internet Explorer */
-if (\$.client.profile().name == 'msie') {
- /** Internet Explorer bug fix **************************************************
- *
- * Description: Fixes IE horizontal scrollbar bug
- * Maintainers: [[User:Tom-]]?
- */
-
- var oldWidth;
- var docEl = document.documentElement;
-
- var fixIEScroll = function() {
- if (!oldWidth || docEl.clientWidth > oldWidth) {
- doFixIEScroll();
- } else {
- setTimeout(doFixIEScroll, 1);
- }
-
- oldWidth = docEl.clientWidth;
- };
-
- var doFixIEScroll = function () {
- docEl.style.overflowX = (docEl.scrollWidth - docEl.clientWidth < 4) ? \"hidden\" : \"\";
- };
-
- document.attachEvent(\"onreadystatechange\", fixIEScroll);
- document.attachEvent(\"onresize\", fixIEScroll);
-
- // In print IE (7?) does not like line-height
- mw.util.addCSS('@media print { sup, sub, p, .documentDescription { line-height: normal; } }');
-
- // IE overflow bug
- mw.util.addCSS('div.overflowbugx { overflow-x: scroll !important; overflow-y: hidden !important; } '
- + 'div.overflowbugy { overflow-y: scroll !important; overflow-x: hidden !important; }');
-
- // IE zoomfix
- // Use to fix right floating div/table inside tables
- mw.util.addCSS('.iezoomfix div, .iezoomfix table { zoom: 1; }');
-
- // Import scripts specific to Internet Explorer 6
- if (\$.client.profile().versionBase == '6') {
- importScript('MediaWiki:Common.js/IE60Fixes.js');
- }
-}
-
-/* Fixes for Windows XP font rendering */
-if (navigator.appVersion.search(/windows nt 5/i) != -1) {
- mw.util.addCSS('.IPA {font-family: \"Lucida Sans Unicode\", \"Arial Unicode MS\";} ' +
- '.Unicode {font-family: \"Arial Unicode MS\", \"Lucida Sans Unicode\";}');
-}
-
-/* Helper script for .hlist class in Common.css
- * Last updated: September 12, 2012
- * Maintainer: [[User:Edokter]]
- */
-
-if ( \$.client.profile().name == 'msie' ) {
- /* Add pseudo-selector class to last-child list items in IE 8 */
- if ( \$.client.profile().versionBase == '8' ) {
- \$( '.hlist' ).find( 'dd:last-child, dt:last-child, li:last-child' )
- .addClass( 'hlist-last-child' );
- }
- /* Generate interpuncts and parens for IE < 8 */
- if ( \$.client.profile().versionBase < '8' ) {
- var hlists = \$( '.hlist' );
- hlists.find( 'dt:not(:last-child)' )
- .append( ': ' );
- hlists.find( 'dd:not(:last-child)' )
- .append( '<b>·</b> ' );
- hlists.find( 'li:not(:last-child)' )
- .append( '<b>·</b> ' );
- hlists.find( 'dl dl, ol ol, ul ul' )
- .prepend( '( ' ).append( ') ' );
- }
-}
-
-/* Test if an element has a certain class
- * Maintainers: [[User:Mike Dillon]], [[User:R. Koot]], [[User:SG]]
- *
- * @deprecated: Use \$(element).hasClass() instead.
- */
-
-window.hasClass = ( function() {
- var reCache = {};
- return function (element, className) {
- return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp(\"(?:\\\\s|^)\" + className + \"(?:\\\\s|\$)\"))).test(element.className);
- };
-})();
-
-
-/** Interwiki links to featured articles ***************************************
- *
- * Description: Highlights interwiki links to featured articles (or
- * equivalents) by changing the bullet before the interwiki link
- * into a star.
- * Maintainers: [[User:R. Koot]]
- */
-
-function LinkFA() {
- if ( document.getElementById( \"p-lang\" ) ) {
- var InterwikiLinks = document.getElementById( \"p-lang\" ).getElementsByTagName( \"li\" );
-
- for ( var i = 0; i < InterwikiLinks.length; i++ ) {
- if ( document.getElementById( InterwikiLinks[i].className + \"-fa\" ) ) {
- InterwikiLinks[i].className += \" FA\";
- InterwikiLinks[i].title = \"This is a featured article in another language.\";
- } else if ( document.getElementById( InterwikiLinks[i].className + \"-ga\" ) ) {
- InterwikiLinks[i].className += \" GA\";
- InterwikiLinks[i].title = \"This is a good article in another language.\";
- }
- }
- }
-}
-
-\$( LinkFA );
-
-
-/** Collapsible tables *********************************************************
- *
- * Description: Allows tables to be collapsed, showing only the header. See
- * [[Wikipedia:NavFrame]].
- * Maintainers: [[User:R. Koot]]
- */
-
-var autoCollapse = 2;
-var collapseCaption = \"bınımne\";
-var expandCaption = \"bıvin\";
-
-window.collapseTable = function( tableIndex ){
- var Button = document.getElementById( \"collapseButton\" + tableIndex );
- var Table = document.getElementById( \"collapsibleTable\" + tableIndex );
-
- if ( !Table || !Button ) {
- return false;
- }
-
- var Rows = Table.rows;
-
- if ( Button.firstChild.data == collapseCaption ) {
- for ( var i = 1; i < Rows.length; i++ ) {
- Rows[i].style.display = \"none\";
- }
- Button.firstChild.data = expandCaption;
- } else {
- for ( var i = 1; i < Rows.length; i++ ) {
- Rows[i].style.display = Rows[0].style.display;
- }
- Button.firstChild.data = collapseCaption;
- }
-}
-
-function createCollapseButtons(){
- var tableIndex = 0;
- var NavigationBoxes = new Object();
- var Tables = document.getElementsByTagName( \"table\" );
-
- for ( var i = 0; i < Tables.length; i++ ) {
- if ( hasClass( Tables[i], \"collapsible\" ) ) {
-
- /* only add button and increment count if there is a header row to work with */
- var HeaderRow = Tables[i].getElementsByTagName( \"tr\" )[0];
- if (!HeaderRow) continue;
- var Header = HeaderRow.getElementsByTagName( \"th\" )[0];
- if (!Header) continue;
-
- NavigationBoxes[ tableIndex ] = Tables[i];
- Tables[i].setAttribute( \"id\", \"collapsibleTable\" + tableIndex );
-
- var Button = document.createElement( \"span\" );
- var ButtonLink = document.createElement( \"a\" );
- var ButtonText = document.createTextNode( collapseCaption );
-
- Button.className = \"collapseButton\"; //Styles are declared in Common.css
-
- ButtonLink.style.color = Header.style.color;
- ButtonLink.setAttribute( \"id\", \"collapseButton\" + tableIndex );
- ButtonLink.setAttribute( \"href\", \"#\" );
- addHandler( ButtonLink, \"click\", new Function( \"evt\", \"collapseTable(\" + tableIndex + \" ); return killEvt( evt );\") );
- ButtonLink.appendChild( ButtonText );
-
- Button.appendChild( document.createTextNode( \"[\" ) );
- Button.appendChild( ButtonLink );
- Button.appendChild( document.createTextNode( \"]\" ) );
-
- Header.insertBefore( Button, Header.firstChild );
- tableIndex++;
- }
- }
-
- for ( var i = 0; i < tableIndex; i++ ) {
- if ( hasClass( NavigationBoxes[i], \"collapsed\" ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[i], \"autocollapse\" ) ) ) {
- collapseTable( i );
- }
- else if ( hasClass( NavigationBoxes[i], \"innercollapse\" ) ) {
- var element = NavigationBoxes[i];
- while (element = element.parentNode) {
- if ( hasClass( element, \"outercollapse\" ) ) {
- collapseTable ( i );
- break;
- }
- }
- }
- }
-}
-
-\$( createCollapseButtons );
-
-
-/** Dynamic Navigation Bars (experimental) *************************************
- *
- * Description: See [[Wikipedia:NavFrame]].
- * Maintainers: UNMAINTAINED
- */
-
-// set up the words in your language
-var NavigationBarHide = '[' + collapseCaption + ']';
-var NavigationBarShow = '[' + expandCaption + ']';
-
-// shows and hides content and picture (if available) of navigation bars
-// Parameters:
-// indexNavigationBar: the index of navigation bar to be toggled
-window.toggleNavigationBar = function(indexNavigationBar){
- var NavToggle = document.getElementById(\"NavToggle\" + indexNavigationBar);
- var NavFrame = document.getElementById(\"NavFrame\" + indexNavigationBar);
-
- if (!NavFrame || !NavToggle) {
- return false;
- }
-
- // if shown now
- if (NavToggle.firstChild.data == NavigationBarHide) {
- for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
- if (hasClass(NavChild, 'NavContent') || hasClass(NavChild, 'NavPic')) {
- NavChild.style.display = 'none';
- }
- }
- NavToggle.firstChild.data = NavigationBarShow;
-
- // if hidden now
- } else if (NavToggle.firstChild.data == NavigationBarShow) {
- for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
- if (hasClass(NavChild, 'NavContent') || hasClass(NavChild, 'NavPic')) {
- NavChild.style.display = 'block';
- }
- }
- NavToggle.firstChild.data = NavigationBarHide;
- }
-}
-
-// adds show/hide-button to navigation bars
-function createNavigationBarToggleButton(){
- var indexNavigationBar = 0;
- // iterate over all < div >-elements
- var divs = document.getElementsByTagName(\"div\");
- for (var i = 0; NavFrame = divs[i]; i++) {
- // if found a navigation bar
- if (hasClass(NavFrame, \"NavFrame\")) {
-
- indexNavigationBar++;
- var NavToggle = document.createElement(\"a\");
- NavToggle.className = 'NavToggle';
- NavToggle.setAttribute('id', 'NavToggle' + indexNavigationBar);
- NavToggle.setAttribute('href', 'javascript:toggleNavigationBar(' + indexNavigationBar + ');');
-
- var isCollapsed = hasClass( NavFrame, \"collapsed\" );
- /*
- * Check if any children are already hidden. This loop is here for backwards compatibility:
- * the old way of making NavFrames start out collapsed was to manually add style=\"display:none\"
- * to all the NavPic/NavContent elements. Since this was bad for accessibility (no way to make
- * the content visible without JavaScript support), the new recommended way is to add the class
- * \"collapsed\" to the NavFrame itself, just like with collapsible tables.
- */
- for (var NavChild = NavFrame.firstChild; NavChild != null && !isCollapsed; NavChild = NavChild.nextSibling) {
- if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) {
- if ( NavChild.style.display == 'none' ) {
- isCollapsed = true;
- }
- }
- }
- if (isCollapsed) {
- for (var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
- if ( hasClass( NavChild, 'NavPic' ) || hasClass( NavChild, 'NavContent' ) ) {
- NavChild.style.display = 'none';
- }
- }
- }
- var NavToggleText = document.createTextNode(isCollapsed ? NavigationBarShow : NavigationBarHide);
- NavToggle.appendChild(NavToggleText);
-
- // Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
- for(var j=0; j < NavFrame.childNodes.length; j++) {
- if (hasClass(NavFrame.childNodes[j], \"NavHead\")) {
- NavToggle.style.color = NavFrame.childNodes[j].style.color;
- NavFrame.childNodes[j].appendChild(NavToggle);
- }
- }
- NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar);
- }
- }
-}
-
-\$( createNavigationBarToggleButton );
-
-
-/** Main Page layout fixes *********************************************************
- *
- * Description: Adds an additional link to the complete list of languages available.
- * Maintainers: [[User:AzaToth]], [[User:R. Koot]], [[User:Alex Smotrov]]
- */
-
-if (wgPageName == 'Main_Page' || wgPageName == 'Talk:Main_Page') {
- \$(function () {
- mw.util.addPortletLink('p-lang', '//meta.wikimedia.org/wiki/List_of_Wikipedias',
- 'Complete list', 'interwiki-completelist', 'Complete list of Wikipedias');
- });
-}
-
-
-/** Table sorting fixes ************************************************
- *
- * Description: Disables code in table sorting routine to set classes on even/odd rows
- * Maintainers: [[User:Random832]]
- */
-ts_alternate_row_colors = false;
-
-
-/***** uploadwizard_newusers ********
- * Switches in a message for non-autoconfirmed users at [[Wikipedia:Upload]]
- *
- * Maintainers: [[User:Krimpet]]
- */
-function uploadwizard_newusers() {
- if (wgNamespaceNumber == 4 && wgTitle == \"Upload\" && wgAction == \"view\") {
- var oldDiv = document.getElementById(\"autoconfirmedusers\"),
- newDiv = document.getElementById(\"newusers\");
- if (oldDiv && newDiv) {
- if (typeof wgUserGroups == \"object\" && wgUserGroups) {
- for (i = 0; i < wgUserGroups.length; i++) {
- if (wgUserGroups[i] == \"autoconfirmed\") {
- oldDiv.style.display = \"block\";
- newDiv.style.display = \"none\";
- return;
- }
- }
- }
- oldDiv.style.display = \"none\";
- newDiv.style.display = \"block\";
- return;
- }
- }
-}
-\$(uploadwizard_newusers);
-
-
-/** IPv6 AAAA connectivity testing
-
-var __ipv6wwwtest_factor = 100;
-var __ipv6wwwtest_done = 0;
-if ((wgServer != \"https://secure.wikimedia.org\") && (Math.floor(Math.random()*__ipv6wwwtest_factor)==42)) {
- importScript(\"MediaWiki:Common.js/IPv6.js\");
-}
-**/
-
-/** Magic editintros ****************************************************
- *
- * Description: Adds editintros on disambiguation pages and BLP pages.
- * Maintainers: [[User:RockMFR]]
- */
-
-function addEditIntro( name ) {
- \$( '.editsection, #ca-edit' ).find( 'a' ).each( function( i, el ) {
- el.href = \$(this).attr(\"href\") + '&editintro=' + name;
- });
-}
-
-if (wgNamespaceNumber === 0) {
- \$(function(){
- if (document.getElementById('disambigbox')) {
- addEditIntro('Template:Disambig_editintro');
- }
- });
-
- \$(function(){
- var cats = document.getElementById('mw-normal-catlinks');
- if (!cats) {
- return;
- }
- cats = cats.getElementsByTagName('a');
- for (var i = 0; i < cats.length; i++) {
- if (cats[i].title == 'Category:Living people' || cats[i].title == 'Category:Possibly living people') {
- addEditIntro('Template:BLP_editintro');
- break;
- }
- }
- });
-}
-
-/**
- * Description: Stay on the secure server as much as possible
- * Maintainers: [[User:TheDJ]]
- */
-if ( mw.config.get('wgServer') == 'https://secure.wikimedia.org' ) {
- /* Old secure server */
- importScript( 'MediaWiki:Common.js/secure.js');
-} else if( document.location && document.location.protocol && document.location.protocol == \"https:\" ) {
- /* New secure servers */
- importScript('MediaWiki:Common.js/secure new.js');
-}
-
-/**
- * Description: Fix the toggle for Mobile view
- * https://bugzilla.wikimedia.org/show_bug.cgi?id=38009
- * Maintainer: [[User:TheDJ]]
- */
-mw.loader.using( 'jquery.cookie', function() {
- \$('a[href\$=\"toggle_view_mobile\"]').click(function(){
- document.cookie = 'stopMobileRedirect=false; domain=.wikipedia.org;'
- + 'path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT;'
- });
-});
-
-/* End of mw.loader.using callback */
-} );
-/* DO NOT ADD CODE BELOW THIS LINE */",
+'common.js' => '/* Any JavaScript here will be loaded for all users on every page load. */',
# Metadata
'notacceptable' => "formatê ma'lumati no peşkeşwanê wikiyi nêweniyeno.",
'minutes' => 'verdê {{PLURAL:$1|$1 daka|$1 daka}}',
'hours' => 'Verdê {{PLURAL:$1|$1 seata|$1 seata}}',
'days' => 'Verdê {{PLURAL:$1|$1 rocan|$1 rocan}}',
+'months' => '{{PLURAL:$1|aşmi|$1 aşman}}',
+'years' => '{{PLURAL:$1|$1 ser|$1 seran}}',
'ago' => 'Verdê $1',
'just-now' => 'Hema newke',
$messages = array(
# User preference toggles
'tog-hideminor' => 'ކުދި އުނި އިތުރުތައް އެންމެފަހުގެ ބަދަލުތަކުގެ ލިސްޓުން ފޮރުއްވަވާ',
+'tog-watchlisthideown' => 'މަގޭ ނަޒަރުން މަގޭ ހިއްސާ ފޮރުއްވާ',
+'tog-watchlisthidebots' => 'މަގޭ ނަޒަރުން ބޮޓުންގެ ހިއްސާ ފޮރުއްވާ',
+'tog-watchlisthideminor' => 'މަގޭ ނަޒަރުން ކުދި އުނިއިތުރުތައް ފޮރުއްވާ',
+'tog-watchlisthideliu' => 'މަގޭ ނަޒަރުން ވަދެފައިވާ މެމްބަރުންގެ އުނިއުތުރުތައް ފޮރުއްވާ',
'tog-ccmeonemails' => 'އަޅުގަނޑު އެހެން މެމްބަރުންނަށް ފޮނުވާ އީމެއިލްގެ ނަކަލެއް އަޅުގަނޑަށް ފޮނުވާ',
'tog-showhiddencats' => 'ފޮރުވިފައިވާ ޤިސްމުތައް ދައްކަވާ',
'youhavenewmessages' => 'ތިޔަބޭފުޅާއަށް $1 ($2)',
'newmessageslink' => 'އައު މެސެޖުތައް',
'newmessagesdifflink' => 'އެންމެ ފަހުގެ ބަދަލު',
+'youhavenewmessagesfromusers' => 'ތިބޭފުޅާއަށް {{PLURAL:$3|މެމްބަރެއް|$3 މެމްބަރުން}} $1 ފޮނުއްވާފައިވެއެވެ. ($2)',
+'youhavenewmessagesmanyusers' => 'ތިބޭފުޅާއަށް ގިނަ މެމްބަރުން $1 ފޮނުއްވާފައިވެއެވެ. ($2)',
+'newmessageslinkplural' => '{{PLURAL:$1|އާ މެސެޖެއް|މެސެޖުތައް}}',
+'newmessagesdifflinkplural' => 'ފަހު {{PLURAL:$1|ބަދަލު|ބަދަލުތައް}}',
'editsection' => 'އުނިއިތުރު ގެންނަވާ',
'editold' => 'އުނިއިތުރު ގެންނަވާ',
'viewsourceold' => 'މަސްދަރު ބައްލަވާ',
'accmailtitle' => 'ސިއްރުބަސް ފޮނުވިއްޖެ.',
'accmailtext' => '"$1" އަށްޓަކައިވާ ސިއްރު ބަސް $2 އަށް ވަނީ ފޮނުވިފައި',
'newarticle' => '(އައު)',
-'noarticletext' => 'މި ޞަފްޙާގައި އެއްވެސް ލިޔުމެއް ނުވެއެވެ. ތިޔަބޭފުޅާއަށް މި ނަން [[Special:Search/{{PAGENAME}}|އެހެން ޞަފްޙާތަކުން ހޯއްދެވިދާނެއެވެ]]. ނުވަތަ <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} މިއާ ގުޅޭ ލޮގްތައް ހޯއްދެވިދާނެއެވެ].
-[{{fullurl:{{FULLPAGENAME}}|action=edit}} ނުވަތަ މި ޞަފްޙާއަށް އުނިއިތުރު ގެނެވިދާނެއެވެ].</span>.',
+'newarticletext' => "<div style=\"border:1px solid black;\">
+<big>'''ވިކިޕީޑިއާގައި އަދި މިހާތަނަށް ތިނަމުންވާ މަޒުމޫނެއް އެކުލެވިފައިނުވެއެވެ.'''</big>
+* ތިޔަ ވަޑައިގެންނެވި ޞަފްޙާގައި އެއްވެސް ލިޔުމެއް އެކުލެވިފައި ނުވެއެވެ.
+*މި ޞަފްޙާއަށް ތިބޭފުޅާއަށް ވަޑައިގަނެވުނީ އޮޅުމަކުން ކަމަށް ވާނަމަ ކޮމްޕިޔުޓަރުގެ `ވެބް ބްރޯޒަރ` ގެ ''ފަހަތް'' ފިތައް އޮބާލައްވާށެވެ. އޭރުން އެންމެ ފަހުން ހުންނެވި ޞަފްޙާ އަށް ވަޑައިގަނެވޭނެއެވެ.
+* މަޒްމޫނެއް ފެއްޓެވުމަށް ތިރީގައި ވާ ފޮށީގައި ލިޔުއްވުމަށް ފަހު މަޒުމޫނުގެ ނަމޫނާ ބެއްލެވުމަށް ފަހު ކުށެއްވާނަމަ ރަނގަޅު ކުރައްވާފައި ފޮށީގެ ތިރީގައިވާ '''ޞަފްޙާ ރައްކާކުރައްވާ'''އަށް ފިއްތަވާ ލައްވަވާ.
+* އިތުރު އެހީ ބޭނުންފުޅު ނަމަ [[{{MediaWiki:Helppage}}|އެހީ ޞަފްހާއަށް]] ވަޑައިގަންނަވާށެވެ.
+</div>",
+'noarticletext' => 'މި ޞަފްޙާގައި އެއްވެސް ލިޔުމެއް ނުވެއެވެ. ތިޔަބޭފުޅާއަށް މި ނަން [[Special:Search/{{PAGENAME}}|އެހެން ޞަފްޙާއަކުން ހޯއްދެވިދާނެއެވެ]]. ނުވަތަ <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} މިއާ ގުޅޭ ލޮގްތައް ހޯއްދެވިދާނެއެވެ].
+[{{fullurl:{{FULLPAGENAME}}|action=edit}} ނުވަތަ މި ޞަފްޙާއަށް އުނިއިތުރު ގެނެވިދާނެއެވެ].</span>',
'previewnote' => "'''މިއީ ހަމައެކަނި ނަމޫނާ އެކެވެ.'''
އަދި ތިބޭފުޅާގެ ބަދަލުތައް ރައްކާނުކުރެވެއެވެ!",
'editing' => '$1 އަށް އުނިއިތުރު ގެންނަނީ',
ފޮހެލުމުގެ އަދި ނަން ބަދަލުކުރުމުގެ ލޮގް ތިރީގައިވަނީއެވެ.',
# History pages
+'viewpagelogs' => 'މިޞަފްޙާގެ ލޮގުތައް ބައްލަވާ',
'currentrev' => 'އެންމެފަހުން ގެނެވުނު ބަދަލު',
'currentrev-asof' => 'އެންމެ ފަހުން ގެނެވުނު ބަދަލު $1',
'revisionasof' => '$1ގެ ނުސްހާ',
'blanknamespace' => '(މައި)',
# Contributions
-'contributions' => 'މެންބަރު ގެ ހިއްސާ',
+'contributions' => '{{GENDER:$1|މެމްބަރުގެ}} ހިއްސާ',
'mycontris' => 'މަގޭ ހިއްސާ',
'sp-contributions-talk' => 'ވާހަކަ',
'tooltip-ca-nstab-category' => 'ޤިސްމު ޞަފްޙާ ބައްލަވާ',
'tooltip-save' => 'ބަދަލުތައް ރައްކާކުރައްވާ',
'tooltip-preview' => 'ބަދަލުތައް ދައްކަވާ، ރައްކާކުރެއްވުމުގެ ކުރިން މި ބޭނުންކުރައްވާ!',
+'tooltip-watch' => 'މިޞަފްޙާއަށް ނަޒަރުބަހައްޓަވާ',
'tooltip-rollback' => '"ކުރީގެ ނުސްހާ އަކަށް ބަދަލުކުރައްވާ" އިން މި ޞަފްޙާއަށް އެންމެ ފަހުން އުނިއިތުރު ގެންނެވި މެމްބަރުގެ އުނިއިތުރު(އުނިއިތުރުތައް) ފޮހެލެވޭނެއެވެ.',
'tooltip-summary' => 'ކުރު ޚުލާސާއެއް ލިޔުއްވާ',
'raw' => array( 0, 'RAW:' ),
'displaytitle' => array( 1, 'DISPLAYTITLE' ),
'rawsuffix' => array( 1, 'R' ),
+ 'nocommafysuffix' => array( 0, 'NOSEP' ),
'newsectionlink' => array( 1, '__NEWSECTIONLINK__' ),
'nonewsectionlink' => array( 1, '__NONEWSECTIONLINK__' ),
'currentversion' => array( 1, 'CURRENTVERSION' ),
'Myuploads' => array( 'MyUploads' ),
'Newimages' => array( 'NewFiles', 'NewImages' ),
'Newpages' => array( 'NewPages' ),
+ 'PagesWithProp' => array( 'PagesWithProp', 'Pageswithprop', 'PagesByProp', 'Pagesbyprop' ),
'PasswordReset' => array( 'PasswordReset' ),
'PermanentLink' => array( 'PermanentLink', 'PermaLink' ),
'Popularpages' => array( 'PopularPages' ),
They may have to link to a more appropriate page instead.<br />
A page is treated as a disambiguation page if it uses a template that is linked from [[MediaWiki:Disambiguationspage]].",
+'pageswithprop' => 'Pages with a page property',
+'pageswithprop-summary' => '', # do not translate or duplicate this message to other languages
+'pageswithprop-legend' => 'Pages with a page property',
+'pageswithprop-text' => 'This page lists pages that use a particular page property.',
+'pageswithprop-prop' => 'Property name:',
+'pageswithprop-submit' => 'Go',
+
'doubleredirects' => 'Double redirects',
'doubleredirects-summary' => '', # do not translate or duplicate this message to other languages
'doubleredirectstext' => 'This page lists pages that redirect to other redirect pages.
'emailuser' => 'Enviar un correo electrónico a {{GENDER:{{BASEPAGENAME}}|este usuario|esta usuaria}}',
'emailuser-title-target' => 'Enviar un correo electrónico a {{GENDER:$1|este usuario|esta usuaria}}',
'emailuser-title-notarget' => 'Enviar un correo electrónico al usuario',
-'emailpage' => 'Correo electrónico a usuario',
+'emailpage' => 'Enviar un correo electrónico a un usuario',
'emailpagetext' => 'Puedes usar el formulario de abajo para enviar un correo electrónico a {{GENDER:$1|este usuario|esta usuaria}}.
La dirección de correo electrónico que indicaste en [[Special:Preferences|tus preferencias de usuario]] aparecerá en el campo "Remitente" o "De" para que el destinatario pueda responderte.',
'usermailererror' => 'El sistema de correo devolvió un error:',
'proxyblocksuccess' => 'Hecho.',
'sorbsreason' => 'Su dirección IP está listada como proxy abierto en DNSBL.',
'sorbs_create_account_reason' => 'Su dirección IP está listada como proxy abierto en DNSBL. No puede crear una cuenta',
-'cant-block-while-blocked' => 'No puedes bloquear a otros usuarios mientras estás bloqueado.',
+'cant-block-while-blocked' => 'No puedes bloquear a otros usuarios mientras estás bloquead{{GENDER:|o|a}}.',
'cant-see-hidden-user' => 'El usuario que está intentando bloquear ya ha sido bloqueado y oculto. Puesto que usted no tiene el derecho hideuser, usted no puede ver o editar los bloqueos del usuario.',
'ipbblocked' => 'No puedes bloquear o desbloquear a otros usuarios porque estás bloqueado',
'ipbnounblockself' => 'No puedes desbloquearte',
'moredotdotdot' => 'Veel...',
'mypage' => 'Minu lehekülg',
'mytalk' => 'Arutelu',
-'anontalk' => 'Arutelu selle IP jaoks',
+'anontalk' => 'Selle IP-aadressi artuelu',
'navigation' => 'Navigeerimine',
'and' => ' ja',
Pane tähele, et seni kuni sa pole oma võrgulehitseja puhvrit tühjendanud, võidakse mõni lehekülg endiselt nii kuvada nagu oleksid ikka sisse logitud.",
'welcomeuser' => 'Tere tulemast, $1!',
'welcomecreation-msg' => 'Sinu konto on loodud.
-Ära unusta seada oma {{GRAMMAR:genitive|{{SITENAME}}}} [[Eri:Eelistused|eelistusi]].',
+Ära unusta seada oma {{GRAMMAR:genitive|{{SITENAME}}}} [[Special:Preferences|eelistusi]].',
'yourname' => 'Kasutajanimi:',
'yourpassword' => 'Parool:',
'yourpasswordagain' => 'Sisesta parool uuesti:',
'gotaccount' => "Kui sul on juba konto, '''$1'''.",
'gotaccountlink' => 'logi sisse',
'userlogin-resetlink' => 'Kas oled unustanud oma sisselogimisandmed?',
-'createaccountmail' => 'E-posti teel',
+'createaccountmail' => 'Kasuta juhuslikku parooli ja saada see allpool määratud e-posti aadressile',
'createaccountreason' => 'Põhjus:',
'badretype' => 'Sisestatud paroolid ei lange kokku.',
'userexists' => 'Sisestatud kasutajanimi on juba kasutusel.
'nosuchusershort' => 'Kasutajat nimega "$1" ei ole olemas. Kontrollige kirjapilti.',
'nouserspecified' => 'Kasutajanimi puudub.',
'login-userblocked' => 'See kasutaja on blokeeritud. Sisselogimine pole lubatud.',
-'wrongpassword' => 'Vale parool. Proovige uuesti.',
+'wrongpassword' => 'Vale parool. Proovi uuesti.',
'wrongpasswordempty' => 'Parool jäi sisestamata. Palun proovi uuesti.',
'passwordtooshort' => 'Parool peab koosnema vähemalt {{PLURAL:$1|ühest|$1}} tähemärgist.',
'password-name-match' => 'Parool peab kasutajanimest erinema.',
'ignorewarning' => 'Ignoreeri hoiatust ja salvesta fail hoiatusest hoolimata',
'ignorewarnings' => 'Ignoreeri hoiatusi',
'minlength1' => 'Faili nimes peab olema vähemalt üks kirjamärk.',
-'illegalfilename' => 'Faili "$1" nimi sisaldab sümboleid, mis pole pealkirjades lubatud. Palun nimetage fail ümber ja proovige uuesti.',
+'illegalfilename' => 'Failinimi "$1" sisaldab märke, mis pole pealkirjades lubatud. Palun nimeta fail ümber ja proovi uuesti.',
'filename-toolong' => 'Failinimed ei või olla pikemad kui 240 baiti.',
'badfilename' => 'Pildi nimi on muudetud. Uus nimi on "$1".',
'filetype-mime-mismatch' => 'Faililaiend ".$1" ei vasta faili ($2) MIME tüübile.',
'linksearch-ok' => 'Otsi',
'linksearch-text' => 'Metamärgina võib kasutada tärni, näiteks "*.wikipedia.org".
Otsingus peab olema vähemalt tipptaseme domeen, näiteks "*.org".<br />
-Toetatud protokollid: <code>$1</code> (määramata protokolli korral vaikimisi http://).',
+Toetatud {{PLURAL:$2|protokoll|protokollid}}: <code>$1</code> (määramata protokolli korral vaikimisi http://).',
'linksearch-line' => '$1 on lingitud leheküljelt $2',
'linksearch-error' => 'Metamärk võib olla ainult internetiaadressi alguses.',
# Special:ActiveUsers
'activeusers' => 'Aktiivsete kasutajate nimekiri',
'activeusers-intro' => 'See on loetelu kasutajatest, kes on viimase $1 {{PLURAL:$1|päev|päeva}} jooksul midagi teinud.',
-'activeusers-count' => '$1 {{PLURAL:$1|muudatus|muudatust}} viimase {{PLURAL:$3|päeva|$3 päeva}} jooksul',
+'activeusers-count' => '$1 {{PLURAL:$1|toiming|toimingut}} viimase {{PLURAL:$3|päeva|$3 päeva}} jooksul',
'activeusers-from' => 'Näita kasutajaid alates:',
'activeusers-hidebots' => 'Peida robotid',
'activeusers-hidesysops' => 'Peida administraatorid',
'protect-cascadeon' => 'See lehekülg on kaitstud, kuna ta on kasutusel {{PLURAL:$1|järgmisel leheküljel|järgmistel lehekülgedel}}, mis on omakorda kaskaadkaitse all.
Sa saad muuta selle lehekülje kaitse staatust, kuid see ei mõjuta kaskaadkaitset.',
'protect-default' => 'Luba kõigile kasutajatele',
-'protect-fallback' => 'Nõuab "$1" õiguseid',
-'protect-level-autoconfirmed' => 'Blokeeri uued ja registreerimata kasutajad',
-'protect-level-sysop' => 'Ainult administraatorid',
+'protect-fallback' => 'Lubatud vaid kasutajatele õigusega "$1"',
+'protect-level-autoconfirmed' => 'Lubatud vaid automaatselt kinnitatud kasutajatele',
+'protect-level-sysop' => 'Lubatud vaid administraatoritele',
'protect-summary-cascade' => 'kaskaad',
'protect-expiring' => 'aegub $1 (UTC)',
'protect-expiring-local' => 'aegub $1',
Kui sa seda ei tee, kontrolli, et teisaldamise tõttu ei jää maha [[Special:DoubleRedirects|kahekordseid]] ega [[Special:BrokenRedirects|katkiseid ümbersuunamisi]].
Sinu kohus on hoolitseda selle eest, et kõik jääks toimima, nagu ette nähtud.
-Pane tähele, et lehekülge '''ei teisaldata''' juhul, kui uue pealkirjaga lehekülg on juba olemas. Erandiks on juhud, kui olemasolev lehekülg on tühi või redigeerimisajaloota ümbersuunamislehekülg.
+Pane tähele, et lehekülge '''ei teisaldata''' juhul, kui uue pealkirjaga lehekülg on juba olemas. Erandiks on juhud, kui viimane on redigeerimisajaloota ümbersuunamislehekülg.
See tähendab, et kogemata ei saa üle kirjutada juba olemasolevat lehekülge, kuid saab ebaõnnestunud ümbernimetamise tagasi pöörata.
'''Hoiatus!'''
'pageinfo-robot-noindex' => 'Indekseerimatu',
'pageinfo-views' => 'Vaatamiste arv',
'pageinfo-watchers' => 'Lehekülje jälgijate arv',
+'pageinfo-few-watchers' => 'Alla {{PLURAL:$1|ühe jälgija|$1 jälgija}}',
'pageinfo-redirects-name' => 'Ümbersuunamisi sellele leheküljele',
'pageinfo-subpages-name' => 'Selle lehekülje alamlehekülgi',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|ümbersuunamine|ümbersuunamist}}; $3 {{PLURAL:$3|mitteümbersuunamine|mitteümbersuunamist}})',
'pageinfo-protect-cascading' => 'Siit lähtub kaskaadkaitse',
'pageinfo-protect-cascading-yes' => 'Jah',
'pageinfo-protect-cascading-from' => 'Kaskaadkaitse lähtub lehekülgedelt',
+'pageinfo-category-info' => 'Kategooria teave',
+'pageinfo-category-pages' => 'Lehekülgede arv',
+'pageinfo-category-subcats' => 'Alamkategooriate arv',
+'pageinfo-category-files' => 'Failide arv',
# Skin names
'skinname-standard' => 'Algeline',
'specialpages-group-highuse' => 'Tihti kasutatud leheküljed',
'specialpages-group-pages' => 'Lehekülgede loendid',
'specialpages-group-pagetools' => 'Töö lehekülgedega',
-'specialpages-group-wiki' => 'Viki andmed ja tööriistad',
+'specialpages-group-wiki' => 'Andmed ja tööriistad',
'specialpages-group-redirects' => 'Ümbersuunavad erilehed',
'specialpages-group-spam' => 'Töö spämmiga',
'hidden-category-category' => 'Kategoria ezkutuak',
'category-subcat-count' => '{{PLURAL:$2|Kategoria honek beste honako azpikategoria baino ez du.|Kategoria honek honako {{PLURAL:$1|azpikategoria du|$1 azpikategoriak ditu}}, guztira dauden $2tik.}}',
'category-subcat-count-limited' => 'Kategoria honek {{PLURAL:$1|azpikategoria hau du|$1 azpikategoria hauek ditu}}.',
-'category-article-count' => '{{PLURAL:$2|Kategoria honek ondorengo orri hau baino ez du.|Ondorengo {{PLURAL:$1|orria kategoria honetan dago|$1 orriak kategoria honetan daude}}; eta kategoria honetan, guztira, $2 orri daude.}}',
+'category-article-count' => '{{PLURAL:$2|Kategoria honek honako orrialdea baino ez du.|Honako {{PLURAL:$1|orrialdea kategoria honetan dago|$1 orrialdeak kategoria hauetan daude}}, guztira dauden $2 (e)tik.}}',
'category-article-count-limited' => 'Ondorengo {{PLURAL:$1|orri hau kategoria honetan dago.|$1 orri hauek kategoria honetan daude.}}',
-'category-file-count' => '{{PLURAL:$2|Kategoria honek fitxategi hau baino ez du.|Ondorengo {{PLURAL:$1|fitxategia kategoria honetan dago|$1 fitxategiak kategoria honetan daude}}. Eta kategoria honetan, guztira, $2 fitxategi daude.}}',
+'category-file-count' => '{{PLURAL:$2|Kategoria honek fitxategi hau baino ez du.|Honako {{PLURAL:$1|fitxategia kategoria honetan dago|$1 fitxategiak kategoria honetan daude}} guztira dauden $2 (e)tik.}}',
'category-file-count-limited' => 'Ondorengo {{PLURAL:$1|fitxategia kategoria honetan dago.|$1 fitxategiak kategoria honetan daude.}}',
'listingcontinuesabbrev' => 'jarr.',
'index-category' => 'Indexatutako orrialdeak',
'newwindow' => '(leiho berrian irekitzen da)',
'cancel' => 'Utzi',
'moredotdotdot' => 'Gehiago...',
+'morenotlisted' => 'Zerrendatu gabeko gehiago...',
'mypage' => 'Orrialdea',
'mytalk' => 'Eztabaida',
'anontalk' => 'IP honen eztabaida',
'youhavenewmessages' => '$1 dauzkazu ($2).',
'newmessageslink' => 'Mezu berriak',
'newmessagesdifflink' => 'azken aldaketa ikusi',
+'youhavenewmessagesfromusers' => '{{PLURAL:$3|Beste erabiltzaile baten|$3 erabiltzaileren}} $1 ($2).',
+'youhavenewmessagesmanyusers' => 'Hainbat erabiltzaileren $1 ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|Mezu berri bat duzu|Mezu berriak dituzu}}',
'newmessagesdifflinkplural' => 'azken {{PLURAL:$1|aldaketa|aldaketak}}',
'youhavenewmessagesmulti' => 'Mezu berriak dituzu $1(e)n',
'editsection' => 'aldatu',
'cannotdelete' => 'Ezin izan da «$1» orria edo fitxategia ezabatu.
Baliteke beste norbaitek ezabatu izana.',
'cannotdelete-title' => 'Ezin da "$1" orrialdea ezabatu',
+'delete-hook-aborted' => 'Ezabatzea hook batek gelditu du.
+Ez du arrazoirik eman.',
'badtitle' => 'Izenburu ezegokia',
'badtitletext' => 'Eskatutako orrialde izenburua ez da baliozkoa, hutsik dago, edo gaizki lotutako hizkuntzen arteko lotura da. Baliteke izenburuetan erabili ezin den karaktereren bat izatea.',
'perfcached' => 'Hurrengo datuak katxean gordeta daude eta litekeena da guztiz eguneratuta ez egotea. Gehienez {{PLURAL:$1|emaitza 1 dago|$1 emaitza daude}} eskuragarri katxean.',
'cascadeprotected' => "Orrialde hau aldaketen aurka babestua dago, ''kaskada'' aukerarekin babestu {{PLURAL:$1|duten orrialde honetan|dituzten orrialde hauetan}} txertaturik dagoelako:
$2",
'namespaceprotected' => "Ez daukazu '''$1''' izen-tarteko orrialdeak aldatzeko baimenik.",
+'customcssprotected' => 'Ez duzu baimenik CSS orrialde hau aldatzeko beste erabiltzaile baten hobespen pertsonalak dituelako.',
+'customjsprotected' => 'Ez duzu baimenik JavaScript orrialde hau aldatzeko beste erabiltzaile baten hobespen pertsonalak dituelako.',
'ns-specialprotected' => 'Ezin dira {{ns:special}} izen-tarteko orrialdeak editatu.',
'titleprotected' => "[[User:$1|$1]]ek izenburu hau sortzea ekidin zuen.
Emandako arrazoia ''$2'' izan zen.",
+'filereadonlyerror' => 'Ezin izan da "$1" fitxategia aldatu, "$2" fitxategi bilduma irakrutzeko-bakarrik moduan dagoelako.
+
+Blokeoa ezarri zuen administratzaileak honako arrazoia eman zuen: "$3".',
+'invalidtitle-knownnamespace' => 'Izenburua gaizki dago "$2" izen eremuan eta "$3" testuan',
+'invalidtitle-unknownnamespace' => 'Izenburua gaizki dago "$1" izen eremuan ezezagunean eta "$2" testuan',
'exception-nologin' => 'Saioa hasi gabe',
# Virus scanner
'gotaccount' => "Baduzu erabiltzaile kontua? '''$1'''.",
'gotaccountlink' => 'Saioa hasi',
'userlogin-resetlink' => 'Saioa hasteko datuak ahaztu dituzu?',
-'createaccountmail' => 'e-postaz',
+'createaccountmail' => 'Erabili behin-behineko pasahitz ausazko bat eta bidali behean agertzeko den e-posta helbidera',
'createaccountreason' => 'Arrazoia:',
'badretype' => 'Idatzitako pasahitzak ez dira berdinak.',
'userexists' => 'Aukeratutako erabiltzaile izena hartuta dago.
'prefs-emailconfirm-label' => 'E-posta baieztapena:',
'prefs-textboxsize' => 'Editatze lehioaren tamaina',
'youremail' => 'E-posta:',
-'username' => 'Erabiltzaile izena:',
-'uid' => 'Erabiltzaile zenbakia:',
-'prefs-memberingroups' => '{{PLURAL:$1|Taldeko|taldeetako}} kidea:',
+'username' => '{{GENDER:$1|Erabiltzaile izena}}:',
+'uid' => '{{GENDER:$1|Erabiltzaile}} zenbakia:',
+'prefs-memberingroups' => '{{PLURAL:$1|Taldeko|taldeetako}} {{GENDER:$2|kidea}}:',
'prefs-registration' => 'Erregistratzeko unea:',
'yourrealname' => 'Benetako izena:',
'yourlanguage' => 'Hizkuntza:',
'blanknamespace' => '(Nagusia)',
# Contributions
-'contributions' => 'Lankidearen ekarpenak',
+'contributions' => '{{GENDER:$1|Lankidearen}} ekarpenak',
'contributions-title' => '$1(r)entzat lankidearen ekarpenak',
'mycontris' => 'Ekarpenak',
'contribsub2' => '$1 ($2)',
# What links here
'whatlinkshere' => 'Honanzko lotura duten orriak',
'whatlinkshere-title' => '$1(e)ra lotura duten orriak',
-'whatlinkshere-page' => 'Orrialdea:',
+'whatlinkshere-page' => 'Orria:',
'linkshere' => "Hauek dute '''[[:$1]]''' orrialderako lotura:",
'nolinkshere' => "Ez dago '''[[:$1]]''' lotura duen orrialderik.",
'nolinkshere-ns' => "Hautatutako izen-tartean ez dago '''[[:$1]]''' orrialderako lotura duenik.",
'seconds-abbrev' => '$1s',
'minutes-abbrev' => '$1m',
'hours-abbrev' => '$1o',
+'seconds' => '{{PLURAL:$1|segundu $1|$1 segundu}}',
+'minutes' => '{{PLURAL:$1|minutu $1|$1 minutu}}',
+'hours' => '{{PLURAL:$1|ordu $1|$1 ordu}}',
+'days' => '{{PLURAL:$1|egun $1|$1 egun}}',
'ago' => 'Duela $1',
# Bad image list
'exif-gpsdifferential' => 'GPSaren zuzenketa diferentziala',
'exif-jpegfilecomment' => 'JPEG fitxategiaren iruzkina',
'exif-keywords' => 'Hitz gakoak',
+'exif-worldregioncreated' => 'Munduko zein eskualdetan egin den argazki hau',
+'exif-countrycreated' => 'Argazkia egin den herrialdea',
+'exif-countrycodecreated' => 'Argazkia egin deneko herrialdearen kodea',
+'exif-provinceorstatecreated' => 'Argazkia egin deneko probintzia edo estatua',
+'exif-citycreated' => 'Argazkia egin deneko hiria',
+'exif-sublocationcreated' => 'Argazkia egin deneko hiriaren azpieremua',
+'exif-worldregiondest' => 'Munduko eskualdea erakusten da',
'exif-countrydest' => 'Erakutsitako herrialdea',
+'exif-countrycodedest' => 'Herrialdearen kodea erakusten da',
+'exif-provinceorstatedest' => 'Pronbitzia edo estatua erakusten da',
+'exif-citydest' => 'Hiria erakusten da',
+'exif-sublocationdest' => 'Hiriaren azpikokapena erakusten da',
'exif-objectname' => 'Izenburua laburra',
+'exif-specialinstructions' => 'Agindu bereziak',
'exif-headline' => 'Goiburua',
+'exif-credit' => 'Kreditua/Emalea',
'exif-source' => 'Jatorria',
'exif-urgency' => 'Larrialdia',
'exif-writer' => 'Idazlea',
'logentry-move-move-noredirect' => '$1 wikilariak «$3» orria «$4» izenera aldatu du, birzuzenketarik utzi gabe',
'logentry-move-move_redir' => '$1 wikilariak «$3» orria «$4» izenera aldatu du, birzuzenketaren gainetik',
'logentry-move-move_redir-noredirect' => '$1 wikilariak «$3» orria «$4» izenera aldatu du, birzuzenketa bat gainidatzita, birzuzenketarik utzi gabe',
-'logentry-newusers-newusers' => '$1 wikilariak erabiltzaile kontu bat sortu du',
-'logentry-newusers-create' => '$1 wikilariak erabiltzaile kontu bat sortu du',
-'logentry-newusers-create2' => '$1 wikilariak $3 erabiltzaile kontu bat sortu du',
+'logentry-newusers-newusers' => '$1 erabiltzaile kontua sortu da',
+'logentry-newusers-create' => '$1 erabiltzaile kontua sortu da',
+'logentry-newusers-create2' => '$1 wikilariak $3 erabiltzaile kontua sortu du',
'rightsnone' => '(bat ere ez)',
# Feedback
'gotaccount' => 'حساب کاربری دارید؟ $1.',
'gotaccountlink' => 'به سامانه وارد شوید',
'userlogin-resetlink' => 'جزئیات ورود را فراموش کردهاید؟',
-'createaccountmail' => 'با راÛ\8cاÙ\86اÙ\85Ù\87',
+'createaccountmail' => 'استÙ\81ادÙ\87 از رÙ\85ز عبÙ\88ر Ù\85Ù\88Ù\82ت تصادÙ\81Û\8c Ù\88 ارساÙ\84 Ø¢Ù\86 بÙ\87 آدرس اÛ\8cÙ\85Û\8cÙ\84 Ù\85شخص شدÙ\87 در زÛ\8cر',
'createaccountreason' => 'دلیل:',
'badretype' => 'گذرواژههایی که وارد کردهاید یکسان نیستند.',
'userexists' => 'نام کاربریای که وارد کردید قبلاً استفاده شدهاست.
'search-interwiki-default' => '$1 نتیجه:',
'search-interwiki-more' => '(بیشتر)',
'search-relatedarticle' => 'مرتبط',
-'mwsuggest-disable' => 'پیشنهادهای مبتنی بر AJAX را غیرفعال کن',
+'mwsuggest-disable' => 'پیشنهادهای مبتنی بر جستجو را غیرفعال کن',
'searcheverything-enable' => 'جستجو در تمام فضاهای نام',
'searchrelated' => 'مرتبط',
'searchall' => 'همه',
# Special:ActiveUsers
'activeusers' => 'فهرست کاربران فعال',
'activeusers-intro' => 'در زیر فهرستی از کاربرانی را میبینید که در $1 {{PLURAL:$1|روز|روز}} گذشته فعالیتی داشتهاند.',
-'activeusers-count' => '$1 {{PLURAL:$1|Ù\88Û\8cراÛ\8cØ´|Ù\88Û\8cراÛ\8cØ´}} در {{PLURAL:$3|روز|$3 روز}} اخیر',
+'activeusers-count' => '$1 {{PLURAL:$1|Ù\81عاÙ\84Û\8cت|Ù\81عاÙ\84Û\8cت}} در {{PLURAL:$3|روز|$3 روز}} اخیر',
'activeusers-from' => 'نمایش کاربران با آغاز از:',
'activeusers-hidebots' => 'نهفتن رباتها',
'activeusers-hidesysops' => 'نهفتن مدیران',
'usermessage-editor' => 'پیغام رسان سامانه',
# Watchlist
-'watchlist' => 'فهرست پیگیریهای من',
+'watchlist' => 'فهرست پیگیری',
'mywatchlist' => 'فهرست پیگیریها',
'watchlistfor2' => 'برای $1 $2',
'nowatchlist' => 'در فهرست پیگیریهای شما هیچ موردی نیست.',
'''شما''' مسئول اطمینان از این هستید که پیوندها هنوز به همانجایی که قرار است بروند.
توجه کنید که اگر از قبل صفحهای در عنوان جدید وجود داشته باشد صفحه منتقل '''نخواهد شد'''،
-مگر این که صفحه خالی یا تغییرمسیر باشد و تاریخچهٔ ویرایشی نداشته باشد.
+مگر این آخرین ویرایش تغییرمسیر باشد و در تاریخچهٔ ویرایشی نداشته باشد.
این یعنی اگر اشتباه کردید میتوانید صفحه را به همان جایی که از آن منتقل شده بود برگردانید، و این که نمیتوانید روی صفحهها موجود بنویسید.
'''هشدار!'''
'pageinfo-robot-noindex' => 'عدم فهرستپذیری',
'pageinfo-views' => 'شمار بازدیدها',
'pageinfo-watchers' => 'شمار پیگیریکنندگان صفحه',
+'pageinfo-few-watchers' => 'کمتر از $1 {{PLURAL:$1| پیگیر|پیگیر}}',
'pageinfo-redirects-name' => 'تغییرمسیرها به این صفحه',
'pageinfo-subpages-name' => 'زیرصفحههای این صفحه',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|تغییرمسیر|تغییرمسیر}}; $3 {{PLURAL:$3|غیرتغییرمسیر|غیرتغییرمسیر}})',
'specialpages-group-highuse' => 'صفحههای پربازدید',
'specialpages-group-pages' => 'فهرستهای صفحهها',
'specialpages-group-pagetools' => 'ابزارهای صفحهها',
-'specialpages-group-wiki' => 'اطÙ\84اعات Ù\88 ابزارÙ\87اÛ\8c Ù\88Û\8cÚ©Û\8c',
+'specialpages-group-wiki' => 'دادÙ\87 Ù\88 ابزارÙ\87ا',
'specialpages-group-redirects' => 'صفحههای ویژهٔ تغییرمسیر دهنده',
'specialpages-group-spam' => 'ابزارهای هرزنگاری',
'logentry-newusers-newusers' => 'حساب کاربری $1 ایجاد شد',
'logentry-newusers-create' => 'حساب کاربری $1 ایجاد شد',
'logentry-newusers-create2' => 'حساب کاربری $3 توسط $1 ایجاد شد',
+'logentry-newusers-byemail' => 'حساب کاربری $3 توسط $1 ایجاد شد و رمز عبور به وسیلهٔ ایمیل ارسال شد',
'logentry-newusers-autocreate' => 'حساب $1 به شکل خودکار ساخته شد',
'logentry-rights-rights' => '$1 عضویت $3 را از گروه $4 به $5 تغییر داد',
'logentry-rights-rights-legacy' => '$1 گروه عضویت $3 را تغییر داد',
'api-error-ok-but-empty' => 'خطای داخلی : پاسخی از سرور دریافت نشد.',
'api-error-overwrite' => 'جای نوشتن یک پرونده موجود مجاز نیست.',
'api-error-stashfailed' => 'خطای داخلی: کارساز نمیتواند پرونده موقت را ذخیره کند.',
+'api-error-publishfailed' => 'خطای داخلی: کارساز نمیتواند پرونده موقت را ذخیره کند.',
'api-error-timeout' => 'کارساز در زمان انتظار هیچ پاسخی نداد.',
'api-error-unclassified' => 'یک خطای ناشناخته رخ داد.',
'api-error-unknown-code' => 'خطای ناشناخته: " $1 "',
'revdelete-radio-set' => 'Kyllä',
'revdelete-radio-unset' => 'Ei',
'revdelete-suppress' => 'Häivytä tiedot myös ylläpitäjien näkyviltä samalla kun piilotat ne muilta käyttäjiltä',
-'revdelete-unsuppress' => 'Poista rajoitukset palautetuilta versiolta',
+'revdelete-unsuppress' => 'Poista rajoitukset palautetuilta versioilta',
'revdelete-log' => 'Syy',
'revdelete-submit' => 'Toteuta {{PLURAL:$1|valittuun versioon|valittuihin versioihin}}',
'revdelete-success' => "'''Version näkyvyys päivitetty.'''",
'revdelete-failure' => "'''Version näkyvyyttä ei voitu päivittää:'''
$1",
-'logdelete-success' => 'Tapahtuman näkyvyys asetettu.',
+'logdelete-success' => "'''Lokitapahtuman näkyvyyttä on muutettu.'''",
'logdelete-failure' => "'''Lokin näkyvyyttä ei voitu asettaa:'''
$1",
'revdel-restore' => 'muuta näkyvyyttä',
-'revdel-restore-deleted' => 'poistetut muutokset',
-'revdel-restore-visible' => 'näkyvät muutokset',
+'revdel-restore-deleted' => 'poistetut versiot',
+'revdel-restore-visible' => 'näkyvät versiot',
'pagehist' => 'Sivun muutoshistoria',
'deletedhist' => 'Poistettujen versioiden historia',
'revdelete-hide-current' => 'Virhe tapahtui $2, $1 päivätyn kohteen piilottamisessa: tämä on nykyinen versio. Sitä ei voi piilottaa.',
Sinulla ei ole oikeutta siihen.',
'revdelete-modify-no-access' => 'Virhe tapahtui $2, $1 kohteen muokkauksessa: tämä kohde on merkitty "rajoitetuksi". Sinulla ei ole oikeuksia sen muokkaukseen.',
'revdelete-modify-missing' => 'Virhe muuttaessa kohdetta, jonka tunnus on $1: Se puuttuu tietokannasta.',
-'revdelete-no-change' => "'''Varoitus:''' kohdalle $2 kello $1 on asetettu valmiiksi näkyvyysasetuksia.",
+'revdelete-no-change' => "'''Varoitus:''' kohteessa $2 kello $1 on jo valmiiksi haluamasi näkyvyysasetukset.",
'revdelete-concurrent-change' => 'Virhe $2, $1 päivätyn kohteen muokkauksessa: sen tilan on näköjään muuttanut joku sillä aikaa kun yritit muokata sitä. Ole hyvä ja tarkista lokit.',
'revdelete-only-restricted' => 'Virhe piilotettaessa $1 kello $2 päivättyä kohdetta: Et voi poistaa kohteita ylläpitäjien näkyviltä valitsematta myös jotain muuta näkyvyysasetusta.',
'revdelete-reason-dropdown' => '*Yleiset poistosyyt
'watcherrortext' => 'Sivun ”$1” tarkkailulista-asetusten muutoksissa tapahtui virhe.',
'enotif_mailer' => '{{GRAMMAR:genitive|{{SITENAME}}}} sivu on muuttunut -ilmoitus',
-'enotif_reset' => 'Merkitse kaikki sivut kerralla nähdyiksi',
+'enotif_reset' => 'Merkitse kaikki sivut nähdyiksi',
'enotif_impersonal_salutation' => '{{GRAMMAR:genitive|{{SITENAME}}}} käyttäjä',
'enotif_subject_deleted' => '{{GENDER:$2|$2}} poisti {{GRAMMAR:elative|{{SITENAME}}}} sivun $1',
'enotif_subject_created' => '{{GENDER:$2|$2}} loi {{GRAMMAR:illative|{{SITENAME}}}} sivun $1',
'helppage' => 'Help:Axuda',
'mainpage' => 'Portada',
'mainpage-description' => 'Portada',
-'policy-url' => 'Project:Política e normas',
+'policy-url' => 'Project:Políticas e normas',
'portal' => 'Portal da comunidade',
'portal-url' => 'Project:Portal da comunidade',
'privacy' => 'Política de protección de datos',
* @author Dineshjk
* @author Hemant wikikosh1
* @author Htt
+ * @author InfinityO O
* @author Kaganer
* @author Kamal
* @author Kannankumar
'youhavenewmessagesfromusers' => 'आपके लिये {{PLURAL:$3|एक अन्य सदस्य का सन्देश है|$3 अन्य सदस्यों के सन्देश हैं}}। ($2)',
'youhavenewmessagesmanyusers' => 'आपके लिये $1 हैं। ($2)',
'newmessageslinkplural' => '{{PLURAL:$1|एक नया सन्देश|नये सन्देश}}',
-'newmessagesdifflinkplural' => 'à¤\85à¤\82तिम {{PLURAL:$1|परिवर्तन}}',
+'newmessagesdifflinkplural' => 'पिà¤\9bलà¥\87 {{PLURAL:$1|परिवर्तन}}',
'youhavenewmessagesmulti' => '$1 पर आपके लिए नया संदेश है',
'editsection' => 'सम्पादन',
'editold' => 'सम्पादन',
* @author J budissin
* @author Kaganer
* @author Michawiki
+ * @author Shirayuki
* @author Tchoř
* @author Tlustulimu
* @author לערי ריינהארט
'newmessagesdifflink' => 'poslednja změna',
'youhavenewmessagesfromusers' => 'Maš $1 wot {{PLURAL:$3|druheho wužiwarja|$3 wužiwarjow|$3 wužiwarjow|$3 wužiwarjow}} ($2).',
'youhavenewmessagesmanyusers' => 'Maš $1 wot wjele wužiwarjow ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|nowa powěsć|nowej powěsći|nowe powěsće|nowe powěsće}}',
+'newmessageslinkplural' => '{{PLURAL:$1|nowu powěsć|nowej powěsći|nowe powěsće}}',
'newmessagesdifflinkplural' => '{{PLURAL:$1|poslednja změna|poslednjej změnje|poslednje změny|poslednje změny}}',
'youhavenewmessagesmulti' => 'Maš nowe powěsće: $1',
'editsection' => 'wobdźěłać',
Tute wobkrućenski kod spadnje $4.',
'confirmemail_body_set' => 'Něchtó, najskerje ty, wot IP-adresy $1,
-je e-mejlowu adresu konta "$2" na {{GRAMMAR:lokatiw|{{STENAME}}}} na tutu adresu stajił.
+je e-mejlowu adresu konta "$2" na {{GRAMMAR:lokatiw|{{SITENAME}}}} na tutu adresu stajił.
-Zo by wobkrućił, zo tute konto ći woprawdźe słuša a zo bychu so e-mejlowe funkcije na {{GRAMMAR:lokatiw|{{STENAME}}}} znowa aktiwizowali, wočiń tutón wotkaz w swojim wobhladowaku:
+Zo by wobkrućił, zo tute konto ći woprawdźe słuša a zo bychu so e-mejlowe funkcije na {{GRAMMAR:lokatiw|{{SITENAME}}}} znowa aktiwizowali, wočiń tutón wotkaz w swojim wobhladowaku:
$3
'newwindow' => '(új ablakban nyílik meg)',
'cancel' => 'Mégse',
'moredotdotdot' => 'Tovább…',
+'morenotlisted' => 'Tovább…',
'mypage' => 'Lapom',
'mytalk' => 'Vitalap',
'anontalk' => 'Az IP-címhez tartozó vitalap',
'gotaccount' => "Ha már korábban regisztráltál, '''$1'''!",
'gotaccountlink' => 'Bejelentkezés',
'userlogin-resetlink' => 'Elfelejtetted a bejelentkezési adataidat?',
-'createaccountmail' => 'e-mailben',
+'createaccountmail' => 'Átmeneti, véletlenszerű jelszó használata és kiküldése az alábbi e-mail címre',
'createaccountreason' => 'Indoklás:',
'badretype' => 'A megadott jelszavak nem egyeznek.',
'userexists' => 'A megadott felhasználónév már foglalt.
# E-mail sending
'php-mail-error-unknown' => 'Ismeretlen hiba a PHP mail() függvényében',
'user-mail-no-addy' => 'E-mail üzenetet próbáltál küldeni e-mail cím megadása nélkül.',
+'user-mail-no-body' => 'Üres vagy nagyon rövid email-t próbáltál küldeni.',
# Change password dialog
'resetpass' => 'Jelszó módosítása',
'''NE KÜLDJ BE JOGVÉDETT MUNKÁT ENGEDÉLY NÉLKÜL!'''",
'longpageerror' => "'''HIBA: Az általad beküldött szöveg {{PLURAL:$1|egy kilobájt|$1 kilobájt}} hosszú, ami több az engedélyezett {{PLURAL:$2|egy kilobájtnál|$2 kilobájtnál}}.
A szerkesztést nem lehet elmenteni.'''",
-'readonlywarning' => "'''FIGYELMEZTETÉS: A wiki adatbázisát karbantartás miatt zárolták, ezért most nem fogod tudni elmenteni a szerkesztéseidet.
-A lap szöveget kimásolhatod egy szövegfájlba, amit elmenthetsz későbbre.'''
+'readonlywarning' => "FIGYELMEZTETÉS: A wiki adatbázisát karbantartás miatt zárolták, ezért most nem fogod tudni elmenteni a szerkesztéseidet!
+A lap szövegét másold egy szövegfájlba, amit később felhasználhatsz!'''
Az adatbázist lezáró adminisztrátor az alábbi magyarázatot adta: $1",
'protectedpagewarning' => "'''Figyelem: Ez a lap le van védve, így csak adminisztrátori jogosultságokkal rendelkező szerkesztők módosíthatják.'''
# Special:ActiveUsers
'activeusers' => 'Aktív szerkesztők listája',
'activeusers-intro' => 'Ez a lap azon felhasználók listáját tartalmazza, akik csináltak valamilyen tevékenységet az elmúlt {{PLURAL:$1|egy|$1}} napban.',
-'activeusers-count' => '{{PLURAL:$1|egy|$1}} szerkesztés az utolsó {{PLURAL:$3|egy|$3}} napban',
+'activeusers-count' => '$1 szerkesztés az utolsó $3 napban',
'activeusers-from' => 'Szerkesztők listázása a következő névtől kezdve:',
'activeusers-hidebots' => 'Botok elrejtése',
'activeusers-hidesysops' => 'Adminisztrátorok elrejtése',
Neked kell biztosítanod, hogy a linkek továbbra is oda mutassanak, ahová mutatniuk kell.
A lap '''nem''' nevezhető át, ha már van egy ugyanilyen című lap, hacsak nem üres vagy átirányítás, és nincs laptörténete.
-Ez azt jelenti, hogy vissza tudsz nevezni egy tévedésből átnevezett lapot, és nem tudsz egy már létező lapot véletlenül felülírni.
+Ez azt jelenti, hogy vissza tudsz nevezni egy tévedésből átnevezett lapot, és nem tudsz létező lapot véletlenül felülírni.
'''FIGYELEM!'''
Népszerű oldalak esetén ez drasztikus és nem várt változtatás lehet;
-győződj meg a folytatás előtt arról, hogy tisztában vagy-e a következményekkel.",
+győződj meg a folytatás előtt arról, hogy tisztában vagy a következményekkel.",
'movepagetext-noredirectfixer' => "Az alábbi űrlap használatával nevezhetsz át egy lapot, és helyezheted át teljes laptörténetét az új nevére.
A régi cím az új címre való átirányítás lesz.
Ellenőrizd a [[Special:DoubleRedirects|dupla]] és a [[Special:BrokenRedirects|hibás átirányításoknál]], hogy a linkek továbbra is oda mutatnak, ahová mutatniuk kell.
'pageinfo-robot-noindex' => 'Nem indexelhető',
'pageinfo-views' => 'Megtekintések száma',
'pageinfo-watchers' => 'Figyelők száma',
+'pageinfo-few-watchers' => 'Kevesebb mint $1 szerkesztő figyeli',
'pageinfo-redirects-name' => 'Átirányítások erre a lapra',
'pageinfo-subpages-name' => 'Az lap allapjai',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|átirányítás}}; $3 {{PLURAL:$3|nem átirányítás}})',
'pageinfo-contentpage' => 'Tartalmi lapnak számít',
'pageinfo-contentpage-yes' => 'Igen',
'pageinfo-protect-cascading-yes' => 'Igen',
+'pageinfo-category-info' => 'Kategória információk',
'pageinfo-category-pages' => 'Lapok száma',
'pageinfo-category-subcats' => 'Alkategóriák száma',
'pageinfo-category-files' => 'Fájlok száma',
'logentry-newusers-newusers' => '$1 felhasználói fiók létrehozva',
'logentry-newusers-create' => '$1 felhasználói fiók létrehozva',
'logentry-newusers-create2' => '$1 létrehozta $3 felhasználói fiókját',
+'logentry-newusers-byemail' => 'Szerkesztői lap $3 néven létrehozva $1 által, jelszó kiküldve emailben.',
'logentry-newusers-autocreate' => '$1 fiók automatikusan létrehozva',
'logentry-rights-rights' => '$1 megváltoztatta $3 csoport tagságát erről: $4 erre: $5',
'logentry-rights-rights-legacy' => '$1 megváltoztatta $3 csoport tagságát',
'api-error-ok-but-empty' => 'Belső hiba: nem érkezett válasz a kiszolgálótól.',
'api-error-overwrite' => 'Létező fájlok felülírására nem engedélyezett.',
'api-error-stashfailed' => 'Belső hiba: a kiszolgálünak nem sikerült eltárolni az ideiglenes fájlt.',
+'api-error-publishfailed' => 'Belső hiba: a kiszolgálónak nem sikerült közzétennie az ideiglenes fájlt.',
'api-error-timeout' => 'A kiszolgáló nem adott választ a várt időn belül.',
'api-error-unclassified' => 'Ismeretlen hiba történt',
'api-error-unknown-code' => 'Ismeretlen hiba: „$1”',
'categorypage' => 'Դիտել կատեգորիայի էջը',
'viewtalkpage' => 'Դիտել քննարկումը',
'otherlanguages' => 'Այլ լեզուներով',
-'redirectedfrom' => '(Վերահղված է $1-ից)',
+'redirectedfrom' => '(Վերահղված է $1ից)',
'redirectpagesub' => 'Վերահղման էջ',
'lastmodifiedat' => 'Այս էջը վերջին անգամ փոփոխվել է $2, $1։',
'viewcount' => 'Այս էջին դիմել են {{PLURAL:$1|մեկ անգամ|$1 անգամ}}։',
'youhavenewmessagesmulti' => 'Դուք նոր ուղերձներ եք ստացել $1 վրա',
'editsection' => 'խմբագրել',
'editold' => 'խմբագրել',
-'viewsourceold' => 'Õ¤Õ«Õ¿Õ¥Õ¬ Õ¥Õ¬Õ¡Õ¿Õ¥Ö\84Õ½Õ¿ը',
+'viewsourceold' => 'Õ¤Õ«Õ¿Õ¥Õ¬ Õ¾Õ«Ö\84Õ«Õ¯Õ¸Õ¤Õ¥Ö\80ը',
'editlink' => 'խմբագրել',
'viewsourcelink' => 'դիտել ելատեքստը',
'editsectionhint' => 'Խմբագրել բաժինը. $1',
'missingarticle-diff' => '(Տարբ. $1, $2)',
'readonly_lag' => 'Տվյալների բազան ավտոմատիկ կողպվել է ժամանակավորապես՝ մինչև ՏԲ-ի երկրորդական սերվերը չհամաժամանակեցվի առաջնայինի հետ։',
'internalerror' => 'Ներքին սխալ',
-'internalerror_info' => 'Ներքին սխալ. $1',
+'internalerror_info' => 'Ներքին սխալ՝ $1',
'fileappenderror' => 'Չհաջողվեց ավելացնել «$1» «$2»-ին։',
'filecopyerror' => 'Չհաջողվեց պատճենել «$1» նիշքը «$2» նիշքի մեջ։',
'filerenameerror' => 'Չհաջողվեց «$1» նիշքը վերանվանել «$2»։',
'perfcachedts' => 'Հետևյալ տվյալները վերցված են քեշից և վերջին անգամ թարմացվել են $1։ A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.',
'querypage-no-updates' => 'Այս էջի փոփոխությունները ներկայումս արգելված են։ Այստեղի տվյալները այժմ չեն թարմացվի։',
'wrong_wfQuery_params' => 'Անթույլատրելի պարամետրեր wfQuery() ֆունկցիայի համար<br />
-Ֆունկցիա. $1<br />
-Հայցում. $2',
-'viewsource' => 'Ô´Õ«Õ¿Õ¥Õ¬ Õ¥Õ¬Õ¡Õ¿Õ¥Ö\84Õ½Õ¿ը',
+Ֆունկցիա՝ $1<br />
+Հայցում՝ $2',
+'viewsource' => 'Ô´Õ«Õ¿Õ¥Õ¬ Õ¾Õ«Ö\84Õ«Õ¯Õ¸Õ¤Õ¥Ö\80ը',
'viewsource-title' => 'Դիտել $1 էջի աղբյուրը',
'actionthrottled' => 'Գործողությունը արգելափակվեց',
'actionthrottledtext' => 'Որպես հակա-սպամային միջոց, այս գործողության չափից շատ կատարումը կարճ ժամանակահատվածի ընթացքում սահմանափակված է։ Խնդրում ենք փորձել կրկին մի քանի րոպե անց։',
'viewsourcetext' => 'Դուք կարող եք դիտել և պատճենել այս էջի ելատեքստը.',
'viewyourtext' => 'Դուք կարող եք դիտել «ձեր ներդրումների» աղբյուրը և պատճենել այս էջ',
'protectedinterface' => 'Այս էջը պարունակում է ծրագրային ապահովման ինտերֆեյսի ուզերձ և կողպված է չարաշահումների կանխարգելման նպատակով։.',
-'editinginterface' => "'''Զգուշացում.''' Դուք խմբագրում եք ծրագրային ապահովման ինտերֆեյսի տեքստ պարունակող էջ։ Այս էջի փոփոխությունը կանդրադառնա այլ մասնակիցներին տեսանելի ինտերֆեյսի տեսքի վրա։
-Թարգմանությունների համար նախընտրելի է օգտագործել [//translatewiki.net/wiki/Main_Page?setlang=hy translatewiki.net]՝ MediaWiki ծրագրի տեղայնացման նախագիծը։",
+'editinginterface' => "'''Զգուշացում՝''' Դուք խմբագրում եք ծրագրային ապահովման ինտերֆեյսի տեքստ պարունակող էջ։ Այս էջի փոփոխությունը կանդրադառնա այլ մասնակիցներին տեսանելի ինտերֆեյսի տեսքի վրա։
+Թարգմանությունների համար նախընտրելի է օգտագործել [//translatewiki.net/wiki/Main_Page?setlang=hy translatewiki.net]՝ Մեդիավիքի ծրագրի տեղայնացման նախագիծը։",
'sqlhidden' => '(SQL հայցումը թաքցված է)',
'cascadeprotected' => 'Այս էջը պաշտպանված է խմբագրումից, քանի որ ընդգրկված է հետևյալ {{PLURAL:$1|էջի|էջերի}} տեքստում, {{PLURAL:$1|որը|որոնք}} պաշտպանվել {{PLURAL:$1|է|են}} կասկադային հնարավորությամբ.
$2',
# Virus scanner
'virus-badscanner' => "Սխալ կարգավորւմ։ Անծանոթ վիրուսների զննիչ. ''$1''",
'virus-scanfailed' => 'զննման սխալ (կոդ $1)',
-'virus-unknownscanner' => 'անծանոթ հակավիրուս.',
+'virus-unknownscanner' => 'անծանոթ հակավիրուս՝',
# Login and logout pages
'logouttext' => "'''Դուք դուրս եկաք համակարգից։'''
'welcomeuser' => 'Բարի գալո՜ւստ, $1',
'welcomecreation-msg' => 'Ձեր հաշիվն ստեղծված է։
Չմոռանաք փոփոխել ձեր [[Special:Preferences|նախընտրությունները]]։',
-'yourname' => 'Մասնակցի անուն.',
+'yourname' => 'Մասնակցի անուն՝',
'yourpassword' => 'Գաղտնաբառ.',
-'yourpasswordagain' => 'Կրկնեք գաղտնաբառը.',
+'yourpasswordagain' => 'Կրկնեք գաղտնաբառը',
'remembermypassword' => 'Հիշել իմ մուտքագրված տվյալները այս համակարգչում ($1 {{PLURAL:$1|օրից|օրից}} ոչ ավել ժամկետով)',
-'yourdomainname' => 'Ձեր դոմենը.',
+'yourdomainname' => 'Ձեր դոմենը՝',
'password-change-forbidden' => 'Այս վիքիում չեք կարող փոխել գաղտնաբառ։',
'externaldberror' => 'Տեղի է ունեցել վավերացման արտաքին տվյալների բազայի սխալ, կամ դուք չունեք բավարար իրավունքներ ձեր արտաքին հաշվի փոփոխման համար։',
'login' => 'Մտնել համակարգ',
'gotaccountlink' => 'Մուտք գործեք համակարգ',
'userlogin-resetlink' => 'Մոռացե՞լ եք Ձեր լոգին տվյալները։',
'createaccountmail' => 'էլ-փոստով',
-'createaccountreason' => 'Պատճառ.',
+'createaccountreason' => 'Պատճառը՝',
'badretype' => 'Ձեր մուտքագրած գաղտնաբառերը չեն համընկնում։',
'userexists' => 'Այս մասնակցի անունը արդեն զբաղված է։ Խնդրում ենք ընտրել մեկ այլ անուն։',
'loginerror' => 'Մուտքի սխալ',
'eauthentsent' => 'Նոր էլ-հասցեին ուղարկվել է վավերացման նամակ։
Հետևե՛ք նամակի ցուցումներին՝ հաստատելու համար, որ այդ հասցեն ձեզ է պատկանում։ Մինչ այդ նոր հասցեին այլ նամակներ չեն կարող ուղարկվել։',
'throttled-mailpassword' => 'Գաղտնաբառի հիշեցման ուղերձ արդեն ուղարկվել է վերջին {{PLURAL:$1|ժամվա|$1 ժամվա}} ընթացքում։ Չարաշահման կանխարգելման նպատակով թույլատրվում է միայն մեկ գաղտնաբառի հիշեցում ամեն {{PLURAL:$1|ժամվա|$1 ժամվա}} ընթացքում։',
-'mailerror' => 'Փոստի ուղարկման սխալ. $1',
+'mailerror' => 'Փոստի ուղարկման սխալ՝ $1',
'acct_creation_throttle_hit' => 'Վերջին օրվա ընթացքում ձեր IP-հասցեից ստեղծվել է {{PLURAL:$1|1 մասնակցի հաշվիվ|$1 մասնակցի հաշվիվ}}, ինչը այս ժամանակաշրջանում առավելագույն թույլատրելի քանակն է։
Այս պատճառով այդ IP-հասցեից այցելուները չեն կարող այլևս հաշիվ ստեղծել այս պահին։',
'emailauthenticated' => 'Ձեր էլ-փոստի հասցեն վավերացվել է $2, $3-ին։',
'usernamehasherror' => 'Մասնակցի անունը չի կարող պարունակել «#» նիշը։',
'login-throttled' => 'Դուք կատարել եք չափից շատ մուտքի փորձ։
Խնդրում ենք սպասել որոշ ժամանակ կրկին փորձելուց առաջ։',
-'loginlanguagelabel' => 'Լեզու $1',
+'loginlanguagelabel' => 'Լեզու՝ $1',
# E-mail sending
'php-mail-error-unknown' => 'Անհայտ սխալ PHP-ի mail() ֆունկցիայում',
'passwordreset-text' => 'Լրացրեք ձևը՝ էլ-փոստով ձեր տվյալների մասին հիշեցում ստանալու համար։',
'passwordreset-legend' => 'Վերականգնել գաղտնաբառը',
'passwordreset-disabled' => 'Գաղտնաբառի վերականգնումը այս վիքիում թույլատրված չէ։',
-'passwordreset-username' => 'Մասնակցի անուն.',
+'passwordreset-username' => 'Մասնակցի անուն՝',
'passwordreset-email' => 'Էլ-փոստի հասցեն՝',
-'passwordreset-emailelement' => 'Մասնակցային անուն. $1
-Ժամանակավոր գաղտնաբառ. $2',
+'passwordreset-emailelement' => 'Մասնակցային անունը՝ $1
+Ժամանակավոր գաղտնաբառը՝ $2',
'passwordreset-emailsent' => 'Ուղարկվեց հիշեցնող էլ․ նամակ։',
'passwordreset-emailsent-capture' => 'Ուղարկվեց հիշեցնող էլ․ նամակ։ Այն ներկայացված է ստորև։',
'passwordreset-emailerror-capture' => 'Ուղարկվեց հիշեցնող էլ․ նամակ։ Այն ներկայացված է ստորև։ Սակայն մասնակցին ուղարկելը չհաջողվեց․',
'changeemail-oldemail' => 'Ներկա էլ․ հասցե․',
'changeemail-newemail' => 'Նոր էլ․ հասցե․',
'changeemail-none' => '(ոչ մի)',
+'changeemail-password' => 'Քո {{SITENAME}} գաղտնաբառը՝',
'changeemail-submit' => 'Փոխել էլ․ հասցեն',
'changeemail-cancel' => 'Չեղարկել',
'''Եթե սա բարեխիղճ խմբագրման փորձ է, խնդրում ենք փորձել կրկին։ Սխալի կրկնման դեպքում՝ փորձեք [[Special:UserLogout|դուրս գալ]], ապա կրկին մտնել համակարգ։'''",
'token_suffix_mismatch' => "'''Ձեր խմբագրումը մերժվել է, քանի որ ձեր օգտագործած ծրագիրը աղավաղել է կետադրության նշանները խմբագրման դաշտում։ Խմբագրումը մերժվել է էջի տեքստի խաթարումը կանխելու նպատակով։ Սա երբեմն պայմանավորված է սխալներ պարունակող անանվանեցնող վեբ-փոխարինորդ (proxy) ծառայության օգտագործմամբ։'''",
-'editing' => 'Ô½Õ´Õ¢Õ¡Õ£Ö\80Õ¸Ö\82Õ´ $1',
-'creating' => 'Õ\8dÕ¿Õ¥Õ²Õ®Õ¸Ö\82Õ´ $1',
-'editingsection' => 'Ô½Õ´Õ¢Õ¡Õ£Ö\80Õ¸Ö\82Õ´Õ\9d $1 (Õ¢Õ¡ÕªÕ«Õ¶)',
-'editingcomment' => 'Ô½Õ´Õ¢Õ¡Õ£Ö\80Õ¸Ö\82Õ´Õ\9d $1 (Õ¶Õ¸Ö\80 Õ¢Õ¡ÕªÕ«Õ¶)',
+'editing' => 'Ô½Õ´Õ¢Õ¡Õ£Ö\80Õ¾Õ¸Ö\82Õ´ Õ§Õ\9d $1 Õ§Õ»Õ¨',
+'creating' => 'Õ\8dÕ¿Õ¥Õ²Õ®Õ¾Õ¸Ö\82Õ´ Õ§Õ\9d $1 Õ§Õ»Õ¨',
+'editingsection' => 'Ô½Õ´Õ¢Õ¡Õ£Ö\80Õ¾Õ¸Ö\82Õ´ Õ§Õ\9d $1 Õ§Õ»Õ« (Õ¢Õ¡ÕªÕ«Õ¶Õ¨)',
+'editingcomment' => 'Ô½Õ´Õ¢Õ¡Õ£Ö\80Õ¾Õ¸Ö\82Õ´ Õ§Õ\9d $1 Õ§Õ»Õ« (Õ¶Õ¸Ö\80 Õ¢Õ¡ÕªÕ«Õ¶Õ¨)',
'editconflict' => 'Խմբագրման ընդհարում. $1',
'explainconflict' => "Մեկ այլ մասնակից փոփոխել է այս տեքստը ձեր խմբագրման ընթացքում։
Վերին խմբագրման դաշտում ընդգրկված է ընթացիկ տեքստը, որն ենթակա է հիշման։
'templatesused' => 'Այս էջում օգտագործված {{PLURAL:$1|կաղապարը|կաղապարները}}.',
'templatesusedpreview' => 'Այս նախադիտման մեջ օգտագործված {{PLURAL:$1|կաղապարը|կաղապարները}}.',
'templatesusedsection' => 'Այս բաժնում օգտագործված {{PLURAL:$1|կաղապարը|կաղապարները}}.',
-'template-protected' => '(պաշտպանված)',
-'template-semiprotected' => '(կիսապաշտպանված)',
+'template-protected' => '(պաշտպանված է)',
+'template-semiprotected' => '(կիսա-պաշտպանված է)',
'hiddencategories' => 'Այս էջը պատկանում է հետևյալ {{PLURAL:$1|1 թաքնված կատեգորիային|$1 թաքնված կատեգորիաներին}}.',
'edittools' => '<!-- Այստեղ տեղադրված տեքստը կցուցադրվի խմբագրման և բեռնման ձևերի տակ։ -->
<div id="Հատուկ նիշ:" class="toccolours specialchars" style="margin-top:.5em; padding: .3em .5em; font-size: 100%; color:#aaa; text-align:left;" title="{{int:bw-edittools-tooltip}}">
'edit-no-change' => 'Ձեր խմբագրումը անտեսվել է, քանի որ ոչ մի փոփոխություն չի կատարվել տեքստի մեջ։',
'defaultmessagetext' => 'Լռելյան տեքստը',
+# Content models
+'content-model-wikitext' => 'վիքիտեքստ',
+
# "Undo" feature
'undo-success' => 'Խմբագրումը կարող է հետ շրջվել։ Ստուգեք տարբերակների համեմատությունը ստորև, որպեսզի համոզվեք, որ դա է ձեզ հետաքրքրող փոփոխությունը և մատնահարեք «Հիշել էջը»՝ գործողությունն ավարտելու համար։',
'undo-failure' => 'Խմբագրումը չի կարող հետ շրջվել միջանկյալ խմբագրումների ընդհարման պատճառով։',
-'undo-summary' => 'Հետ է շրջվում $1 խմբագրումը, որի հեղինակն է՝ [[Special:Contributions/$2|$2]] ([[User talk:$2|քննարկում]])',
+'undo-summary' => 'Հետ է շրջվում $1 խմբագրումը, որի հեղինակն է՝ [[Special:Contributions/$2|$2]] ([[User talk:$2|քննարկում]]) {{GENDER:$2|մասնակիցը|մասնակցուհին}}',
# Account creation failure
'cantcreateaccounttitle' => 'Չհաջողվեց ստեղծել մասնակցային հաշիվ',
'histfirst' => 'Առաջին',
'histlast' => 'Վերջին',
'historysize' => '({{PLURAL:$1|1 բայթ|$1 բայթ}})',
-'historyempty' => '(դատարկ)',
+'historyempty' => '(դատարկ է)',
# Revision feed
'history-feed-title' => 'Փոփոխությունների պատմություն',
'editinguser' => '<b>$1</b> մասնակցի համար ([[User talk:$1|{{int:talkpagelinktext}}]] | [[Special:Contributions/$1|{{int:contribslink}}]])',
'userrights-editusergroup' => 'Խմբագրել մասնակցի խմբերը',
'saveusergroups' => 'Հիշել մասնակցի խմբերը',
-'userrights-groupsmember' => 'Անդամ է.',
+'userrights-groupsmember' => 'Անդամ է՝ $2-ին',
'userrights-reason' => 'Պատճառ.',
'userrights-changeable-col' => 'Խմբեր, որոնք դուք կարող եք ձևափոխել',
# Associated actions - in the sentence "You do not have permission to X"
'action-edit' => 'խմբագրել այս էջը',
'action-createpage' => 'Ստեղծել էջ',
+'action-move-rootuserpages' => 'տեղափոխել մասնակցի էջի արմատը',
+'action-movefile' => 'տեղափոխել այս ֆայլը',
'action-upload' => 'Բեռնել այս ֆայլը',
'action-upload_by_url' => 'Բեռնել այս ֆայլը URL-ից',
'action-delete' => 'Ջնջել այս էջը',
'uploadvirus' => 'Նիշքը պարունակում է վիրո՜ւս։ Տես $1',
'upload-source' => 'Աղբյուրը ֆայլի',
'sourcefilename' => 'Սկզբնական նիշք՝',
+'sourceurl' => 'Այդ Տեղի URL-ն՝',
'destfilename' => 'Նիշքի նոր անվանում՝',
'upload-description' => 'Ֆայլի մեկնաբանություն',
'upload-options' => 'Բեռնման ընտրանքներ',
'filewasdeleted' => 'Այս անվանմամբ նիշք նախկինում բեռնվել է և հետագայում ջնջվել։ Այն կրկին բեռնելուց առաջ խնդրում ենք ստուգել $1։',
'filename-bad-prefix' => "Բեռնվող նիշքի անվանումը սկսվում է '''<tt>«$1»</tt>''' արտահայտությամբ, որը ոչ-նկարագրական է և սովորաբար տրվում է թվային լուսանկարչական ապարատների կողմից։ Խնդրում ենք ընտրել ավելի նկարագրական անվանում ձեր նիշքի համար։",
'upload-success-subj' => 'Բեռնումը կատարված է',
+'upload-failure-subj' => 'Ներբեռնման սխալ',
+'upload-warning-subj' => 'Ներբեռնման զգուշացում',
'upload-proto-error' => 'Սխալ պրոտոկոլ',
'upload-proto-error-text' => 'Հեռավոր բեռնումը պահանջում է URL-հասցե, որը սկսվում է <code>http://</code> կամ <code>ftp://</code> նախածանցով։',
'upload-file-error-text' => 'Տեղի ունեցավ ներքին սխալ՝ սերվերի վրա ժամանակավոր նիշք ստեղծելիս։ Խնդրում ենք կապվել համակարգային [[Special:ListUsers/sysop|ադմինիստրատորի]] հետ։',
'upload-misc-error' => 'Բեռնման անհայտ սխալ',
'upload-misc-error-text' => 'Տեղի ունեցավ անհայտ սխալ բեռնման ընթացքում։ Խնդրում ենք ստուգել URL-հասցեի ճշտությունն ու հասանելիությունը և փորձել կրկին։ Սխալի կրկնման դեպքում կապնվեք համակարգային ադմինիստրատորի հետ։',
+'upload-unknown-size' => 'Անհնար չափս',
# Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
'upload-curl-error6' => 'URL-հասցեն անհասանելի է',
'filepage-nofile' => 'Այս անունով նիշք գոյություն չունի։',
'filepage-nofile-link' => 'Այս անունով նիշք գոյություն չունի, դուք կարող եք [$1 բեռնել այն]:',
'uploadnewversion-linktext' => 'Բեռնել այս նիշքի նոր տարբերակ',
+'shared-repo-from' => '$1-ից',
# File reversion
-'filerevert' => 'Հետ շրջել $1',
-'filerevert-legend' => 'Հետ շրջել նիշք',
+'filerevert' => 'Հետ շրջել $1-ը',
+'filerevert-legend' => 'Հետ շրջել նիշքը',
'filerevert-intro' => "Դուք հետ եք շրջում '''[[Media:$1|$1]]''' նիշքը [$4 տարբերակի՝ $3, $2 պահով]։",
'filerevert-comment' => 'Մեկնաբանություն.',
'filerevert-defaultcomment' => 'Հետ է շրջվում հին տարբերակին՝ $2, $1 պահով',
'protectedpagesempty' => 'Ներկայումս չկան պաշտպանված էջեր նշված պարամետրերով։',
'protectedtitles' => 'Պաշտպանված անվանումներ',
'listusers' => 'Մասնակիցների ցանկ',
+'usereditcount' => '
+$1 {{PLURAL:$1|խմբագրում|խմբագրումներ}}',
+'usercreated' => '{{GENDER:$3|Ստեղծվել է}} $1-ին, ժամը $2-ին',
'newpages' => 'Նոր էջեր',
'newpages-username' => 'Մասնակից՝',
'ancientpages' => 'Ամենահին էջերը',
# Special:LinkSearch
'linksearch' => 'Արտաքին հղումներ',
'linksearch-ok' => 'Որոնել',
+'linksearch-line' => '
+$1-ը հղվել է $2 ից',
# Special:ListUsers
'listusersfrom' => 'Ցուցադրել մասնակիցներին՝ սկսած.',
# Special:ActiveUsers
'activeusers' => 'Ակտիվ մասնակիցների ցանկ',
+'activeusers-noresult' => 'Այդպիսի մասնակիցներ չեն գտնվել։',
# Special:ListGroupRights
'listgrouprights-members' => '(անդամների ցանկ)',
+'listgrouprights-addgroup' => 'Ավելացնեել {{PLURAL:$2|խումբ|խմբեր}}՝ $1',
# E-mail user
'mailnologin' => 'Ուղարկման հասցե չկա',
'noemailtitle' => 'Չկա էլ-փոստի հասցե',
'noemailtext' => 'Այս մասնակիցը չի նշել էլ-փոստի հասցե կամ նախընտրել է չստանալ էլ-նամակներ այլ մասնակիցներից։',
'emailusername' => 'Մասնակցի անուն՝',
+'emailusernamesubmit' => 'Հաշվել',
'email-legend' => 'Ուղարկել էլ․ նամակ {{SITENAME}}յի այլ մասնակցի',
-'emailfrom' => 'Ումից.',
+'emailfrom' => 'Ումից',
'emailto' => 'Ում.',
'emailsubject' => 'Թեմա.',
'emailmessage' => 'Ուղերձ.',
# Watchlist
'watchlist' => 'Իմ հսկողության ցանկը',
'mywatchlist' => 'Հսկացանկ',
+'watchlistfor2' => '$1 $2-ի համար',
'nowatchlist' => 'Ձեր հսկողության ցանկը դատարկ է։',
'watchlistanontext' => 'Անհրաժեշտ է $1՝ հսկացանկը դիտելու կամ խմբագրելու համար։',
'watchnologin' => 'Չեք մտել համակարգ',
'enotif_mailer' => '{{grammar:genitive|{{SITENAME}}}} Տեղեկացման ծառայություն',
'enotif_reset' => 'Նշել բոլոր էջերը այցելված',
'enotif_impersonal_salutation' => '{{grammar:genitive|{{SITENAME}}}} մասնակից',
+'enotif_subject_deleted' => '{{SITENAME}} էջը $1 {{GENDER:$2|ջնջվել է}} $2-ի կողմից',
+'enotif_subject_created' => '{{SITENAME}} էջը $1 {{GENDER:$2|ստեղծվել է}} $2-ի կողմից',
+'enotif_subject_moved' => '{{SITENAME}} էջը $1 {{GENDER:$2|վերահղվել է}} $2-ի կողմից',
+'enotif_body_intro_created' => '{{SITENAME}} էջը $1 {{GENDER:$2|ստեղծվել է}} ժամը $PAGEEDITDATE-ին $2-ի կողմից, նայիր $3 ընդացիկ տարբերակը:',
'enotif_lastvisited' => 'Տես $1՝ ձեր վերջին այցից ի վեր կատարված փոփոխությունների համար։',
'enotif_lastdiff' => 'Տես $1՝ այս փոփոխությունը դիտելու համար։',
'enotif_anon_editor' => 'անանուն մասնակից $1',
'blanknamespace' => '(Գլխավոր)',
# Contributions
-'contributions' => 'Մասնակցի ներդրում',
+'contributions' => ' {{GENDER:$1|Մասնակցի}} ներդրում',
'contributions-title' => '$1 մասնակցի ներդրումը',
'mycontris' => 'Ներդրում',
'contribsub2' => '$1-ի ներդրումները ($2)',
Այսպիսի դեպքերում հարկավոր է տեղափոխել կամ միաձուլել էջերը ձեռքով, եթե դա ցանկանաք։",
'movearticle' => 'Տեղափոխել էջը',
+'moveuserpage-warning' => "'''Զգուշացո՜ւմ՝ '''You are about to move a user page. Please note that only the page will be moved and the user will ''not'' be renamed.",
'movenologin' => 'Դուք չեք մտել համակարգ',
'movenologintext' => 'Անհրաժեշտ է [[Special:UserLogin|մտնել համակարգ]]՝ էջը տեղափոխելու համար։',
'movenotallowed' => 'Դուք չունեք էջերի տեղափոխման իրավունք։',
'importhistoryconflict' => 'Գոյություն ունեցող տարբերակների ընդհարում (հավանաբար այս էջն արդեն ներմուծվել է նախկինում)',
'importnosources' => 'Միջվիքի ներմուծման աղբյուր ընտրված չէ, իսկ փոփոխումների պատմության ուղիղ ներմուծումը անջատված է։',
'importnofile' => 'Ներմուծման նիշք չի բեռնվել։',
+'import-upload' => 'Բեռնված է XML-ի դատան',
# Import log
'importlogpage' => 'Ներմուծման տեղեկամատյան',
'exif-componentsconfiguration-0' => 'գոյություն չունի',
+'exif-urgency-normal' => 'Նորմալ ($1)',
+
# External editor support
'edit-externally' => 'Խմբագրել այս նիշքը արտաքին խմբագրիչով',
'edit-externally-help' => '(Մանրամասնությունների համար տես [//www.mediawiki.org/wiki/Manual:External_editors տեղակայման հրահանգները])',
'dberr-problems' => 'Այս կայքում առաջացել են տեխնիկական խնդիրներ։ Հայցում ենք ձեր ներողությունը։',
'dberr-again' => 'Փորձեք մի քանի րոպե սպասել և վերաբեռնել էջը։',
+# HTML forms
+'htmlform-submit' => '
+Հաշվել',
+
# New logging system
'logentry-delete-delete' => '$1 ջնջեց էջը $3',
'logentry-delete-restore' => '$1 վերականգնեց էջը $3',
'blocklog-showsuppresslog' => 'Pengguna ini telah diblokir dan disembunyikan sebelumnya. Log supresi disediakan di bawah untuk referensi:',
'blocklogentry' => 'memblokir [[$1]] dengan waktu kedaluwarsa $2 $3',
'reblock-logentry' => 'mengubah pemblokiran [[$1]] dengan waktu kedaluwarsa $2 $3',
-'blocklogtext' => 'Di bawah ini adalah log pemblokiran dan pembukaan blokir terhadap pengguna.
-Alamat IP yang diblokir secara otomatis tidak terdapat di dalam daftar ini.
-Lihat [[Special:BlockList|daftar pemblokiran]] untuk semua pengguna yang saat ini diblokir.',
+'blocklogtext' => 'Di bawah ko adolah log panyakek jo pambukaan sakek pado pangguno.
+Alamaik IP nan kanai sakek sacaro otomatis indak nampak dalam dafta ko.
+Lihek [[Special:BlockList|dafta panyakek]] untuak kasado pangguno nan koni kanai sakek.',
'unblocklogentry' => 'menghilangkan blokir "$1"',
'block-log-flags-anononly' => 'hanya pengguna anonim',
'block-log-flags-nocreate' => 'pembuatan akun dimatikan',
Judul lama akan menjadi halaman pengalihan ke judul baru.
Anda dapat memperbarui pengalihan yang menuju ke judul asli secara otomatis.
Jika Anda memilih tidak, pastikan untuk memeriksa
-[[Special:DoubleRedirects|double]] atau [[Special:BrokenRedirects|broken redirects]].
+[[Special:DoubleRedirects|pengalihan ganda]] atau [[Special:BrokenRedirects|pengalihan rusak]].
Anda bertanggung jawab untuk memastikan bahwa pranala terhubung ke tempat seharusnya.
Perhatikan bahwa halaman '''tidak''' akan dipindah apabila telah ada halaman pada judul yang baru, kecuali bila halaman peralihan dan tidak mempunyai sejarah penyuntingan.
'pageinfo-robot-noindex' => 'Tidak dapat diindeks',
'pageinfo-views' => 'Jumlah penampilan',
'pageinfo-watchers' => 'Jumlah pemantau halaman',
+'pageinfo-few-watchers' => 'Kurang dari $1 {{PLURAL:$1|pengunjung}}',
'pageinfo-redirects-name' => 'Pengalihan ke halaman ini',
'pageinfo-redirects-value' => '$1',
'pageinfo-subpages-name' => 'Subhalaman halaman ini',
'category-empty' => "''Daytoy a kategoria ket agdama a saan nga aglaon kadagiti panid wenno midia.''",
'hidden-categories' => '{{PLURAL:$1|Nailemmeng a kategoria|Nailemmeng a katkategoria}}',
'hidden-category-category' => 'Nailemmeng a katkategoria',
-'category-subcat-count' => '{{PLURAL:$2|Daytoy a kategoria ket adda laeng ti sumaganad nga apo ti kategoria.|Daytoy a kategoria ket adda kadagiti sumaganad nga {{PLURAL:$1|nga apo ti kategoria|$1 nga apo dagiti kategoria}}, manipud ti dagup nga $2.}}',
+'category-subcat-count' => '{{PLURAL:$2|Daytoy a kategoria ket adda laeng ti sumaganad a subkategoria.|Daytoy a kategoria ket adda ti sumaganad {{PLURAL:$1|a subkategoria|$1 a dagiti subkategoria}}, manipud ti dagup nga $2.}}',
'category-subcat-count-limited' => 'Daytoy a kategoria ket adda ti sumaganad {{PLURAL:$1|nga apo ti kategoria|$1 nga apo dagiti kategoria}}.',
'category-article-count' => '{{PLURAL:$2|Daytoy a kategoria ket aglaon laeng ti sumaganad a panid.|Ti sumaganad {{PLURAL:$1|a panid|$1 a pampanid}} ket adda iti daytoy a kategoria, manipud ti dagup nga $2.}}',
'category-article-count-limited' => 'Ti sumaganad {{PLURAL:$1|a panid |$1 a pampanid}} ket adda iti agdama a kategoria.',
'newwindow' => '(aglukat iti sabali a tawa)',
'cancel' => 'Ukasen',
'moredotdotdot' => 'Adu pay...',
+'morenotlisted' => 'Adu a saan a nailista...',
'mypage' => 'Panid',
'mytalk' => 'Tungtungan',
'anontalk' => 'Tungtungan para iti daytoy a pagtaengan ti IP',
'gotaccount' => "Addaanka kadin ti pakabilangam? '''$1'''.",
'gotaccountlink' => 'Sumrek',
'userlogin-resetlink' => 'Nalipatam dagiti salaysay ti pagserrek mo?',
-'createaccountmail' => 'Babaen ti e-surat',
+'createaccountmail' => 'Agusar ti maysa a temporario a pugto a kontrasenias ken ipatulod idiay e-surat a pagtaengan a nainganan dita baba',
'createaccountreason' => 'Rason:',
'badretype' => 'Saan nga agpada dagiti impanmo a kontrasenias.',
'userexists' => 'Maus-usaren ti nagan a kayatmo.
# E-mail sending
'php-mail-error-unknown' => 'Di am-ammo a biddut iti surat ti PHP () a pamay-an.',
'user-mail-no-addy' => 'Pinadas nga impatulod ti e-surat nga awan ti e-surat a pagtaengan.',
+'user-mail-no-body' => 'Nangpadaska a nangipatulod ti e-surat nga awan linaonna wenno ababa laeng a bagi.',
# Change password dialog
'resetpass' => 'Sukatan ti kontrasenias',
'changeemail-oldemail' => 'Agdama nga E-surat a pagtaengam:',
'changeemail-newemail' => 'Baro nga e-surat a pagtaengan:',
'changeemail-none' => '(awan)',
+'changeemail-password' => 'Ti bukodmo a kontrasenias ti {{SITENAME}}:',
'changeemail-submit' => 'Sukatan ti e-surat',
'changeemail-cancel' => 'Ukasen',
'search-interwiki-default' => '$1 dagiti nagbanagan:',
'search-interwiki-more' => '(adu pay)',
'search-relatedarticle' => 'Mainaig',
-'mwsuggest-disable' => 'Pagsardengen dagiti AJAX a naisingasing',
+'mwsuggest-disable' => 'Ibaldado dagiti singasing ti panagbiruk',
'searcheverything-enable' => 'Agbirukka kadagiti amin a nagan ti lugar',
'searchrelated' => 'mainaig',
'searchall' => 'amin',
'prefs-emailconfirm-label' => 'Pagsingkedan ti e-surat:',
'prefs-textboxsize' => 'Ti kadakkel ti pagurnosan a tawa',
'youremail' => 'E-surat:',
-'username' => 'Nagan ti agar-aramat:',
-'uid' => 'ID ti agar-aramat:',
-'prefs-memberingroups' => 'Kameng {{PLURAL:$1|ti grupo|dagiti grupo}}:',
+'username' => '{{GENDER:$1|Nagan ti agar-aramat}}:',
+'uid' => 'ID ti {{GENDER:$1|Agar-aramat}}:',
+'prefs-memberingroups' => '{{GENDER:$2|Kameng}} ti {{PLURAL:$1|a grupo|a grupgrupo}}:',
'prefs-registration' => 'Oras a nagrehistro:',
'yourrealname' => 'Pudno a nagan:',
'yourlanguage' => 'Pagsasao:',
'linksearch-ok' => 'Biruken',
'linksearch-text' => 'Ti naataap a tarheta a kas ti "*.wikipedia.org" ket mabalin nga usaren.
Masapul ti kangatuan a pagturayan, a kaspagarigan "*.org".<br />
-{PLURAL:$2|Ti protokol|Dagiti protokol}} a nasuportaran: <code>$1</code> (naipakasigud ti http:// no awan ti protokol a nainaganan).',
+{{PLURAL:$2|Ti protokol|Dagiti protokol}} a nasuportaran: <code>$1</code> (naipakasigud ti http:// no awan ti protokol a nainaganan).',
'linksearch-line' => 'Ti $1 ket nakasilpo idiay $2',
'linksearch-error' => 'Ti naatap a tarheta ket agparang laeng iti pinagrugi ti nagan ti agsangaili.',
'enotif_subject_moved' => 'Ti {{SITENAME}} panid ti $1 ket naiyalis idin babaen ni {{gender:$2|$2}}',
'enotif_subject_restored' => 'Ti {{SITENAME}} a panid ti $1 ket naipasubli idin babaen ni {{gender:$2|$2}}',
'enotif_subject_changed' => 'Ti {{SITENAME}} a panid ti $1 ket nasukatan idin babaen ni {{gender:$2|$2}}',
-'enotif_body_intro_deleted' => 'Ti {{SITENAME}} a panid ti $1 ket naikkat idin idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.',
+'enotif_body_intro_deleted' => 'Ti {{SITENAME}} a panid tie $1 ket {{GENDER:$2|naikkaten}} idiay $PAGEEDITDATE babaen ni $2, kitaen ti $3.',
'enotif_body_intro_created' => 'Ti {{SITENAME}} a panid ti $1 ket napartuat idin idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.',
'enotif_body_intro_moved' => 'Ti {{SITENAME}} a panid ti $1 ket naiyalis idin idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.',
'enotif_body_intro_restored' => 'Ti {{SITENAME}} a panid ti $1 ket naipasubli idi idiay $PAGEEDITDATE babaen ni {{gender:$2|$2}}, kitaen ti $3 para iti agdama panagbaliw.',
'prot_1movedto2' => '[[$1]] naiyalis iti [[$2]]',
'protect-badnamespace-title' => 'Saan a mabalin a salakniban a nagan ti lugar',
'protect-badnamespace-text' => 'Dagiti panid ditoy a nagan ti lugar ket saan a mabalin a masalakniban.',
+'protect-norestrictiontypes-text' => 'Daytoy a panid ket saan a mabalin a masalakniban gaputa awan dagiti maiparit a kita a magun-od.',
+'protect-norestrictiontypes-title' => 'Di masalakniban a panid',
'protect-legend' => 'Pasingkedan ti panagsalaknib',
'protectcomment' => 'Rason:',
'protectexpiry' => 'Agpaso:',
No agpilika a saanmo a kayat, pasaraduam a kitaen ti [[Special:DoubleRedirects|doble]] wenno [[Special:BrokenRedirects|nadadael a baw-ing]].
Renbbengmo ti mangpatalged nga amin a silpo ket agtultuloy a nakatudo iti nasken a papananda.
-Laglagipen a ti panid ket '''saan''' a maiyalis no addan sigud a panid iti baro a titulo, malaksid no daytoy ket maysa a baw-ing ken awan ti napalabas a pakasaritaan ti panag-urnos.
+Laglagipen a ti panid ket '''saan''' a maiyalis no addan sigud a panid iti baro a titulo, malaksid no ti kinaudi ket maysa a baw-ing ken awan ti napalabas a pakasaritaan ti panag-urnos.
Kayat a sawen daytoy a mabalinmo a suktan ti nagan ti maysa a panid manipud iti punto ti pannakasukat ti nagan no nagbiddutka, ken saan mo a mabalin a suratan manen ti addaan a panid.
'''Ballaag!'''
'import-error-interwiki' => 'Ti panid ti "$1" ket saan a naala ngamin ket ti nagan ket nailasin para iti ruar a panagsilpo (interwiki).',
'import-error-special' => 'Ti panid ti "$1" ket saan a naala ngamin ket bukod ti espesial a nagan a lugar a saan nga agpalubos ti pampanid.',
'import-error-invalid' => 'Ti panid ti "$1" ket saan a naala ngamin ket ti nagan ket imbalido.',
+'import-error-unserialize' => 'Ti panagbaliw ti $2 iti panid ti "$1" ket di maipagsasaruno. Ti panagbalbaliw ket naireporta idi nga agus-usar ti modelo ti $3 a naipagsasaruno a kas $4.',
'import-options-wrong' => 'Saan nga husto {{PLURAL:$2|a pagpilian|a pagpilpilian}}: <nowiki>$1</nowiki>',
'import-rootpage-invalid' => 'Ti naited a ramut ti panid ket imbalido a titulo.',
'import-rootpage-nosubpage' => 'Ti nagan ti lugar ti "$1" iti ramut ti panid ket saan amangpalubos kadagiti apo ti panid.',
'pageinfo-robot-noindex' => 'Saan a mabalin a maipasurotan',
'pageinfo-views' => 'Bilang dagiti panagkita',
'pageinfo-watchers' => 'Bilang dagiti agbuybuya ti panid',
+'pageinfo-few-watchers' => 'Basbassit ngem $1 {{PLURAL:$1|ti agbuybuya|dagiti agbuybuya}}',
'pageinfo-redirects-name' => 'Maibaw-ing ti daytoy a panid',
'pageinfo-subpages-name' => 'Apo dagiti panid ti daytoy a panid',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|baw-ing|bawbaw-ing}}; $3 {{PLURAL:$3|saan a baw-ing|saan a bawbaw-ing}})',
'pageinfo-magic-words' => 'Salamangka {{PLURAL:$1|a balikas|a balbalikas}} ($1)',
'pageinfo-hidden-categories' => 'Nailemmeng {{PLURAL:$1|a kategoria|a katkategoria}} ($1)',
'pageinfo-templates' => 'Nailak-am {{PLURAL:$1|a plantilia|a planplantilia}} ($1)',
+'pageinfo-transclusions' => '{{PLURAL:$1|A panid|A pampanid}} ti nailak-an=m idiay ($1)',
'pageinfo-toolboxlink' => 'Pakaammo ti panid',
'pageinfo-redirectsto' => 'Maibaw-ing idiay',
'pageinfo-redirectsto-info' => 'pakaammo',
'pageinfo-protect-cascading' => 'Dagiti panagsalaknib ket agsariap manipud ditoy',
'pageinfo-protect-cascading-yes' => 'Wen',
'pageinfo-protect-cascading-from' => 'Dagiti panagsalaknib ket agsariap manipud idiay',
+'pageinfo-category-info' => 'Pakaammo ti kategoria',
+'pageinfo-category-pages' => 'Bilang dagiti panid',
+'pageinfo-category-subcats' => 'Bilang dagiti subkategoria',
+'pageinfo-category-files' => 'Bilang dagiti papeles',
# Patrolling
'markaspatrolleddiff' => 'Markaan a kas napatruliaan',
'minutes' => '{{PLURAL:$1|$1 minuto|$1 minutos}}',
'hours' => '{{PLURAL:$1|$1 oras$1 oras}}',
'days' => '{{PLURAL:$1|$1 aldaw|$1 al-aldaw}}',
+'months' => '{{PLURAL:$1|$1 a bulan|$1 a bulbulan}}',
+'years' => '{{PLURAL:$1|$1 a tawen|$1 a tawtawen}}',
'ago' => '$1 nagtapos',
'just-now' => 'tatta laeng',
'logentry-newusers-newusers' => 'Nagpartuat idi ti $1 a pakabilangan ti agar-aramat',
'logentry-newusers-create' => 'Nagpartuat idi ti $1 a pakabilangan ti agar-aramat',
'logentry-newusers-create2' => 'Nagpartuat ni ti $3 a pakabilangan ti agar-aramat babaen ni $1',
+'logentry-newusers-byemail' => 'Ti pakabilangan a $3 ket pinartuat idi babaen ni $1 ken ti kontrasenias ket naipatulod idi babaen ti e-surat',
'logentry-newusers-autocreate' => 'Ti pakabilangan ni $1 ket automatiko a napartuat',
'logentry-rights-rights' => 'Ni $1 ket nangbaliw ti grupo a panakaikameng para kenni $3 manipud ti $4 iti $5',
'logentry-rights-rights-legacy' => 'Ni $1 ket nangbaliw ti grupo a panakaikameng para kenni $3',
'api-error-ok-but-empty' => 'Kinauneg a biddut: Awan ti sungbat manipud idiay server.',
'api-error-overwrite' => 'Saan a mabalin a suratan manen iti papeles nga adda ditan.',
'api-error-stashfailed' => 'Kinauneg a biddut: Napaay ti server ti agidulin ti temporario a papeles',
+'api-error-publishfailed' => 'Kinauneg a biddut: Napaay ti server a nagipablaak ti temporario a papeles.',
'api-error-timeout' => 'Saan a simmungbat ti server iti nanamnama nga oras.',
'api-error-unclassified' => 'Adda di amammo a biddut a rumsua.',
'api-error-unknown-code' => 'Di amamo a biddut: "$1"',
'tog-enotifrevealaddr' => 'Gefa upp netfang mitt í tilkynningarpóstum',
'tog-shownumberswatching' => 'Sýna fjölda vaktandi notenda',
'tog-oldsig' => 'Núverandi undirskrift:',
-'tog-fancysig' => 'Meðhöndla undirskrift sem wikitexti (án sjálfvirks tengils)',
-'tog-externaleditor' => 'Nota utanaðkomandi ritil sjálfgefið (eingöngu fyrir reynda, þarfnast sérstakra stillinga á tölvunni þinni)',
-'tog-externaldiff' => 'Nota utanaðkomandi mismun sjálfgefið (eingöngu fyrir reynda, þarfnast sérstakra stillinga á tölvunni þinni)',
+'tog-fancysig' => 'Meðhöndla undirskrift sem wikimál (án sjálfvirks tengils)',
+'tog-externaleditor' => 'Nota utanaðkomandi ritil sjálfgefið (eingöngu fyrir reynda, þarfnast sérstakra stillinga á tölvunni þinni. [//www.mediawiki.org/wiki/Manual:External_editors Frekari upplýsingar.])',
+'tog-externaldiff' => 'Nota utanaðkomandi mismun sjálfgefið (eingöngu fyrir reynda, þarfnast sérstakra stillinga á tölvunni þinni. [//www.mediawiki.org/wiki/Manual:External_editors Frekari upplýsingar.])',
'tog-showjumplinks' => 'Virkja „stökkva á“ aðgengitengla',
'tog-uselivepreview' => 'Nota beina forskoðun (JavaScript) (Á tilraunastigi)',
'tog-forceeditsummary' => 'Birta áminningu þegar breytingarágripið er tómt',
'october' => 'október',
'november' => 'nóvember',
'december' => 'desember',
-'january-gen' => 'janúar',
-'february-gen' => 'febrúar',
+'january-gen' => 'janúars',
+'february-gen' => 'febrúars',
'march-gen' => 'mars',
-'april-gen' => 'apríl',
+'april-gen' => 'apríls',
'may-gen' => 'maí',
'june-gen' => 'júní',
'july-gen' => 'júlí',
'category-subcat-count' => '{{PLURAL:$2|Þessi flokkur hefur einungis eftirfarandi undirflokk.|Þessi flokkur hefur eftirfarandi {{PLURAL:$1|undirflokk|$1 undirflokka}}, af alls $2.}}',
'category-subcat-count-limited' => 'Þessi flokkur hefur eftirfarandi {{PLURAL:$1|undirflokk|$1 undirflokka}}.',
'category-article-count' => '{{PLURAL:$2|Þessi flokkur inniheldur aðeins eftirfarandi síðu.|Eftirfarandi {{PLURAL:$1|síða er|síður eru}} í þessum flokki, af alls $1.}}',
-'category-article-count-limited' => 'Eftirfarndi {{PLURAL:$1|síða er|$1 síður eru}} í þessum flokki.',
+'category-article-count-limited' => 'Eftirfarandi {{PLURAL:$1|síða er|$1 síður eru}} í þessum flokki.',
'category-file-count' => '{{PLURAL:$2|Þessi flokkur inniheldur einungis eftirfarandi skrá.|Eftirfarandi {{PLURAL:$1|skrá er|$1 skrár eru}} í þessum flokki, af alls $2.}}',
'category-file-count-limited' => 'Eftirfarandi {{PLURAL:$1|skrá er|$1 skrár eru}} í þessum flokki.',
'listingcontinuesabbrev' => 'frh.',
'gotaccount' => "Nú þegar með notandanafn? '''$1'''.",
'gotaccountlink' => 'Skráðu þig inn',
'userlogin-resetlink' => 'Gleymdir þú notendaupplýsingunum þínum?',
-'createaccountmail' => 'Nota tímabundið handahófsvalið lykilorð og senda það á netfangið sem er tilgreint hér fyrir neðan',
+'createaccountmail' => 'Nota handahófsvalið bráðabirgðalykilorð og senda það á netfangið sem er tilgreint hér fyrir neðan',
'createaccountreason' => 'Ástæða:',
'badretype' => 'Lykilorðin sem þú skrifaðir eru ekki eins.',
'userexists' => 'Þetta notandanafn er þegar í notkun.
# E-mail sending
'php-mail-error-unknown' => 'Óþekkt villa í PHP mail() aðgerð.',
'user-mail-no-addy' => 'Gat ekki sent tölvupóst því ekkert tölvupóstfang fannst.',
+'user-mail-no-body' => 'Reyndi að senda tölvupóst með engu eða verulega stuttu meginmáli.',
# Change password dialog
'resetpass' => 'Breyta lykilorði',
Þú lofar okkur einnig að þú hafir skrifað þetta sjálfur, að efnið sé í almannaeigu eða að það heyri undir frjálst leyfi. (sjá $1).
'''EKKI SENDA INN HÖFUNDARRÉTTARVARIÐ EFNI ÁN LEYFIS RÉTTHAFA!'''",
'longpageerror' => "'''VILLA: Textinn sem þú sendir inn er {{PLURAL:$1|eitt kílóbæti|$1 kílóbæti}} að lengd, en hámarkið er {{PLURAL:$2|eitt kílóbæti|$2 kílóbæti}}. Ekki er hægt að vista textann.'''",
-'readonlywarning' => "'''AÐVÖRUN: Gagnagrunninum hefur verið læst til að unnt sé að framkvæma viðhaldsaðgerðir, svo þú getur ekki vistað breytingar þínar núna.
-Þú kannt að vilja að klippa og líma textann í textaskjal og vista hann fyrir síðar.'''
+'readonlywarning' => "'''AÐVÖRUN: Gagnagrunninum hefur verið læst til að unnt sé að framkvæma viðhaldsaðgerðir, svo þú getur ekki vistað breytingar þínar núna.'''
+Þú ættir að klippa og líma textann yfir í textaskjal til þess að geyma hann til seinni tíma.
Stjórnandinn sem læsti honum gaf þessa skýringu: $1",
'protectedpagewarning' => "'''Viðvörun: Þessari síðu hefur verið læst svo aðeins notendur með möppudýraréttindi geti breytt henni.'''
'post-expand-template-argument-category' => 'Síður sem innihalda frumbreytur sniða sem hefur verið sleppt',
'parser-template-loop-warning' => 'Lykkja í sniði fundin: [[$1]]',
'parser-template-recursion-depth-warning' => 'Sniðið er sjálkveðið of mörgum sinnum ($1)',
-'node-count-exceeded-category' => 'Síður þar sem er umfram fjöldi hnúta',
+'language-converter-depth-warning' => 'Farið út fyrir dýptarmörk tungumálabreytara ($1)',
+'node-count-exceeded-category' => 'Síður þar sem er umframfjöldi hnúta',
+'node-count-exceeded-warning' => 'Síðan fór fram yfir nóðutölu',
+'expansion-depth-exceeded-category' => 'Þær síður þar sem farið er út fyrir leyfða dýpt útvíkkunar',
+'expansion-depth-exceeded-warning' => 'Síðan fer út fyrir leyfða dýpt útvíkkunar',
+'parser-unstrip-loop-warning' => '"Unstrip" lykkja fannst',
+'parser-unstrip-recursion-limit' => 'Farið út fyrir „unstrip“ endurkvæmnismörk ($1)',
+'converter-manual-rule-error' => 'Villa í reglu handvirks tungumálabreytis',
# "Undo" feature
'undo-success' => 'Breytingin hefur verið tekin tilbaka. Vinsamlegast staðfestu og vistaðu svo.',
'revisiondelete' => 'Eyða/endurvekja breytingar',
'revdelete-nooldid-title' => 'Ógild markbreyting',
'revdelete-nooldid-text' => 'Annaðhvort hefur útgáfan sem á að fela ekki verið tilgreind, þessi útgáfa ekki verið til, eða að þú sért að reyna að fela núverandi útgáfu.',
+'revdelete-nologtype-title' => 'Engin skráargerð uppgefin',
+'revdelete-nologtype-text' => 'Þú tilgreindir ekki skráargerð til þess að framkvæma þessa aðgerð á.',
'revdelete-nologid-title' => 'Ógild aðgerðarskráar færsla',
-'revdelete-nologid-text' => 'Þú hefur annaðhvort ekki tilgreint færslu í aðgerðarskrá til að framkvæma þessa aðgerð á, eða að færslan sé ekki til.',
+'revdelete-nologid-text' => 'Þú hefur annaðhvort ekki tilgreint færslu í aðgerðarskrá til að framkvæma þessa aðgerð á, eða færslan er ekki til.',
'revdelete-no-file' => 'Umbeðin skrá er ekki til.',
'revdelete-show-file-confirm' => 'Ertu viss um að þú viljir sjá eydda breytingu af síðunni "<nowiki>$1</nowiki>" frá $2 $3?',
'revdelete-show-file-submit' => 'Já',
'revdelete-success' => "'''Sýnileiki útgáfu er uppfærð.'''",
'revdelete-failure' => "'''Mistókst að uppfæra sýnileika útgáfu:'''
$1",
-'logdelete-success' => "'''Sýnleiki aðgerðarskráar uppfærð.'''",
+'logdelete-success' => "'''Sýnleiki aðgerðarskráar uppfærður.'''",
'logdelete-failure' => "'''Mistókst að uppfæra sýnileika aðgerðarskráar:'''
$1",
'revdel-restore' => 'Breyta sýn',
Þú hefur ekki aðgang að henni.',
'revdelete-modify-missing' => 'Mistókst að breyta hlut með auðkennið $1: Hann finnst ekki í gagnabankanum!',
'revdelete-no-change' => "'''Viðvörun:''' Breytingin frá $1 $2 hefur þegar umbeðnar sýnileika stillingar.",
-'revdelete-concurrent-change' => 'Mistókst að breyta hlut frá $1 $2: Staða hans virðist hafa verið breytt af einhverjum öðrum á meðan þú reyndir að breyta honum.
+'revdelete-concurrent-change' => 'Mistókst að breyta hlut frá $1 $2: Stöðu hans virðist hafa verið breytt af einhverjum öðrum á meðan þú reyndir að breyta honum.
Vinsamlegast athugaðu í aðgerðarskránum.',
'revdelete-only-restricted' => 'Mistókst að fela breytingu frá $1 $2: Þú getur ekki falið breytingu fyrir möppudýrum án þess að velja eina af hinum sýnileika stillingunum.',
'revdelete-reason-dropdown' => '*Algengar eyðingarástæður
'mergehistory-from' => 'Heimildsíða:',
'mergehistory-into' => 'Áætlunarsíða:',
'mergehistory-list' => 'Breytingarskrá sem hægt er að sameina',
+'mergehistory-merge' => 'Eftirtaldar útgáfur [[:$1]] má sameina [[:$2]].
+Notaðu valtakkadálkinn til þess að sameina aðeins þær útgáfur sem stofnaðar voru fyrir uppgefið tímamark.
+Athugaðu að með því að nota flakktenglana er þessi dálkur endurstilltur.',
+'mergehistory-go' => 'Sýna breytingar sem hægt er að sameina',
+'mergehistory-submit' => 'Sameina útgáfur',
+'mergehistory-empty' => 'Engar útgáfur sem hægt er að sameina.',
+'mergehistory-success' => '$3 {{PLURAL:$3|útgáfa|útgáfur}} af [[:$1]] sameinaðar í [[:$2]].',
+'mergehistory-fail' => 'Gat ekki sameinað breytingasögur. Vinsamlegast athugaðu síðuna og tímabreyturnar.',
+'mergehistory-no-source' => 'Upprunasíðan $1 er ekki til.',
+'mergehistory-no-destination' => 'Marksíðan $1 er ekki til.',
+'mergehistory-invalid-source' => 'Upprunasíðan verður að hafa gildan titil.',
+'mergehistory-invalid-destination' => 'Marksíðan verður að hafa gildan titil.',
+'mergehistory-autocomment' => 'Sameinaði [[:$1]] inn í [[:$2]]',
+'mergehistory-comment' => 'Sameinaði [[:$1]] inn í [[:$2]]: $3',
+'mergehistory-same-destination' => 'Upprunasíðan og marksíðan mega ekki vera sú sama',
'mergehistory-reason' => 'Ástæða:',
# Merge log
'diff-multi-manyusers' => '({{PLURAL:$1|Ein millibreyting ekki sýnd|$1 millibreytingar ekki sýndar}} frá fleiri en {{PLURAL:$2|einum notanda|$2 notendum}}.)',
'difference-missing-revision' => '{{PLURAL:$2|Ein útgáfa|$2 útgáfur}} samanburðarins ($1) {{PLURAL:$2|fannst|fundust}} ekki.
-Þetta gerist oftast þegar úreldur samanburðar-tengill tengir á síðu sem hefur verið eytt. Frekari upplýsingar eru í [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} eyðingarskránni].',
+Þetta gerist oftast þegar úreldur samanburðartengill tengir á síðu sem hefur verið eytt.
+Frekari upplýsingar eru í [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} eyðingarskránni].',
# Search results
'searchresults' => 'Leitarniðurstöður',
'backend-fail-stream' => 'Gat ekki streymt skránni „$1“.',
'backend-fail-backup' => 'Öryggisafritun skráarinnar $1 mistókst.',
'backend-fail-notexists' => 'Skráin $1 er ekki til.',
+'backend-fail-hashes' => 'Gat ekki nálgast tætigildi skráanna til samanburðar.',
'backend-fail-notsame' => 'Ólík skrá er þegar til á $1.',
'backend-fail-invalidpath' => '$1 er ekki gildur geymslustaður.',
'backend-fail-delete' => 'Mistókst að eyða skránni $1.',
'backend-fail-create' => 'Mistókst að skrifa skrá $1.',
'backend-fail-maxsize' => 'Mistókst að skrifa skránna $1 því hún er stærri en {{PLURAL:$2|eitt bæti|$2 bæti}}.',
'backend-fail-readonly' => 'Gagnabankann "$1" er engöngu hægt að lesa í augnablikinu. Ástæðan sem var gefin er: "\'\'$2\'\'"',
+'backend-fail-synced' => 'Skráin $1 er í ósamkvæmu ástandi innan innri geymslubakenda',
'backend-fail-connect' => 'Mistókst að tengjast gagnabankanum "$1".',
'backend-fail-internal' => 'Óþekkt villa átti sér stað í gagnabankanum "$1".',
+'backend-fail-contenttype' => 'Gat ekki ákvarðað innihaldgerð skráarinnar til geymslu á „$1“.',
+'backend-fail-batchsize' => 'Geymslubakendinn fékk bunka af $1 {{PLURAL:$1|skráaraðgerð|skráaraðgerðum}}; mest eru leyfðar $2 {{PLURAL:$2|aðgerð|aðgerðir}}.',
+'backend-fail-usable' => 'Gat ekki lesið skrána „$1“ vegna ófullnægjandi aðgangsheimilda eða týndra mappa/íláta.',
+
+# File journal errors
+'filejournal-fail-dbconnect' => 'Gat ekki tengst dagbókargrunni fyrir geymslubakendann „$1“.',
+'filejournal-fail-dbquery' => 'Gat ekki uppfært dagbókargrunn vegna geymslubakendans „$1“.',
+
+# Lock manager
+'lockmanager-notlocked' => 'Gat ekki aflæst „$1“; það er ekki læst.',
+'lockmanager-fail-closelock' => 'Gat ekki lokað lásaskrá vegna „$1“.',
+'lockmanager-fail-deletelock' => 'Gat ekki eytt lásaskrá vegna „$1“.',
+'lockmanager-fail-acquirelock' => 'Gat ekki nálgast lás vegna „$1“.',
+'lockmanager-fail-openlock' => 'Gat ekki opnað lásaskrá vegna „$1“.',
+'lockmanager-fail-releaselock' => 'Gat ekki opnað lás vegna „$1“.',
+'lockmanager-fail-db-bucket' => 'Náði ekki sambandi við nógu marga lása í fötunni $1.',
+'lockmanager-fail-db-release' => 'Gat ekki opnað lása á gagnagrunninum $1.',
+'lockmanager-fail-svr-acquire' => 'Gat ekki nálgast lása á þjóninum $1.',
+'lockmanager-fail-svr-release' => 'Gat ekki opnað lása á þjóninum $1.',
# ZipDirectoryReader
'zip-file-open-error' => 'Mistök við opnun skráarinnar fyrir ZIP athuganir.',
Reyndu aftur.',
'uploadstash-errclear' => 'Tæming listans mistókst.',
'uploadstash-refresh' => 'Endurhlaða listann',
+'invalid-chunk-offset' => 'Ógild raðbreyting bunka',
# img_auth script messages
'img-auth-accessdenied' => 'Aðgangur óheimill',
Biðlarinn þínn er ekki stilltur til að gefa upp þessar upplýsingar.
Þær mega vera CGI-byggðar og mega ekki styðja img_auth.
https://www.mediawiki.org/wiki/Manual:Image_Authorization',
+'img-auth-notindir' => 'Umbeðin slóð var ekki í stilltri upphlaðsmöppu.',
'img-auth-badtitle' => 'Mistókst að búa til gildan titil útfrá „$1”.',
+'img-auth-nologinnWL' => 'Þú ert ekki skráð(ur) inn og „$1“ er ekki á hvítlista.',
'img-auth-nofile' => 'Skráin "$1" er ekki til.',
+'img-auth-isdir' => 'Þú ert að reyna að nálgast möppuna „$1“.
+Aðeins skráaraðgangur er leyfður.',
'img-auth-streaming' => 'Streymi "$1".',
+'img-auth-public' => 'Virkni img_auth.php er að flytja út skrár frá einkawiki.
+Þessi wiki er stilltur sem opinber wiki.
+Vegna öryggissjónarmiða er img_auth.php óvirkt.',
'img-auth-noread' => 'Notandinn hefur ekki rétt til að lesa "$1"',
'img-auth-bad-query-string' => 'Vefslóðin hefur ógildan fyrirspurnar streng.',
** Yfirþyrmandi framkoma/áreitni
** Misnotkun á fjölda notandanafna
** Óásættanlegt notandanafn',
-'ipb-hardblock' => 'Hindra innskráðum notendum frá því að breyta frá þessu vistfangi.',
-'ipbcreateaccount' => 'Banna nýskráningu notanda',
+'ipb-hardblock' => 'Banna innskráðum notendum að breyta frá þessu vistfangi.',
+'ipbcreateaccount' => 'Banna nýskráningu notandanafns',
'ipbemailban' => 'Banna notanda að senda tölvupóst',
'ipbenableautoblock' => 'Banna síðasta vistfang notanda sjálfkrafa; og þau vistföng sem viðkomandi notar til að breyta síðum',
'ipbsubmit' => 'Banna notanda',
'ipbotherreason' => 'Önnur/auka ástæða:',
'ipbhidename' => 'Fela notandanafn úr breytingarskrá og listum',
'ipbwatchuser' => 'Vakta notanda- og spjallsíður þessa notanda',
-'ipb-disableusertalk' => 'Banna þessum notenda að breyta egin spjallsíðu',
+'ipb-disableusertalk' => 'Banna þessum notanda að breyta eigin spjallsíðu',
'ipb-change-block' => 'Endurbanna notanda með þessum stillingum',
'ipb-confirm' => 'Staðfesta bann',
'badipaddress' => 'Ógilt vistfang',
'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] hefur verið bannaður/bönnuð.<br />
Sjá [[Special:BlockList|bannaðir notendur og vistföng]] fyrir yfirlit yfir núverandi bönn.',
'ipb-blockingself' => 'Þú ert í þann mund að banna sjálfan þig! Ertu viss um að þú viljir gera það?',
-'ipb-confirmhideuser' => 'Þú ert í þann mund að banna notenda sem er falinn. Notendanafn hans mun ekki birtast í listum og aðgerðarskrám. Ertu viss um að þú viljir gera það?',
+'ipb-confirmhideuser' => 'Þú ert í þann mund að banna notanda sem er falinn. Notandanafn hans mun ekki birtast í listum og aðgerðarskrám. Ertu viss um að þú viljir gera það?',
'ipb-edit-dropdown' => 'Breyta ástæðu fyrir banni',
'ipb-unblock-addr' => 'Afbanna $1',
'ipb-unblock' => 'Afbanna notanda eða vistfang',
# Developer tools
'lockdb' => 'Læsa gagnagrunninum',
'unlockdb' => 'Opna gagnagrunninn',
+'lockdbtext' => 'Læsing gagnagrunnsins mun hindra alla notendur í því að breyta síðum, stillingum, vaktlistum og öðrum möguleikum sem þarfnast aðgangs að gagnagrunninum.
+Staðfestu að þetta er það sem þú vilt gera og að þú munir aflæsa grunninum eftir að viðhaldsverki er lokið.',
+'unlockdbtext' => 'Aflæsing gagnagrunnsins mun gera öllum notendum kleift á ný að breyta síðum, stillingum, vaktlistum og öðrum möguleikum sem þarfnast aðgangs að gagnagrunninum.
+Staðfestu að þetta er það sem þú vilt gera.',
'lockconfirm' => 'Já, ég vil læsa gagnagrunninum.',
'unlockconfirm' => 'Já, ég vil aflæsa gagnagrunninum.',
'lockbtn' => 'Læsa gagnagrunni',
'lockdbsuccesstext' => 'Gagnagrunninum hefur verið læst.<br />
Mundu að [[Special:UnlockDB|opna hann aftur]] þegar þú hefur lokið viðgerðum.',
'unlockdbsuccesstext' => 'Gagnagrunnurinn hefur verið opnaður.',
+'lockfilenotwritable' => 'Skrá gagnagrunnslássins er ekki skrifanleg.
+Til þess að læsa eða aflæsa gagnagrunni þarf vefþjónninn að geta skrifað í skrána.',
'databasenotlocked' => 'Gagnagrunnurinn er ekki læstur.',
'lockedbyandtime' => '(af {{GENDER:$1|$1}} kl. $3, $2)',
'immobile-target-namespace-iw' => 'Óheimilt er að færa síðu með tungumálatengli.',
'immobile-source-page' => 'Þessi síða er ekki færanleg.',
'immobile-target-page' => 'Get ekki fært á áætlaðan titil.',
+'bad-target-model' => 'Markstaðurinn sem þú valdir notast við annað innihaldslíkan. Get ekki umbreytt frá $1 í $2.',
'imagenocrossnamespace' => 'Get ekki fært skrá í skrálaust nafnrými',
'nonfile-cannot-move-to-file' => 'Get ekki fært annað en skrár í nafnrými skráa.',
'imagetypemismatch' => 'Nýi nafnaukinn passar ekki við tegund hennar',
'thumbnail-more' => 'Stækka',
'filemissing' => 'Skrá vantar',
'thumbnail_error' => 'Villa við gerð smámyndar: $1',
+'djvu_page_error' => 'DjVu-blaðsíða er utan marka',
'djvu_no_xml' => 'Mistókst að sækja XML-gögn fyrir DjVu skrá',
'thumbnail-temp-create' => 'Mistókst að búa til tímabundna smámynd.',
+'thumbnail-dest-create' => 'Gat ekki vistað smámynd á markstað',
'thumbnail_invalid_params' => 'Breytur smámyndarinnar eru rangar',
'thumbnail_dest_directory' => 'Mistókst að búa til niðurhals möppu',
'thumbnail_image-type' => 'Enginn stuðningur er við þetta skráarsnið',
+'thumbnail_gd-library' => 'Ófullkomin stilling GD-safns: Skortir aðgerðina $1',
'thumbnail_image-missing' => 'Skránna vantar: $1',
# Special:Import
'import-interwiki-templates' => 'Innifala öll snið með',
'import-interwiki-submit' => 'Flytja inn',
'import-interwiki-namespace' => 'Ákvörðunarnafnrými:',
-'import-interwiki-rootpage' => 'Ákvörðunar grunnsíða (valfrjáls):',
+'import-interwiki-rootpage' => 'Markmóðursíða (valfrjáls):',
'import-upload-filename' => 'Skráarnafn:',
'import-comment' => 'Athugasemdir:',
'importtext' => 'Vinsamlegast fluttu út skránna frá upprunalegum wiki með því að nota [[Special:Export|Flytja út síður]].
'importnopages' => 'Engar síður til innflutnings.',
'imported-log-entries' => '$1 {{PLURAL:$1|breytingar færsla|breytingar færslur}} hafa verið fluttar inn',
'importfailed' => 'Innhlaðning mistókst: $1',
+'importunknownsource' => 'Óþekkt innflutningstilfangsgerð',
'importcantopen' => 'Get ekki opnað innflutt skjal',
'importbadinterwiki' => 'Villa í tungumálatengli',
'importnotext' => 'Tómt eða enginn texti',
'import-error-interwiki' => 'Síðan "$1" var ekki flutt inn því nafn hennar er frátekið fyrir ytri tengla (tungumálatengla).',
'import-error-special' => 'Síðan "$1" var ekki flutt inn því hún tilheyrir ákveðnu nafnrými sem leyfir ekki síður.',
'import-error-invalid' => 'Síðan "$1" var ekki flutt inn því nafn hennar er ógilt.',
+'import-error-unserialize' => 'Ekki unnt að afraða útgáfu $2 af síðunni „$1“. Útgáfan var sögð nota innihaldslíkan $3 raðað sem $4.',
'import-options-wrong' => '{{PLURAL:$2|Rangur möguleiki|Rangir möguleikar}}: <nowiki>$1</nowiki>',
-'import-rootpage-invalid' => 'Uppgefin ákvörðunar síða er ógildur titill.',
-'import-rootpage-nosubpage' => 'Nafnrými „$1“ ákvörðunar síðunar leyfir ekki undirsíður.',
+'import-rootpage-invalid' => 'Uppgefin móðursíða hefur ógildan titil.',
+'import-rootpage-nosubpage' => 'Nafnrými „$1“ móðursíðunnar leyfir ekki undirsíður.',
# Import log
'importlogpage' => 'Innflutningsskrá',
'javascripttest' => 'JavaScript prófun',
'javascripttest-title' => 'Keyri $1 prófun',
'javascripttest-pagetext-noframework' => 'Þessi síða er frátekin fyrir JavaScript prófanir.',
+'javascripttest-pagetext-unknownframework' => 'Óþekktur prófunarrammi „$1“.',
+'javascripttest-pagetext-frameworks' => 'Veldu einn eftirtalinna prófunarramma: $1',
'javascripttest-pagetext-skins' => 'Veldu þema sem á að keyra prófanirnar á:',
+'javascripttest-qunit-intro' => 'Sjá [$1 tilraunaskjölun] á mediawiki.org.',
# Tooltip help for the actions
'tooltip-pt-userpage' => 'Notandasíðan þín',
'pageinfo-robot-noindex' => 'Óskráanleg',
'pageinfo-views' => 'Fjöldi innlita',
'pageinfo-watchers' => 'Fjöldi notenda, sem vakta síðuna',
-'pageinfo-few-watchers' => 'Vöktuð af færri en $1 {{PLURAL:$1|notandi|notendum}}',
+'pageinfo-few-watchers' => 'Vöktuð af færri en $1 {{PLURAL:$1|notanda|notendum}}',
'pageinfo-redirects-name' => 'Tilvísanir til þessarar síðu',
'pageinfo-subpages-name' => 'Undirsíður þessarar síðu',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|tilvísun|tilvísanir}}; $3 {{PLURAL:$3|ekki tilvísun|ekki tilvísanir}})',
'pageinfo-magic-words' => 'Töfra {{PLURAL:$1|orð}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Falinn flokkur|Faldir flokkar}} ($1)',
'pageinfo-templates' => '{{PLURAL:$1|Innifalið snið|Innifalin snið}} ($1)',
-'pageinfo-transclusions' => '{{PLURAL:$1|Síða|Síður}} ítengdar á ($1)',
+'pageinfo-transclusions' => '{{PLURAL:$1|Síða|Síður}} innfelldar á ($1)',
'pageinfo-toolboxlink' => 'Síðuupplýsingar',
'pageinfo-redirectsto' => 'Vísar til',
'pageinfo-redirectsto-info' => 'upplýsingar',
'pageinfo-protect-cascading' => 'Keðjuvörn hefst hér',
'pageinfo-protect-cascading-yes' => 'Já',
'pageinfo-protect-cascading-from' => 'Keðjuvörn stafar frá',
-'pageinfo-category-info' => 'Flokka upplýsingar',
+'pageinfo-category-info' => 'Flokkaupplýsingar',
'pageinfo-category-pages' => 'Fjöldi síðna',
'pageinfo-category-subcats' => 'Fjöldi undirflokka',
'pageinfo-category-files' => 'Fjöldi skráa',
'file-info-png-looped' => 'síendurtekin hreyfimynd',
'file-info-png-repeat' => 'spilað {{PLURAL:$1|einu sinni|$1 sinnum}}',
'file-info-png-frames' => '$1 {{PLURAL:$1|rammi|rammar}}',
+'file-no-thumb-animation' => "'''Athugið: Vegna tæknilegra takmarkanna birtast smámyndir af þessari skrá aðeins sem kyrrmyndir.'''",
+'file-no-thumb-animation-gif' => "'''Athugið:Vegna tæknilegra takmarkanna munu smámyndir af GIF-myndum í hárri upplausn eins og þessari ekki birtast sem hreyfimyndir.'''",
# Special:NewFiles
'newimages' => 'Myndasafn nýlegra skráa',
'exif-orientation' => 'Lega',
'exif-samplesperpixel' => 'Fjöldi eininga',
'exif-planarconfiguration' => 'Tilhögun gagna',
+'exif-ycbcrsubsampling' => 'Undirstökunarsnið Y gagnvart C',
'exif-ycbcrpositioning' => 'Staðsetning Y og C',
'exif-xresolution' => 'Lárétt upplausn',
'exif-yresolution' => 'Lóðrétt upplausn',
'exif-stripoffsets' => 'Staðsetning gagna',
'exif-rowsperstrip' => 'Fjöldi raða á ræmu',
'exif-stripbytecounts' => 'Bæti á hverri þjappaðri ræmu',
+'exif-jpeginterchangeformat' => 'Jöfnun JPEG SOI',
'exif-jpeginterchangeformatlength' => 'bæti af JPEG gögnum',
'exif-whitepoint' => 'Krómatísmi hvíta punkts',
'exif-primarychromaticities' => 'Krómatísmi grunnlita',
+'exif-ycbcrcoefficients' => 'Litarýmisumbreytingargfylkistuðlar',
'exif-referenceblackwhite' => 'Pör svartra og hvítra tilvísana gilda',
'exif-datetime' => 'Dagsetning og tími breytingar',
'exif-imagedescription' => 'Titill myndar',
'exif-datetimeoriginal' => 'Upprunaleg dagsetning',
'exif-datetimedigitized' => 'Dagsetning stafrænnar myndar',
'exif-subsectime' => 'DagsetningTími sekúndubrot',
+'exif-subsectimeoriginal' => 'DagurTímiUpprunaleg sekúndubrot',
+'exif-subsectimedigitized' => 'DagurTímiStafrænt sekúndubrot',
'exif-exposuretime' => 'Lýsingartími',
'exif-exposuretime-format' => '$1 sekúnda ($2)',
+'exif-fnumber' => 'F-tala',
'exif-exposureprogram' => 'Ljósastilling',
'exif-spectralsensitivity' => 'Litrófsnæmni',
'exif-isospeedratings' => 'ISO filmuhraði',
'exif-shutterspeedvalue' => 'APEX lokunarhraði',
'exif-aperturevalue' => 'APEX ljósop',
'exif-brightnessvalue' => 'APEX birtustig',
+'exif-exposurebiasvalue' => 'APEX lýsingarbjagi',
+'exif-maxaperturevalue' => 'Hámarksvídd ljósops innra byrðis linsu',
'exif-subjectdistance' => 'Lengd að viðfangsefni',
+'exif-meteringmode' => 'Mælingarhamur',
'exif-lightsource' => 'Uppspretta ljóssins',
'exif-flash' => 'Leifturljós',
'exif-focallength' => 'Brennivídd',
'exif-gpslatitude' => 'Breiddargráða',
'exif-gpslongituderef' => 'Austur- eða vestur lengdargráða',
'exif-gpslongitude' => 'Lengdargráða',
+'exif-gpsaltituderef' => 'Hæðarviðmið',
'exif-gpsaltitude' => 'Stjörnuhæð',
'exif-gpstimestamp' => 'GPS tími (atómklukka)',
'exif-gpssatellites' => 'Gervihnettir sem voru notaðir við mælingu',
'exif-planarconfiguration-2' => 'planar snið',
+'exif-colorspace-65535' => 'Ókvarðað',
+
'exif-componentsconfiguration-0' => 'er ekki til',
'exif-exposureprogram-0' => 'Ekki skilgreind',
'exif-meteringmode-3' => 'Blettur',
'exif-meteringmode-4' => 'Margir-blettir',
'exif-meteringmode-5' => 'Mynstur',
+'exif-meteringmode-6' => 'Að hluta',
'exif-meteringmode-255' => 'Annað',
'exif-lightsource-0' => 'Óþekkt',
'exif-lightsource-9' => 'Gott veður',
'exif-lightsource-10' => 'Skýjað',
'exif-lightsource-11' => 'Skuggi',
+'exif-lightsource-12' => 'Dagsljós flúrlýsing (D 5700 - 7100K)',
+'exif-lightsource-13' => 'Dagur hvít flúrlýsing (N 4600 - 5400K)',
+'exif-lightsource-14' => 'Köld hvít flúrlýsing (W 3900 - 4500K)',
+'exif-lightsource-15' => 'Hvít flúrlýsing (WW 3200 - 3700K)',
'exif-lightsource-17' => 'Staðaljós A',
'exif-lightsource-18' => 'Staðaljós B',
'exif-lightsource-19' => 'Staðaljós C',
+'exif-lightsource-24' => 'ISO stúdíótungsten',
'exif-lightsource-255' => 'Önnur ljósuppspretta',
# Flash modes
'exif-sensingmethod-4' => 'Þriggja-kísilflögu litsviðs skynjari',
'exif-sensingmethod-5' => 'Raðbundinn litsviðs skynjari',
+'exif-filesource-3' => 'Stafræn ljósmyndavél',
+
'exif-customrendered-0' => 'Venjuleg vinnsla',
'exif-customrendered-1' => 'Sérstök vinnsla',
'exif-objectcycle-p' => 'að kvöldi',
'exif-objectcycle-b' => 'að morgni og kvöldi',
+# Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t' => 'Raunátt',
+'exif-gpsdirection-m' => 'Segulátt',
+
'exif-ycbcrpositioning-1' => 'Miðjuð',
'exif-dc-contributor' => 'Framleggjendur',
'exif-dc-relation' => 'Tengd margmiðlunargögn',
'exif-dc-rights' => 'Réttindi',
'exif-dc-source' => 'Uppruni margmiðlunarskrár',
+'exif-dc-type' => 'Gerð miðlunarefnis',
'exif-rating-rejected' => 'Hafnað',
'exif-iimcategory-edu' => 'Menntun',
'exif-iimcategory-evn' => 'Umhverfi',
'exif-iimcategory-hth' => 'Heilsa',
+'exif-iimcategory-hum' => 'Maðurinn',
'exif-iimcategory-lab' => 'Verkamennska',
'exif-iimcategory-lif' => 'Lífstíll og tómstundagaman',
'exif-iimcategory-pol' => 'Pólitík',
'logentry-newusers-newusers' => 'Notandaaðgangurinn $1 var stofnaður',
'logentry-newusers-create' => 'Notandaaðgangurinn $1 var stofnaður',
'logentry-newusers-create2' => '$1 stofnaði notandaaðganginn $3',
-'logentry-newusers-byemail' => 'Notenda aðgangurinn $3 var búinn til af $1 og lykilorðið var sent með tölvupósti',
+'logentry-newusers-byemail' => 'Notandaaðgangurinn $3 var búinn til af $1 og lykilorðið var sent með tölvupósti',
'logentry-newusers-autocreate' => 'Aðgangurinn $1 var stofnaður sjálfvirkt',
'logentry-rights-rights' => '$1 breytti réttindum $3 frá $4 í $5',
'logentry-rights-rights-legacy' => '$1 breytti réttindum $3',
'api-error-ok-but-empty' => 'Innri villa: ekkert svar frá vefþjón.',
'api-error-overwrite' => 'Óheimilt er að skrifa yfir skrá sem er þegar til.',
'api-error-stashfailed' => 'Innri villa: Vefþjónninn gat ekki geymt tímabundna skrá.',
-'api-error-publishfailed' => 'Innri villa: Vefþjónninn gat ekki gefið út tímabundna skrá.',
+'api-error-publishfailed' => 'Innri villa: Vefþjónninn gat ekki gefið út bráðabirgðaskrá.',
'api-error-timeout' => 'Vefþjónninn svaraði ekki á tilætluðum tíma.',
'api-error-unclassified' => 'Óþekkt villa kom upp.',
'api-error-unknown-code' => 'Óþekkt villa: "$1"',
'confirm-unwatch-button' => 'OK',
'confirm-unwatch-top' => 'Elimina questa pagina dalla tua lista degli osservati speciali?',
+# Separators for various lists, etc.
+'percent' => '$1 %',
+
# Multipage image navigation
'imgmultipageprev' => '← pagina precedente',
'imgmultipagenext' => 'pagina seguente →',
'hidetoc' => '非表示',
'collapsible-collapse' => '折り畳む',
'collapsible-expand' => '展開する',
-'thisisdeleted' => '$1を閲覧または復元しますか?',
-'viewdeleted' => '$1を閲覧しますか?',
+'thisisdeleted' => '$1を閲覧または復元しますか?',
+'viewdeleted' => '$1を閲覧しますか?',
'restorelink' => '{{PLURAL:$1|削除された$1編集}}',
'feedlinks' => 'フィード:',
'feed-invalid' => 'フィード形式の指定が正しくありません。',
'page-atom-feed' => '「$1」のAtomフィード',
'feed-atom' => 'Atom',
'feed-rss' => 'RSS',
-'red-link-title' => '$1(存在しないページ)',
+'red-link-title' => '$1 (存在しないページ)',
'sort-descending' => '降順に並べ替え',
'sort-ascending' => '昇順に並べ替え',
'enterlockreason' => 'ロックの理由とロック解除の予定を入力してください',
'readonlytext' => 'データベースは現在、新しいページの追加や編集を受け付けない「ロック状態」になっています。これはおそらくデータベースの定期メンテナンスのためで、メンテナンス終了後は正常な状態に復帰します。
-データベースをロックした管理者による説明は以下の通りです:$1',
+データベースをロックした管理者による説明は以下の通りです: $1',
'missing-article' => '指定されたページ「$1」$2 の本文がデータベース内で見つかりませんでした。
通常、削除されたページの版への古い差分表示や固定リンクをたどった際に、このようなことが起きます。
# Virus scanner
'virus-badscanner' => "環境設定が不適合です: 不明なウイルス対策ソフトウェア: ''$1''",
-'virus-scanfailed' => 'スキャンに失敗しました(コード $1)',
+'virus-scanfailed' => 'スキャンに失敗しました (コード $1)',
'virus-unknownscanner' => '不明なウイルス対策ソフトウェア:',
# Login and logout pages
'createaccount' => 'アカウント作成',
'gotaccount' => 'アカウントを既に持っている場合、$1。',
'gotaccountlink' => 'ログインしてください',
-'userlogin-resetlink' => 'ログイン情報をお忘れですか?',
+'userlogin-resetlink' => 'ログイン情報をお忘れですか?',
'createaccountmail' => '一時的でランダムなパスワードを生成して、以下に指定したメールアドレスに送信する',
'createaccountreason' => '理由:',
'badretype' => '入力したパスワードが一致しません。',
'accountcreated' => 'アカウントを作成しました',
'accountcreatedtext' => '利用者アカウント「$1」を作成しました。',
'createaccount-title' => '{{SITENAME}}のアカウント作成',
-'createaccount-text' => '誰か(おそらくあなた)が、{{SITENAME}} ($4) にあなたのメールアドレスのアカウントを作成しました。
+'createaccount-text' => '誰か (おそらくあなた) が、{{SITENAME}} ($4) にあなたのメールアドレスのアカウントを作成しました。
アカウント名「$2」、パスワード「$3」です。
今すぐログインしてパスワードを変更してください。
# Change password dialog
'resetpass' => 'パスワードの変更',
'resetpass_announce' => 'メールでお送りした仮パスワードでログインしました。
-ログインを完了するには、ここで新しいパスワードを設定する必要があります:',
+ログインを完了するには、ここで新しいパスワードを設定する必要があります:',
'resetpass_text' => '<!-- ここに文を挿入 -->',
'resetpass_header' => 'アカウントのパスワードの変更',
'oldpassword' => '古いパスワード:',
'passwordreset-username' => '利用者名:',
'passwordreset-domain' => 'ドメイン:',
'passwordreset-capture' => 'お送りするメールの内容を表示しますか?',
-'passwordreset-capture-help' => 'このボックスにチェックを入れると、利用者に送信されるメールの内容(仮パスワードを含む)をあなたも閲覧できます。',
+'passwordreset-capture-help' => 'このボックスにチェックを入れると、利用者に送信されるメールの内容 (仮パスワードを含む) をあなたも閲覧できます。',
'passwordreset-email' => 'メールアドレス:',
'passwordreset-emailtitle' => '{{SITENAME}}上のアカウントの詳細',
'passwordreset-emailtext-ip' => '誰か (おそらくあなた、IP アドレス $1) が {{SITENAME}} ($4) での
'media_sample' => 'サンプル.ogg',
'media_tip' => 'ファイルへのリンク',
'sig_tip' => '時刻印付きの署名',
-'hr_tip' => '水平線を挿入(利用は控えめに)',
+'hr_tip' => '水平線を挿入 (利用は控えめに)',
# Edit pages
'summary' => '編集内容の要約:',
ブロックは$1によって実施されました。
ブロックの理由は ''$2'' です。
-* ã\83\96ã\83ã\83\83ã\82¯é\96\8bå§\8bæ\99\82æ\9c\9fï¼\9a$8
-* ブロック解除予定:$6
-* ブロック対象:$7
+* ã\83\96ã\83ã\83\83ã\82¯é\96\8bå§\8bæ\97¥æ\99\82: $8
+* ブロック解除予定: $6
+* ブロック対象: $7
このブロックについて、$1もしくは他の[[{{MediaWiki:Grouppage-sysop}}|管理者]]に問い合わせることができます。
ただし、[[Special:Preferences|個人設定]]で有効なメールアドレスが登録されていない場合、またはメール送信機能の使用がブロックされている場合、「この利用者にメールを送信」の機能は使えません。
:''$2''
-* ブロックの開始:$8
-* ブロック解除予定:$6
-* 意図されているブロック対象者:$7
+* ブロック開始日時: $8
+* ブロック解除予定: $6
+* ブロック対象: $7
$1または他の[[{{MediaWiki:Grouppage-sysop}}|管理者]]にこのブロックについて問い合わせることができます。
これらの引数を省略しました。",
'post-expand-template-argument-category' => '省略されたテンプレート引数を含むページ',
'parser-template-loop-warning' => 'テンプレートのループを検出しました: [[$1]]',
-'parser-template-recursion-depth-warning' => 'テンプレートの再帰の深さ($1)が上限を超えました',
-'language-converter-depth-warning' => '言語変換機能の深さ($1)が制限を超えました',
+'parser-template-recursion-depth-warning' => 'テンプレートの再帰の深さ ($1) が上限を超えました',
+'language-converter-depth-warning' => '言語変換機能の深さ ($1) が制限を超えました',
'node-count-exceeded-category' => 'ノード数が制限を超えたページ',
'node-count-exceeded-warning' => 'ページがノード数の制限を超えました',
'expansion-depth-exceeded-category' => '展開の深さ制限を超えたページ',
'expansion-depth-exceeded-warning' => 'ページが展開の深さ制限を超えました',
-'parser-unstrip-loop-warning' => 'Unstrip のループが検出されました',
-'parser-unstrip-recursion-limit' => 'Unstrip の再帰($1)が上限を超えました',
+'parser-unstrip-loop-warning' => 'unstrip のループを検出しました',
+'parser-unstrip-recursion-limit' => 'unstrip の再帰 ($1) が上限を超えました',
'converter-manual-rule-error' => '手動の言語変換規則でエラーを検出しました。',
# "Undo" feature
'mergehistory' => 'ページの履歴の統合',
'mergehistory-header' => 'このページでは、ある元ページの履歴を新しいページに統合できます。
この変更を行ってもページの履歴の連続性が確実に保たれるようにしてください。',
-'mergehistory-box' => '2ページの過去の版を統合する:',
-'mergehistory-from' => '統合元となるページ:',
-'mergehistory-into' => '統合先のページ:',
+'mergehistory-box' => '2ページの過去の版を統合する:',
+'mergehistory-from' => '統合元となるページ:',
+'mergehistory-into' => '統合先のページ:',
'mergehistory-list' => '統合できる編集履歴',
'mergehistory-merge' => '以下の [[:$1]] の履歴を [[:$2]] に統合できます。
特定の日時以前に作成された版のみを統合するには、ラジオボタンで版を選択してください。
'mergehistory-invalid-source' => '統合元のページは有効な名前でなければなりません。',
'mergehistory-invalid-destination' => '統合先のページは有効な名前でなければなりません。',
'mergehistory-autocomment' => '[[:$1]]を[[:$2]]に統合',
-'mergehistory-comment' => '[[:$1]]を[[:$2]]に統合:$3',
+'mergehistory-comment' => '[[:$1]]を[[:$2]]に統合: $3',
'mergehistory-same-destination' => '統合元と統合先のページを同じにはできません',
-'mergehistory-reason' => '理由:',
+'mergehistory-reason' => '理由:',
# Merge log
'mergelog' => '統合記録',
-'pagemerge-logentry' => '[[$1]]を[[$2]]に統合($3 版まで)',
+'pagemerge-logentry' => '[[$1]]を[[$2]]に統合 ($3 版まで)',
'revertmerge' => '統合解除',
'mergelogpagetext' => '以下は、最近行われたあるページから別のページへの統合の一覧です。',
# Diffs
'history-title' => '「$1」の変更履歴',
-'difference-title' => '$1:版間の差分',
-'difference-title-multipage' => '$1 と $2:ページ間の差分',
+'difference-title' => '「$1」の版間の差分',
+'difference-title-multipage' => 'ページ「$1」と「$2」の間の差分',
'difference-multipage' => '(ページ間の差分)',
-'lineno' => '$1行:',
+'lineno' => '$1行:',
'compareselectedversions' => '選択した版同士を比較',
'showhideselectedversions' => '選択した版を表示/非表示',
'editundo' => '取り消し',
'searchresults' => '検索結果',
'searchresults-title' => '「$1」の検索結果',
'searchresulttext' => '{{SITENAME}}の検索に関する詳しい情報は、[[{{MediaWiki:Helppage}}|{{int:help}}]]をご覧ください。',
-'searchsubtitle' => "'''[[:$1]]'''の検索([[Special:Prefixindex/$1|「$1」から始まるページ]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|「$1」へリンクしている全ページ]])",
+'searchsubtitle' => "'''[[:$1]]'''の検索 ([[Special:Prefixindex/$1|「$1」から始まるページ]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|「$1」へリンクしている全ページ]])",
'searchsubtitleinvalid' => "'''$1'''を検索しました",
'toomanymatches' => '一致したページが多すぎます。他の検索語を指定してください。',
'titlematches' => 'ページ名と一致',
'showingresultsnum' => "'''$2''' 件目以降の {{PLURAL:$3|'''$3''' 件の結果}}を表示しています。",
'showingresultsheader' => "「'''$4'''」の検索結果 {{PLURAL:$5|'''$3''' 件中の '''$1''' 件目|'''$3''' 件中の '''$1''' 件目から '''$2''' 件目}}",
'nonefound' => "'''注意''': 既定では一部の名前空間のみを検索します。
-''all:''を前に付けると、すべて(トークページやテンプレートなどを含む)を対象にできます。検索する名前空間を前に付けることもできます。",
+''all:''を前に付けると、すべて (トークページやテンプレートなどを含む) を対象にできます。検索する名前空間を前に付けることもできます。",
'search-nonefound' => '問い合わせに合致する検索結果はありませんでした。',
'powersearch' => '高度な検索',
'powersearch-legend' => '高度な検索',
'timezonelegend' => 'タイムゾーン:',
'localtime' => 'ローカルの時刻:',
'timezoneuseserverdefault' => 'ウィキの既定を使用 ($1)',
-'timezoneuseoffset' => 'その他(時差を指定)',
+'timezoneuseoffset' => 'その他 (時差を指定)',
'timezoneoffset' => '時差¹:',
'servertime' => 'サーバーの時刻:',
'guesstimezone' => 'ブラウザーの設定から入力',
'userrights-groups-help' => 'この利用者が属するグループを変更できます。
* チェックが入っているボックスは、この利用者がそのグループに属していることを意味します。
* チェックが入っていないボックスは、この利用者がそのグループに属していないことを意味します。
-* 「*」はグループに一旦追加した場合に除去(あるいはその逆)ができないことを示しています。',
+* 「*」はグループに一旦追加した場合に除去 (あるいはその逆) ができないことを示しています。',
'userrights-reason' => '理由:',
'userrights-no-interwiki' => '他ウィキ上における利用者権限の編集権限はありません。',
'userrights-nodatabase' => 'データベース$1は存在しないか、ローカル上にありません。',
# Rights
'right-read' => 'ページを閲覧',
'right-edit' => 'ページを編集',
-'right-createpage' => 'ページ(議論ページ以外)を作成',
+'right-createpage' => 'ページ (議論ページ以外) を作成',
'right-createtalk' => '議論ページを作成',
'right-createaccount' => '新しい利用者アカウントを作成',
'right-minoredit' => '細部の編集の印を付ける',
'right-bigdelete' => '大きな履歴があるページを削除',
'right-deletelogentry' => '特定の記録項目を削除/復元',
'right-deleterevision' => 'ページの特定の版を削除/復元',
-'right-deletedhistory' => '削除された履歴項目(関連する本文を除く)を閲覧',
+'right-deletedhistory' => '削除された履歴項目 (関連する本文を除く) を閲覧',
'right-deletedtext' => '削除された本文と削除された版間の差分を閲覧',
'right-browsearchive' => '削除されたページを検索',
'right-undelete' => 'ページを復元',
'right-proxyunbannable' => 'プロキシの自動ブロックを回避',
'right-unblockself' => '自身に対するブロックを解除',
'right-protect' => '保護レベルを変更し、保護されたページを編集',
-'right-editprotected' => '保護ページ(カスケード保護を除く)を編集',
+'right-editprotected' => '保護ページ (カスケード保護を除く) を編集',
'right-editinterface' => 'ユーザーインターフェイスを編集',
'right-editusercssjs' => '他の利用者のCSSファイル/JavaScriptファイルを編集',
'right-editusercss' => '他の利用者のCSSファイルを編集',
'boteditletter' => 'ボ',
'unpatrolledletter' => '!',
'number_of_watching_users_pageview' => '[{{PLURAL:$1|$1 人の利用者}}がウォッチしています]',
-'rc_categories' => 'カテゴリを限定(「|」で区切る)',
+'rc_categories' => 'カテゴリを限定 (「|」で区切る)',
'rc_categories_any' => 'すべて',
'rc-change-size' => '$1',
'rc-change-size-new' => '変更後は $1 {{PLURAL:$1|バイト}}',
'newsectionsummary' => '/* $1 */ 新しい節',
-'rc-enhanced-expand' => '詳細を表示(JavaScript が必要)',
+'rc-enhanced-expand' => '詳細を表示 (JavaScript が必要)',
'rc-enhanced-hide' => '詳細を非表示',
'rc-old-title' => '作成時のページ名は「$1」',
'recentchangeslinked-toolbox' => '関連ページの更新状況',
'recentchangeslinked-title' => '「$1」と関連する変更',
'recentchangeslinked-noresult' => '指定期間中に指定ページのリンク先に変更はありませんでした。',
-'recentchangeslinked-summary' => "これは指定したページからリンクされている(または指定したカテゴリに含まれている)ページの最近の変更の一覧です。
+'recentchangeslinked-summary' => "これは指定したページからリンクされている (または指定したカテゴリに含まれている) ページの最近の変更の一覧です。
[[Special:Watchlist|自分のウォッチリスト]]にあるページは'''太字'''で表示されます。",
'recentchangeslinked-page' => 'ページ名:',
'recentchangeslinked-to' => 'このページへのリンク元での変更の表示に切り替え',
新しい概要を表示させるには、説明ページを手動で編集する必要があります。
[[$1|thumb]]',
'fileexists-extension' => '類似した名前のファイルが既に存在します: [[$2|thumb]]
-* アップロード中のファイルの名前:<strong>[[:$1]]</strong>
+* アップロード中のファイルの名前: <strong>[[:$1]]</strong>
* 既存ファイルの名前: <strong>[[:$2]]</strong>
違う名前を選択してください。',
-'fileexists-thumbnail-yes' => "このファイルは元の画像から縮小されたもの''(サムネイル)''のようです。
+'fileexists-thumbnail-yes' => "このファイルは元の画像から縮小されたもの ''(サムネイル)'' のようです。
[[$1|thumb]]
-ファイル<strong>[[:$1]]</strong>を確認してください。
+ファイル <strong>[[:$1]]</strong> を確認してください。
確認したファイルが同じ画像の元のサイズの版の場合は、サムネイルを別途アップロードする必要はありません。",
-'file-thumbnail-no' => "ファイル名が<strong>$1</strong>から始まっています。
-他の画像から縮小されたもの''(サムネイル)''のようです。
+'file-thumbnail-no' => "ファイル名が <strong>$1</strong> で始まっています。
+他の画像から縮小されたもの ''(サムネイル)'' のようです。
より高精細な画像をお持ちの場合はそれをアップロードしてください。お持ちではない場合はファイル名を変更してください。",
'fileexists-forbidden' => 'この名前のファイルは既に存在しており、上書きできません。
アップロードを継続したい場合は、前のページに戻り、別のファイル名を使用してください。
'fileexists-shared-forbidden' => 'この名前のファイルは共有ファイルリポジトリに既に存在しています。
アップロードを継続したい場合は、前のページに戻り、別のファイル名を使用してください。
[[File:$1|thumb|center|$1]]',
-'file-exists-duplicate' => 'このファイルは以下の{{PLURAL:$1|ファイル|ファイル群}}と重複しています:',
-'file-deleted-duplicate' => 'このファイル([[:$1]])と同一のファイルが以前に削除されています。
+'file-exists-duplicate' => 'このファイルは以下の{{PLURAL:$1|ファイル|ファイル群}}と重複しています:',
+'file-deleted-duplicate' => 'このファイル ([[:$1]]) と同一のファイルが以前に削除されています。
再度アップロードをする前に、以前削除されたファイルの削除記録を確認してください。',
'uploadwarning' => 'アップロード警告',
'uploadwarning-text' => '下記のファイル解説を修正して再試行してください。',
それでもこのエラーが発生する場合は、[[Special:ListUsers/sysop|管理者]]に連絡してください。',
'upload-too-many-redirects' => 'そのURLに含まれるリダイレクトが多すぎます',
'upload-unknown-size' => 'サイズ不明',
-'upload-http-error' => 'HTTPエラー発生:$1',
+'upload-http-error' => 'HTTP エラー発生: $1',
'upload-copy-upload-invalid-domain' => 'このドメインからのアップロードは許可されていません。',
# File backend
'img-auth-bad-query-string' => 'URLの中に無効なクエリ文字列があります。',
# HTTP errors
-'http-invalid-url' => '無効なURL:$1',
+'http-invalid-url' => '無効なURL: $1',
'http-invalid-scheme' => 'スキーム「$1」の URL には未対応です。',
'http-request-error' => '不明なエラーによりHTTPリクエストに失敗しました。',
'http-read-error' => 'HTTP読み込みエラーです。',
'http-timed-out' => 'HTTP要求がタイムアウトしました。',
'http-curl-error' => 'URLからの取得に失敗しました: $1',
'http-host-unreachable' => 'URLに到達できません。',
-'http-bad-status' => 'HTTP要求中に問題が発生しました:$1$2',
+'http-bad-status' => 'HTTP リクエストで問題が発生しました: $1 $2',
# Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
'upload-curl-error6' => 'URLに到達できませんでした',
'filehist-comment' => 'コメント',
'filehist-missing' => 'ファイルがありません',
'imagelinks' => 'ファイルの使用状況',
-'linkstoimage' => '以下の {{PLURAL:$1| ページ|$1 ページ}}が、このファイルへリンクしています:',
+'linkstoimage' => '以下の{{PLURAL:1|ページ| $1 ページ}}がこのファイルにリンクしています:',
'linkstoimage-more' => 'このファイルへは $1 を超える数のページからリンクがあります。
以下の一覧ではこのファイルにリンクしている最初の $1 ページのみを表示しています。
[[Special:WhatLinksHere/$2|完全な一覧]]も参照してください。',
# Random page
'randompage' => 'おまかせ表示',
-'randompage-nopages' => '以下の{{PLURAL:$2|名前空間}}にはページがありません:$1。',
+'randompage-nopages' => '以下の{{PLURAL:$2|名前空間}}にはページがありません: $1',
# Random redirect
'randomredirect' => 'おまかせリダイレクト',
'allpagesprev' => '前へ',
'allpagesnext' => '次へ',
'allpagessubmit' => '表示',
-'allpagesprefix' => '次の文字列から始まるページを表示:',
+'allpagesprefix' => '次の文字列から始まるページを表示:',
'allpagesbadtitle' => '指定したページ名は無効か、言語間またはインターウィキ接頭辞を含んでいます。
ページ名に使用できない文字が1つ以上含まれている可能性があります。',
'allpages-bad-ns' => '{{SITENAME}}に「$1」という名前空間はありません。',
'categoriespagetext' => '以下の{{PLURAL:$1|カテゴリ}}にはページまたはメディアがあります。
[[Special:UnusedCategories|未使用のカテゴリ]]はここには表示していません。
[[Special:WantedCategories|望まれるカテゴリ]]も参照してください。',
-'categoriesfrom' => '最初に表示するカテゴリ:',
+'categoriesfrom' => '最初に表示するカテゴリ:',
'special-categories-sort-count' => '項目数順に並べ替え',
'special-categories-sort-abc' => '辞書順に並べ替え',
'listgrouprights-members' => '(該当者一覧)',
'listgrouprights-right-display' => '<span class="listgrouprights-granted">$1 (<code>$2</code>)</span>',
'listgrouprights-right-revoked' => '<span class="listgrouprights-revoked">$1 (<code>$2</code>)</span>',
-'listgrouprights-addgroup' => '{{PLURAL:$2|グループ}}を追加:$1',
-'listgrouprights-removegroup' => '{{PLURAL:$2|グループ}}を除去:$1',
+'listgrouprights-addgroup' => '{{PLURAL:$2|グループ}}を追加: $1',
+'listgrouprights-removegroup' => '{{PLURAL:$2|グループ}}を除去: $1',
'listgrouprights-addgroup-all' => '全グループを追加可能',
'listgrouprights-removegroup-all' => '全グループを除去可能',
-'listgrouprights-addgroup-self' => '自分のアカウントに{{PLURAL:$2|グループ}}を追加:$1',
-'listgrouprights-removegroup-self' => '自分のアカウントから{{PLURAL:$2|グループ}}を除去:$1',
+'listgrouprights-addgroup-self' => '自身のアカウントに{{PLURAL:$2|グループ}}を追加: $1',
+'listgrouprights-removegroup-self' => '自身のアカウントから{{PLURAL:$2|グループ}}を除去: $1',
'listgrouprights-addgroup-self-all' => '自分のアカウントに全グループを追加可能',
'listgrouprights-removegroup-self-all' => '自分のアカウントから全グループを除去可能',
'emailpage' => '利用者にメールを送信',
'emailpagetext' => '以下のフォームを使用してこの{{GENDER:$1|利用者}}にメールを送信できます。
「差出人」として、[[Special:Preferences|利用者の個人設定]]で入力したメールアドレスが設定されます。これにより、受信者があなたに直接返信できるようになります。',
-'usermailererror' => 'メールが以下のエラーを返しました:',
+'usermailererror' => 'メールが以下のエラーを返しました:',
'defemailsubject' => '{{SITENAME}} 利用者「$1」からのメール',
'usermaildisabled' => '利用者メール機能は無効です',
'usermaildisabledtext' => 'このウィキでは他の利用者にメールを送信できません',
$PAGEINTRO $NEWPAGE
-編集内容の要約:$PAGESUMMARY($PAGEMINOREDIT)
+編集内容の要約: $PAGESUMMARY ($PAGEMINOREDIT)
-投稿者の連絡先:
-メール:$PAGEEDITOR_EMAIL
-ウィキ:$PAGEEDITOR_WIKI
+投稿者の連絡先:
+メール: $PAGEEDITOR_EMAIL
+ウィキ: $PAGEEDITOR_WIKI
このページを訪れない限り、これ以上の活動に対する通知は送信されません。ウォッチリスト内のすべてのページについて、通知を再設定することもできます。
{{SITENAME}}通知システム
--
-メール通知の設定は、以下のページで変更してください:
+メール通知の設定は、以下のページで変更してください:
{{canonicalurl:{{#special:Preferences}}}}
-ウォッチリストの設定は、以下のページで変更してください:
+ウォッチリストの設定は、以下のページで変更してください:
{{canonicalurl:{{#special:EditWatchlist}}}}
-このページは、以下のページでウォッチリストから削除できます:
+このページは、以下のページでウォッチリストから削除できます:
$UNWATCHURL
-ご意見、お問い合わせ:
+ご意見、お問い合わせ:
{{canonicalurl:{{MediaWiki:Helppage}}}}',
'created' => '作成',
'changed' => '変更',
'rollbackfailed' => '巻き戻しに失敗しました',
'cantrollback' => '編集を差し戻せません。
最後の投稿者が、このページの唯一の作者です。',
-'alreadyrolled' => 'ページ[[:$1]]の[[User:$2|$2]]([[User talk:$2|トーク]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]])による編集を巻き戻せません。
+'alreadyrolled' => 'ページ[[:$1]]の[[User:$2|$2]] ([[User talk:$2|トーク]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) による編集を巻き戻せません。
他の利用者が既に編集または巻き戻しを行ったためです。
-このページの最後の編集は[[User:$3|$3]]([[User talk:$3|トーク]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]])によるものです。',
+このページの最後の編集は[[User:$3|$3]] ([[User talk:$3|トーク]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) によるものです。',
'editcomment' => "編集内容の要約:「''$1''」",
-'revertpage' => '[[Special:Contributions/$2|$2]]([[User talk:$2|トーク]])による編集を[[User:$1|$1]]による直前の版へ差し戻しました',
-'revertpage-nouser' => '(利用者名削除)による編集を[[User:$1|$1]]による直前の版へ差し戻しました',
+'revertpage' => '[[Special:Contributions/$2|$2]] ([[User talk:$2|トーク]]) による編集を[[User:$1|$1]]による直前の版へ差し戻しました',
+'revertpage-nouser' => '(利用者名削除) による編集を[[User:$1|$1]]による直前の版へ差し戻しました',
'rollback-success' => '$1による編集を差し戻しました。
$2による直前の版へ変更されました。',
** 高負荷ページ',
'protect-edit-reasonlist' => '保護理由を編集',
'protect-expiry-options' => '1時間:1 hour,1日:1 day,1週間:1 week,2週間:2 weeks,1か月:1 month,3か月:3 months,6か月:6 months,1年:1 year,無期限:infinite',
-'restriction-type' => '許可:',
-'restriction-level' => '制限レベル:',
+'restriction-type' => '許可:',
+'restriction-level' => '制限レベル:',
'minimum-size' => '最小サイズ',
-'maximum-size' => '最大サイズ:',
+'maximum-size' => '最大サイズ:',
'pagesize' => '(バイト)',
# Restrictions (nouns)
移動先が既に存在する場合は、そのページが転送ページであり、かつ過去の版を持たない場合を除いて移動'''できません'''。
つまり、間違えてページ名を変更した場合には元に戻せます。また移動によって既存のページを上書きしてしまうことはありません。
-'''警告!'''
+'''警告!'''
多く閲覧されるページや多くリンクされているページを移動すると、予期しない大きな変化が起こるかもしれないことにご注意ください。
ページの移動に伴う影響をよく考えてから移動してください。",
'movepagetalktext' => "関連付けられたトークページも一緒に、自動的に移動されます。ただし、'''以下の場合を除きます:'''
'importbadinterwiki' => 'ウィキ間リンクが正しくありません',
'importnotext' => '内容が空、または本文がありません',
'importsuccess' => '取り込みが完了しました!',
-'importhistoryconflict' => '取り込み時にいくつかの版が競合しました(以前に同じページが取り込まれているかもしれません)',
+'importhistoryconflict' => '取り込み時にいくつかの版が競合しました (以前に同じページが取り込まれているかもしれません)',
'importnosources' => 'ウィキ間移動の取り込み元が定義されていないため、履歴の直接アップロードは無効になっています。',
'importnofile' => '取り込みファイルはアップロードされませんでした。',
'importuploaderrorsize' => '取り込みファイルのアップロードに失敗しました。
'javascripttest-title' => '$1 のテストの実行',
'javascripttest-pagetext-noframework' => 'このページは JavaScript のテストを実行するために予約されています。',
'javascripttest-pagetext-unknownframework' => 'テストフレームワーク「$1」は不明です。',
-'javascripttest-pagetext-frameworks' => '次のテストフレームワークからひとつを選択してください:$1',
-'javascripttest-pagetext-skins' => 'テストを実行する外装を選択してください:',
+'javascripttest-pagetext-frameworks' => '以下のテストフレームワークから1つ選択してください: $1',
+'javascripttest-pagetext-skins' => 'テストを実行する外装を選択してください:',
'javascripttest-qunit-intro' => 'mediawiki.org上の[$1 テストのドキュメント]を参照してください。',
'javascripttest-qunit-heading' => 'MediaWiki JavaScript QUnit テストスイート',
'spamprotectiontitle' => 'スパム防御フィルター',
'spamprotectiontext' => '保存しようとした文章はスパムフィルターによってブロックされました。
これはおそらく、ブラックリストにある外部サイトへのリンクが原因で発生します。',
-'spamprotectionmatch' => '以下の文章はスパムフィルターが発動したものです:$1',
+'spamprotectionmatch' => '以下の文章はスパムフィルターが発動したものです: $1',
'spambot_username' => 'MediaWikiスパム除去',
'spam_reverting' => '$1へのリンクを含まない最新の版に差し戻し',
'spam_blanking' => 'すべての版が$1へのリンクを含んでいます。白紙化します。',
'just-now' => 'ちょうど今',
# Bad image list
-'bad_image_list' => '書式は以下の通りです:
+'bad_image_list' => '書式は以下の通りです:
-箇条書き項目(*で始まる行)のみが考慮されます。
-各行最初のリンクは、好ましくないファイルへのリンクとしてください。
-å\90\8cã\81\98è¡\8cã\81§それ以降にあるリンクは例外、つまりインライン挿入されてもいいページと見なされます。',
+箇条書き項目 (*で始まる行) のみが考慮されます。
+各行の最初のリンクは、好ましくないファイルへのリンクにしてください。
+å\90\8cã\81\98è¡\8cã\81®それ以降にあるリンクは例外、つまりインライン挿入されてもいいページと見なされます。',
/*
Short names for language variants used for language conversion links.
'exif-gpslongitude' => '経度',
'exif-gpsaltituderef' => '高度の基準',
'exif-gpsaltitude' => '高度',
-'exif-gpstimestamp' => 'GPS日時(原子時計)',
+'exif-gpstimestamp' => 'GPS日時 (原子時計)',
'exif-gpssatellites' => '測位に用いた衛星信号',
'exif-gpsstatus' => 'GPS受信機の状態',
'exif-gpsmeasuremode' => 'GPSの測位方法',
'exif-label' => 'ラベル',
'exif-datetimemetadata' => 'メタデータの最終更新日',
'exif-nickname' => '画像の非公式名',
-'exif-rating' => '評価(5点満点)',
+'exif-rating' => '評価 (5点満点)',
'exif-rightscertificate' => '権利管理証明書',
'exif-copyrighted' => '著作権情報',
'exif-copyrightowner' => '著作権者',
$3
もしアカウントの登録をした覚えがない場合は、
-次のURLをブラウザーで開いて、メールアドレスの確認を中止してください:
+次のURLをブラウザーで開いて、メールアドレスの確認をキャンセルしてください:
$5
この確認用コードは、$4に期限切れになります。',
-'confirmemail_body_changed' => '誰か(おそらくあなた)が IP アドレス $1 から、
+'confirmemail_body_changed' => '誰か (おそらくあなた) が IP アドレス $1 から、
{{SITENAME}} のアカウント「$2」のメールアドレスをこのアドレスに変更しました。
このアカウントが本当にあなたのものであれば、以下のリンクをブラウザーで開いて、
-{{SITENAME}} のメール機能を再び有効にしてください:
+{{SITENAME}} のメール機能を再び有効にしてください:
$3
もしあなたのアカウント *ではない* 場合は、
-ブラウザーで以下のリンクを開いて、メールアドレスの確認をキャンセルしてください:
+ブラウザーで以下のリンクを開いて、メールアドレスの確認をキャンセルしてください:
$5
この確認コードは $4 に期限切れになります。',
-'confirmemail_body_set' => '誰か(おそらくあなた)が IP アドレス $1 から
+'confirmemail_body_set' => '誰か (おそらくあなた) が IP アドレス $1 から
{{SITENAME}} のアカウント「$2」のメールアドレスをこのアドレスに設定しました。
このアカウントが本当にあなたのものであれば、以下のリンクをブラウザーで開いて、
$3
もしあなたのアカウントではない場合は、
-次のリンクをブラウザーで開いて、メールアドレスの確認をキャンセルしてください:
+次のリンクをブラウザーで開いて、メールアドレスの確認をキャンセルしてください:
$5
'hebrew-calendar-m12-gen' => 'エルール',
# Signatures
-'signature' => '[[{{ns:user}}:$1|$2]]([[{{ns:user_talk}}:$1|トーク]])',
+'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|トーク]])',
# Core parser functions
'unknown_extension_tag' => '不明な拡張機能タグ「$1」です',
'version-poweredby-credits' => "このウィキは、'''[//www.mediawiki.org/ MediaWiki]'''(copyright © 2001-$1 $2)で動作しています。",
'version-poweredby-others' => 'その他',
'version-credits-summary' => '[[Special:Version|MediaWiki]] に貢献した以下の人たちに感謝します。',
-'version-license-info' => 'MediaWikiはフリーソフトウェアです。あなたは、フリーソフトウェア財団の発行するGNU一般公衆利用許諾書 (GNU General Public License)(バージョン2、またはそれ以降のライセンス)の規約に基づき、このライブラリを再配布および改変できます。
+'version-license-info' => 'MediaWikiはフリーソフトウェアです。あなたは、フリーソフトウェア財団の発行するGNU一般公衆利用許諾書 (GNU General Public License) (バージョン2、またはそれ以降のライセンス) の規約に基づき、このライブラリを再配布および改変できます。
MediaWikiは、有用であることを期待して配布されていますが、商用あるいは特定の目的に適するかどうかも含めて、暗黙的にも、一切保証されません。詳しくは、GNU一般公衆利用許諾書をご覧ください。
-あなたはこのプログラムと共に、[{{SERVER}}{{SCRIPTPATH}}/COPYING GNU一般公衆利用許諾契約書の複製]を受け取ったはずです。もし受け取っていなければ、フリーソフトウェア財団(the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA)まで請求するか、[//www.gnu.org/licenses/old-licenses/gpl-2.0.html オンラインで閲覧]してください。',
+あなたはこのプログラムと共に、[{{SERVER}}{{SCRIPTPATH}}/COPYING GNU一般公衆利用許諾契約書の複製]を受け取ったはずです。受け取っていない場合は、フリーソフトウェア財団 (the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA) まで請求するか、[//www.gnu.org/licenses/old-licenses/gpl-2.0.html オンラインで閲覧]してください。',
'version-software' => 'インストール済みソフトウェア',
'version-software-product' => '製品',
'version-software-version' => 'バージョン',
# External image whitelist
'external_image_whitelist' => ' #この行はこのままにしておいてください<pre>
-#この下に正規表現(//の間に入る記述)を置いてください
-#外部の(ホットリンクされている)画像の URL と一致するか検査されます
+#この下に正規表現 (//の間に入る記述) を置いてください
+#外部の (ホットリンクされている) 画像の URL と一致するか検査されます
#一致する場合は画像として、一致しない場合は画像へのリンクとして表示されます
#行の頭に # を付けるとコメントとして扱われます
#大文字と小文字は区別されません
# Special:Tags
'tags' => '有効な変更タグ',
-'tag-filter' => '[[Special:Tags|タグ]]絞り込み:',
+'tag-filter' => '[[Special:Tags|タグ]]絞り込み:',
'tag-filter-submit' => '絞り込み',
'tags-title' => 'タグ',
'tags-intro' => 'このページは、ソフトウェアが編集に対して付けるタグとその意味の一覧です。',
'htmlform-selectorother-other' => 'その他',
# SQLite database support
-'sqlite-has-fts' => '$1(全文検索あり)',
-'sqlite-no-fts' => '$1(全文検索なし)',
+'sqlite-has-fts' => '$1 (全文検索あり)',
+'sqlite-no-fts' => '$1 (全文検索なし)',
# New logging system
'logentry-delete-delete' => '$1 がページ「$3」を削除しました',
'logentry-delete-restore' => '$1 がページ「$3」を復元しました',
-'logentry-delete-event' => '$1 が$3の{{PLURAL:$5|記録項目$5件}}の閲覧レベルを変更しました:$4',
-'logentry-delete-revision' => '$1 がページ「$3」の{{PLURAL:$5|$5版}}の閲覧レベルを変更しました:$4',
+'logentry-delete-event' => '$1 が$3の{{PLURAL:$5|記録項目$5件}}の閲覧レベルを変更しました: $4',
+'logentry-delete-revision' => '$1 がページ「$3」の{{PLURAL:$5|$5版}}の閲覧レベルを変更しました: $4',
'logentry-delete-event-legacy' => '$1 が「$3」の記録項目の閲覧レベルを変更しました',
'logentry-delete-revision-legacy' => '$1 がページ「$3」の版の閲覧レベルを変更しました',
'logentry-suppress-delete' => '$1 がページ「$3」を隠蔽しました',
-'logentry-suppress-event' => '$1 が$3の{{PLURAL:$5|記録項目$5件}}の閲覧レベルを見えない形で変更しました:$4',
-'logentry-suppress-revision' => '$1 がページ「$3」の{{PLURAL:$5|$5版}}の閲覧レベルを見えない形で変更しました:$4',
+'logentry-suppress-event' => '$1 が$3の{{PLURAL:$5|記録項目$5件}}の閲覧レベルを見えない形で変更しました: $4',
+'logentry-suppress-revision' => '$1 がページ「$3」の{{PLURAL:$5|$5版}}の閲覧レベルを見えない形で変更しました: $4',
'logentry-suppress-event-legacy' => '$1 が$3で記録項目の閲覧レベルを見えない形で変更しました',
'logentry-suppress-revision-legacy' => '$1 がページ「$3」の版の閲覧レベルを見えない形で変更しました',
'revdelete-content-hid' => '本文の不可視化',
# Feedback
'feedback-bugornote' => '技術的な問題の詳細を説明する準備ができている場合は、[$1 バグ報告]をお願いします。
準備ができていない場合は、下の簡易フォームを使用してください。あなたのコメントと利用者名が、ページ「[$3 $2]」に追加されます。',
-'feedback-subject' => '件名:',
-'feedback-message' => 'メッセージ:',
+'feedback-subject' => '件名:',
+'feedback-message' => 'メッセージ:',
'feedback-cancel' => 'キャンセル',
'feedback-submit' => 'フィードバックを送信',
'feedback-adding' => 'ページへのフィードバックの追加...',
'statistics-pages' => 'გვერდები',
'statistics-pages-desc' => 'ვიკის ყველა გვერდი, განხილვის, გადამისამართების და სხვ. ჩათვლით.',
'statistics-files' => 'ატვირთული ფაილები',
-'statistics-edits' => 'გვერდის შესწორებები {{SITENAME}}-ის შექმნიდან',
+'statistics-edits' => 'გვერდის შესწორებები პროექტის {{SITENAME}} შექმნის შემდეგ',
'statistics-edits-average' => 'რედაქტირების საერთო რაოდენობა გვერდზე',
'statistics-views-total' => 'სულ ხილვა',
'statistics-views-total-desc' => 'სათვალავში არ მიიღება არარსებული და სამუშაო გვერდების გადახედვა',
'exif-lens' => 'გამოყენებული ლინზა',
'exif-serialnumber' => 'კამერის სერიული ნომერი',
'exif-cameraownername' => 'კამერის მფლობელი',
-'exif-label' => 'á\83\98á\83\90á\83 á\83\9aá\83\98á\83§ი',
+'exif-label' => 'á\83¡á\83\90á\83®á\83\94á\83\9aი',
'exif-datetimemetadata' => 'მეტამონაცემების ბოლო ცვლილების თარიღი',
'exif-nickname' => 'სურათის არაფორმალური სახელი',
'exif-rating' => 'რეიტინგი (5-დან)',
* @author Nayvik
* @author Nk rahul14
* @author Omshivaprakash
+ * @author Prashwiki
* @author Shankar
* @author Shushruth
* @author Teju2friends
'newwindow' => '(새 창으로 열림)',
'cancel' => '취소',
'moredotdotdot' => '더 보기...',
-'morenotlisted' => '목ë¡\9dì\97\90 ì\97\86ë\8a\94 항목 더 보기...',
+'morenotlisted' => 'ë\8b¤ë¥¸ 항목 더 보기...',
'mypage' => '문서',
'mytalk' => '토론',
'anontalk' => '익명 사용자 토론',
'action-sendemail' => '이메일 보내기',
# Recent changes
-'nchanges' => '$1개 바뀜',
+'nchanges' => '$1개 {{PLURAL:$1|바뀜}}',
'recentchanges' => '최근 바뀜',
'recentchanges-legend' => '최근 바뀜 설정',
'recentchanges-summary' => '위키의 최근 바뀜 내역이 나와 있습니다.',
'recentchanges-label-minor' => '사소한 편집',
'recentchanges-label-bot' => '봇의 편집',
'recentchanges-label-unpatrolled' => '아직 검토하지 않은 편집',
-'rcnote' => "다음은 $4 $5 까지의 '''$2'''일동안 바뀐 문서 '''$1'''개입니다.",
+'rcnote' => "다음은 $4 $5 까지의 {{PLURAL:$2|'''$2'''일}}동안 {{PLURAL:$1|바뀐 문서 '''$1'''개입니다}}.",
'rcnotefrom' => "다음은 '''$2'''에서부터 바뀐 문서 '''$1'''개입니다.",
'rclistfrom' => '$1 이래로 바뀐 문서',
'rcshowhideminor' => '사소한 편집을 $1',
'undeletehistory' => '문서를 되살리면 모든 역사가 같이 복구됩니다.
문서가 삭제된 뒤 같은 이름의 문서가 만들어졌다면, 복구되는 역사는 지금 역사의 과거 부분에 나타날 것입니다.',
'undeleterevdel' => '복구하려는 문서의 최신판이 삭제되어 있는 경우 문서를 복구시킬 수 없습니다.
-이러한 경우, 삭제된 최신판 문서의 체크박스를 선택 해제하거나 숨김을 해제해야 합니다.',
+이러한 경우 삭제된 최신판 문서의 확인 상자를 선택 해제하거나 숨김을 해제해야 합니다.',
'undeletehistorynoadmin' => '이 문서는 삭제되었습니다.
삭제된 이유와 삭제되기 전에 이 문서를 편집한 사용자가 아래에 나와 있습니다.
삭제된 문서의 내용을 보려면 관리자 권한이 필요합니다.',
'pageinfo-authors' => '총 서로 다른 편집자 수',
'pageinfo-recent-edits' => '최근 편집 수 (지난 $1 이내)',
'pageinfo-recent-authors' => '최근 기여자 수',
-'pageinfo-magic-words' => '매직 {{PLURAL:$1|워드}} ($1개)',
+'pageinfo-magic-words' => '특수 {{PLURAL:$1|명령}} ($1개)',
'pageinfo-hidden-categories' => '숨은 {{PLURAL:$1|분류}} ($1개)',
'pageinfo-templates' => '포함한 {{PLURAL:$1|틀}} ($1개)',
'pageinfo-transclusions' => '포함한 {{PLURAL:$1|문서}} ($1개)',
'watchlistedit-normal-title' => '주시문서 목록 편집하기',
'watchlistedit-normal-legend' => '주시문서 목록에서 문서 제거하기',
'watchlistedit-normal-explain' => '주시문서 목록에 있는 문서의 제목이 아래에 나열되어 있습니다.
-주시문서 목록에서 제거하려는 문서가 있으면, 각 항목의 체크박스를 선택한 다음 "{{int:Watchlistedit-normal-submit}}"를 클릭해주세요.
+주시문서 목록에서 제거하려는 문서가 있으면 각 항목의 확인 상자를 선택한 다음 "{{int:Watchlistedit-normal-submit}}"를 클릭해주세요.
또는 [[Special:EditWatchlist/raw|목록을 직접 편집]]할 수도 있습니다.',
'watchlistedit-normal-submit' => '항목 삭제',
'watchlistedit-normal-done' => '주시문서 목록에서 다음 {{PLURAL:$1|항목}}을 주시하지 않습니다:',
'tags-description-header' => '태그에 대한 설명',
'tags-hitcount-header' => '태그된 바뀜',
'tags-edit' => '편집',
-'tags-hitcount' => '$1개 바뀜',
+'tags-hitcount' => '$1개 {{PLURAL:$1|바뀜}}',
# Special:ComparePages
'comparepages' => '문서 비교',
'tags-description-header' => 'Bedüggtening',
'tags-hitcount-header' => 'Makeete Änderunge',
'tags-edit' => 'ändere',
-'tags-hitcount' => '{{PLURAL:$1|Ein Änderong|$1 Änderonge|kein Änderonge}}',
+'tags-hitcount' => '{{PLURAL:$1|Ein Änderong|$1 Änderonge|Kein Änderonge}}',
# Special:ComparePages
'comparepages' => 'Sigge verjliesche',
'userjspreview' => "'''Zanibe ku tu tenê JavaScript'a xwe diceribînî, ew hê nehatiye tomarkirin!'''",
'updated' => '(Hate rojanekirin)',
'note' => "'''Nîşe:'''",
-'previewnote' => "'''Ji bîr neke ku ev bi tenê çavdêriyek e, ev rûpel hîn nehatiye tomarkirin!'''",
+'previewnote' => "'''Ji bîr neke ku ev bi tenê çavdêriyek e.'''
+Ev rûpel hîn nehatiye tomarkirin!",
'continue-editing' => 'Guhertinê bidomîne',
'editing' => 'Biguherîne: "$1"',
'creating' => '$1 tê çêkirin',
'siteusers' => '{{PLURAL:$2|usor|usores}} {{grammar:genitive|{{SITENAME}}}} $1',
'creditspage' => 'Auctores paginae',
+# Info page
+'pageinfo-title' => 'Res quae ad "$1" pertinent',
+'pageinfo-header-basic' => 'De hac pagina',
+'pageinfo-display-title' => 'Titulus ut in pagina ipsa monstratur',
+'pageinfo-length' => 'Magnitudo paginae (octeti)',
+'pageinfo-article-id' => 'Identificatio paginis',
+'pageinfo-language' => 'Lingua verborum in pagina',
+'pageinfo-firstuser' => 'Creator paginae',
+'pageinfo-firsttime' => 'Dies et tempus creationis paginae',
+'pageinfo-lastuser' => 'Usor qui ultimam recensionem fecit',
+'pageinfo-lasttime' => 'Dies ultimae emendationis',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Categoria celata|Categoriae celatae}} ($1)',
+'pageinfo-toolboxlink' => 'De hac pagina',
+
# Skin names
'skinname-standard' => 'Norma',
'skinname-cologneblue' => 'Caerulus Colonia',
Den Administrateur den d'Datebank gespaart huet, huet dës Erklärung ginn: $1",
'protectedpagewarning' => "'''OPGEPASST: Dës Säit gouf gespaart a kann nëmme vun engem Administrateur geännert ginn.''' Déi lescht Zeil aus de Logbicher fannt Dir zu Ärer Informatioun hei ënnendrënner.",
-'semiprotectedpagewarning' => "'''Bemierkung:''' Dës Säit gouf esou gespaart, datt nëmme ugemellte Benotzer s'ännere kënnen. Déi lescht Zeil aus de Logbicher fannt Dir zu Ärer Informatioun hei ënnendrënner.",
+'semiprotectedpagewarning' => "'''Bemierkung:''' Dës Säit gouf esou gespaart, datt nëmme ugemellt Benotzer s'ännere kënnen. Déi lescht Zeil aus de Logbicher fannt Dir zu Ärer Informatioun hei ënnendrënner.",
'cascadeprotectedwarning' => "'''Passt op:''' Dës Säit gouf gespaart a kann nëmme vu Benotzer mat Administreursrechter geännert ginn. Si ass an dës {{PLURAL:$1|Säit|Säiten}} agebonnen, déi duerch Cascadespäroptioun gespaart {{PLURAL:$1|ass|sinn}}:'''",
'titleprotectedwarning' => "'''OPGEPASST: Dës Säit gouf gespaart sou datt [[Special:ListGroupRights|spezifesch Rechter]] gebraucht gi fir se uleeën ze kënnen.''' Déi lescht Zeil aus de Logbicher fannt Dir zu Ärer Informatioun hei ënnendrënner.",
'templatesused' => '{{PLURAL:$1|Schabloun|Schablounen}} déi op dëser Säit am Gebrauch sinn:',
# Restriction levels
'restriction-level-sysop' => 'ganz gespaart',
-'restriction-level-autoconfirmed' => 'hallef-gespaart (nëmmen ugemellte Benotzer déi net nei sinn)',
+'restriction-level-autoconfirmed' => 'hallef gespaart (nëmmen ugemellt Benotzer déi net nei sinn)',
'restriction-level-all' => 'alleguerten',
# Undelete
'blanknamespace' => '(Haapt)',
# Contributions
-'contributions' => 'Kontributioune {{GENDER:$1|vum Benotzer $1}}',
+'contributions' => '{{GENDER:$1|Benotzer}}kontributiounen',
'contributions-title' => 'Kontributioune vum $1',
'mycontris' => 'Kontributiounen',
'contribsub2' => 'Fir $1 ($2)',
'import-error-interwiki' => 'D\'Säit "$1" gouf net importéiert well deen Numm fir extern Linken (Interwiki) reservéiert ass.',
'import-error-special' => 'D\'Säit "$1" gouf net importéiert well se zu engem speziellen Nummraum gehéiert an deem et keng Säite gëtt.',
'import-error-invalid' => 'D\'Säit "$1" gouf net importéiert well hiren Numm net valabel ass.',
+'import-error-unserialize' => 'D\'Versioun $2 vun der Säit "$1" konnt net deserialiséiert ginn. Et gouf uginn datt déi Versioun den Inhaltsmodell $3 benotzt deen als $4 serialiséiert ass.',
'import-options-wrong' => 'Falsch {{PLURAL:$2|Optioun|Optiounen}}: <nowiki>$1</nowiki>',
'import-rootpage-invalid' => 'Déi Basis-Säit déi Dir uginn hutt ass kee valabelen Titel.',
'import-rootpage-nosubpage' => 'Am Nummraum "$1" vun der Basis-Säit si keng Ënnersäiten erlaabt.',
'pageinfo-length' => 'Gréisst vun der Säit (a Bytes)',
'pageinfo-article-id' => 'ID (Nummer) vun der Säit',
'pageinfo-language' => 'Sprooch vum Inhalt vun der Säit',
+'pageinfo-robot-policy' => 'Sichmaschinnestatus',
+'pageinfo-robot-index' => 'Indexéierbar',
'pageinfo-robot-noindex' => 'Net indexéierbar',
'pageinfo-views' => 'Zuel vun de Kéieren déi dës Säit gekuckt gouf',
'pageinfo-watchers' => "Zuel vun de Benotzer déi d'Säit iwwerwaachen",
'pageinfo-magic-words' => '{{PLURAL:$1|Magescht Wuert|Magesch Wierder}} ($1)',
'pageinfo-hidden-categories' => 'Verstoppte {{PLURAL:$1|Kategorie|Kategorien}} ($1)',
'pageinfo-templates' => 'Agebonne {{PLURAL:$1|Schabloun|Schabloune}} ($1)',
+'pageinfo-transclusions' => 'Agebonnen {{PLURAL:$1|an eng Säit|a(n) $1 Säiten}}',
'pageinfo-toolboxlink' => "Informatiounen iwwert d'Säit",
'pageinfo-redirectsto' => 'Viruleedung op',
'pageinfo-redirectsto-info' => 'Informatioun',
'subject' => 'Тема/кьилинцIар',
'minoredit' => 'ГъвечIи дуьзар хъувун',
'watchthis' => 'И ччин гуьзетун',
-'savearticle' => 'ЧÑ\87ин Ñ\85Ñ\83Ñ\8cн',
+'savearticle' => 'ЧÑ\8aин Ñ\85вин',
'preview' => 'Сифтедин килигун',
'showpreview' => 'Сифтедин килигун къалурун',
'showlivepreview' => 'Фад сифтедин килигун',
'revertmerge' => 'Ччара авун',
# Diffs
-'history-title' => 'Masak\'avilerin q\'isa "$1"',
+'history-title' => '$1 - масакӀавилерин тарих',
'lineno' => 'ЦIар $1:',
'compareselectedversions' => 'Хкягъай жуьреяр гекъигун',
'editundo' => 'гьич авун',
'recentchangeslinked-toolbox' => 'Галкlанвай масакIавилер',
'recentchangeslinked-title' => '"$1" галаз галкlанавай масакIавилер',
'recentchangeslinked-noresult' => 'Ганвай чlава галкlанавай ччинра са масакIавални хьанвайд туш',
-'recentchangeslinked-summary' => 'Им къалурай ччиниз (ва я къалурай категориядиз гьатзавай ччинриз) элячIзавай ччинра мукьвара хьайи масакIавилерин сиягь я. Куь [[Special:Watchlist| вилив хуьнин сиягь ]]диз гьатзавай ччинар яцlу шрифтдал къалурнава.',
+'recentchangeslinked-summary' => 'Им къалурай ччиниз (ва я къалурай категориядиз гьатзавай ччинриз) элячӀзавай ччинра мукьвара хьайи масакӀавилерин сиягь я. Куь [[Special:Watchlist|вилив хуьнин сиягь диз]] гьатзавай ччинар яцӀу шрифтдал къалурнава.',
'recentchangeslinked-page' => 'Ччинин тlвар:',
'recentchangeslinked-to' => 'Аксина, къалурай ччиниз элячlзавай ччинра масакIавилер къалура',
'file-info-size' => '$1 × $2 пикселар, файлдин кьадар: $3, MIME жуьре: $4',
'file-nohires' => 'Идалайни хъсан ери авайд туш',
'svg-long-desc' => 'SVG файл, номилдаказ $1 $2 × пикселяр, файлдин кьадар: $3',
-'show-big-image' => 'Цlарафа хвена тунвай жергедай',
+'show-big-image' => 'ЦӀарафа хвена тунвай жергедай',
# Bad image list
'bad_image_list' => 'Формат гьихьтинди хьана кlанда:
'timezoneregion-europe' => 'Eoropa',
'timezoneregion-indian' => 'Ranomasimbe Indianina',
'timezoneregion-pacific' => 'Ranomasimbe Pasifika',
-'allowemail' => "Ekeo ny handraisana imailaka avy amin'ny mpikambana hafa",
+'allowemail' => "Hanaiky ny fandefasana mailaka avy amin'ny mpikambana hafa",
'prefs-searchoptions' => 'Karoka',
'prefs-namespaces' => "Toeran'anarana",
'defaultns' => "Fikarohana tsipalotra anatin'ireo anaran-tsehatra ireo :",
'tog-hideminor' => 'Suruakkan suntingan ketek di parubahan tabaru',
'tog-hidepatrolled' => 'Suruakkan suntingan nan lah dijago di parubahan tabaru',
'tog-newpageshidepatrolled' => 'Suruakkan laman nan lah dijago dari dafta laman baru',
-'tog-extendwatchlist' => 'Kambangkan dafta pantauan untuak malihek sado parubahan, indak nan baru se',
+'tog-extendwatchlist' => 'Kambangkan dafta pantau untuak malihek sado parubahan, indak nan baru se',
'tog-usenewrc' => 'Gunokan tampilan parubahan tingkek lanjuik (paralu JavaScript)',
'tog-numberheadings' => 'Agiah nomor judua sacaro otomatis',
'tog-showtoolbar' => 'Tampilkan bilah suntiang (paralu JavaScript)',
'tog-editsectiononrightclick' => 'Hiduikkan bagian panyuntiangan jo mangklik kanan pado judul bagian (paralu JavaScript)',
'tog-showtoc' => 'Tunjuakkan dafta isi (untuak laman nan labiah dari 3 subbagian)',
'tog-rememberpassword' => 'Ingek log masuak denai di paramban ko (salamo $1 {{PLURAL:$1|hari}})',
-'tog-watchcreations' => 'Tambahkan laman nan den buek jo gambar nan den unggah ka dafta pantauan',
-'tog-watchdefault' => 'Tambahkan laman jo gamba nan den suntiang ka dafta pantauan',
-'tog-watchmoves' => 'Tambahkan laman jo gamba nan den pindah ka dafta pantauan',
-'tog-watchdeletion' => 'Tambahkan laman jo gamba nan den hapuih ka dafta pantauan',
+'tog-watchcreations' => 'Tambahkan laman nan den buek jo gambar nan den unggah ka dafta pantau',
+'tog-watchdefault' => 'Tambahkan laman jo gamba nan den suntiang ka dafta pantau',
+'tog-watchmoves' => 'Tambahkan laman jo gamba nan den pindah ka dafta pantau',
+'tog-watchdeletion' => 'Tambahkan laman jo gamba nan den hapuih ka dafta pantau',
'tog-minordefault' => 'Tandoi sadoalah suntiangan sabagai suntiangan ketek sacaro baku',
'tog-previewontop' => 'Tampilkan pratonton sabalun kotak suntiang',
'tog-previewonfirst' => 'Tunjuakkan pratonton pado suntiangan patamo',
'tog-nocache' => 'Matikan panyinggahan laman paramban',
-'tog-enotifwatchlistpages' => 'Kirimkan surel, kalau laman atau gambar pado daftar pantauan den lah barubah',
-'tog-enotifusertalkpages' => "Kirimkan denai surel ko' laman diskusi den lah barubah",
+'tog-enotifwatchlistpages' => 'Kirimkan surel, kok laman atau gambar pado dafta pantau Ambo lah barubah',
+'tog-enotifusertalkpages' => 'Kirimkan surel, koq laman diskusi Ambo lah barubah',
'tog-enotifminoredits' => 'Kirimkan surel juo untuk saketek suntingan pado laman jo gambar',
'tog-enotifrevealaddr' => 'Tunjuakkan alamaik surel ambo pado pambaritauan surel',
'tog-shownumberswatching' => 'Tunjuakkan jumlah pamantau',
'tog-showjumplinks' => 'Aktifkan tautan pambantu "langsuang ka"',
'tog-uselivepreview' => 'Gunokan pratayang langsuang (JavaScript) (eksperimental)',
'tog-forceeditsummary' => 'Ingekkan awak bilo kotak ringkasan suntiangan masih kosoang',
-'tog-watchlisthideown' => 'Suruakkan suntiangan surang di dafta pantauan',
-'tog-watchlisthidebots' => 'Suruakkan suntiangan bot di dafta pantauan',
-'tog-watchlisthideminor' => 'Suruakkan suntiangan ketek di dafta pantauan',
-'tog-watchlisthideliu' => 'Suruakkan suntiangan pangguno masuak log di dafta pantauan',
-'tog-watchlisthideanons' => 'Suruakkan suntiangan pangguno indak di kana di dafta pantauan',
-'tog-watchlisthidepatrolled' => 'Suruakkan suntiangan tapatroli di dafta pantauan',
-'tog-ccmeonemails' => 'Kiriman awak salinan surel nan dikiriman ka urang lain',
+'tog-watchlisthideown' => 'Suruakkan suntiangan surang di dafta pantau',
+'tog-watchlisthidebots' => 'Suruakkan suntiangan bot di dafta pantau',
+'tog-watchlisthideminor' => 'Suruakkan suntiangan ketek di dafta pantau',
+'tog-watchlisthideliu' => 'Suruakkan suntiangan pangguno masuak log di dafta pantau',
+'tog-watchlisthideanons' => 'Suruakkan suntiangan pangguno indak di kana di dafta pantau',
+'tog-watchlisthidepatrolled' => 'Suruakkan suntiangan tapatroli di dafta pantau',
+'tog-ccmeonemails' => 'Kiriman Ambo salinan surel nan dikiriman ka urang lain',
'tog-diffonly' => 'Jan tampilan isi laman di bawah pabedoan suntiangan',
'tog-showhiddencats' => 'Tampilan kategori tasambunyi',
'tog-norollbackdiff' => 'Jan tampilan pabedoan sasudah malakukan pangambalian',
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategori}}',
-'category_header' => 'Laman dalam kategori "$1"',
+'category_header' => 'Laman pado kategori "$1"',
'subcategories' => 'Subkategori',
'category-media-header' => 'Laman/Media dalam kategori "$1"',
'category-empty' => "''Kini ko, indak ado laman ataupun media dalam kategori ko.''",
'history_short' => 'Riwayaik',
'updatedmarker' => 'diubah sajak kunjuangan tarakhir ambo',
'printableversion' => 'Versi cetak',
-'permalink' => 'Pranala permanen',
+'permalink' => 'Pautan parmanen',
'print' => 'Cetak',
'view' => 'Tampilkan',
'edit' => 'Suntiang',
'viewtalkpage' => 'Caliak laman diskusi',
'otherlanguages' => 'Dalam bahaso lain',
'redirectedfrom' => '(Dialiahkan dari $1)',
-'redirectpagesub' => 'Laman pengalihan',
+'redirectpagesub' => 'Laman pangaliahan',
'lastmodifiedat' => 'Laman ko taakia diubah pado $2, $1.',
-'viewcount' => 'Laman iko alah diakses sabanyak {{PLURAL:$1|ciek kali|$1 kali}}.<br />',
-'protectedpage' => 'Laman nan dilindungi',
+'viewcount' => 'Laman ko lah dicaliak {{PLURAL:$1|$1 kali}}.',
+'protectedpage' => 'Laman nan dilinduangi',
'jumpto' => 'Lompek ka:',
'jumptonavigation' => 'pinteh',
'jumptosearch' => 'cari',
-'view-pool-error' => 'Maaf, server sadang sibuak pado kini ko.
-Talalu banyak pangguno barusaho mancaliak laman ko.
-Tunggu sabanta sabalum Sanak mancubo baliak mangakses laman ko.
+'view-pool-error' => 'Maaf, server sadang kalabiahan baban.
+Banyak bana nan barusaho mancaliak laman ko.
+Tunggu santa koq nio mancubo baliak ka laman ko.
$1',
-'pool-timeout' => 'Lewat waktu manunggu kunci',
-'pool-queuefull' => 'Kumpulan antrean panuah',
+'pool-timeout' => 'Abih wakatu',
+'pool-queuefull' => 'Antrian panuah',
'pool-errorunknown' => 'Kasalahan nan indak dikatahui',
# All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage) and the disambiguation template definition (see disambiguations).
'disclaimers' => 'Sanggah',
'disclaimerpage' => 'Project:Sanggahan umum',
'edithelp' => 'Bantuan suntiangan',
-'edithelppage' => 'Help:Suntingan',
+'edithelppage' => 'Help:Panyuntiangan',
'helppage' => 'Help:Isi',
'mainpage' => 'Palanta',
'mainpage-description' => 'Palanta',
'versionrequiredtext' => 'MediaWiki versi $1 dibutuahkan untuak manggunokan laman ko. Caliak [[Special:Version|versi laman]]',
'ok' => 'OK',
+'pagetitle' => '$1 - {{SITENAME}} bahaso Minang',
+'pagetitle-view-mainpage' => '{{SITENAME}} bahaso Minang',
+'backlinksubtitle' => '← $1',
'retrievedfrom' => 'Didapek dari "$1"',
'youhavenewmessages' => 'Awak punyo $1 ($2).',
'newmessageslink' => 'pasan baru',
'editlink' => 'suntiang',
'viewsourcelink' => 'caliak sumber',
'editsectionhint' => 'Suntiang bagian: $1',
-'toc' => 'Daftar isi',
+'toc' => 'Dafta isi',
'showtoc' => 'tampilkan',
'hidetoc' => 'suruakkan',
'collapsible-collapse' => 'Ketekan',
# Main script and global functions
'nosuchaction' => 'Indak ado tindakan tasabuik',
-'nosuchactiontext' => 'Tindakan nan diminta oleh URL tasabuik indak valid. Sanak mungkin salah mangetikkan URL, atau mangikuti suatu pranala nan ndak batua. Hal iko juo mungkin mangindikasikan suatu bug pado parangkaik lunak nan digunokan oleh {{SITENAME}}.',
+'nosuchactiontext' => 'Tindakan nan diminta dek URL tasabuik indak valid. Sanak mungkin salah mangetikkan URL, atau mangikuiki suatu pautan nan indak batua. Hal iko mungkin juo manunjuakan adonyo suatu bug pado parangkaik lunak nan dipagunoan dek {{SITENAME}}.',
'nosuchspecialpage' => 'Indak ado laman istimewa tarsabuik',
'nospecialpagetext' => '<strong>Sanak maminta laman istimewa nan indak sah.</strong>
'readonlytext' => 'Basis data sadang dikunci tahadok masuakan baru. Panguruih nan malakukan panguncian mamberikan panjalehan sabagai berikut: <p>$1',
'missing-article' => 'Basisdata indak dapek manamukan teks dari laman nan saharuihnyo ado, yaitu "$1" $2.
-Hal ko biasonyo disababkan dek pranala usang ka pabaikkan tadahulu laman nan alah dihapuih.
+Hal ko biasonyo disababkan dek pautan usang ka pabaikkan tadahulu laman nan alah dihapuih.
Jikok bukan ko panyababnyo, Sanak mungkin alah manamukan sabuah bug dalam pakakeh lunak.
Silakan laporkan hal iko ka [[Special:ListUsers/sysop|pangurus]], sarato manyabuikkan alamaik URL nan dituju.',
'mailerror' => 'Kasalahan dalam mangirimkan surel: $1',
'acct_creation_throttle_hit' => 'Pangunjung wiki iko jo alamaik IP nan samo jo Sanak alah mambuek {{PLURAL:$1|1 akun|$1 akun}} dalam sahari tarakhir, hinggo jumlah maksimum nan diizinan.
Karanonyo, pangunjuang jo alamaik IP iko indak dapek baliak mambuek akun lain untuak samantaro.',
-'emailauthenticated' => 'Alamaik surel Sanak alah dikonfirmasi pado $3, $2.',
+'emailauthenticated' => 'Alamaik surel Sanak lah dikonfirmasi pado $3, $2.',
'emailnotauthenticated' => 'Alamaik surel Sanak alum dikonfirmasi. Sabalun dikonfirmasi Sanak ndak bisa manggunokan fitur surel.',
'noemailprefs' => 'Sanak harus mamasukan alamaik surel di preferensi Sanak untuak dapek manggunokan fitur-fitur iko.',
'emailconfirmlink' => 'Konfirmasikan alamaik surel Sanak',
'bold_tip' => 'Teks taba',
'italic_sample' => 'Teks miriang',
'italic_tip' => 'Teks miriang',
-'link_sample' => 'Judul pranala',
-'link_tip' => 'Pranala internal',
-'extlink_sample' => 'http://www.hanyo-contoh.com judul pranala',
-'extlink_tip' => 'Pranala lua (ingek awalannyo http://)',
+'link_sample' => 'Judua pautan',
+'link_tip' => 'Pautan dalam',
+'extlink_sample' => 'http://www.anyo-contoh.com judua pautan',
+'extlink_tip' => 'Pautan lua (ingek awalannyo http://)',
'headline_sample' => 'Teks judul',
'headline_tip' => 'Tingkek 2 judul',
'nowiki_sample' => 'Masuakkan disiko teks nan indak baformat',
'nowiki_tip' => 'Abaikan format wiki',
'image_tip' => 'Cantumkan berkas',
-'media_tip' => 'Pranala berkas',
+'media_tip' => 'Pautan berkas',
'sig_tip' => 'Tandotangan sanak jo waktu',
'hr_tip' => 'Garih mandata',
# Edit pages
-'summary' => 'Ringkasan:',
+'summary' => 'Ikhtisar:',
'subject' => 'Subjek/judul:',
'minoredit' => 'Suntiangan ketek',
'watchthis' => 'Pantau laman ko',
'summary-preview' => 'Ringkasan pratayang:',
'subject-preview' => 'Pratayang subyek/judul:',
'blockedtitle' => 'Pangguno diblokir',
-'blockedtext' => "'''Namo pangguno atau alamaik IP Sanak alah diblokir.'''
+'blockedtext' => "'''Namo pangguno atau alamaik IP Sanak alah kanai sakek.'''
-Blokir dilakuan oleh $1.
+Sakek dibuek dek $1.
Alasan nan diagiahan adolah ''$2''.
-* Diblokir sajak: $8
-* Blokir kadaluwarsa pado: $6
-* Sasaran pamblokiran: $7
+* Kanai sakek sajak: $8
+* Maso sakek habih pado: $6
+* Sasaran nan disakek: $7
-Sanak dapek mahubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|pangurus lainnyo]] untuak mambicarokan hal iko.
+Sanak dapek manghubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|panguruih lainnyo]] untuak mambicarokan hal iko.
-Sanak indak dapek manggunoan fitur 'Kirim surel ka pangguna iko' kacuali Sanak alah mamasuakan alamaik surel nan sah di [[Special:Preferences|preferensi akun]] dan Sanak indak diblokir untuak manggunoannyo.
+Sanak indak dapek manggunoan fitua 'Kirim surel ka pangguna iko' kacuali Sanak alah mamasuakan alamaik surel nan sah di [[Special:Preferences|pangaturan akun]] dan Sanak indak sadang disakek untuak manggunoannyo.
-Alamaik IP Sanak adolah $3, dan ID pamblokiran adolah $5.
-Toloang saratokan ciek atau kaduo informasi ini pado satiok patanyaan nan Sanak buek.",
-'autoblockedtext' => 'Alamaik IP Sanak alah tablokir sacaro otomatis karano digunokan oleh pangguno lain, nan diblokir oleh $1. Pamblokiran dilakuan ateh alasan:
+Alamaik IP Sanak adolah $3, dan ID panyakek adolah $5.
+Tolong saratoan informasi di ateh pado satiok patanyaan nan Sanak buek.",
+'autoblockedtext' => "Alamaik IP Sanak alah kanai sakek sacaro otomatis dek digunoan jo pangguno lain, nan sakek dek $1. Panyakek ko dibuek dek alasan:
-:\'\'$2\'\'
+:''$2''
-* Diblokir sajak: $8
-* Blokir kadaluwarsa pado: $6
-* Sasaran pamblokiran: $7
+* Kanai sakek sajak: $8
+* Maso sakek habih pado: $6
+* Sasaran nan disakek: $7
-Sanak dapek mahubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|pengurus lainnya]] untuak mambicarokan hal iko.
+Sanak dapek mahubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|penguruih lainnya]] untuak mambicarokan hal iko.
-Sanak indak dapek manggunoan fitur "kirim surel ka pangguno iko" kacuali Sanak alah mamasuakan alamaik surel nan sah di [[Special:Preferences|preferensi akun]] Sanak dan Sanak indak diblokir untuak manggunoannyo.
+Sanak indak dapek manggunoan fitua 'Kirim surel ka pangguna iko' kacuali Sanak alah mamasuakan alamaik surel nan sah di [[Special:Preferences|pangaturan akun]] dan Sanak indak sadang disakek untuak manggunoannyo.
-Alamat IP Sanak saat ini adolah $3, dan ID pamblokiran adolah #$5.
-Toloang saratokan informasi-informasi iko dalam satiok patanyaan Sanak.',
+Alamaik IP Sanak adolah $3, dan ID panyakek adolah $5.
+Tolong saratoan informasi di ateh pado satiok patanyaan nan Sanak buek.",
'blockednoreason' => 'indak ado alasan nan diagiah.',
-'whitelistedittext' => 'Sanak harus $1 untuak dapek manyuntiang laman.',
-'confirmedittext' => 'Sanak harus mangkonfirmasian dahulu alamaik surel Sanak sabalun manyuntiang laman.
-Harap masuakan dan validasian alamaik surel Sanak malalui [[Special:Preferences|laman preferensi pangguno]] Sanak.',
+'whitelistedittext' => 'Sanak musti $1 untuak manyuntiang laman.',
+'confirmedittext' => 'Sanak musti mangkonfirmasian alamaik surel sabalun manyuntiang laman.
+Masuakan dan validasian alamaik surel Sanak pado [[Special:Preferences|pangaturan pangguno]] Sanak.',
'nosuchsectiontitle' => 'Bagian indak ditamuan',
'nosuchsectiontext' => 'Sanak mancubo manyuntiang suatu subbagian nan indak ado.
-Subbagian iko mungkin dipindahan atau dihapuih katiko Sanak mambukanyo.',
+Subbagian ko mungkin lah dipindahan atau dihapuih sangkek Sanak mambukaknyo.',
'loginreqtitle' => 'Harus masuak log',
'loginreqlink' => 'masuak log',
'loginreqpagetext' => 'Sanak harus $1 untuak dapek maliek laman lainnyo.',
Sanak dapek [[Special:Search/{{PAGENAME}}|malakukan pancarian untuak judul laman ko]] di laman lain, atau <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} mancahari log takaik] </span>, tapi Sanak indak punyo izin untuak mambuek laman ko.',
'missing-revision' => 'Revisi $1 di laman nan banamo "{{PAGENAME}}" ko indak ado.
-Hal iko biasonyo disababkan dek pranala sijarah nan alah kadaluarsa ka laman nan alah dihapuih.
-Rinciannyo dapek dicaliak di [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log panghapuihan].',
+Hal iko biasonyo disababkan dek pautan sijarah nan alah kadaluarsa ka laman nan alah diapuih.
+Rinciannyo dapek dicaliak di [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log pangapuihan].',
'userpage-userdoesnotexist' => 'Akun pangguno "<nowiki>$1</nowiki>" indak tadafta.',
'userpage-userdoesnotexist-view' => 'Pangguno "$1" indak tadafta.',
'blocked-notice-logextract' => 'Pangguno ko tangah diblokir.
'pagehist' => 'Riwayaik laman',
'revdelete-otherreason' => 'Alasan lain/tambahan:',
'revdelete-reasonotherlist' => 'Alasan lain',
+'revdelete-edit-reasonlist' => 'Alasan mangapuih laman',
+
+# History merging
+'mergehistory-reason' => 'Alasan:',
# Merge log
+'mergelog' => 'Log panggabuangan',
'revertmerge' => 'Batal gabuang',
# Diffs
'history-title' => 'Riwayaik revisi dari "$1"',
+'difference-title' => 'Pabedoan antaro revisi dari "$1"',
+'difference-title-multipage' => 'Pabedoan antaro laman "$1" jo "$2"',
+'difference-multipage' => '(Pabedoan antaro laman)',
'lineno' => 'Barih $1:',
'compareselectedversions' => 'Bandiangan versi tapiliah',
+'showhideselectedversions' => 'Tampilkan/suruakan versi tapiliah',
'editundo' => 'batal',
'diff-multi' => '({{PLURAL:$1|$1 revisi antaro}} oleh {{PLURAL:$2|$2 pangguno}} indak ditampilkan)',
'searchresults' => 'Hasil pancarian',
'searchresults-title' => 'Hasil pancarian untuak "$1"',
'searchresulttext' => 'Untuak informasi labiah lanjuik tantang pancarian {{SITENAME}}, caliak [[{{MediaWiki:Helppage}}|{{int:help}}]].',
-'searchsubtitle' => 'Awak mancari \'\'\'[[:$1]]\'\'\' ([[Special:Prefixindex/$1|sado laman yang dimulai jo "$1"]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|sado laman nan tapauik ka "$1"]])',
-'searchsubtitleinvalid' => "Awak mancari '''$1'''",
+'searchsubtitle' => 'Sanak mancari \'\'\'[[:$1]]\'\'\' ([[Special:Prefixindex/$1|sado laman nan dimulai jo "$1"]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|sado laman nan tapauik ka "$1"]])',
+'searchsubtitleinvalid' => "Sanak mancari '''$1'''",
+'titlematches' => 'Judul laman pas',
'notitlematches' => 'Indak ado judul nan pas',
+'textmatches' => 'Teks laman pas',
'notextmatches' => 'Indak ado judul nan pas',
'prevn' => '{{PLURAL:$1|$1}} sabalunnyo',
-'nextn' => '{{PLURAL:$1|$1}} salanjuiknyo',
+'nextn' => '{{PLURAL:$1|$1}} barikuiknyo',
'prevn-title' => '$1 {{PLURAL:$1|hasil}} sabalunnyo',
'nextn-title' => '$1 {{PLURAL:$1|hasil}} barikuiknyo',
'shown-title' => 'Tampilkan $1 {{PLURAL:$1|hasil}} per laman',
'viewprevnext' => 'Caliakkan ($1 {{int:pipe-separator}} $2) ($3)',
+'searchmenu-legend' => 'Atua pancarian',
'searchmenu-exists' => "'''Ado laman nan banamo \"[[:\$1]]\" pado wiki ko.'''",
'searchmenu-new' => "'''Buek laman \"[[:\$1]]\" di wiki ko!'''",
'searchhelp-url' => 'Help:Isi',
+'searchmenu-prefix' => '[[Special:PrefixIndex/$1|Cari laman jo awalan ko]]',
'searchprofile-articles' => 'Laman isi',
'searchprofile-project' => 'Laman Bantuan jo Proyek',
'searchprofile-images' => 'Multimedia',
'search-result-score' => 'Relevansi: $1%',
'search-redirect' => '(pangaliahan $1)',
'search-section' => '(bagian $1)',
-'search-suggest' => 'Mungkin maksud awak: $1',
+'search-suggest' => 'Mungkin makasuiknyo: $1',
'search-interwiki-caption' => 'Proyek badunsanak',
'search-interwiki-default' => 'Hasil $1:',
-'search-interwiki-more' => '(selanjutnyo)',
+'search-interwiki-more' => '(salanjuiknyo)',
+'search-relatedarticle' => 'Bakaitan',
+'mwsuggest-disable' => 'Matian saran pancarian',
+'searcheverything-enable' => 'Cari di sagalo ruang namo',
'searchrelated' => 'bakaitan',
'searchall' => 'sado',
'showingresults' => "Di bawah ko dikaluaan sampai {{PLURAL:$1|'''$1''' hasil}}, dimulai dari #'''$2'''.",
# Preferences page
'preferences' => 'Pangaturan',
'mypreferences' => 'Pangaturan',
+'prefs-edits' => 'Jumlah suntiangan:',
+'prefsnologintext' => 'Sanak musti <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} masuak log]</span> untuak mengeset pangaturan.',
+'changepassword' => 'Tuka kato sandi',
'prefs-skin' => 'Kulik',
'skin-preview' => 'Caliak',
'datedefault' => 'Indak usah diatua',
'prefs-user-pages' => 'Laman pangguno',
'prefs-personal' => 'Profil pangguno',
'prefs-rc' => 'Parubahan tabaru',
-'prefs-watchlist' => 'Dafta pantauan',
-'prefs-watchlist-days' => 'Lamonyo dalam daftar pantauan:',
+'prefs-watchlist' => 'Dafta pantau',
+'prefs-watchlist-days' => 'Lamonyo dalam dafta pantau:',
'prefs-watchlist-days-max' => 'Maksimum $1 {{PLURAL:$1|hari}}',
-'prefs-watchlist-edits' => 'Jumlah suntiangan maksimum nan ditampilkan di dafta pantauan nan labiah langkok:',
+'prefs-watchlist-edits' => 'Jumlah suntiangan maksimum nan ditampilkan didafta pantaun nan labiah langkok:',
'prefs-watchlist-edits-max' => 'Nilai maksimum: 1000',
'prefs-watchlist-token' => 'Token pantauan:',
'prefs-misc' => 'Lain-lain',
'prefs-rendering' => 'Tampilan',
'saveprefs' => 'Simpan',
'resetprefs' => 'Batalan parubahan',
-'restoreprefs' => 'Baliakkan ka setelan bawaan',
+'restoreprefs' => 'Baliakan ka setelan awal',
'prefs-editing' => 'Panyuntiangan',
'prefs-edit-boxsize' => 'Ukuran kotak panyuntiangan.',
'rows' => 'Barih:',
'recentchangesdays-max' => 'Maksimum $1 {{PLURAL:$1|hari}}',
'recentchangescount' => 'Standar jumlah suntiangan nan ditampilkan:',
'prefs-help-recentchangescount' => 'Iko untuak parubahan tabaru, riwayaik laman nan lalu, sarato log.',
-'prefs-help-watchlist-token' => 'Mangisi kotak ko jo kunci rasio (PIN) akan manghasilkan sindikasi RSS untuak dafta pantauan Angku. Sia juo nan tau jo kunci ko dapek mambaco dafta pantauan Angku, jadi hati-hatilah mamiliah nilainyo
-Barikuik ko nilai acak nan dapek Angku gunoan: $1',
-'savedprefs' => 'Pangaturan Angku alah tasimpan',
+'prefs-help-watchlist-token' => 'Mangisi kotak ko jo kunci rasio (PIN) akan manghasilkan sindikasi RSS untuak dafta pantau Sanak. Sia juo nan tau jo kunci ko dapek mambaco dafta pantau Sanak, jadi hati-hatilah mamiliah nilainyo.
+Barikuik ko nilai acak nan dapek Sanak gunoan: $1',
+'savedprefs' => 'Pangaturan lah tasimpan',
'timezonelegend' => 'Zona wakatu:',
'localtime' => 'Wakatu satampaik:',
'timezoneuseserverdefault' => 'Gunokan nan dari wiki ($1)',
'prefs-files' => 'Berkas',
'prefs-custom-css' => 'CSS pribadi',
'prefs-custom-js' => 'JS pribadi',
-'prefs-common-css-js' => 'CSS/JS babagi untuak sado kulik:',
+'prefs-common-css-js' => 'CSS/JS untuak kasado kulik:',
'prefs-reset-intro' => 'Angku dapek manggunokan laman ko untuak mangambalikan pangaturan ka setelan baku situs ko.
Pangambalian pangaturan indak dapek dibatalan.',
'prefs-emailconfirm-label' => 'Surel konfirmasi:',
'prefs-textboxsize' => 'Ukuran kotak suntiang',
'youremail' => 'Surel:',
'username' => '{{GENDER:$1|Namo pangguno}}:',
+'uid' => 'ID {{GENDER:$1|pangguno}}:',
+'prefs-memberingroups' => '{{GENDER:$2|Anggota}} {{PLURAL:$1|kalompok}}:',
'prefs-registration' => 'Wakatu pandaftaran:',
'yourrealname' => 'Namo sabananyo:',
'yourlanguage' => 'Bahaso',
'email' => 'Surel',
'prefs-help-realname' => "Namo asli sifaiknyo opsional.
Jiko' Angku manambahkannyo, namo asli Angku akan digunoan untuak mengenal hasil karaja Angku.",
-'prefs-help-email' => 'Alamaik surel ko hanyo tambahan se, namun paralu untuak maulang kato kunci, jikok Sanak lupo kato kunci.',
+'prefs-help-email' => "Alamaik surel ko hanyolah tambahan, tapi paralu untuak ma-''reset'' kato sandi, bilo Sanak lupo kato sandi.",
'prefs-help-email-others' => 'Sanak dapek mamiliah untuak mangizinkan urang lain manghubungi jo surel malalui laman pangguno atau laman diskusi.
Alamaik surel tu indakkan tau dek urang nan manghubungi sanak tu.',
'prefs-help-email-required' => 'Alamaik surel wajib diisi.',
# Recent changes
'nchanges' => '$1 {{PLURAL:$1|parubahan}}',
'recentchanges' => 'Parubahan baru',
-'recentchanges-legend' => 'Pilihan parubahan baru',
-'recentchanges-summary' => 'Manjajak parubahan terbaru dalam wiki di laman ko.',
+'recentchanges-legend' => 'Piliahan parubahan baru',
+'recentchanges-summary' => 'Caliak parubahan tabaru pado wiki di laman ko.',
'recentchanges-feed-description' => 'Temukan parubahan baru dalam umpan wiki ko',
'recentchanges-label-newpage' => 'Suntiangan ko mambuek laman baru',
'recentchanges-label-minor' => 'Iko suntiangan ketek',
'rcshowhideanons' => '$1 pangguno anon',
'rcshowhidepatr' => '$1 suntiangan nan tajago',
'rcshowhidemine' => '$1 suntingan denai',
-'rclinks' => 'Tampilkan $1 parubahan tabaru dalam $2 hari tarakhir<br />$3',
+'rclinks' => 'Tunjuakkan $1 parubahan tabaru dalam $2 hari tarakhia<br />$3',
'diff' => 'bedo',
'hist' => 'sijarah',
'hide' => 'Suruakkan',
'recentchangeslinked-title' => 'Parubahan nan takaik jo "$1"',
'recentchangeslinked-noresult' => 'Indak ado parubahan pado laman nan tapauik salamo periode nan ditantuan',
'recentchangeslinked-summary' => "Iko dafta parubahan tarakhir pado laman nan tahubuang dari laman tatantu (atau anggota dari kategori tatantu).
-Laman pado [[Special:Watchlist|pantauan Sanak]] ditandoi jo '''cetak taba'''.",
+Laman pado [[Special:Watchlist|dafta pantau Sanak]] ditandoi jo '''cetak taba'''.",
'recentchangeslinked-page' => 'Namo laman:',
'recentchangeslinked-to' => 'Tampilkan parubahan dari laman nan takaik jo laman nan ko',
# Upload
'upload' => 'Muek berkas',
'uploadlogpage' => 'Log unggah',
-'filedesc' => 'Ringkasan',
+'filename' => 'Namo berkas',
+'filedesc' => 'Ikhtisar',
+'fileuploadsummary' => 'Ikhtisar:',
+'filereuploadsummary' => 'Parubahan berkas:',
+'filestatus' => 'Status hak cipta:',
+'filesource' => 'Sumber:',
+'uploadedfiles' => 'Berkas nan lah dimuek',
+'ignorewarning' => 'Acuahkan pasan dan langsuang simpan berkas.',
+'ignorewarnings' => 'Acuahkan pasan apo pun',
+'minlength1' => 'Namo berkas paliang indak ado satu hurup.',
+'illegalfilename' => 'Namo berkas "$1" ado karakter nan indak dipabuliahkan ado dalam judul. Ubah namo berkas dan cubalah muek baliak.',
+'filename-toolong' => 'Namo berkas indak buliah labiah panjang dari 240 bita.',
+'badfilename' => 'Namo berkas lah diubah manjadi "$1".',
+'filetype-mime-mismatch' => 'Ekstensi berkas ".$1" indak cocok jo MIME nan tadeteksi dari berkas ($2).',
+'filetype-badmime' => 'Berkas batipe MIME "$1" indak buliah dimuek.',
+'filetype-bad-ie-mime' => 'Indak dapek mamuek berkas dek Internet Explorer mandeteksinyo sabagai "$1", nan indak diizinkan dan marupokan tipe berkas bapotensi bahayo.',
+'fileexists-thumbnail-yes' => "Berkas ko nampaknyo marupoan gambar nan ukurannyo dipaketek ''(miniatua)''. [[$1|thumb]]
+Cubo pareso berkas <strong>[[:$1]]</strong> tasabuik.
+Koq berkas tu samemang marupoan gambar dalam ukuran aslinyo, Sanak indak paralu untuak mamuak baliak miniatur lainnyo.",
+'file-thumbnail-no' => "Namo berkas dimulai jo <strong>$1</strong>.
+Nampaknyo berkas ko marupoan gambar jo ukuran dipaketek ''(miniatua)''.
+Koq Sanak ado versi resolusi panuah dari gambar ko, cubolah muekan berkas tasabuik. Koq indak, harap ubah namo berkas ko.",
'uploadedimage' => 'muek "[[$1]]"',
'license' => 'Lisensi:',
'linkstoimage' => 'Barikuik ko {{PLURAL:$1|$1 laman nan takaik}} jo berkas:',
'nolinkstoimage' => 'Indak ado laman nan batauik ka berkas ko.',
'sharedupload' => 'Berkas ko barasal dari $1 dan mungkin digunoan oleh berbagai proyek lain.',
-'sharedupload-desc-here' => 'Berkas ko dari $1 dan mungkin digunoan untuak proyek-proyek lain.
-Katarangan dari [$2 laman kataranagn berkas] ditampilkan di bawah.',
+'sharedupload-desc-here' => 'Berkas ko dari $1, mungkin juo digunoan untuak proyek-proyek lain.
+Informasi dari [$2 laman katarangannyo] ado di bawah.',
'uploadnewversion-linktext' => 'Unggah versi baru dari berkas ko',
# Random page
# Statistics
'statistics' => 'Statistik',
-
+'statistics-header-pages' => 'Statistik laman',
+'statistics-header-edits' => 'Statistik suntiangan',
+'statistics-header-views' => 'Statistik tampilan',
+'statistics-header-users' => 'Statistik pangguno',
+'statistics-header-hooks' => 'Statistik lainnyo',
+'statistics-articles' => 'Laman konten',
+'statistics-pages' => 'Jumlah laman',
+'statistics-pages-desc' => 'Sado laman pado wiki, tamasuak laman maota, pangaliahan, dll.',
+'statistics-files' => 'Berkas nan lah dimuek',
+'statistics-edits' => 'Jumlah suntiangan sangkek {{SITENAME}} ko dimulai',
+'statistics-edits-average' => 'Rato-rato suntiangan per-laman',
+'statistics-views-total' => 'Jumlah tampilan laman',
+'statistics-views-total-desc' => 'Tampilan ka laman nan indak ado jo laman khusus nan indak ikuik',
+'statistics-views-peredit' => 'Tampilan per-suntiangan',
+'statistics-users' => 'Jumlah [[Special:ListUsers|pangguno tadafta]]',
+'statistics-users-active' => 'Pangguno aktip',
+'statistics-users-active-desc' => 'Pangguno nan aktip dalam {{PLURAL:$1|$1 ari}} tarakhia.',
+'statistics-mostpopular' => 'Laman nan paliang banyak ditampilkan',
+
+'disambiguations' => 'Laman nan tahubuang ka laman disambiguasi',
'disambiguationspage' => 'Template:sanamo',
+'doubleredirects' => 'Pangaliahan ganda',
+
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|bita}}',
+'ncategories' => '$1 {{PLURAL:$1|kategori}}',
+'ninterwikis' => '$1 {{PLURAL:$1|interwiki}}',
+'nlinks' => '$1 {{PLURAL:$1|pautan}}',
'nmembers' => '$1 {{PLURAL:$1|anggota}}',
+'nrevisions' => '$1 {{PLURAL:$1|revisi}}',
+'nviews' => 'dilihek $1 {{PLURAL:$1|kali}}',
+'nimagelinks' => 'Digunoan pado $1 {{PLURAL:$1|laman}}',
+'ntransclusions' => 'digunoan pado $1 {{PLURAL:$1|laman}}',
+'lonelypages' => 'Laman yatim',
'prefixindex' => 'Sado laman jo awalan',
+'prefixindex-namespace' => 'Sado laman jo awalan (ruang namo $1)',
+'shortpages' => 'Laman pendek',
+'longpages' => 'Laman panjang',
+'deadendpages' => 'Laman buntu',
+'deadendpagestext' => 'Laman-laman ko indak ad pautan ka laman lain di {{SITENAME}}.',
+'protectedpages' => 'Laman nan dilinduangi',
+'usereditcount' => '$1 {{PLURAL:$1|suntiangan}}',
'usercreated' => '{{GENDER:$3|Dibuek}} pado $1 pukua $2',
'newpages' => 'Laman baru',
+'newpages-username' => 'Namo pangguno:',
+'ancientpages' => 'Laman paliang lamo',
'move' => 'Pindah',
'movethispage' => 'Pindahan laman ko',
+'unusedimagestext' => 'Berkas barikuik ado tapi indak takaik jo laman mana pun.
+Harap paratikan bahwa situs web lain mungkin ado tautan ka suatu berkas jo URL langsung, dan masih tadafta di siko walaupun indak digunoan aktif.',
'pager-newer-n' => '{{PLURAL:$1|$1 labiah baru}}',
'pager-older-n' => '{{PLURAL:$1|$1 labiah lamo}}',
# Special:Categories
'categories' => 'Kategori',
+'categoriespagetext' => '{{PLURAL:$1|Isi kategori}} ko ado laman atau media.
+[[Special:UnusedCategories|Kategori nan indak tapakai]] indak nampak di siko.
+Lihek pulo [[Special:WantedCategories|kategori nan diinginkan]].',
# Special:LinkSearch
-'linksearch' => 'Pranala lua',
+'linksearch' => 'Pancarian pautan lua',
'linksearch-line' => '$1 tapauik dari $2',
# Special:ListGroupRights
'listgrouprights-members' => '(dafta anggota)',
# E-mail user
-'emailuser' => 'Kirim surel pangguno ko',
+'emailuser' => 'Surel pangguno',
+'emailuser-title-target' => 'Kirim surel ka {{GENDER:$1|panggun}} ko',
+'emailuser-title-notarget' => 'Kirim surel',
+'emailpage' => 'Kirim surel ka pangguno ko',
+'emailpagetext' => 'Sanak dapek manggunoan formulir di bawah ko untuak mangirimkan surel ka {{GENDER:$1|pangguna}} ko.
+Alamaik surel nan Sanak masuakkan di [[Special:Preferences|pangaturan akun]] akan kalua sabagai alamaik "Dari" pado surel tasabuik, jadi panarimo dapek langsuang mambalehnyo.',
+'usermaildisabled' => 'Surel pangguno non-aktif',
+'emailtarget' => 'Masuakan namo pangguno nan ka manarimo surel',
+'emailusername' => 'Namo pangguno:',
+'emailusernamesubmit' => 'Kirim',
+'email-legend' => 'Kirim surel ka pangguno {{SITENAME}} lainnyo',
+'emailfrom' => 'Dari:',
+'emailto' => 'Untuak:',
+'emailsubject' => 'Perihal:',
+'emailmessage' => 'Pasan:',
+'emailsend' => 'Kirim',
+'emailccme' => 'Kirimkan denai salinan pasan.',
# Watchlist
-'watchlist' => 'Daftapantau',
-'mywatchlist' => 'Daftapantau',
+'watchlist' => 'Dafta pantau',
+'mywatchlist' => 'Dafta pantau',
'watchlistfor2' => 'Untuak $1 $2',
'addedwatchtext' => "Laman \"[[:\$1]]\" lah ditambahkan ka [[Special:Watchlist|senarai pantauan awak]].
Parubahan laman ko tamasuak laman otanyo akan ditampilkan dalam '''cetak taba''' pado [[Special:RecentChanges|senarai parubahan]] agar lebih mudah manjagonyo.",
-'removedwatchtext' => 'Laman "[[:$1]]" lah dihapuih dari [[Special:Watchlist|senarai pantauan awak]].',
+'removewatch' => 'Hapuih dari dafta pantau',
+'removedwatchtext' => 'Laman "[[:$1]]" lah dihapuih dari [[Special:Watchlist|dafta pantau Sanak]].',
'watch' => 'Pantau',
'watchthispage' => 'Pantau laman ko',
'unwatch' => 'Batal pantau',
-'watchlist-details' => '{{PLURAL:$1|$1 laman}} dalam daftapantau awak, indak tamasuak laman diskusi.',
+'unwatchthispage' => 'Batal pantau laman ko',
+'watchlist-details' => '{{PLURAL:$1|$1 laman}} dalam dafta pantau awak, indak tamasuak laman rundiangnyo.',
'wlshowlast' => 'Tampilkan $1 jam $2 hari tarakhia $3',
-'watchlist-options' => 'Piliahan daftapantau',
+'watchlist-options' => 'Piliahan dafta pantau',
# Displayed when you click the "watch" button and it is in the process of watching
'watching' => 'Mamantau...',
# Delete
'deletepage' => 'Hapuih laman',
+'confirm' => 'Konfirmasi',
'confirmdeletetext' => 'Awak akan mahapuih laman atau berkas basamo riwayatnyo.
Pastikan awak mainginkannyo, dan awak lah tahu sagalo akibatnyo dan sasuai jo [[{{MediaWiki:Policy-url}}|kebijakan]] yang balaku.',
'actioncomplete' => 'Proses salasai',
'deletereasonotherlist' => 'Alasan lain',
# Rollback
-'rollbacklink' => 'baliakkan',
+'rollback' => 'Baliakan suntiangan',
+'rollback_short' => 'Baliakan',
+'rollbacklink' => 'baliakan',
+'rollbacklinkcount' => 'baliakan $1 {{PLURAL:$1|suntiangan}}',
+'rollbacklinkcount-morethan' => 'baliakan labiah dari $1 {{PLURAL:$1|suntiangan}}',
+'rollbackfailed' => 'Gagal mambaliakan',
# Protect
'protectlogpage' => 'Log palinduangan',
'protect-cascadeon' => 'Laman ko sedang dilindungi karano tamasuak dalam {{PLURAL:$1|laman|laman}} aktif perlindungan batingkek.
Awak dapek maubah tingkek perlindungannyo, walaupun indak pangaruah pado perlindungan batingkeknyo.',
'protect-default' => 'Semua pangguno diizinkan',
-'protect-fallback' => 'Memerlukan hak akses "$1"',
-'protect-level-autoconfirmed' => 'Blokir pangguno baru dan indak terdaftar',
-'protect-level-sysop' => 'Hanya pengurus',
+'protect-fallback' => 'Cumo untuak pangguno jo izin "$1"',
+'protect-level-autoconfirmed' => 'Cumo untuak pangguno takonfirmasi otomatis',
+'protect-level-sysop' => 'Cumo untuak panguruih',
'protect-summary-cascade' => 'batingkek',
-'protect-expiring' => 'kadaluwarsa $1 (UTC)',
-'protect-cascade' => 'Lindungi semua laman yang bakaik jo laman ko (perlindungan batingkek)',
-'protect-cantedit' => 'Awak indak dapek maubah tingkek perlindungan laman ko, karano awak indak berhak.',
+'protect-expiring' => 'sampai $1 (UTC)',
+'protect-expiring-local' => 'sampai $1',
+'protect-expiry-indefinite' => 'sataruihnyo',
+'protect-cascade' => 'Linduangi laman nan takaik jo laman ko (palinduangan batingkek)',
+'protect-cantedit' => 'Sanak indak dapek maubah tingkek palinduangan laman ko, karano indak ado izin untuak itu.',
+'protect-othertime' => 'Wakatu lain:',
+'protect-othertime-op' => 'wakatu lain',
+'protect-existing-expiry' => 'Alah sampai: $3, $2',
+'protect-otherreason' => 'Alasan lain/tambahan:',
+'protect-otherreason-op' => 'Alasan lain',
'restriction-type' => 'Perlindungan:',
'restriction-level' => 'Tingkek larangan:',
+'minimum-size' => 'Ukuran min',
+'maximum-size' => 'Ukuran max',
+'pagesize' => '(bita)',
# Restrictions (nouns)
-'restriction-move' => 'Pindahan',
+'restriction-edit' => 'Suntiang',
+'restriction-move' => 'Pindah',
+'restriction-create' => 'Buek',
+'restriction-upload' => 'Muek',
# Undelete
'undeletelink' => 'caliak/cegakkan',
# Namespace form on various pages
'namespace' => 'Ruangnamo:',
-'invert' => 'Baliakkan pilihan',
+'invert' => 'Baliakkan piliahan',
+'namespace_association' => 'Ruangnamo takaik',
'blanknamespace' => '(Utamo)',
# Contributions
'sp-contributions-submit' => 'Cari',
# What links here
-'whatlinkshere' => 'Pranala baliak',
+'whatlinkshere' => 'Pautan baliak',
'whatlinkshere-title' => 'Laman yang bakaik ka "$1"',
'whatlinkshere-page' => 'Laman:',
'linkshere' => "Laman-laman ko bakaik ka '''[[:$1]]''':",
'nolinkshere' => "Indak ado laman nan punyo tautan ka '''[[:$1]]'''.",
'isredirect' => 'laman pengaliahan',
'istemplate' => 'transklusi',
-'isimage' => 'tautan berkas',
-'whatlinkshere-prev' => '{{PLURAL:$1|sabalunnyo|sabalunnyo $1}}',
-'whatlinkshere-next' => '{{PLURAL:$1|salanjuiknyo|salanjuiknyo $1}}',
-'whatlinkshere-links' => '← pranala',
-'whatlinkshere-hideredirs' => '$1 pengalihan',
+'isimage' => 'pautan berkas',
+'whatlinkshere-prev' => '{{PLURAL:$1|sabalunnyo}}',
+'whatlinkshere-next' => '{{PLURAL:$1|salanjuiknyo}}',
+'whatlinkshere-links' => '← pautan',
+'whatlinkshere-hideredirs' => '$1 pangaliahan',
'whatlinkshere-hidetrans' => '$1 transklusi',
-'whatlinkshere-hidelinks' => '$1 pranala',
-'whatlinkshere-hideimages' => '$1 pahubuang berkas',
-'whatlinkshere-filters' => 'Panapiah',
+'whatlinkshere-hidelinks' => '$1 pautan',
+'whatlinkshere-hideimages' => '$1 pautan berkas',
+'whatlinkshere-filters' => 'Panyariang',
# Block/unblock
-'blockip' => 'Blokir pangguno',
+'autoblockid' => 'Sakek otomatis #$1',
+'block' => 'Sakek pangguno',
+'unblock' => 'Lapeh sakek',
+'blockip' => 'Sakek pangguno',
+'blockip-title' => 'Sakek pangguno',
+'blockip-legend' => 'Sakek pangguno',
+'ipadressorusername' => 'Alamaik IP atau namo pangguno:',
+'ipbexpiry' => 'Sampai:',
+'ipbreason' => 'Alasan:',
+'ipbreasonotherlist' => 'Alasan lain',
+'ipbreason-dropdown' => '*Alasan umum
+** Marusak (vandal)
+** Mangagiah informasi palsu
+** Mangilangkan isi laman
+** Spam pautan ka situs lua
+** Mambuek ota gadang di laman
+** Babuek intimidasi/palecehan
+** Manyalahgunoan babarapo akun
+** Namo pangguno talarang',
+'ipb-hardblock' => 'Halang pangguno tadafta untuak manyuntiang dari alamaik IP ko',
+'ipbcreateaccount' => 'Halang mambuek akun',
+'ipbemailban' => 'Halang pangguno mangirim surel',
+'ipbenableautoblock' => 'Otomatis sakek alamaik IP tarakhia nan digunoan pangguno ko, jo sado alamaik IP takaik nan mancubo manyuntiang.',
+'ipbsubmit' => 'Sakek pangguno ko',
+'ipbother' => 'Salamo:',
'ipboptions' => '2 jam:2 hours,1 hari:1 day,3 hari:3 days,1 minggu:1 week,2 minggu:2 weeks,1 bulan:1 month,3 bulan:3 months,6 bulan:6 months,1 taun:1 year,salamonyo:infinite',
+'ipbotheroption' => 'lainnyo',
+'ipbotherreason' => 'Alasan lain/tambahan:',
+'ipbhidename' => 'Suruakan namo pangguno dari dafta jo suntiangan',
+'ipbwatchuser' => 'Pantau laman pangguno ko jo laman diskusinyo',
+'ipb-disableusertalk' => 'Halang pangguno ko manyuntiang laman diskusinyo wakatu disakek',
+'ipb-change-block' => 'Sakek baliak pangguno jo setelan ko',
+'ipb-confirm' => 'Konfirmasi sakek',
+'badipaddress' => 'Alamaik IP salah',
+'blockipsuccesssub' => 'Sakek barasil',
+'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] lah disakek.<br />
+Liek [[Special:BlockList|dafta sakek]] buek maninjaunyo.',
+'ipb-blockingself' => 'Angku ka manyakek diri surang! Lai yakin apo nan dikarajoan?',
+'ipb-edit-dropdown' => 'Suntiang alasan manyakek',
+'ipb-unblock-addr' => 'Lapeh sakek $1',
+'blocklist' => 'Pangguno tablokir',
'ipblocklist' => 'Pangguno tablokir',
-'blocklink' => 'balokir',
-'unblocklink' => 'hilangkan blokir',
-'change-blocklink' => 'ubah balokir',
+'blocklink' => 'sakek',
+'unblocklink' => 'hilangkan sakek',
+'change-blocklink' => 'ubah sakek',
'contribslink' => 'jariah',
'blocklogpage' => 'Log pamblokiran',
-'blocklogentry' => 'mamblokir [[$1]] dalam maso $2 $3',
-'unblocklogentry' => 'mahilangkan blokir $1',
+'blocklogentry' => 'Manyakek [[$1]] dalam maso $2 $3',
+'unblocklogentry' => 'mahilangkan sakek $1',
'block-log-flags-nocreate' => 'mambuek akun dimatikan',
+'blockme' => 'Sakek denai',
# Move page
-'movepagetext' => "Formulir di bawah ko digunoan untuak maubah namo suatu laman dan mamindahkan semua data riwayat ka namo baru. Judul lamo tu akan manjadi laman peralihan manuju judul yang baru. Pranala ka judul lamo indak akan baubah. Pastikan diperiksa laman yang [[Special:DoubleRedirects|peralihan ganda]] atau [[Special:BrokenRedirects|peralihan rusak]]. Awak bertanggungjawab untuak memastikan bahwa pranala tu terus manyambuang ka laman yang seharusnyo.
+'movepagetext' => "Formulir di bawah ko digunoan untuak maubah namo suatu laman dan mamindahan sadonyo data riwayaik ka namo baru.
+Judua lamo tu ka manjadi laman paraliahan manuju judua nan baru.
+Awak dapek mampabarui paraliahan-paraliahan nan manuju ka judua lamo sacaro otomatis.
+Kok indak dipabarui sacaro otomatis, pastikan lah dipareso laman ko dari [[Special:DoubleRedirects|paraliahan ganda]] atau [[Special:BrokenRedirects|paralihan rusak]]. Awak batanggung-jawak untuak mamastian bahaso pautan tu taruih manyambuang ka laman nan saaruihnyo.
-Perhatikan bahwa laman '''indak''' akan dipindah apobilo lah ado laman yang manggunokan judul yang baru, kecuali bilo laman tu kosong atau marupokan laman peralihan dan indak punyo riwayat suntingan. Maksudnyo awak dapek maubah namo laman seperti samulo apobilo ado kesalahan, dan awak indak dapek manimpo laman yang lah ado.
+Ingeklah bahaso laman ko '''indak''' ka bapindah apobilo lah ado laman nan manggunoan judua nan baru, kacuali bilo laman tu kosong atau marupoan laman paraliahan dan indak punyo riwayaik suntiangan. Aratinyo awak dapek maubah baliak namo laman ka namo samulo apobilo ado kasalahan, dan bahaso awak indak dapek manimpo laman nan lah ado.
-'''Peringatan:''' Iko dapek maakibatkan parubahan yang tak diduga pado laman yang populer. Jadi pastikan awak paham akibat tindakan ko sabalun melanjutkannyo.",
+'''Paringatan!'''
+Iko dapek maakibaikan parubahan nan indak dipakiroan pado laman nan populer; jadi pastikan awak paham akibaik tindakan ko sabalun malanjuikannyo.",
'movepagetalktext' => "Laman diskusi nan bakaitan akan dipindahkan sacaro otomatis '''kacuali apobilo:'''
*Sabuah laman diskusi nan indak kosong lah ado pado judul baru, atau
'thumbnail_error' => 'Gagal mambuek miniatur: $1',
# Tooltip help for the actions
-'tooltip-pt-userpage' => 'Laman pangguno sanak',
+'tooltip-pt-userpage' => 'Laman pangguno Sanak',
'tooltip-pt-anonuserpage' => 'Laman pangguno IP Sanak',
-'tooltip-pt-mytalk' => 'Laman diskusi sanak',
-'tooltip-pt-anontalk' => 'Diskusi tantang suntiangan dari alamat IP ko',
+'tooltip-pt-mytalk' => 'Laman rundiang Sanak',
+'tooltip-pt-anontalk' => 'Parundiangan tantang suntiangan dari IP ko',
'tooltip-pt-preferences' => 'Pangaturan denai',
'tooltip-pt-watchlist' => 'Dafta laman nan dipantau.',
-'tooltip-pt-mycontris' => 'Daftar jariah Sanak',
+'tooltip-pt-mycontris' => 'Dafta jariah Sanak',
'tooltip-pt-login' => 'Sanak disaranan untuak masuak log; walaupun indak wajib',
'tooltip-pt-logout' => 'Kalua log',
'tooltip-ca-talk' => 'Parudiangan tantang isi laman',
Sanak hanyo buliah mancaliak sumbernyo sajo',
'tooltip-ca-history' => 'Revisi sabalunnyo dari laman ko',
'tooltip-ca-protect' => 'Linduangi laman ko',
+'tooltip-ca-unprotect' => 'Tuka palinduangan laman ko',
'tooltip-ca-delete' => 'Hapuih laman ko',
'tooltip-ca-move' => 'Pindahan laman ko',
-'tooltip-ca-watch' => 'Tambahkan laman ko ka dafta pantauan sanak',
-'tooltip-ca-unwatch' => 'Kaluaan laman ko dari daftapantau',
+'tooltip-ca-watch' => 'Tambahkan laman ko ka dafta pantau sanak',
+'tooltip-ca-unwatch' => 'Kaluaan laman ko dari dafta pantau',
'tooltip-search' => 'Cari {{SITENAME}}',
'tooltip-search-go' => 'Cari laman jo namo nan samo jikok ado',
'tooltip-search-fulltext' => 'Cari laman untuak teks ko',
'tooltip-feed-rss' => 'Umpan RSS untuak laman ko',
'tooltip-feed-atom' => 'Umpan Atom untuak laman ko',
'tooltip-t-contributions' => 'Caliak dafta jariah pangguno ko',
-'tooltip-t-emailuser' => 'Kirim surel ka pangguno ko',
+'tooltip-t-emailuser' => 'Kirimkan surel pado pangguno ko',
'tooltip-t-upload' => 'Muek berkas',
'tooltip-t-specialpages' => 'Dafta dari sado laman istimewa',
'tooltip-t-print' => 'Versi cetak dari laman ko',
-'tooltip-t-permalink' => 'Pranala permanen untuak revisi laman ko',
+'tooltip-t-permalink' => 'Pautan parmanen untuak revisi laman ko',
'tooltip-ca-nstab-main' => 'Caliak isi laman',
'tooltip-ca-nstab-user' => 'Caliak laman pangguno',
'tooltip-ca-nstab-media' => 'Caliak laman media',
'tooltip-preview' => 'Caliak dulu nan diubah, gunokan ko sabalun manyimpan',
'tooltip-diff' => 'Caliak parubahan nan alah awak buek tu',
'tooltip-compareselectedversions' => 'Caliak pabedoan antaro duo revisi pilihan laman ko',
-'tooltip-watch' => 'Tambahkan laman ko ka daftapantau',
+'tooltip-watch' => 'Tambahkan laman ko ka dafta pantau',
'tooltip-recreate' => 'Buek baliak laman walaupun sabananyo pernah dihapuih',
'tooltip-upload' => 'Mulai mamuek',
'tooltip-rollback' => '"Baliakkan" uruangkan suntiang laman ko pado kontribusi tarakhir dalam sakali klik',
'tooltip-preferences-save' => 'Simpan preferensi',
'tooltip-summary' => 'Masuakan sabuah ringkasan pendek',
+# Stylesheets
+'print.css' => '/* CSS placed here will affect the print output */',
+
# Metadata
'notacceptable' => 'Layanan wiki indak manyadioan data dalam format yang dapek dibaco dek pelanggan awak.',
'anonymous' => '{{PLURAL:$1|Pangguno}} anonim {{SITENAME}}',
'siteuser' => 'pangguno {{SITENAME}} $1',
'anonuser' => 'pangguno anonim {{SITENAME}} $1',
+'others' => 'lainnyo',
'siteusers' => '{{PLURAL:$2|pangguno}} {{SITENAME}} $1',
'anonusers' => '{{PLURAL:$2|pangguno}} anonim {{SITENAME}} $1',
'creditspage' => 'Panghargaan laman',
'pageinfo-length' => 'Panjang laman (dalam bita)',
'pageinfo-article-id' => 'ID Laman',
'pageinfo-firstuser' => 'Pambuek laman',
+'pageinfo-toolboxlink' => 'Informasi laman',
# Skin names
'skinname-standard' => 'Klasik',
'skinname-modern' => 'Moderen',
'skinname-vector' => 'Vektor',
+# Patrolling
+'markaspatrolleddiff' => 'Tandoi lah dipatroli',
+'markaspatrolledtext' => 'Tandoi laman ko lah dipatroli',
+'markedaspatrolled' => 'Tandoi lah dipatroli',
+
# Browsing diffs
'previousdiff' => '← Revisi sabalunnyo',
'nextdiff' => 'Revisi salanjuiknyo →',
# Media information
-'thumbsize' => 'Ukuran miniatur:',
+'imagemaxsize' => "Bateh ukuran gambar:<br />''(untuak laman katarangan berkas)''",
+'thumbsize' => 'Ukuran miniatua:',
'widthheight' => '$1 × $2',
'widthheightpage' => '$1 × $2, $3 {{PLURAL:$3|laman}}',
'file-info' => 'ukuran berkas: $1, tipe MIME: $2',
'file-nohires' => 'Indak tasadio resolusi nan labiah gadang.',
'svg-long-desc' => 'Berkas SVG, $1 × $2 piksel, ukuran berkas: $3',
'svg-long-desc-animated' => 'Berkas anmasi SVG, $1 × $2 piksel, ukuran berkas: $3',
+'svg-long-error' => 'Berkas SVG indak sah: $1',
'show-big-image' => 'Resolusi panuah',
'show-big-image-preview' => 'Ukuran pratonton ko: $1',
'show-big-image-other' => '{{PLURAL:$2|Resolusi}} lainnyo: $1.',
'file-info-png-frames' => '$1 {{PLURAL:$1|bingkai}}',
# Special:NewFiles
-'newimages-legend' => 'Panyaring',
+'newimages-legend' => 'Panyariang',
'newimages-label' => 'Namo berkas (atau sabagian darinyo):',
'showhidebots' => '($1 bot)',
'noimages' => 'Indak ado nan dicaliak.',
'minutes' => '{{PLURAL:$1|$1 minik}}',
'hours' => '{{PLURAL:$1|$1 jam}}',
'days' => '{{PLURAL:$1|$1 hari}}',
+'months' => '{{PLURAL:$1|$1 bulan}}',
+'years' => '{{PLURAL:$1|$1 taun}}',
'ago' => '$1 nan lalu',
+'just-now' => 'kini ko',
# Bad image list
-'bad_image_list' => 'Ukurannyo adolah sabagai barikuik:
+'bad_image_list' => 'Formatnyo adolah sabagai barikuik:
-Hanyo dafta butia (barih nan dimulai jo tando *) nan dianggap.
-Pranala patamo pado barih musti pranala ka berkas buruak.
-Satiok pranala salanjuiknyo pado barih nan samo dianggap pangacualian, yaitu laman dima berkas tasabuik bisa tajadi sajajar.',
+Anyo dafta babutia (barih nan dimulai jo tando *) nan dianggap.
+Pautan patamo pado barih musiti pautan ka berkas buruak.
+Satiok pautan salanjuiknyo pado barih nan samo dianggap pangacualian, yaitu laman-laman dima berkas ko bisa tacaliak.',
/*
Short names for language variants used for language conversion links.
'watchlistall2' => 'kasadonyo',
'namespacesall' => 'sadonyo',
'monthsall' => 'sadonyo',
+'limitall' => 'sadonyo',
# Watchlist editing tools
'watchlisttools-view' => 'Tampilkan parubahan takaik',
-'watchlisttools-edit' => 'Tampilkan sarato suntiang daftapantau',
+'watchlisttools-edit' => 'Tampilkan sarato suntiang dafta pantau',
'watchlisttools-raw' => 'Suntiang pantauan mantah',
# Signatures
'duplicate-defaultsort' => '\'\'\'Peringatan:\'\'\' Kunci panguruitan default "$2" sabalunnyo mangabaikan kunci panguruitan default "$1".',
# Special:Version
+'version' => 'Versi',
+'version-extensions' => 'Ekstensi tarinstal',
+'version-specialpages' => 'Laman istimewa',
+'version-parserhooks' => 'Kaik parser',
+'version-variables' => 'Variabel',
+'version-antispam' => 'Pancagahan spam',
'version-skins' => 'Kulik',
'version-other' => 'Lain-lain',
+'version-version' => '(Versi $1)',
'version-license' => 'Lisensi',
+'version-poweredby-credits' => "Wiki ko didukuang jo '''[//www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
+'version-poweredby-others' => 'lainnyo',
+'version-software-version' => 'Versi',
+'version-entrypoints-header-url' => 'URL',
'version-entrypoints-articlepath' => '[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Artikel path]',
'version-entrypoints-scriptpath' => '[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Skrip path]',
# Special:FilePath
+'filepath' => 'Lokasi berkas',
'filepath-page' => 'Berkas:',
+'filepath-submit' => 'Cari',
# Special:FileDuplicateSearch
-'fileduplicatesearch-result-n' => 'Berkas "$1" punyo {{PLURAL:$2|1 duplikat identik|$2 duplikat identik}}.',
+'fileduplicatesearch-result-n' => 'Berkas "$1" ado {{PLURAL:$2|$2 duplikat nan samo}}.',
'fileduplicatesearch-noresults' => 'Indak basobok berkas banamo "$1".',
# Special:SpecialPages
'specialpages' => 'Laman istimewa',
+'specialpages-group-login' => 'Masuak log / mandafta',
+
+# Special:BlankPage
+'blankpage' => 'Laman kosong',
# External image whitelist
'external_image_whitelist' => '#Bia se barih ko apo adonyo<pre>
'searchsuggest-containing' => 'Barisi...',
# Durations
-'duration-millennia' => '$1 {{PLURAL:$1|millennium|millenia}}',
+'duration-millennia' => '$1 {{PLURAL:$1|milenium}}',
);
'prefs-user-pages' => 'Кориснички страници',
'prefs-personal' => 'Кориснички профил',
'prefs-rc' => 'Скорешни промени',
-'prefs-watchlist' => 'Ð\9dабљудувања',
+'prefs-watchlist' => 'набљудувања',
'prefs-watchlist-days' => 'Број на денови за приказ во списокот на набљудувања:',
'prefs-watchlist-days-max' => 'Највеќе $1 {{PLURAL:$1|ден|дена}}',
'prefs-watchlist-edits' => 'Максимален број на прикажани промени во проширениот список на набљудувања:',
'exblank' => 'страницата беше празна',
'delete-confirm' => 'Избриши „$1“',
'delete-legend' => 'Бришење',
-'historywarning' => "'''Предупредување:''' Страницата којашто сакате да ја избришете има историја со околу $1 {{PLURAL:$1|ревизија|ревизии}}:",
+'historywarning' => "'''Предупредување:''' Страницата што сакате да ја избришете има историја со околу $1 {{PLURAL:$1|ревизија|ревизии}}:",
'confirmdeletetext' => 'На пат сте трајно да избришете страница заедно со нејзината историја.
Потврдете дека имате намера да го направите ова, дека ги разбирате последиците од тоа, дека го правите ова во согласност со [[{{MediaWiki:Policy-url}}|политиката]].',
'actioncomplete' => 'Дејството е спроведено',
'revdelete-content-unhid' => 'содржината е откриена',
'revdelete-summary-unhid' => 'описот на уредувањето е откриен',
'revdelete-uname-unhid' => 'корисничкото име е скриено',
-'revdelete-restricted' => 'применети ограничувања на систем оператори',
+'revdelete-restricted' => 'применети ограничувања на администратори',
'revdelete-unrestricted' => 'отстранети ограничувања за систем оператори',
'logentry-move-move' => '$1 ја премести страницата $3 на $4',
'logentry-move-move-noredirect' => '$1 ја премести страницата $3 на $4 без да остави пренасочување',
* @author Aan
* @author Angela
* @author Ankitgadgil
+ * @author Ashupawar
* @author Balaji
* @author Chandu
* @author Dnyanesh325
* @author Mohanpurkar
* @author Mvkulkarni23
* @author Prabodh1987
+ * @author Pranav jagtap
* @author Rahuldeshmukh101
* @author Rdeshmuk
* @author Sankalpdravid
* @author Sudhanwa
* @author Tusharpawar1982
* @author V.narsikar
+ * @author Vibhavari
* @author Vpnagarkar
* @author Ydyashad
* @author Ynwala
'moredotdotdot' => 'अजून...',
'morenotlisted' => 'आणखी यादीत नाही...',
'mypage' => 'माझे पान',
-'mytalk' => 'माà¤\9dà¥\8dया à¤\9aरà¥\8dà¤\9aा',
+'mytalk' => 'चर्चा',
'anontalk' => 'या अंकपत्त्याचे चर्चा पान उघडा',
'navigation' => 'सुचालन',
'and' => ' आणि',
'namespaces' => 'नामविश्वे',
'variants' => 'अस्थिर',
+'navigation-heading' => 'दिक्चालन यादी',
'errorpagetitle' => 'चूक',
'returnto' => '$1 कडे परत चला.',
'tagline' => '{{SITENAME}} कडून',
'badarticleerror' => 'या पानावर ही कृती करता येत नाही.',
'cannotdelete' => '$1 हे पान किंवा संचिका वगळता आलेली नाही. (आधीच इतर कुणी वगळले असण्याची शक्यता आहे.)',
'cannotdelete-title' => '$1 ला वगळू शकत नाहि',
+'delete-hook-aborted' => 'खोडण्याची क्रिया मधेच थांबवीण्यात येत आहे.
+कोणतेही कारण देण्यात आले नाही',
'badtitle' => 'चुकीचे शीर्षक',
'badtitletext' => 'आपण मागितलेले शीर्षक पान अयोग्य, रिकामे अथवा चूकीने जोडलेले आंतर-भाषिय किंवा आंतर-विकि शीर्षक आहे. त्यात एक किंवा अधिक शीर्षकअयोग्य चिन्हे आहेत.',
'perfcached' => 'खालील माहिती सयीमध्ये(कॅशे) ठेवली आहे त्यामुळे ती नवीनतम {{PLURAL:$1|one result is|$1 results }} नसावी.',
'edit-no-change' => 'तुमचे संपादन दुर्लक्षित करण्यात आले आहे, कारण माहितीमध्ये काहीही बदल झालेला नाही.',
'edit-already-exists' => 'नवीन पान तयार करता येऊ शकले नाही.
या नावाचे पान आधीच अस्तित्वात आहे.',
+'defaultmessagetext' => 'कसूर पाठ्य मजकूर',
+'invalid-content-data' => 'अवैध माहिती',
# Content models
'content-model-wikitext' => 'विकिमजकूर',
'right-writeapi' => 'लेखन एपीआय चा उपयोग',
'right-delete' => 'पृष्ठे वगळा',
'right-bigdelete' => 'जास्त इतिहास असणारी पाने वगळा',
+'right-deletelogentry' => 'थरविक् लोग् प्रवेश् बन्द आनि चालु करने',
'right-deleterevision' => 'एखाद्या पानाच्या विशिष्ट आवृत्त्या लपवा',
'right-deletedhistory' => 'वगळलेल्या इतिहास नोंदी, त्यांच्या संलग्न मजकूराशिवाय पहा',
'right-deletedtext' => 'वगळलेला मजकूर व वगळलेल्या आवर्तनांमधील बदल पहा',
'alllogstext' => '{{SITENAME}}च्या सर्व नोंदीचे एकत्र दर्शन.नोंद प्रकार, सदस्यनाव किंवा बाधीत पान निवडून तुम्ही तुमचे दृश्यपान मर्यादीत करू शकता.',
'logempty' => 'नोंदीत अशी बाब नाही.',
'log-title-wildcard' => 'या मजकुरापासून सुरू होणारी शिर्षके शोधा.',
+'showhideselectedlogentries' => 'निवडलेले लॉग पहाणे /लपवणे',
# Special:AllPages
'allpages' => 'सर्व पृष्ठे',
'allpages-hide-redirects' => 'पुनर्निर्देशने लपवा',
# SpecialCachedPage
+'cachedspecial-viewing-cached-ttl' => 'तुम्ही पाहत आहात या पाठया ची छोटी आवृत्ती,जी की १ तास ३० मिनिट जुनी असू शकते',
'cachedspecial-refresh-now' => 'आखेरचे दृश्य',
# Special:Categories
'import-error-interwiki' => 'इंटर विकी लिंक साठी $1 पान आरक्षित केल्यामुळे ते इम्पोर्ट करू शकत नाही',
'import-error-special' => 'विशेष नामविश्वासाठी $1 पान आरक्षित केल्यामुळे ते इम्पोर्ट करू शकत नाही. या नामविश्वात पाने असत नाहीत.',
'import-error-invalid' => 'नाव अयोग्य असल्याने $1 पान इम्पोर्ट करू शकत नाही.',
+'import-rootpage-invalid' => 'दिलेले मूळ पान अवैध नाव आहे',
# Import log
'importlogpage' => 'ईम्पोर्ट सूची',
'pageinfo-display-title' => 'दृश्य शीर्षक',
'pageinfo-length' => 'पानाचा आकार (बाइट्समध्ये)',
'pageinfo-language' => 'पानाच्या मजकूराची भाषा',
+'pageinfo-robot-index' => 'आनुक्रमानीत',
+'pageinfo-robot-noindex' => 'आनुक्रमानीत करू शकत नाही',
'pageinfo-views' => 'अभिप्रायांची संख्या',
'pageinfo-watchers' => 'पाहणाऱ्यांची संख्या',
'pageinfo-redirects-name' => 'या पानाकडील पुनर्निर्देशने',
+'pageinfo-firstuser' => 'पृष्ठ निर्मानक',
'pageinfo-firsttime' => 'पान निर्मितीचा दिनांक',
'pageinfo-lastuser' => 'अलीकडील संपादक',
'pageinfo-lasttime' => 'अलीकडिल संपादनाचा दिनांक',
'search-interwiki-default' => 'Keputusan daripada $1:',
'search-interwiki-more' => '(lagi)',
'search-relatedarticle' => 'Berkaitan',
-'mwsuggest-disable' => 'Matikan ciri cadangan AJAX',
+'mwsuggest-disable' => 'Matikan ciri cadangan carian',
'searcheverything-enable' => 'Cari dalam semua ruang nama',
'searchrelated' => 'berkaitan',
'searchall' => 'semua',
'newwindow' => '(नयाँ विन्डोमा खुल्छ)',
'cancel' => 'रद्द',
'moredotdotdot' => 'थप...',
+'morenotlisted' => 'थप जानकारी दिइएको छैन',
'mypage' => 'पृष्ठ',
'mytalk' => 'वार्ता',
'anontalk' => 'यस IP को वारेमा वार्तालाप गर्नुहोस्',
'search-interwiki-default' => '$1-resultat:',
'search-interwiki-more' => '(meir)',
'search-relatedarticle' => 'Relatert',
-'mwsuggest-disable' => 'Slå av AJAX-forslag',
+'mwsuggest-disable' => 'Slå av søkjeframlegg',
'searcheverything-enable' => 'Søk i alle namneroma',
'searchrelated' => 'relatert',
'searchall' => 'alle',
'pageinfo-robot-noindex' => 'Kan ikkje indekserast',
'pageinfo-views' => 'Tal på visningar',
'pageinfo-watchers' => 'Tal på overvakarar av sida',
+'pageinfo-few-watchers' => 'Færre enn $1 {{PLURAL:$1|som overvakar}}',
'pageinfo-redirects-name' => 'Omdirigeringar til sida',
'pageinfo-subpages-name' => 'Undersider av sida',
'pageinfo-subpages-value' => '$1 ({{PLURAL:$2|éi omdirigering|$2 omdirigeringar}}; {{PLURAL:$3|éi ikkje-omdirigering|$3 ikkje-omdirigeringar}})',
'tog-extendwatchlist' => 'Espandir la lista de seguiment per afichar totas las modificacions e non pas solament las mai recentas',
'tog-usenewrc' => 'Agropar los cambiaments dins los darrièrs cambiaments e la lista de seguiment (necessita JavaScript)',
'tog-numberheadings' => 'Numerotar automaticament los títols',
-'tog-showtoolbar' => 'Far veire la barra de menut de modificacion (JavaScript)',
+'tog-showtoolbar' => 'Far veire la barra de menú de modificacion (JavaScript)',
'tog-editondblclick' => 'Modificar una pagina amb un clic doble (JavaScript)',
'tog-editsection' => 'Modificar una seccion via los ligams [modificar]',
'tog-editsectiononrightclick' => 'Modificar una seccion en fasent un clic drech sus son títol (JavaScript)',
'protectedpagetext' => "Aquesta pagina es estada protegida per empachar sa modificacion o d'autras accions.",
'viewsourcetext' => 'Podètz veire e copiar lo contengut de l’article per poder trabalhar dessús :',
'viewyourtext' => "Podètz veire e copiar lo contengut de '''vòstras modificacions''' a aquesta pagina :",
-'protectedinterface' => 'Aquesta pagina provesís de tèxte d’interfàcia pel logicial e es protegida per evitar los abuses.',
+'protectedinterface' => 'Aquesta pagina provesís de tèxte d’interfàcia pel logicial susaqueste wiki, e es protegida per evitar los abuses.
+Per apondre o modificar de traduccions sus totes los wikis, utilizatz [//translatewiki.net/ translatewiki.net], lo projècte de localizacion de MediaWiki.',
'editinginterface' => "'''Atencion :''' sètz a editar una pagina utilizada per crear lo tèxte de l’interfàcia del logicial. Los cambiaments se repercutaràn, segon lo contèxte, sus totas o d'unas paginas visiblas pels autres utilizaires. Per las traduccions, vos convidam a utilizar lo projècte MediaWiki d'internacionalizacion dels messatges [//translatewiki.net/wiki/Main_Page?setlang=oc translatewiki.net].",
'sqlhidden' => '(Requèsta SQL amagada)',
'cascadeprotected' => "Aquesta pagina es actualament protegida perque es inclusa dins {{PLURAL:$1|la pagina seguenta|las paginas seguentas}}, {{PLURAL:$1|qu'es estada protegida|que son estadas protegidas}} amb l’opcion « proteccion en cascada » activada :
'gotaccount' => "Ja avètz un compte ? '''$1'''.",
'gotaccountlink' => 'Identificatz-vos',
'userlogin-resetlink' => 'Avètz doblidat vòstres detalhs de connexion ?',
-'createaccountmail' => 'per corrièr electronic',
+'createaccountmail' => 'Utilizar un senhal aleatòri temporari e lo mandar a l’adreça de corrièl especificada çaijós',
'createaccountreason' => 'Motiu :',
'badretype' => "Los senhals qu'avètz picats son pas identics.",
'userexists' => "Lo nom d'utilizaire qu'avètz picat ja es utilizat.
'passwordreset-legend' => 'Reïnicializar lo senhal',
'passwordreset-username' => "Nom d'utilizaire :",
'passwordreset-domain' => 'Domeni:',
+'passwordreset-capture' => 'Veire lo corrièl resultant ?',
'passwordreset-email' => 'Adreça de corrièr electronic :',
'passwordreset-emailtitle' => "Detailhs d'un compte per {{SITENAME}}",
'passwordreset-emailelement' => 'Utilizaire: $1
'lockmanager-fail-openlock' => 'Impossible de dobrir lo fichièr de varrolh per « $1 ».',
'lockmanager-fail-releaselock' => 'Impossible de daissar anar lo fichièr de varrolh per « $1 ».',
+# Special:UploadStash
+'uploadstash' => "Escondedor d'impòrt",
+
# img_auth script messages
'img-auth-accessdenied' => 'Accès refusat',
'img-auth-nopathinfo' => 'PATH_INFO mancant.
'statistics-users-active-desc' => "Utilizaires qu'an fach al mens una accion durant {{PLURAL:$1|lo darrièr jorn|los $1 darrièrs jorns}}",
'statistics-mostpopular' => 'Paginas mai consultadas',
-'disambiguations' => "Paginas d'omonimia",
+'disambiguations' => "Paginas qu'an de ligams cap a de paginas d'omonimia",
'disambiguationspage' => 'Template:Omonimia',
'disambiguations-text' => "Las paginas seguentas puntan cap a una '''pagina d’omonimia'''.
Deurián puslèu puntar cap a una pagina apropriada.<br />
'usermessage-editor' => 'Messatgièr del sistèma',
# Watchlist
-'watchlist' => 'Ma lista de seguiment',
+'watchlist' => 'Lista de seguiment',
'mywatchlist' => 'Lista de seguiment',
'watchlistfor2' => 'Per $1 ($2)',
'nowatchlist' => "Vòstra lista de seguiment conten pas cap d'article.",
L’article de destinacion « [[:$1]] » existís ja.
Lo volètz suprimir per permetre lo cambiament de nom ?',
'delete_and_move_confirm' => 'Òc, accèpti de suprimir la pagina de destinacion per permetre lo cambiament de nom.',
-'delete_and_move_reason' => 'Pagina suprimida per permetre un cambiament de nom',
+'delete_and_move_reason' => 'Pagina suprimida per permetre lo cambiament de nom dempuèi « [[$1]] »',
'selfmove' => 'Los títols d’origina e de destinacion son los meteisses : impossible de tornar nomenar una pagina sus ela-meteissa.',
'immobile-source-namespace' => "Podètz pas tornar nomenar de paginas dins l'espaci de noms « $1 »",
'immobile-target-namespace' => "Podètz pas desplaçar de paginas cap a l'espaci de noms « $1 »",
Per exportar de paginas, entratz lors títols dins la bóstia de tèxte çaijós, un títol per linha, e seleccionatz s'o desiratz o pas la version actuala amb totas las versions ancianas, amb la pagina d’istoric, o simplament la pagina actuala amb d'informacions sus la darrièra modificacion.
Dins aqueste darrièr cas, podètz tanben utilizar un ligam, coma [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] per la pagina [[{{MediaWiki:Mainpage}}]].",
+'exportall' => 'Exportar totas las paginas',
'exportcuronly' => 'Exportar unicament la version correnta sens l’istoric complet',
'exportnohistory' => "----
'''Nòta :''' l’exportacion completa de l’istoric de las paginas amb l’ajuda d'aqueste formulari es estada desactivada per de rasons de performàncias.",
'import-logentry-interwiki' => 'a importat (transwiki) $1',
'import-logentry-interwiki-detail' => '$1 {{PLURAL:$1|version|versions}} dempuèi $2',
+# JavaScriptTest
+'javascripttest' => 'Tèst de JavaScript',
+'javascripttest-title' => 'Execucion dels tèsts $1',
+
# Tooltip help for the actions
'tooltip-pt-userpage' => "Vòstra pagina d'utilizaire",
'tooltip-pt-anonuserpage' => "La pagina d'utilizare de l’IP amb la quala contribuissètz",
'tooltip-ca-viewsource' => 'Aquesta pagina es protegida. Çaquelà, ne podètz veire lo contengut.',
'tooltip-ca-history' => "Los autors e versions precedentas d'aquesta pagina.",
'tooltip-ca-protect' => 'Protegir aquesta pagina',
-'tooltip-ca-unprotect' => 'Desprotegir aquesta pagina',
+'tooltip-ca-unprotect' => "Cambiar la proteccion d'aquesta pagina",
'tooltip-ca-delete' => 'Suprimir aquesta pagina',
'tooltip-ca-undelete' => 'Restablir aquesta pagina',
'tooltip-ca-move' => 'Tornar nomenar aquesta pagina',
'tooltip-diff' => "Permet de visualizar los cambiaments qu'avètz efectuats",
'tooltip-compareselectedversions' => "Afichar las diferéncias entre doas versions d'aquesta pagina",
'tooltip-watch' => 'Apondre aquesta pagina a vòstra lista de seguiment',
+'tooltip-watchlistedit-normal-submit' => 'Levar los títols',
+'tooltip-watchlistedit-raw-submit' => 'Mesa a jorn de la lista de seguiment',
'tooltip-recreate' => 'Tornar crear la pagina, quitament se es estada escafada',
'tooltip-upload' => 'Amodar lo mandadís',
'tooltip-rollback' => '"Revocar" anulla en un clic la o las edicion(s) sus aquesta pagina del darrièr contributor.',
'pageinfo-magic-words' => '{{PLURAL:$1|Mot magic|Mots magics}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Categoria amagada|Categorias amagadas}} ($1)',
'pageinfo-templates' => '{{PLURAL:$1|Modèl inclús|Modèls incluses}} ($1)',
+'pageinfo-toolboxlink' => 'Informacion sus la pagina',
+'pageinfo-redirectsto' => 'Redirigir cap a',
'pageinfo-redirectsto-info' => 'info',
'pageinfo-contentpage-yes' => 'Òc',
'pageinfo-protect-cascading-yes' => 'Òc',
+'pageinfo-category-info' => 'Informacions sus la categoria',
+'pageinfo-category-pages' => 'Nombre de paginas',
+'pageinfo-category-subcats' => 'Nombre de soscategorias',
+'pageinfo-category-files' => 'Nombre de fichièrs',
# Skin names
'skinname-standard' => 'Estandard',
'hours' => '{{PLURAL:$1|$1 ora|$1 oras}}',
'days' => '{{PLURAL:$1|$1 jorn|$1 jorns}}',
'ago' => 'I a $1',
+'just-now' => 'sulpic',
# Bad image list
'bad_image_list' => "Lo format es lo seguent :
'filepath' => "Camin d'accès d'un fichièr",
'filepath-page' => 'Fichièr :',
'filepath-submit' => 'Validar',
-'filepath-summary' => "Aquesta pagina especiala balha lo camin d'accès complet d’un fichièr ; los imatges son mostrats en nauta resolucion, los fichièrs audiò e vidèo s’executan amb lor programa associat.
-
-Picatz lo nom del fichièr sens lo prefix « {{ns:file}}: »",
+'filepath-summary' => "Aquesta pagina especiala retorna lo camin d'accès complet d’un fichièr.
+Los imatges son afichats en nauta resolucion, los fichièrs àudio e vidèo son cargats e aviats dirèctament amb lor programa associat.",
# Special:FileDuplicateSearch
'fileduplicatesearch' => 'Recèrca dels fichièrs en doble',
'fileduplicatesearch-info' => '$1 × $2 pixèls<br />Talha del fichièr : $3<br />MIME type : $4',
'fileduplicatesearch-result-1' => 'Lo fichièr « $1 » a pas de doble identic.',
'fileduplicatesearch-result-n' => 'Lo fichièr « $1 » a {{PLURAL:$2|1 doble identic|$2 dobles identics}}.',
+'fileduplicatesearch-noresults' => 'Cap de fichièr nomenat « $1 » es pas estat trobat.',
# Special:SpecialPages
'specialpages' => 'Paginas especialas',
'specialpages-note' => '----
-* Las paginas especialas
-* <strong class="mw-specialpagerestricted">en gras</strong> son restrenhudas.',
+* Paginas especialas normalas.
+* <span class="mw-specialpagerestricted">Paginas especialas restrenchas.</span>
+* <span class="mw-specialpagecached">Paginas especialas solament en escondedor (poirián èsser obsolètas).</span>',
'specialpages-group-maintenance' => 'Rapòrts de mantenença',
'specialpages-group-other' => 'Autras paginas especialas',
'specialpages-group-login' => "S'identificar / s'inscriure",
'specialpages-group-highuse' => 'Utilizacion intensa de las paginas',
'specialpages-group-pages' => 'Listas de paginas',
'specialpages-group-pagetools' => 'Aisinas per las paginas',
-'specialpages-group-wiki' => 'Donadas del wiki e aisinas',
+'specialpages-group-wiki' => 'Donadas e aisinas',
'specialpages-group-redirects' => 'Redireccions',
'specialpages-group-spam' => 'Aisinas antispam',
'htmlform-selectorother-other' => 'Autre',
# New logging system
+'logentry-delete-delete' => '$1 a suprimit la pagina $3',
+'logentry-delete-restore' => '$1 a restablit la pagina $3',
'revdelete-content-hid' => 'contengut amagat',
'revdelete-summary-hid' => 'resumit de modificacion amagat',
'revdelete-uname-hid' => 'nom d’utilizaire amagat',
'fri' => 'ଶୁକ୍ର',
'sat' => 'ଶନି',
'january' => 'ଜାନୁଆରୀ',
-'february' => 'ଫà\87ବà\8dରà\81ଆରୀ',
+'february' => 'ଫà\87ବà\83ଆରୀ',
'march' => 'ମାର୍ଚ୍ଚ',
'april' => 'ଅପ୍ରେଲ',
'may_long' => 'ମଇ',
'november' => 'ନଭେମ୍ବର',
'december' => 'ଡିସେମ୍ବର',
'january-gen' => 'ଜାନୁଆରୀ',
-'february-gen' => 'ଫà\87ବà\8dରà\81ଆରୀ',
+'february-gen' => 'ଫà\87ବà\83ଆରୀ',
'march-gen' => 'ମାର୍ଚ୍ଚ',
'april-gen' => 'ଅପ୍ରେଲ',
'may-gen' => 'ମଇ',
'namespaces' => 'ନେମସ୍ପେସ',
'variants' => 'ନିଆରା',
-'navigation-heading' => 'ଦିà¬\97ବାରà\87ଣà\80 ମିନୁ',
+'navigation-heading' => 'ଦିà¬\97ବାରà\87ଣି ମà\87ନୁ',
'errorpagetitle' => 'ଭୁଲ',
'returnto' => '$1କୁ ଫେରିଯାନ୍ତୁ ।',
'tagline' => '{{SITENAME}} ରୁ',
'imagepage' => 'ଫାଇଲ ପୃଷ୍ଠାଗୁଡ଼ିକ ଦେଖନ୍ତୁ',
'mediawikipage' => 'ମେସେଜ ପୃଷ୍ଠାଟି ଦେଖାଇବେ',
'templatepage' => 'ଛାଞ୍ଚ ପୃଷ୍ଠାଗୁଡ଼ିକ ଦେଖନ୍ତୁ',
-'viewhelppage' => 'ସହାଯà\8bà¬\97 ପà\83ଷà\8dଠାà¬\97à\81ଡ଼ିà¬\95 ଦà\87à¬\96ନà\8dତà\81',
+'viewhelppage' => 'ସହଯୋଗ ପୃଷ୍ଠାଗୁଡ଼ିକ ଦେଖନ୍ତୁ',
'categorypage' => 'ଶ୍ରେଣୀ ପୃଷ୍ଠାଟିକୁ ଦେଖାଇବେ',
'viewtalkpage' => 'ଆଲୋଚନାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ',
'otherlanguages' => 'ଅଲଗା ଭାଷା',
'mainpage' => 'ପ୍ରଧାନ ପୃଷ୍ଠା',
'mainpage-description' => 'ପ୍ରଧାନ ପୃଷ୍ଠା',
'policy-url' => 'Project:ନୀତି',
-'portal' => 'ସà¬\99à\8dଘ ସୂଚନା ଫଳକ',
-'portal-url' => 'Project:ସà¬\99à\8dଘ ସୂଚନା ଫଳକ',
+'portal' => 'ସà¬\82ଘ ସୂଚନା ଫଳକ',
+'portal-url' => 'Project:ସà¬\82ଘ ସୂଚନା ଫଳକ',
'privacy' => 'ଗୁମର ନୀତି',
'privacypage' => 'Project:ଗୁମର ନୀତି',
'badaccess' => 'ଅନୁମତି ମିଳିବାରେ ଅସୁବିଧା',
-'badaccess-group0' => 'à¬\86ପଣ à¬\85ନà\81ରà\8bଷ କରିଥିବା ପୃଷ୍ଠାଟିରେ କିଛି କାମ କରିବା ନିମନ୍ତେ ଆପଣଙ୍କୁ ଅନୁମତି ମିଳିନାହିଁ',
+'badaccess-group0' => 'à¬\86ପଣ à¬\85ନà\81ରà\8bଧ କରିଥିବା ପୃଷ୍ଠାଟିରେ କିଛି କାମ କରିବା ନିମନ୍ତେ ଆପଣଙ୍କୁ ଅନୁମତି ମିଳିନାହିଁ',
'badaccess-groups' => 'ଆପଣ ଅନୁରୋଧ କରିଥିବା କାମଟି କେବଳ {{PLURAL:$2|ଗୋଠ|ଗୋଠମାନଙ୍କ ଭିତରୁ ଗୋଟିଏ ଗୋଠ}}: $1 ର ସଭ୍ୟମାନଙ୍କ ଭିତରେ ସୀମିତ ।',
'versionrequired' => 'ମିଡ଼ିଆଉଇକି ର $1 ତମ ସଙ୍କଳନଟି ଲୋଡ଼ା',
# General errors
'error' => 'ଭୁଲ',
'databaseerror' => 'ଡାଟାବେସରେ ଭୁଲ',
-'dberrortext' => 'à¬\8fହା à¬\8fହି ସଫà\8dà¬\9fବେରରେ ଭୁଲଟିଏକୁ ମଧ୍ୟ ସୂଚାଇପାରେ ।
+'dberrortext' => 'à¬\8fହା à¬\8fହି ସଫà\8dà¬\9fà±େରରେ ଭୁଲଟିଏକୁ ମଧ୍ୟ ସୂଚାଇପାରେ ।
ଶେଷଥର ଖୋଜାଯାଇଥିବା ଡାଟାବେସ ପ୍ରଶ୍ନଟି ଥିଲା:
<blockquote><code>$1</code></blockquote>
ଯାହାକି "<code>$2</code>"ରୁ ଥିଲା
'protectedpagetext' => 'ଏହି ପୃଷ୍ଠାଟି ସମ୍ପାଦନା କିମ୍ବା ଅନ୍ୟକୌଣସି କାର୍ଯ୍ୟ କରିବାରୁ କିଳାଯାଇଛି ।',
'viewsourcetext' => 'ଆପଣ ଏହି ପୃଷ୍ଠାର ଲେଖା ଦେଖିପାରିବେ ଓ ନକଲ କରିପାରିବେ:',
'viewyourtext' => "ଆପଣ '''ଆପଣଙ୍କ ସମ୍ପାଦିତ ''' ଅଧରଟିକୁ ଦେଖିପାରିବେ ଓ ଏହି ପୃଷ୍ଠାକୁ ନକଲ କରି ପାରିବେ",
-'protectedinterface' => 'à¬\8fହି ପà\83ଷà\8dଠାà¬\9fି à¬\8fହି à¬\89à¬\87à¬\95ିରà\87 ଥିବା ସଫà\8dà¬\9fà±à\87ର ନିମନà\8dତà\87 à¬\87ଣà\8dà¬\9fରଫà\87ସ ଲà\87à¬\96ା ଯà\8bà¬\97ାà¬\87ଥାà¬\8f à¬\93 à¬\8fହା à¬\85ବà\8dପà\9fବହାରà¬\95à\81 ରà\8bà¬\95ିବା ନିମନà\8dତà\87 à¬\95ିଳାଯାà¬\87à¬\85à¬\9bି । ସମସà\8dତ à¬\89à¬\87à¬\95ିର à¬\85ନà\81ବାଦà¬\95à\81 ଯà\8bଡିବା à¬\8fବà¬\82 ବଦଳାà¬\87ବା ପାà¬\87à¬\81 ମà\87ଡିଆଉଇକିର ସ୍ଥାନୀୟ ପ୍ରକଳ୍ପରେ ଥିବା [//translatewiki.net/ translatewiki.net]କୁ ବ୍ୟବହାର କରନ୍ତୁ ।',
-'editinginterface' => "'''à¬\9aà\87ତାବନà\80:''' à¬\86ପଣ ସଫà\8dà¬\9fବେରର ଇଣ୍ଟରଫେସ ଲେଖା ଯୋଗାଇବା ନିମନ୍ତେ ବ୍ୟବହାର କରାଯାଉଥିବା ଏକ ପୃଷ୍ଠାର ସମ୍ପାଦନା କରୁଅଛନ୍ତି ।
+'protectedinterface' => 'à¬\8fହି ପà\83ଷà\8dଠାà¬\9fି à¬\8fହି à¬\89à¬\87à¬\95ିରà\87 ଥିବା ସଫà\8dà¬\9fà±à\87ର ନିମନà\8dତà\87 à¬\87ଣà\8dà¬\9fରଫà\87ସ ଲà\87à¬\96ା ଯà\8bà¬\97ାà¬\87ଥାà¬\8f à¬\93 à¬\8fହା à¬\85ପବà\8dà\9fବହାରà¬\95à\81 ରà\8bà¬\95ିବା ନିମନà\8dତà\87 à¬\95ିଳାଯାà¬\87à¬\85à¬\9bି । ସମସà\8dତ à¬\89à¬\87à¬\95ିର à¬\85ନà\81ବାଦà¬\95à\81 ଯà\8bଡ଼ିବା à¬\8fବà¬\82 ବଦଳାà¬\87ବା ପାà¬\87à¬\81 ମà\87ଡ଼ିଆଉଇକିର ସ୍ଥାନୀୟ ପ୍ରକଳ୍ପରେ ଥିବା [//translatewiki.net/ translatewiki.net]କୁ ବ୍ୟବହାର କରନ୍ତୁ ।',
+'editinginterface' => "'''à¬\9aà\87ତାବନà\80:''' à¬\86ପଣ ସଫà\8dà¬\9fà±େରର ଇଣ୍ଟରଫେସ ଲେଖା ଯୋଗାଇବା ନିମନ୍ତେ ବ୍ୟବହାର କରାଯାଉଥିବା ଏକ ପୃଷ୍ଠାର ସମ୍ପାଦନା କରୁଅଛନ୍ତି ।
ଏହି ଉଇକିପୃଷ୍ଠାର କିଛି ବି ବଦଳ ବାକି ସଭ୍ୟମାନଙ୍କ ଇଣ୍ଟରଫେସର ଦେଖଣାକୁ ପ୍ରଭାବିତ କରିବ ।
ସମସ୍ତ ଉଇକିର ଅନୁବାଦ ନିମନ୍ତେ, ଦୟାକରି ମିଡ଼ିଆଉଇକିର ସ୍ଥାନୀୟକରଣ ପ୍ରକଳ୍ପ [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net] ବ୍ୟବହାର କରନ୍ତୁ ।",
'sqlhidden' => '(SQL ପ୍ରଶ୍ନ ଲୁଚାଯାଇଅଛି)',
ଆପଣ ବନାନ ପରଖି ନିଅନ୍ତୁ ।',
'nouserspecified' => 'ଆପଣଙ୍କୁ ଇଉଜର ନାମଟିଏ ଦେବାକୁ ପଡ଼ିବ ।',
'login-userblocked' => 'ଏହି ସଭ୍ୟଙ୍କୁ ଅଟକାଯାଇଛି । ଲଗ ଇନ କରିବାକୁ ଅନୁମତି ନାହିଁ ।',
-'wrongpassword' => 'ଦିà¬\86ଯାà¬\87ଥିବା ପାସବାର୍ଡ଼ଟି ଭୁଲ ଅଟେ ।
+'wrongpassword' => 'ଦିà¬\86ଯାà¬\87ଥିବା ପାସà±ାର୍ଡ଼ଟି ଭୁଲ ଅଟେ ।
ଦୟାକରି ଆଉଥରେ ଚେଷ୍ଟା କରନ୍ତୁ ।',
'wrongpasswordempty' => 'ଦିଆଯାଇଥିବା ପାସବାର୍ଡ଼ଟି ଖାଲି ଛଡ଼ାଯାଇଛି ।
ଦୟାକରି ଆଉଥରେ ଚେଷ୍ଟା କରନ୍ତୁ ।',
-'passwordtooshort' => 'ପାସବାର୍ଡ଼ଟି ଅତି କମରେ {{PLURAL:$1|ଗୋଟିଏ ଅକ୍ଷର|$1ଟି ଅକ୍ଷର}}ର ହୋଇଥିବା ଲୋଡ଼ା ।',
-'password-name-match' => 'à¬\86ପଣà¬\99à\8dà¬\95 ପାସବାର୍ଡ଼ଟି ଆପଣଙ୍କ ଇଉଜର ନାମ ଠାରୁ ଅଲଗା ହେବା ଉଚିତ ।',
-'password-login-forbidden' => 'à¬\8fହି à¬\87à¬\89à¬\9cର ନାମ à¬\93 ପାସବାର୍ଡ଼ର ବ୍ୟବହାରକୁ ବାରଣ କରାଯାଇଅଛି ।',
-'mailmypassword' => 'ପାସବାର୍ଡ଼ଟିକୁ ଇମେଲ କରି ପଠାଇବେ',
+'passwordtooshort' => 'ପାସà±ାର୍ଡ଼ଟି ଅତି କମରେ {{PLURAL:$1|ଗୋଟିଏ ଅକ୍ଷର|$1ଟି ଅକ୍ଷର}}ର ହୋଇଥିବା ଲୋଡ଼ା ।',
+'password-name-match' => 'à¬\86ପଣà¬\99à\8dà¬\95 ପାସà±ାର୍ଡ଼ଟି ଆପଣଙ୍କ ଇଉଜର ନାମ ଠାରୁ ଅଲଗା ହେବା ଉଚିତ ।',
+'password-login-forbidden' => 'à¬\8fହି à¬\87à¬\89à¬\9cର ନାମ à¬\93 ପାସà±ାର୍ଡ଼ର ବ୍ୟବହାରକୁ ବାରଣ କରାଯାଇଅଛି ।',
+'mailmypassword' => 'ପାସà±ାର୍ଡ଼ଟିକୁ ଇମେଲ କରି ପଠାଇବେ',
'passwordremindertitle' => '{{SITENAME}} ପାଇଁ ନୂଆ ଅଳ୍ପ କାଳର ପାସୱାର୍ଡ଼',
'passwordremindertext' => 'କେହିଜଣେ (ବୋଧେ ଆପଣ, $1 IP ଠିକଣାରୁ)
ନୂଆ ପାସବାର୍ଡ଼ଟିଏ ପାଇଁ {{SITENAME}} ($4) ରେ ଆବେଦନ କରିଅଛନ୍ତି । "$2"ଙ୍କ ପାଇଁ ଏକ ଅସ୍ଥାୟୀ ପାସବାର୍ଡ଼
continue using your old password.',
'noemail' => 'ସଭ୍ୟ "$1"ଙ୍କ ପାଇଁ କିଛି ବି ଇ-ମେଲ ଆଇ.ଡି. ସାଇତାଯାଇନାହିଁ ।',
'noemailcreate' => 'ଆପଣଙ୍କୁ ଏକ ସଚଳ ଇ-ମେଲ ଠିକଣା ଦେବାକୁ ପଡ଼ିବ',
-'passwordsent' => '"$1" ପାà¬\87à¬\81 ଥà\9f à¬\95ରାଯାà¬\87ଥିବା à¬\87-ମà\87ଲà¬\95à\81 ନà\82à¬\86 ପାସବାର୍ଡ଼ଟିଏ ପଠାଇଦିଆଗଲା ।
+'passwordsent' => '"$1" ପାà¬\87à¬\81 ଥà\9f à¬\95ରାଯାà¬\87ଥିବା à¬\87-ମà\87ଲà¬\95à\81 ନà\82à¬\86 ପାସà±ାର୍ଡ଼ଟିଏ ପଠାଇଦିଆଗଲା ।
ତାହା ମିଳିଲା ପରେ ଆଉଥରେ ଲଗ ଇନ କରନ୍ତୁ ।',
-'blocked-mailpassword' => 'à¬\86ପଣà¬\99à\8dà¬\95 IP ଠିà¬\95ଣାà¬\9fି ସମà\8dପାଦନାରà\87 à¬à¬¾à¬\97 ନà\87ବାରà\81 à¬\85à¬\9fà¬\95ାଯାà¬\87à¬\9bି, ତà\87ଣà\81 ପାସବାର୍ଡ଼ ଫେରନ୍ତା କାମ ବ୍ୟବହାର କରି ଅବ୍ୟବହାରକୁ ରୋକିବା ଅନୁମୋଦିତ ନୁହେଁ ।',
+'blocked-mailpassword' => 'à¬\86ପଣà¬\99à\8dà¬\95 IP ଠିà¬\95ଣାà¬\9fି ସମà\8dପାଦନାରà\87 à¬à¬¾à¬\97 ନà\87ବାରà\81 à¬\85à¬\9fà¬\95ାଯାà¬\87à¬\9bି, ତà\87ଣà\81 ପାସà±ାର୍ଡ଼ ଫେରନ୍ତା କାମ ବ୍ୟବହାର କରି ଅବ୍ୟବହାରକୁ ରୋକିବା ଅନୁମୋଦିତ ନୁହେଁ ।',
'eauthentsent' => 'ଆପଣଙ୍କ ବଛା ଇ-ମେଲ ଠିକଣାକୁ ଏକ ଥୟ କରିବା ଇ-ମେଲଟିଏ ପଠାଇଦିଆଗଲା ।
ଖାତାଟି ଆପଣଙ୍କର ବୋଲି ଥୟ କରିବା ନିମନ୍ତେ ଆଉ କେଉଁ ଇ-ମେଲ ଆପଣଙ୍କ ଖାତାକୁ ପଠାହେବା ଆଗରୁ ଆପଣଙ୍କୁ ସେହି ଇ-ମେଲରେ ଥିବା ସୂଚନା ଅନୁସରଣ କରିବାକୁ ପଡ଼ିବ ।',
-'throttled-mailpassword' => 'à¬\97ତ {{PLURAL:$1|à¬\8fà¬\95 à¬\98ଣà\8dà¬\9fାରà\87|$1 à¬\98ଣà\8dà¬\9fାରà\87}} à¬\86ପଣà¬\99à\8dà¬\95à\81 à¬\8fà¬\95 ପାସବାର୍ଡ଼ ମନେକରିବା ସୂଚନାଟିଏ ପଠାଯାଇଛି ।
-à¬\85ବà\8dà\9fବହାରà¬\95à\81 ରà\8bà¬\95ିବା ନିମନà\8dତà\87, {{PLURAL:$1|à¬\8fà¬\95 à¬\98ଣà\8dà¬\9fାରà\87|$1 à¬\98ଣà\8dà¬\9fାରà\87}} à¬\95à\87ବଳ à¬\97à\8bà¬\9fିà¬\8f ପାସବାର୍ଡ଼ ହିଁ ପଠାହେବ ।',
+'throttled-mailpassword' => 'à¬\97ତ {{PLURAL:$1|à¬\8fà¬\95 à¬\98ଣà\8dà¬\9fାରà\87|$1 à¬\98ଣà\8dà¬\9fାରà\87}} à¬\86ପଣà¬\99à\8dà¬\95à\81 à¬\8fà¬\95 ପାସà±ାର୍ଡ଼ ମନେକରିବା ସୂଚନାଟିଏ ପଠାଯାଇଛି ।
+à¬\85ବà\8dà\9fବହାରà¬\95à\81 ରà\8bà¬\95ିବା ନିମନà\8dତà\87, {{PLURAL:$1|à¬\8fà¬\95 à¬\98ଣà\8dà¬\9fାରà\87|$1 à¬\98ଣà\8dà¬\9fାରà\87}} à¬\95à\87ବଳ à¬\97à\8bà¬\9fିà¬\8f ପାସà±ାର୍ଡ଼ ହିଁ ପଠାହେବ ।',
'mailerror' => 'ମେଲ ପଠାଇବାରେ ଭୁଲ : $1',
'acct_creation_throttle_hit' => 'ଏହି ଉଇକିର ଦେଖଣାହାରୀ ମାନେ ଆପଣଙ୍କ IP ଠିକଣା ବ୍ୟବହାର କରି ବିଗତ ଦିନରେ {{PLURAL:$1|ଖାତାଟିଏ|$1 ଗୋଟି ଖାତା}} ତିଆରି କରିଛନ୍ତି ଯାହା ସେହି ସମୟସୀମା ଭିତରେ ସବୁଠାରୁ ଅଧିକ ଥିଲା ।
ତେଣୁ, ଏହି IP ଠିକଣାର ଦେଖଣାହାରୀ ଗଣ ଏବେ ଆଉ ଅଧିକ ଖାତା ଖୋଲିପାରିବେ ନାହିଁ ।',
'emailauthenticated' => '$2 ତାରିଖ $3 ଘଟିକା ବେଳେ ଆପଣଙ୍କ ଇ-ମେଲ ଠିକଣାଟି ଅନୁମୋଦିତ ହେଲା ।',
-'emailnotauthenticated' => 'à¬\86ପନà¬\99à\8dà¬\95 à¬\87-ମà\87ଲ ଠିà¬\95ଣାà¬\9fି à¬\85ନà\81ମà\8bଦିତà\8d ହୋଇନାହିଁ ।
+'emailnotauthenticated' => 'à¬\86ପଣà¬\99à\8dà¬\95 à¬\87-ମà\87ଲ ଠିà¬\95ଣାà¬\9fି à¬\85ନà\81ମà\8bଦିତ ହୋଇନାହିଁ ।
ଏହି ସବୁ ସୁବିଧାକୁ ନେଇ କିଛି ବି ଇ-ମେଲ ଆପଣଙ୍କୁ ପଠାଯିବ ନାହିଁ ।',
'noemailprefs' => 'ଆପଣଙ୍କ ପସନ୍ଦ ଭିତରେ ଏକ ଇ-ମେଲ ଠିକଣା ଦିଅନ୍ତୁ ଯାହା ଏହି ସବୁ ସୁବିଧାକୁ ସଚଳ କରାଇବ ।',
'emailconfirmlink' => 'ଆପଣଙ୍କ ଇମେଲ ଆଇ.ଡି.ଟି ଠିକ ବୋଲି ଥୟ କରନ୍ତୁ',
'accountcreated' => 'ଖାତାଟି ଖୋଲାହୋଇଗଲା',
'accountcreatedtext' => '$1 ପାଇଁ ନୂଆ ଖାତାଟିଏ ତିଆରି ହୋଇଗଲା ।',
'createaccount-title' => '{{SITENAME}} ପାଇଁ ଖାତା ଖୋଲା',
-'createaccount-text' => 'à¬\95à\87ହି à¬\9cଣà\87 à¬\86ପଣà¬\99à\8dà¬\95 à¬\87-ମà\87ଲ ଠିà¬\95ଣାରà\87 {{SITENAME}} ($4) ରà\87 "$2" ନାମରà\87, "$3" ପାସବାର୍ଡ଼ରେ ଖାତାଟିଏ ତିଆରି କରିଅଛି ।
+'createaccount-text' => 'à¬\95à\87ହି à¬\9cଣà\87 à¬\86ପଣà¬\99à\8dà¬\95 à¬\87-ମà\87ଲ ଠିà¬\95ଣାରà\87 {{SITENAME}} ($4) ରà\87 "$2" ନାମରà\87, "$3" ପାସà±ାର୍ଡ଼ରେ ଖାତାଟିଏ ତିଆରି କରିଅଛି ।
ଆପଣ ଏବେ ଲଗ ଇନ କରି ନିଜର ପାସବାର୍ଡ଼ଟିକୁ ବଦଳାଇଦିଅନ୍ତୁ ।
-ଯଦି ଭୁଲରେ ଏହି ଖାତାଟି ତିଆରି କରାଯାଇଥାଏ ତେବେ ଏହି ସୂଚନାଟିକୁ ଅଣଦେଖା କରିବେ ।',
+ଯଦି ଭୁଲରେ ଏହି ଖାତାଟି ତିଆରି କରାଯାଇଥାଏ, ତେବେ ଏହି ସୂଚନାଟିକୁ ଅଣଦେଖା କରିବେ ।',
'usernamehasherror' => 'ଇଉଜର ନାମରେ ହାସ ଅକ୍ଷର (hash characters) ରହି ପାରିବନାହିଁ',
'login-throttled' => 'ଆପଣ ବହୁ ଥର ଲଗ ଇନ କରିବାର ଉଦ୍ୟମ କରିଅଛନ୍ତି ।
ଦୟାକରି ଆଉଥରେ ଚେଷ୍ଟା କରିବା ଆଗରୁ କିଛି କାଳ ଅପେକ୍ଷ କରନ୍ତୁ ।',
'resetpass' => 'ପାସୱାର୍ଡ଼ ବଦଳାନ୍ତୁ',
'resetpass_announce' => 'ଆପଣ ଏକ ଅସ୍ଥାୟୀ ଇ-ମେଲରେ ଯାଇଥିବା କୋଡ଼ ସହାୟତାରେ ଲଗ ଇନ କରିଅଛନ୍ତି ।
ଲଗ ଇନ ଶେଷ କରିବା ନିମନ୍ତେ ଆପଣଙ୍କୁ ଏହିଠାରେ ନୂଆ ପାସବାର୍ଡ଼ଟିଏ ଦେବାକୁ ପଡ଼ିବ:',
-'resetpass_header' => 'à¬\96ାତାର ପାସବାର୍ଡ଼ଟିକୁ ବଦଳାଇ ଦିଅନ୍ତୁ',
+'resetpass_header' => 'à¬\96ାତାର ପାସà±ାର୍ଡ଼ଟିକୁ ବଦଳାଇ ଦିଅନ୍ତୁ',
'oldpassword' => 'ପୁରୁଣା ପାସୱାର୍ଡ଼:',
'newpassword' => 'ନୂଆ ପାସୱାର୍ଡ଼:',
'retypenew' => 'ପାସୱାର୍ଡ଼ ଆଉଥରେ ଦିଅନ୍ତୁ:',
-'resetpass_submit' => 'ପାସବାରà\8dଡ଼à¬\9fି ଦେଇ ଲଗ ଇନ କରନ୍ତୁ',
+'resetpass_submit' => 'ପାସà±à¬¾à¬°à\8dଡ଼à¬\9fିà¬\8f ଦେଇ ଲଗ ଇନ କରନ୍ତୁ',
'resetpass_success' => 'ଆପଣଙ୍କ ପାସବାର୍ଡ଼ଟି ବଦଳାଇ ଦିଆଗଲା !
ଏବେ ଲଗ ଇନ କରୁଅଛୁଁ...',
'resetpass_forbidden' => 'ପାସବାର୍ଡ଼ମାନ ବଦଳା ଯାଇପାରିବ ନାହିଁ',
'resetpass-no-info' => 'ଏହି ପୃଷ୍ଠାଟିକୁ ସିଧା ଖୋଲିବା ନିମନ୍ତେ ଆପଣଙ୍କୁ ଲଗ ଇନ କରିବାକୁ ପଡ଼ିବ ।',
'resetpass-submit-loggedin' => 'ପାସୱାର୍ଡ଼ ବଦଳାନ୍ତୁ',
'resetpass-submit-cancel' => 'ନାକଚ',
-'resetpass-wrong-oldpass' => 'à¬\85ସà\8dଥାà\9fà\80 ବା à¬\8fବà\87à¬\95ାର ପାସବାର୍ଡ଼ଟି ଭୁଲ ଅଟେ ।
-à¬\86ପଣ ବà\8bଧ ହà\81à¬\8f à¬\86à¬\97ରà\81 ସଫଳ à¬à¬¾à¬¬à¬°à\87 ନିà¬\9cର ପାସବାରà\8dଡ଼à¬\9fି ବଦଳାà¬\87ଦà\87à¬\87à¬\9bନà\8dତି ବା ନà\82à¬\86 à¬\85ସà\8dଥାà\9fà\80 ପାସବାର୍ଡ଼ଟିଏ ପାଇଁ ଆବେଦନ କରିଅଛନ୍ତି ।',
+'resetpass-wrong-oldpass' => 'à¬\85ସà\8dଥାà\9fà\80 ବା à¬\8fବà\87à¬\95ାର ପାସà±ାର୍ଡ଼ଟି ଭୁଲ ଅଟେ ।
+à¬\86ପଣ ବà\8bଧ ହà\81à¬\8f à¬\86à¬\97ରà\81 ସଫଳ à¬à¬¾à¬¬à¬°à\87 ନିà¬\9cର ପାସà±à¬¾à¬°à\8dଡ଼à¬\9fି ବଦଳାà¬\87ଦà\87à¬\87à¬\9bନà\8dତି ବା ନà\82à¬\86 à¬\85ସà\8dଥାà\9fà\80 ପାସà±ାର୍ଡ଼ଟିଏ ପାଇଁ ଆବେଦନ କରିଅଛନ୍ତି ।',
'resetpass-temp-password' => 'ଅସ୍ଥାୟୀ ପାସୱାର୍ଡ଼:',
# Special:PasswordReset
$2
-{{PLURAL:$3|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସବାରà\8dଡ଼à¬\9fି|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସବାର୍ଡ଼ସବୁ}} {{PLURAL:$5|ଦିନକରେ|$5 ଦିନରେ ଅଚଳ}} ହୋଇଯିବ ।
-à¬\86ପଣ à¬\8fବà\87 ଲà¬\97 à¬\87ନ à¬\95ରି ନà\82à¬\86 ପାସବାର୍ଡ଼ଟିଏ ବାଛନ୍ତୁ । ଯହି ଆଉ କେହି ଜଣେ ଏହି ଅନୁରୋଧ କରିଥାନ୍ତି
-à¬\95ିମà\8dବା à¬\86ପଣ à¬\8fବà\87 ନିà¬\9cର ମà\82ଳ ପାସବାରà\8dଡ଼ ମନà\87 ପà¬\95ାà¬\87 ପାରିଥାନà\8dତି ତà\87ବà\87 à¬\8fହି ପାସବାର୍ଡ଼ଟିକୁ ଆଉ ବଦଳାଇବା ଲୋଡ଼ା ନାହିଁ ।
-à¬\86ପଣ ନିà¬\9c ପà\81ରà\81ଣା ପାସବାର୍ଡ଼ଟି ଆଗପରି ବ୍ୟବହାର କରିପାରନ୍ତି ।',
-'passwordreset-emailtext-user' => '{{SITENAME}}ରà\87 ଥିବା ବà\8dà\9fà\9fବହାରà¬\95ାରà\80 $1 {{SITENAME}} ($4) ସାà¬\87à¬\9fରà\87 ଥିବା à¬\86ପଣà¬\99à\8dà¬\95 à¬\96ାତାର ସବିଶà\87ଷ à¬\9cାଣିବାà¬\95à\81 à¬\85ନà\81ରà\8bଧ à¬\95ରିà¬\9bନà\8dତି । à¬\8fହି à¬\87ମà\87ଲ ଠିà¬\95ଣା ସହିତ ତଳଲିà¬\96ିତ ବà\8dà\9fବହାରà¬\95ାରà\80à¬\99à\8dà¬\95 {{PLURAL:$3|à¬\96ାତା|à¬\96ାତାସମà\82ହ}} ଯà\8bଡ଼ା:
+{{PLURAL:$3|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସà±à¬¾à¬°à\8dଡ଼à¬\9fି|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସà±ାର୍ଡ଼ସବୁ}} {{PLURAL:$5|ଦିନକରେ|$5 ଦିନରେ ଅଚଳ}} ହୋଇଯିବ ।
+à¬\86ପଣ à¬\8fବà\87 ଲà¬\97 à¬\87ନ à¬\95ରି ନà\82à¬\86 ପାସà±ାର୍ଡ଼ଟିଏ ବାଛନ୍ତୁ । ଯହି ଆଉ କେହି ଜଣେ ଏହି ଅନୁରୋଧ କରିଥାନ୍ତି
+à¬\95ିମà\8dବା à¬\86ପଣ à¬\8fବà\87 ନିà¬\9cର ମà\82ଳ ପାସà±à¬¾à¬°à\8dଡ଼ ମନà\87 ପà¬\95ାà¬\87 ପାରିଥାନà\8dତି ତà\87ବà\87 à¬\8fହି ପାସà±ାର୍ଡ଼ଟିକୁ ଆଉ ବଦଳାଇବା ଲୋଡ଼ା ନାହିଁ ।
+à¬\86ପଣ ନିà¬\9c ପà\81ରà\81ଣା ପାସà±ାର୍ଡ଼ଟି ଆଗପରି ବ୍ୟବହାର କରିପାରନ୍ତି ।',
+'passwordreset-emailtext-user' => '{{SITENAME}}ରେ ଥିବା ବ୍ୟବହାରକାରୀ $1 {{SITENAME}} ($4) ସାଇଟରେ ଥିବା ଆପଣଙ୍କ ଖାତାର ସବିଶେଷ ଜାଣିବାକୁ ଅନୁରୋଧ କରିଛନ୍ତି । ଏହି ଇମେଲ ଠିକଣା ସହିତ ତଳଲିଖିତ ବ୍ୟବହାରକାରୀଙ୍କ {{PLURAL:$3|ଖାତା|ଖାତାସମୂହ}} ଯୋଡ଼ା:
$2
-{{PLURAL:$3|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସବାରà\8dଡ଼à¬\9fି|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସବାର୍ଡ଼ସବୁ}} {{PLURAL:$5|ଦିନକରେ|$5 ଦିନରେ ଅଚଳ}} ହୋଇଯିବ ।
-à¬\86ପଣ à¬\8fବà\87 ଲà¬\97 à¬\87ନ à¬\95ରି ନà\82à¬\86 ପାସବାର୍ଡ଼ଟିଏ ବାଛନ୍ତୁ । ଯହି ଆଉ କେହି ଜଣେ ଏହି ଅନୁରୋଧ କରିଥାନ୍ତି
-à¬\95ିମà\8dବା à¬\86ପଣ à¬\8fବà\87 ନିà¬\9cର ମà\82ଳ ପାସବାରà\8dଡ଼ ମନà\87 ପà¬\95ାà¬\87 ପାରିଥାନà\8dତି ତà\87ବà\87 à¬\8fହି ପାସବାର୍ଡ଼ଟିକୁ ଆଉ ବଦଳାଇବା ଲୋଡ଼ା ନାହିଁ ।
-à¬\86ପଣ ନିà¬\9c ପà\81ରà\81ଣା ପାସବାର୍ଡ଼ଟି ଆଗପରି ବ୍ୟବହାର କରିପାରନ୍ତି ।',
+{{PLURAL:$3|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସà±à¬¾à¬°à\8dଡ଼à¬\9fି|à¬\8fହି à¬\85ସà\8dଥାà\9fà\80 ପାସà±ାର୍ଡ଼ସବୁ}} {{PLURAL:$5|ଦିନକରେ|$5 ଦିନରେ ଅଚଳ}} ହୋଇଯିବ ।
+à¬\86ପଣ à¬\8fବà\87 ଲà¬\97 à¬\87ନ à¬\95ରି ନà\82à¬\86 ପାସà±ାର୍ଡ଼ଟିଏ ବାଛନ୍ତୁ । ଯହି ଆଉ କେହି ଜଣେ ଏହି ଅନୁରୋଧ କରିଥାନ୍ତି
+à¬\95ିମà\8dବା à¬\86ପଣ à¬\8fବà\87 ନିà¬\9cର ମà\82ଳ ପାସà±à¬¾à¬°à\8dଡ଼ ମନà\87 ପà¬\95ାà¬\87 ପାରିଥାନà\8dତି ତà\87ବà\87 à¬\8fହି ପାସà±ାର୍ଡ଼ଟିକୁ ଆଉ ବଦଳାଇବା ଲୋଡ଼ା ନାହିଁ ।
+à¬\86ପଣ ନିà¬\9c ପà\81ରà\81ଣା ପାସà±ାର୍ଡ଼ଟି ଆଗପରି ବ୍ୟବହାର କରିପାରନ୍ତି ।',
'passwordreset-emailelement' => 'ଇଉଜର ନାମ: $1
-à¬\85ସà\8dଥାà\9fà\80 ପାସବାର୍ଡ଼: $2',
+à¬\85ସà\8dଥାà\9fà\80 ପାସà±ାର୍ଡ଼: $2',
'passwordreset-emailsent' => 'ଏକ ମନେପକାଇବା ଇ-ମେଲ ପଠାଇଦିଆଯାଇଅଛି ।',
'passwordreset-emailsent-capture' => 'ତଳେ ଦିଆଯାଇଥିବା ଭଳି ମନେପକାଇବା ଇ-ମେଲଟିଏ ପଠାଦିଆଗଲା ।',
-'passwordreset-emailerror-capture' => 'à¬\97à\8bà¬\9fିà¬\8f ସବିଶà\87ଷ à¬\8fମà\87ଲà¬\9fିà¬\8f ବାହାରିà¬\9bି, ଯାହାକି ତଳେ ଅଛି, କିନ୍ତୁ ଏହାକୁ ବ୍ୟବହାରକାରୀକୁ ପଠାଇବାରେ ଅସଫଳ ହେଲା :$1',
+'passwordreset-emailerror-capture' => 'à¬\97à\8bà¬\9fିà¬\8f ମନà\87ପà¬\95ାà¬\87ବା à¬\87-ମà\87ଲ ତିà¬\86ରି à¬\95ରାଯାà¬\87ଥିଲା, ଯାହାକି ତଳେ ଅଛି, କିନ୍ତୁ ଏହାକୁ ବ୍ୟବହାରକାରୀକୁ ପଠାଇବାରେ ଅସଫଳ ହେଲା :$1',
# Special:ChangeEmail
'changeemail' => 'ଇ-ମେଲ ଠିକଣା ବଦଳାଇବେ',
'changeemail-header' => 'ଖାତା ଇ-ମେଲ ଠିକଣା ବଦଳାଇବେ',
-'changeemail-text' => 'à¬\86ପଣା à¬\87-ମà\87ଲ ଠିà¬\95ଣା ବଦଳାà¬\87ବା ନିମନà\8dତà\87 à¬\8fହି à¬\86ବà\87ଦନ ପତà\8dରà¬\9fି ପà\82ରଣ à¬\95ରନà\8dତà\81 । à¬\86ପଣà¬\99à\8dà¬\95à\81 à¬\8fହି ବଦଳ ଥà\9f à¬\95ରିବା ପାà¬\87à¬\81 ନିà¬\9cର ପାସବାର୍ଡ଼ ଦେବାକୁ ପଡ଼ିବ ।',
+'changeemail-text' => 'à¬\86ପଣା à¬\87-ମà\87ଲ ଠିà¬\95ଣା ବଦଳାà¬\87ବା ନିମନà\8dତà\87 à¬\8fହି à¬\86ବà\87ଦନ ପତà\8dରà¬\9fି ପà\82ରଣ à¬\95ରନà\8dତà\81 । à¬\86ପଣà¬\99à\8dà¬\95à\81 à¬\8fହି ବଦଳ ଥà\9f à¬\95ରିବା ପାà¬\87à¬\81 ନିà¬\9cର ପାସà±ାର୍ଡ଼ ଦେବାକୁ ପଡ଼ିବ ।',
'changeemail-no-info' => 'ଏହି ପୃଷ୍ଠାଟିକୁ ସିଧା ଖୋଲିବା ନିମନ୍ତେ ଆପଣଙ୍କୁ ଲଗ ଇନ କରିବାକୁ ପଡ଼ିବ ।',
'changeemail-oldemail' => 'ଏବେକାର ଇ-ମେଲ ଠିକଣା:',
'changeemail-newemail' => 'ନୂଆ ଇ-ମେଲ ଠିକଣା:',
'link_sample' => 'ଲିଙ୍କ ଶିରୋନାମା',
'link_tip' => 'ଭିତର ଲିଙ୍କ',
'extlink_sample' => 'http://www.example.com ଲିଙ୍କ ଶିରୋନାମା',
-'extlink_tip' => 'ବାହାର ଲିଙ୍କ (http:// ଆଗରେ ଲଗାଇବାକୁ ମନେରଖିଥିବେ)',
+'extlink_tip' => 'ବାହାର ଲିଙ୍କ (ଆରମ୍ଭରେ http:// ଲେଖିବାକୁ ମନେରଖିଥିବେ)',
'headline_sample' => 'ଶିରୋନାମା ଲେଖା',
'headline_tip' => '୨କ ଆକାରର ମୂଳଧାଡ଼ି',
'nowiki_sample' => 'ଅସଜଡ଼ା ଲେଖା ଏଠାରେ ଭରିବେ',
'nowiki_tip' => 'ଉଇକି ସଜାଣି ବିନା',
-'image_tip' => 'ଏମବେଡ଼ ହୋଇ ଥିବା ଫାଇଲ',
+'image_tip' => 'à¬\8fମà\8dବà\87ଡ଼ ହà\8bà¬\87 ଥିବା ଫାà¬\87ଲ',
'media_tip' => 'ଫାଇଲର ଲିଙ୍କ',
-'sig_tip' => 'ଲà\87à¬\96ାର ସମà\9f ସହ à¬\86ପଣà¬\99à\8dà¬\95 ସନà\8dତà¬\95',
+'sig_tip' => 'ସମୟ ସହ ଆପଣଙ୍କ ସନ୍ତକ',
'hr_tip' => 'ସମାନ୍ତରାଳ ରେଖା (ବେଳେବେଳେ ବ୍ୟବହାର କରିବେ)',
# Edit pages
'summary' => 'ସାରକଥା:',
-'subject' => 'ବିଷà\9f/ମà\82ଳ ଲà\87à¬\96ା',
+'subject' => 'ବିଷà\9f/ଶିରà\8bନାମା',
'minoredit' => 'ଏହା ଖୁବ ଛୋଟ ବଦଳଟିଏ',
'watchthis' => 'ଏହି ପୃଷ୍ଠାଟିକୁ ଦେଖିବେ',
'savearticle' => 'ସାଇତିବେ',
'showlivepreview' => 'ଜୀବନ୍ତ ଦେଖଣା',
'showdiff' => 'ବଦଳଗୁଡ଼ିକ ଦେଖାଇବେ',
'anoneditwarning' => "'''ଜାଣିରଖନ୍ତୁ:''' ଆପଣ ଲଗଇନ କରିନାହାନ୍ତି ।
-à¬\8fହି ଫରଦର '''à¬\87ତିହାସ''' ପà\83ଷà\8dଠାରେ ଆପଣଙ୍କ ଆଇପି ଠିକଣାଟି ସାଇତା ହୋଇଯିବ ।",
-'anonpreviewwarning' => "''à¬\86ପଣ ଲà¬\97 à¬\87ନ à¬\95ରି ନାହାନà\8dତି । à¬\86ପଣ ଯà\87à¬\89à¬\81 ବଦଳସବà\81 à¬\95ରିବେ ଆପଣଙ୍କର IP ଠିକଣା ଏହି ପୃଷ୍ଠାର ଇତିହାସରେ ସାଇତା ହୋଇଯିବ ।''",
+à¬\8fହି ପà\83ଷà\8dଠାର à¬\87ତିହାସରେ ଆପଣଙ୍କ ଆଇପି ଠିକଣାଟି ସାଇତା ହୋଇଯିବ ।",
+'anonpreviewwarning' => "''à¬\86ପଣ ଲà¬\97 à¬\87ନ à¬\95ରି ନାହାନà\8dତି । ବଦଳà¬\95ରି ସାà¬\87ତିଲେ ଆପଣଙ୍କର IP ଠିକଣା ଏହି ପୃଷ୍ଠାର ଇତିହାସରେ ସାଇତା ହୋଇଯିବ ।''",
'missingsummary' => "'''ଚେତାବନୀ:''' ଆପଣ ଏକ ସମ୍ପାଦନା ସାରକଥା ଦେଇନାହାନ୍ତି ।
ଯଦି ଆପଣ \"{{int:savearticle}}\"ରେ ଆଉଥରେ କ୍ଲିକ କରନ୍ତି, ତେବେ ଆପଣଙ୍କ ବଦଳ ସାରକଥା ବିନା ସାଇତା ହୋଇଯିବ ।",
'missingcommenttext' => 'ଦୟାକରି ତଳେ ଏକ ମତାମତ ଦିଅନ୍ତୁ ।',
'imagelinks' => 'Usage dech fichié',
'linkstoimage' => "{{PLURAL:$1|L'pache d'apreu est liée|Chés $1 paches d'apreu sont liées}} à ch'fichié-lo :",
'nolinkstoimage' => "Autchune pache n'est loïée aveuc ch'fichié-lo",
-'sharedupload' => "Cht'fichié vient éd $1 pi i put ète imploïé par d'eutes proujés.",
-'sharedupload-desc-here' => "Ch'fichié i vient éd $1. I put ète uzer pèr d’eutes prodjés.
-Vir apré ([$2 pache]).",
+'sharedupload' => "Ch'fichié i vient éd $1. I put ète imploïé par d'eutes proujés.",
+'sharedupload-desc-there' => "Ch'fichié i vient éd $1. I put ète uzé pèr d’eutes prodjés. Vir l'pache [$2 édseur Commons].",
+'sharedupload-desc-here' => "Ch'fichié i vient éd $1. I put ète uzé pèr d’eutes prodjés.
+Vir l'pache [$2 édseur Commons].",
+'sharedupload-desc-edit' => "Ch'fichié i vient éd $1. I put ète imploïé par d'eutes proujés. Os pouvez canjer l' déscripcion dsu s' [$2 pache Commons].",
+'sharedupload-desc-create' => "Ch'fichié i vient éd $1. I put ète imploïé par d'eutes proujés. Os pouvez canjer l' déscripcion dsu s' [$2 pache Commons].",
'uploadnewversion-linktext' => 'Quértcher eune novèle vérchion del pache-lo',
+'shared-repo-from' => 'à : $1',
+'shared-repo' => 'un dépôt partagé',
# MIME search
'mimesearch' => 'Tracher pèr type éd contenu MIME',
'prefs-datetime' => 'Data e hora',
'prefs-labs' => 'Funcionalidades dos laboratórios',
'prefs-user-pages' => 'Páginas de utilizador',
-'prefs-personal' => 'Perfil de utilizador',
+'prefs-personal' => 'Dados do utilizador',
'prefs-rc' => 'Mudanças recentes',
'prefs-watchlist' => 'Páginas vigiadas',
'prefs-watchlist-days' => 'Dias a mostrar nas mudanças às páginas vigiadas:',
'prefs-datetime' => 'Data e hora',
'prefs-labs' => 'Características de laboratório',
'prefs-user-pages' => 'Páginas de usuário',
-'prefs-personal' => 'Perfil de usuário',
+'prefs-personal' => 'Dados do usuário',
'prefs-rc' => 'Mudanças recentes',
'prefs-watchlist' => 'Lista de páginas vigiadas',
'prefs-watchlist-days' => 'Dias a mostrar na lista de páginas vigiadas:',
# Categories related messages
'pagecategories' => 'Used in the categories section of pages. Is followed by a colon and a list of categories.',
'category_header' => 'In category description page',
-'subcategories' => 'Used as a header on category pages that have subcategories.',
+'subcategories' => 'Used as a header on category pages that have subcategories.
+{{Identical|Subcategory}}',
'category-media-header' => 'In category description page',
'category-empty' => 'The text displayed in category page when that category is empty',
'hidden-categories' => 'Used in the categories section of pages. Is followed by a colon and a list of categories.',
* $1: number of files shown',
'listingcontinuesabbrev' => 'Shown in contiuation of each first letter group.
See http://test.wikipedia.org/wiki/Category:Test_ko?uselang={{SUBPAGENAME}}, for example.',
-'index-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__INDEX__</nowiki> behaviour switch are listed. For description of this behaviour switch see [//www.mediawiki.org/wiki/Help:Magic_words#Behavior_switches mediawiki].',
-'noindex-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__NOINDEX__</nowiki> behaviour switch are listed. For description of this behaviour switch see [//www.mediawiki.org/wiki/Help:Magic_words#Behavior_switches mediawiki].',
+'index-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__INDEX__</nowiki> behaviour switch are listed. For description of this behaviour switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].',
+'noindex-category' => 'Name of the [[mw:Help:Tracking categories|tracking category]] where pages with the <nowiki>__NOINDEX__</nowiki> behaviour switch are listed. For description of this behaviour switch see [[mw:Help:Magic_words#Behavior_switches|MediaWiki]].',
'broken-file-category' => 'Name of [[mw:Help:Tracking categories|tracking category]] where pages that embed files that do not exist ("broken images") are listed.',
'categoryviewer-pagedlinks' => '{{Optional}}
The pagination links in category viewer. Parameters:
'linkprefix' => '{{optional}}',
'about' => '{{Identical|About}}',
-'article' => "A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [//www.mediawiki.org/wiki/Manual:Using_custom_namespaces#Content_namespaces Mediawiki].
+'article' => "A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].
Possible alternatives to the word 'content' are 'subject matter' or 'wiki subject' or 'wiki purpose'.
{{Identical|Navigation}}',
'and' => 'The translation for "and" appears in the [[Special:Version]] page, between the last two items of a list. If a comma is needed, add it at the beginning without a gap between it and the "&". <nowiki> </nowiki> is a blank space, one character long. Please leave it as it is.
-This can also appear in the credits page if the credits feature is enabled,for example [http://translatewiki.net/wiki/Support&action=credits the credits of the support page]. (To view any credits page type <nowiki>&action=credits</nowiki> at the end of any URL in the address bar.)
-
+This can also appear in the credits page if the credits feature is enabled,for example [{{canonicalurl:Support|action=credits}} the credits of the support page]. (To view any credits page type <nowiki>&action=credits</nowiki> at the end of any URL in the address bar.)
{{Identical|And}}',
# Cologne Blue skin
'qbedit' => '{{Identical|Edit}}',
'qbmyoptions' => 'Heading in the Cologne Blue skin user menu containing links to user (talk) page, preferences, watchlist, etc.
{{Identical|My pages}}',
-'qbspecialpages' => '{{Identical|Special pages}}',
+'qbspecialpages' => '{{Identical|Special page}}',
'faq' => "FAQ is short for ''frequently asked questions''.",
'faqpage' => "FAQ is short for ''frequently asked questions''. This page is only linked on some of the old skins, not in Monobook or Modern.
{{doc-important|Do not translate <tt>Project:</tt> part.}}",
# Vector skin
-'vector-action-addsection' => 'Used in the Vector skin. See for example http://translatewiki.net/wiki/Talk:Main_Page?useskin=vector',
-'vector-action-delete' => 'Used in the Vector skin, as the name of a tab at the top of the page. See for example http://translatewiki.net/wiki/Main_Page?useskin=vector
+'vector-action-addsection' => 'Used in the Vector skin. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}',
+'vector-action-delete' => 'Used in the Vector skin, as the name of a tab at the top of the page. See for example {{canonicalurl:Main_Page|useskin=vector}}
{{Identical|Delete}}',
-'vector-action-move' => 'Used in the Vector skin, on the tabs at the top of the page. See for example http://translatewiki.net/wiki/Talk:Main_Page?useskin=vector
+'vector-action-move' => 'Used in the Vector skin, on the tabs at the top of the page. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}
{{Identical|Move}}',
'vector-action-protect' => 'Tab at top of page, in vector skin
{{Identical|Unprotect}}',
'vector-simplesearch-preference' => 'Preference for enhanced search suggestion in the Vector skin.',
-'vector-view-create' => 'Tab label in the Vector skin. See for example http://translatewiki.net/wiki/Foo?useskin=vector
+'vector-view-create' => 'Tab label in the Vector skin. See for example {{canonicalurl:Foo|useskin=vector}}
{{Identical|Create}}',
-'vector-view-edit' => 'Tab label in the Vector skin. See for example http://translatewiki.net/wiki/Main_Page?useskin=vector
+'vector-view-edit' => 'Tab label in the Vector skin. See for example {{canonicalurl:Main_Page|useskin=vector}}
{{Identical|Edit}}',
-'vector-view-history' => 'Tab label in the Vector skin. See for example http://translatewiki.net/wiki/Main_Page?useskin=vector
+'vector-view-history' => 'Tab label in the Vector skin. See for example {{canonicalurl:Main_Page|useskin=vector}}
{{Identical|View history}}',
-'vector-view-view' => 'Tab label in the Vector skin (verb). See for example http://translatewiki.net/w/i.php?title=Main_Page&useskin=vector',
+'vector-view-view' => 'Tab label in the Vector skin (verb). See for example {{canonicalurl:Main_Page|useskin=vector}}',
'vector-view-viewsource' => 'Tab label in the Vector skin.
{{Identical|View source}}',
'actions' => '{{Identical|Action}}',
{{Identical|Error}}',
'returnto' => '{{Identical|Return to $1}}',
-'tagline' => 'Used to identify the source of copied information. Do not change <nowiki>{{SITENAME}}</nowiki>.',
+'tagline' => '{{doc-important|Do not change <code><nowiki>{{SITENAME}}</nowiki></code>.}}
+Used to identify the source of copied information.',
'help' => 'General text (noun) used in the sidebar (by default).
See also [[MediaWiki:Helppage/{{SUBPAGENAME}}|{{int:helppage}}]] and [[MediaWiki:Edithelp/{{SUBPAGENAME}}|{{int:edithelp}}]].
'searcharticle' => 'Button description in the search menu displayed on every page. The "Search" button is [[MediaWiki:Searchbutton/{{SUBPAGENAME}}]].
{{Identical|Go}}',
+'history' => '{{Identical|Page history}}',
'history_short' => 'Text used on the history tab.
{{Identical|History}}',
See also:
* {{msg-mw|Printableversion}}
* {{msg-mw|Accesskey-t-print}}
-* {{msg-mw|Tooltip-t-print}}',
+* {{msg-mw|Tooltip-t-print}}
+{{Identical|Printable version}}',
'permalink' => 'Display name for a permanent link to the current revision of a page. When the page is edited, permalink will still link to this revision. Example: Last menu link on [[{{MediaWiki:Mainpage}}]]
See also:
* {{msg-mw|Permalink}}
* {{msg-mw|Accesskey-t-permalink}}
-* {{msg-mw|Tooltip-t-permalink}}',
+* {{msg-mw|Tooltip-t-permalink}}
+{{Identical|Permalink}}',
'print' => '{{Identical|Print}}',
'view' => 'The default text of the "View" or "Read" (Vector) views tab which represents the basic view for the page. Should be in the infinitive mood.
'talkpagelinktext' => 'Used as name of links going to talk page in some places, like in [[Special:RecentChanges]], [[Special:Allmessages]], [[Special:Logs]], and [[Special:Watchlist/edit]].
{{Identical|Talk}}',
-'specialpage' => '{{Identical|Special pages}}',
-'personaltools' => 'Heading for a group of links to your user page, talk page, preferences, watchlist, and contributions. This heading is visible in the sidebar in some skins. For an example, see [http://translatewiki.net/wiki/Main_Page?useskin=simple Main Page using simple skin].',
+'specialpage' => '{{Identical|Special page}}',
+'personaltools' => 'Heading for a group of links to your user page, talk page, preferences, watchlist, and contributions. This heading is visible in the sidebar in some skins. For an example, see [{{canonicalurl:Main_Page|useskin=simple}} Main Page using simple skin].',
'articlepage' => "'Content page' is used for NS_MAIN and any other non-standard namespace and this message is only used in skins Nostalgia, Cologneblue and Standard in the bottomLinks part.
{{Identical|Content page}}",
* {{msg-mw|Accesskey-ca-talk}}
* {{msg-mw|Tooltip-ca-talk}}
{{Identical|Discussion}}',
-'views' => 'Subtitle for the list of available views, for the current page. In "monobook" skin the list of views are shown as tabs, so this sub-title is not shown. For an example, see [http://translatewiki.net/wiki/Main_Page?useskin=simple Main Page using simple skin].
+'views' => 'Subtitle for the list of available views, for the current page. In "monobook" skin the list of views are shown as tabs, so this sub-title is not shown. For an example, see [{{canonicalurl:Main_Page|useskin=simple}} Main Page using simple skin].
\'\'\'Note:\'\'\' This is "views" as in "appearances"/"representations", \'\'\'not\'\'\' as in "visits"/"accesses".
{{Identical|View}}',
-'toolbox' => 'The title of the toolbox below the search menu.',
+'toolbox' => 'The title of the toolbox below the search menu.
+{{Identical|Toolbox}}',
'userpage' => '',
'projectpage' => 'Used as link text in Talk page of project page.',
'imagepage' => 'Used as link text in Talk page of file page.',
'view-pool-error' => 'Error message. $1 is probably unused.',
'pool-timeout' => "Part of {{msg-mw|view-pool-error}}.
-For explanation of 'lock' see [http://en.wikipedia.org/wiki/Lock_%28computer_science%29 wikipedia].",
+For explanation of 'lock' see [[w:Lock_(computer_science)|wikipedia]].",
'pool-queuefull' => 'Part of {{msg-mw|view-pool-error}}
"Pool" refers to a pool of processes.',
* {{msg-mw|Portal-url}}
* {{msg-mw|Accesskey-n-portal}}
* {{msg-mw|Tooltip-n-portal}}',
-'privacy' => 'Used as page name and link at the bottom of each wiki page. The page contains a legal notice providing information about the use of personal information by the website owner.of the site. Example: [[Privacy policy]].',
+'privacy' => 'Used as page name and link at the bottom of each wiki page. The page contains a legal notice providing information about the use of personal information by the website owner.of the site. Example: [[Privacy policy]].
+{{Identical|Privacy policy}}',
'privacypage' => 'Used as page for that contains the privacy policy. Used at the bottom of every page on the wiki. Example: [[{{MediaWiki:Privacypage}}|{{MediaWiki:Privacy}}]].
{{doc-important|Do not change the "<tt>Project:</tt>" part.}}',
{{Identical|View source}}',
'editsectionhint' => "Tool tip shown when hovering the mouse over the link to '[{{MediaWiki:Editsection}}]' a section. Example: Edit section: Heading name",
-'toc' => 'This is the title of the table of contents displayed in pages with more than 3 sections
-
-{{Identical|Contents}}',
+'toc' => 'This is the title of the table of contents displayed in pages with more than 3 sections.
+{{Identical|Content}}',
'showtoc' => 'This is the link used to show the table of contents
{{Identical|Show}}',
See the following example:
{{Identical|Expand}}',
-'thisisdeleted' => 'Message shown on a deleted page when the user has the undelete right. $1 is a link to [[Special:Undelete]], with {{msg-mw|restorelink}} as the text. See also {{msg-mw|viewdeleted}}.',
-'viewdeleted' => 'Message shown on a deleted page when the user does not have the undelete right (but has the deletedhistory right). $1 is a link to [[Special:Undelete]], with {{msg-mw|restorelink}} as the text. See also {{msg-mw|thisisdeleted}}.',
+'thisisdeleted' => 'Message shown on a deleted page when the user has the undelete right. Parameters:
+* $1 - a link to [[Special:Undelete]], with {{msg-mw|restorelink}} as the text
+See also:
+* {{msg-mw|viewdeleted}}',
+'viewdeleted' => 'Message shown on a deleted page when the user does not have the undelete right (but has the deletedhistory right). Parameters:
+* $1 - a link to [[Special:Undelete]], with {{msg-mw|restorelink}} as the text
+See also:
+* {{msg-mw|thisisdeleted}}',
'restorelink' => "This text is always displayed in conjunction with the {{msg-mw|thisisdeleted}} message (View or restore $1?). The user will see
View or restore <nowiki>{{PLURAL:$1|one deleted edit|$1 deleted edits}}</nowiki>? i.e ''View or restore one deleted edit?'' or
''View or restore n deleted edits?''",
See also:
* {{msg-mw|Nstab-special}}
* {{msg-mw|Tooltip-ca-nstab-special}}
-{{Identical|Special pages}}',
+{{Identical|Special page}}',
'nstab-project' => 'The name for the tab of the project namespace. Example: [[Project:Example]]
See also:
# Main script and global functions
'nosuchaction' => 'The title of the error you get when trying to open a page with invalid "action" parameter. The text of the warning is the message {{msg-mw|nosuchactiontext}}.
-See example [//translatewiki.net/wiki/Main_page?action=x action=x].',
-'nosuchactiontext' => 'This error is shown when trying to open a page with invalid "action" parameter, e.g. [//translatewiki.net/wiki/Main_page?action=x action=x].
+See example [{{canonicalurl:Main_page|action=x}} action=x].',
+'nosuchactiontext' => 'This error is shown when trying to open a page with invalid "action" parameter, e.g. [{{canonicalurl:Main_page|action=x}} action=x].
* The title of this error is the message {{msg-mw|nosuchaction}}.',
'nosuchspecialpage' => 'The title of the error you get when trying to open a special page which does not exist. The text of the warning is the message {{msg-mw|nospecialpagetext}}. Example: [[Special:Nosuchpage]]',
'nospecialpagetext' => '{{doc-important|Link <code><nowiki>[[Special:SpecialPages|{{int:specialpages}}]]</nowiki></code> should remain untranslated.}}
'readonlytext' => 'Used as error message when the database is locked.',
'missing-article' => "This message is shown when a revision does not exist, either as permalink or as diff. Examples:
-# [http://translatewiki.net/w/i.php?title=Project:News&oldid=9999999 Permalink with invalid revision#]
-# [http://translatewiki.net/w/i.php?title=Project:News&diff=426850&oldid=99999999 Diff with invalid revision#]
+# [{{canonicalurl:Project:News|oldid=9999999}} Permalink with invalid revision#]
+# [{{canonicalurl:Project:News|diff=426850&oldid=99999999}} Diff with invalid revision#]
'''Parameters'''
* $1: Pagename
* $1: revision# of the requested id
-[http://translatewiki.net/w/i.php?title=Translating:Tasks&oldid=371789000 Click here] to see an example of such an error message.',
+[{{canonicalurl:Translating:Tasks|oldid=371789000}} Click here] to see an example of such an error message.',
'missingarticle-diff' => 'Parameter $2 of {{msg-mw|Missing-article}}: It is shown after the articlename.
* $1: revision# of the old id
* $2: revision# of the id build the diff with.
-[http://translatewiki.net/w/i.php?title=Translating:Tasks&diff=372398&oldid=371789000 Click here] to see an example of such an error message.',
+[{{canonicalurl:Translating:Tasks|diff=372398&oldid=371789000}} Click here] to see an example of such an error message.',
'readonly_lag' => 'Error message displayed when the database is locked.',
'internalerror' => '{{Identical|Internal error}}',
'internalerror_info' => '* $1 - error message',
-'fileappenderrorread' => '"Append" is a computer procedure, explained on [http://en.wikipedia.org/wiki/Append Wikipedia].
+'fileappenderrorread' => '"Append" is a computer procedure, explained on [[w:Append|Wikipedia]].
$1 is a filename, I think.',
'fileappenderror' => 'Parameters:
'nologin' => 'A message shown in the log in form. $1 is a link to the account creation form, and the text of it is "[[MediaWiki:Nologinlink/{{SUBPAGENAME}}|{{int:nologinlink}}]]".',
'nologinlink' => 'Text of the link to the account creation form. Before that link, the message [[MediaWiki:Nologin/{{SUBPAGENAME}}]] appears.
{{Identical|Create an account}}',
-'createaccount' => 'The title of Special:CreateAccount, where users can register a new account. Used on Special:SpecialPages and on the submit button in the form where you register a new account.
+'createaccount' => 'The title of [[Special:CreateAccount]], where users can register a new account. Used on [[Special:SpecialPages]] and on the submit button in the form where you register a new account.
It is also used on the top of the page for logged out users, where it appears next to {{msg-mw|login}}, so consider making them similar.
{{Identical|Create account}}',
* $3 is a password. Example: er##@fdas!
* $4 is a URL. Example: http://wiki.example.com
* $5 is a number of days in which the temporary password will expire',
-'noemail' => 'Shown as error message when trying to register a user sending password to e-mail adress and no e-mail address has been given. Registering users and sending a password to an e-mail address may require non-standard user rights ([http://translatewiki.net/w/i.php?title=Special:UserLogin&action=submitlogin&type=signup register user link]).
+'noemail' => 'Shown as error message when trying to register a user sending password to e-mail adress and no e-mail address has been given. Registering users and sending a password to an e-mail address may require non-standard user rights ([{{canonicalurl:Special:UserLogin|action=submitlogin&type=signup}} register user link]).
Parameters:
* $1 is a user name. This parameter can be used with GENDER.',
See also:
* {{msg-mw|Showpreview}}
* {{msg-mw|Accesskey-preview}}
-* {{msg-mw|Tooltip-preview}}',
+* {{msg-mw|Tooltip-preview}}
+{{Identical|Show preview}}',
'showlivepreview' => 'An edit preview without needing to reload the edit form.',
'showdiff' => 'Button below the edit page. See also {{msg|showpreview}} and {{msg|savearticle}} for the other buttons.
'loginreqtitle' => 'Used as title of error message.
See also:
-* {{msg-mw|permissionserrors}}',
+* {{msg-mw|permissionserrors}}
+{{Identical|Login required}}',
'loginreqlink' => 'Take a look on inflection. Used as parameter in {{msg-mw|loginreqpagetext}}, {{msg-mw|whitelistedittext}}, {{msg-mw|watchlistanontext}} and {{msg-mw|Confirmemail needlogin}}.
{{Identical|Log in}}',
'noarticletext-nopermission' => 'See also {{msg-mw|Noarticletext}}.',
'missing-revision' => 'Text displayed when the requested revision does not exist using a permalink.
-Example: [http://translatewiki.net/w/i.php?title=Project:News&oldid=9999999 Permalink with invalid revision#]
+Example: [{{canonicalurl:Project:News|oldid=9999999}} Permalink with invalid revision#]
* $1 is the ID of the missing revision',
'userpage-userdoesnotexist' => 'Error message displayed when trying to edit or create a page or a subpage that belongs to a user who is not registered on the wiki. Parameters:
* $1 is a possible username that has not been registered.',
-'userpage-userdoesnotexist-view' => 'Shown in user pages of non existing users. See for example [http://translatewiki.net/wiki/User:Foo User:Foo]. Parameters:
+'userpage-userdoesnotexist-view' => 'Shown in user pages of non existing users. See for example [{{canonicalurl:User:Foo}} User:Foo]. Parameters:
* $1 is a username.',
'blocked-notice-logextract' => 'Parameters:
* $1 is the name of the blocked user (optional). Can be used for GENDER.',
See also:
* {{msg-mw|Nocreatetext}}',
-'sectioneditnotsupported-title' => 'Page title of special page, which presumably appears when someone tries to edit a section, and section editing is disabled. Explanation of section editing on [http://meta.wikimedia.org/wiki/Help:Section_editing#Section_editing meta].',
-'sectioneditnotsupported-text' => 'I think this is the text of an error message, which presumably appears when someone tries to edit a section, and section editing is disabled. Explanation of section editing on [http://meta.wikimedia.org/wiki/Help:Section_editing#Section_editing meta].',
+'sectioneditnotsupported-title' => 'Page title of special page, which presumably appears when someone tries to edit a section, and section editing is disabled. Explanation of section editing on [[meta:Help:Section_editing#Section_editing|meta]].',
+'sectioneditnotsupported-text' => 'I think this is the text of an error message, which presumably appears when someone tries to edit a section, and section editing is disabled. Explanation of section editing on [[meta:Help:Section_editing#Section_editing|meta]].',
'permissionserrors' => 'Used as title of error message.
See also:
Please report at [[Support]] if you are unable to properly translate this message. Also see [[bugzilla:14246]]',
'recreate-moveddeleted-warn' => 'Warning shown when creating a page which has already been deleted. See for example [[Test]].',
-'moveddeleted-notice' => 'Shown on top of a deleted page in normal view modus ([http://translatewiki.net/wiki/Test example]).',
+'moveddeleted-notice' => 'Shown on top of a deleted page in normal view modus ([{{canonicalurl:Test}} example]).',
'log-fulllog' => 'Used as link text.',
'edit-hook-aborted' => 'Used as error message.
* <tt>$1</tt> is the value of the node-count limit
* <tt>$2</tt> is the value of the max node-count limit',
-'expansion-depth-exceeded-category' => 'This message is used as a category name for a [[mw:Help:Tracking categories|tracking category]] where pages are placed automatically if the [http://meta.wikimedia.org/wiki/Help:Expansion_depth expansion depth] of the preprocessor exceeds the limit.',
-'expansion-depth-exceeded-warning' => 'Error message shown when a page exceeded the [http://meta.wikimedia.org/wiki/Help:Expansion_depth expansion depth limit] of the preprocessor
+'expansion-depth-exceeded-category' => 'This message is used as a category name for a [[mw:Help:Tracking categories|tracking category]] where pages are placed automatically if the [[meta:Help:Expansion_depth|expansion depth]] of the preprocessor exceeds the limit.',
+'expansion-depth-exceeded-warning' => 'Error message shown when a page exceeded the [[meta:Help:Expansion_depth|expansion depth limit]] of the preprocessor.
+Parameters:
* <tt>$1</tt> is the value of the depth limit
* <tt>$2</tt> is the value of the max depth limit',
-'parser-unstrip-loop-warning' => 'This error is shown when a parser extension tag such as <pre> includes a reference to itself in its own output.
+'parser-unstrip-loop-warning' => '{{Doc-important|Do not translate function name "<code>unstrip</code>".}}
+This error is shown when a parser extension tag such as <pre> includes a reference to itself in its own output.
+
The reference must be to the exact same invocation of the tag at the same location in the source, merely writing <pre><pre></pre></pre> will not do it.
+
This is usually impossible and unlikely to happen by accident, so translation is not essential.
-"Unstrip" refers to the internal function of the parser, called \'unstrip\', which recursively puts the output of parser functions in the place of the parser function call and which would enter an infinite loop in the situation above. See also:
+
+"Unstrip" refers to the internal function of the parser, called \'unstrip\', which recursively puts the output of parser functions in the place of the parser function call and which would enter an infinite loop in the situation above.
+
+See also:
*{{msg-mw|Parser-unstrip-recursion-limit}}',
-'parser-unstrip-recursion-limit' => 'This message is shown when the recursion limit for nested parser extension tags is exceeded.
+'parser-unstrip-recursion-limit' => '{{doc-important|Do not translate function name "<code>unstrip</code>".}}
+This message is shown when the recursion limit for nested parser extension tags is exceeded.
+
This warning may be encountered due to input text like <ref><ref><ref>...</ref></ref></ref>.
-* <tt>$1</tt> is the depth limit
+Parameters:
+* $1 - the depth limit
+
+"Unstrip" refers to the internal function of the parser, called \'unstrip\', which recursively puts the output of parser functions in the place of the parser function call and which would enter an infinite loop in the situation above.
-"Unstrip" refers to the internal function of the parser, called \'unstrip\', which recursively puts the output of parser functions in the place of the parser function call and which would enter an infinite loop in the situation above. See also:
-*{{msg-mw|Parser-unstrip-loop-warning}}',
+See also:
+* {{msg-mw|Parser-unstrip-loop-warning}}',
'converter-manual-rule-error' => "This message is shown when a manual conversion rule for the language converter has errors. For example it's not using the correct syntax, or not supplying text in all variants.",
# "Undo" feature
'revdel-restore-deleted' => '{{RevisionDelete}}',
'revdel-restore-visible' => '{{RevisionDelete}}',
'pagehist' => '{{RevisionDelete}}
-
-Links to page history at Special:RevisionDelete header together with links to the logs and Special:Undelete.',
+Links to page history at Special:RevisionDelete header together with links to the logs and [[Special:Undelete]].
+{{Identical|Page history}}',
'deletedhist' => '{{RevisionDelete}}
-Links to Special:Undelete at Special:RevisionDelete header together with links to the logs and page history.',
+Links to [[Special:Undelete]] at [[Special:RevisionDelete]] header together with links to the logs and page history.',
'revdelete-hide-current' => '{{RevisionDelete}}
Parameters:
* $1 is a date
Please note that the parameters in a log entry will appear in the log only in the default language of the wiki. View [[Special:Log]] for examples on translatewiki.net with English default language.",
'revertmerge' => 'Used as link text',
-'mergelogpagetext' => 'Description of the [http://translatewiki.net/w/i.php?title=Special%3ALog&type=merge&user=&page=&year=&month=-1 merge log], on the log. The associated [[Special:MergeHistory|Merge]] special page is not enabled by default.',
+'mergelogpagetext' => 'Description of the [{{canonicalurl:Special:Log|type=merge&user=&page=&year=&month=-1}} merge log], on the log. The associated [[Special:MergeHistory|Merge]] special page is not enabled by default.',
# Diffs
'history-title' => 'Displayed as page title when you click on the "history" tab. The parameter $1 is the normal page title.',
* {{msg-mw|Tooltip-compareselectedversions}}',
'showhideselectedversions' => 'Text of the button which brings up the [[mw:RevisionDelete|RevisionDelete]] menu on history pages.',
'editundo' => 'Undo link when viewing diffs
-{{Identical|Undo}}
-This message has sometimes a tooltip {{msg-mw|tooltip-undo}}',
+This message has sometimes a tooltip {{msg-mw|tooltip-undo}}
+{{Identical|Undo}}',
'diff-multi' => "This message appears in the revision history of a page when comparing two versions which aren't consecutive.
*Parameter $1 is the number of revisions
* $2 is the number of users that were found, which was limited at 100.",
'difference-missing-revision' => 'Text displayed when the requested revision does not exist using a diff link.
-Example: [http://translatewiki.net/w/i.php?title=Project:News&diff=426850&oldid=99999999 Diff with invalid revision#]
+Example: [{{canonicalurl:Project:News|diff=426850&oldid=99999999}} Diff with invalid revision#]
* $1 is the list of missing revisions IDs
* $2 is the number of items in $1 (one or two)',
* $1 - prefix string',
'searchprofile-articles' => "A quick link in the advanced search box on [[Special:Search]]. Clicking on this link starts a search in the content pages of the wiki.
-A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [//www.mediawiki.org/wiki/Manual:Using_custom_namespaces#Content_namespaces Mediawiki].
+A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].
Possible alternatives to the word 'content' are 'subject matter' or 'wiki subject' or 'wiki purpose'.
'powersearch-ns' => 'Used in the extended search form at [[Special:Search]]',
'powersearch-redir' => 'Used in the extended search form at [[Special:Search]]',
'powersearch-field' => 'Used in the extended search form at [[Special:Search]]',
-'powersearch-togglelabel' => 'Used in [http://translatewiki.net/w/i.php?title=Special:Search&advanced=1 Advanced search]. Synonym: "Select" as verb.',
-'powersearch-toggleall' => '"All" refers to namespaces. It is used in Advanced search: http://translatewiki.net/w/i.php?title=Special:Search&advanced=1
+'powersearch-togglelabel' => 'Used in [{{canonicalurl:Special:Search|advanced=1}} Advanced search]. Synonym: "Select" as verb.',
+'powersearch-toggleall' => '"All" refers to namespaces. It is used in Advanced search: {{canonicalurl:Special:Search|advanced=1}}
{{Identical|All}}',
-'powersearch-togglenone' => '"None" refers to namespaces. It is used in Advanced search: http://translatewiki.net/w/i.php?title=Special:Search&advanced=1
+'powersearch-togglenone' => '"None" refers to namespaces. It is used in Advanced search: {{canonicalurl:Special:Search|advanced=1}}
{{Identical|None}}',
'search-external' => 'Legend of the fieldset for the input form when the internal search is disabled. Inside the fieldset [[MediaWiki:Searchdisabled]] and [[MediaWiki:Googlesearch]] is shown.',
'searchdisabled' => '{{doc-singularthey}}
'qbsettings-directionality' => '"Fixed", as in the position "fixed left or right". For left-to-right languages, the quickbar will be positioned at the left, for right-to-left languages at the right.',
# Preferences page
-'preferences' => 'Title of the Special:Preferences page.
-
+'preferences' => 'Title of the [[Special:Preferences]] page.
{{Identical|Preferences}}',
-'mypreferences' => 'Action link label that leads to Special:Preferences; appears in the top menu (e.g. "Username Talk Preferences Watchlist Contributions Log out").
+'mypreferences' => 'Action link label that leads to [[Special:Preferences]]; appears in the top menu (e.g. "Username Talk Preferences Watchlist Contributions Log out").
See also:
* {{msg-mw|Mypreferences}}
Shown as legend of the second fieldset of the tab 'Search' in [[Special:Preferences]]",
'defaultns' => 'Used in [[Special:Preferences]], tab "Search".',
'default' => '{{Identical|Default}}',
-'prefs-files' => 'Title of a tab in [[Special:Preferences]].',
+'prefs-files' => 'Title of a tab in [[Special:Preferences]].
+{{Identical|File}}',
'prefs-custom-css' => 'visible on [[Special:Preferences]] -[Skins].',
'prefs-custom-js' => 'visible on [[Special:Preferences]] -[Skins].',
'prefs-common-css-js' => 'Used as label in [[Special:Preferences#mw-prefsection-rendering|preferences]], tab "Appearance", section "Skin".',
'prefs-reset-intro' => 'Used in [[Special:Preferences/reset]].',
'prefs-emailconfirm-label' => 'Sub-heading in [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.',
'prefs-textboxsize' => "Header for the box specifying the size of the editing window, displayed on the 'editing' tab of the [[Special:Preferences|user preferences]] special page.",
-'youremail' => 'Label of the e-mail text box of the "E-mail options" section of "Special:Preferences".
-
+'youremail' => 'Label of the e-mail text box of the "E-mail options" section of [[Special:Preferences]].
{{Identical|E-mail}}',
'username' => 'Username field in [[Special:Preferences]]. $1 is the current user name for GENDER distinction (depends on sex setting).
* {{msg-mw|prefs-help-email-others|help}}
* {{msg-mw|prefs-changeemail|link title}}
* {{msg-mw|prefs-setemail|link title}}',
-'prefs-info' => "Header for the box giving basic information on the user account, displayed on the 'user profile' tab of the [[Special:Preferences|user preferences]] special page.",
+'prefs-info' => "Header for the box giving basic information on the user account, displayed on the 'user profile' tab of the [[Special:Preferences|user preferences]] special page.
+{{Identical|Basic information}}",
'prefs-i18n' => 'Field set legend for user preferences regarding the interface language',
'prefs-signature' => '{{Identical|Signature}}',
-'prefs-dateformat' => 'Used in [[Special:Preferences#mw-prefsection-datetime|Special:Preferences]], tab "Date and time".',
+'prefs-dateformat' => 'Used in [[Special:Preferences#mw-prefsection-datetime|Special:Preferences]], tab "Date and time".
+{{Identical|Date format}}',
'prefs-timeoffset' => 'Used in [[Special:Preferences]], tab "Date and time".',
'prefs-advancedediting' => 'Used in [[Special:Preferences]], tab "Editing".
{{Identical|Advanced options}}',
{{Identical|Reason}}',
'userrights-no-interwiki' => 'Error message when editing user groups',
'userrights-nodatabase' => 'Error message when editing user groups. "Local" means databases/wikis of the same farm/cluster; that is, meta, enwiki, dewiki, commons, etc are all local databases of the Wikimedia Foundation.
-See http://meta.wikimedia.org/w/index.php?title=Special%3ALog&type=rights for a usage of local databases: username@barwiki',
+See [{{canonicalurl:meta:Special:Log|type=rights}} meta:Special:Log?type=rights] for a usage of local databases: username@barwiki',
'userrights-nologin' => "Error displayed on [[Special:UserRights]] when you aren't logged in. If you are logged in, but don't have the correct permission, you see {{msg|userrights-notallowed|pl=yes}}.",
'userrights-notallowed' => "Error displayed on [[Special:UserRights]] when you don't have the permission.",
'userrights-changeable-col' => 'Used when editing user groups in [[Special:Userrights]]. The message is the head of a column of group assignements.
'right-movefile' => '{{doc-right|movefile}}',
'right-suppressredirect' => '{{doc-right|suppressredirect}}',
'right-upload' => '{{doc-right|upload}}
-The right to [[Special:Upload|upload]] a file (this includes images, media, audio, ...).',
+The right to [[Special:Upload|upload]] a file (this includes images, media, audio, ...).
+{{Identical|Upload file}}',
'right-reupload' => '{{doc-right|reupload}}
The right to upload a file under a file name that already exists.
'action-upload_by_url' => '{{Doc-action|upload by url}}',
'action-writeapi' => '{{Doc-action|writeapi}}
-API is an abbreviation for [http://en.wikipedia.org/wiki/API application programming interface].',
+API is an abbreviation for [[w:API|application programming interface]].',
'action-delete' => '{{Doc-action|delete}}',
'action-deleterevision' => '{{Doc-action|deleterevision}}',
'action-deletedhistory' => '{{Doc-action|deletedhistory}}',
{{Identical|Recent changes}}',
'recentchanges-legend' => 'Legend of the fieldset of [[Special:RecentChanges]]',
'recentchanges-summary' => 'Summary of [[Special:RecentChanges]].',
-'recentchanges-feed-description' => 'Used in feed of RecentChanges. See example [http://translatewiki.net/w/i.php?title=Special:RecentChanges&feed=atom feed].',
+'recentchanges-feed-description' => 'Used in feed of RecentChanges. See example [{{canonicalurl:Special:RecentChanges|feed=atom}} feed].',
'recentchanges-label-newpage' => 'Tooltip for {{msg-mw|newpageletter}}',
'recentchanges-label-minor' => 'Tooltip for {{msg-mw|minoreditletter}}',
'recentchanges-label-bot' => 'Tooltip for {{msg-mw|boteditletter}}',
* {{msg-mw|Filesource}}
{{Identical|Summary}}',
'fileuploadsummary' => '{{Identical|Summary}}',
-'filereuploadsummary' => 'Label of textearea in Special:Upload when uploading a new version of existing file.',
+'filereuploadsummary' => 'Label of textearea in [[Special:Upload]] when uploading a new version of existing file.',
'filestatus' => 'Used as section header in [[Special:Upload]].
See also:
* {{msg-mw|hookaborted}}
* {{msg-mw|filename-toolong}}
* {{msg-mw|unknown-error}}',
-'fileexists' => "{{doc-important|''thumb'' is a magic word. Leave it untranslated!}}",
+'fileexists' => "{{doc-important|''thumb'' is a magic word. Leave it untranslated!}}
+Parameters:
+* $1 - name of the existing file",
'filepageexists' => "{{doc-important|''thumb'' is a magic word. Leave it untranslated!}}
-Shown on [[Special:Upload]], $1 is link to the page. This message is displayed if a description page exists, but a file with the same name does not yet exists, and a user tries to upload a file with that name. In that case the description page is not changed, even if the uploading user specifies a description with the upload.",
-'fileexists-extension' => "{{doc-important|''thumb'' is a magic word. Leave it untranslated!}}",
-'fileexists-thumbnail-yes' => "{{doc-important|''thumb'' is a magic word. Leave it untranslated!}}",
-'file-thumbnail-no' => 'Error message at [[Special:Upload]]',
-'fileexists-forbidden' => "{{doc-important|''thumb'' and ''center'' are magic words. Leave it untranslated!}}",
+Shown on [[Special:Upload]]. Parameters:
+* $1 - link to the page
+This message is displayed if a description page exists, but a file with the same name does not yet exists, and a user tries to upload a file with that name. In that case the description page is not changed, even if the uploading user specifies a description with the upload.",
+'fileexists-extension' => "{{doc-important|''thumb'' is a magic word. Leave it untranslated!}}
+Parameters:
+* $1 - name of the uploading file
+* $2 - name of the existing file",
+'fileexists-thumbnail-yes' => "{{doc-important|''thumb'' is a magic word. Leave it untranslated!}}
+Parameters:
+* $1 - name of thumbnail file",
+'file-thumbnail-no' => 'Error message at [[Special:Upload]]. Parameters:
+* $1 - String (e.g. "180px-")',
+'fileexists-forbidden' => "{{doc-important|''thumb'' and ''center'' are magic words. Leave it untranslated!}}
+Parameters:
+* $1 - name of the existing file",
'fileexists-shared-forbidden' => "{{doc-important|''thumb'' and ''center'' are magic words. Leave it untranslated!}}
-Error message at [[Special:Upload]]",
+Error message at [[Special:Upload]].
+Parameters:
+* $1 - name of the existing file",
'file-exists-duplicate' => 'Used as warning in [[Special:Upload]].
This message is followed by the gallery of the duplicate files.
'savefile' => 'When uploading a file',
'uploadedimage' => 'This is the text of an entry in the [[Special:Log|upload log]] (and Recent Changes), after hour (and date, only in the Upload log) and user name. $1 is the name of the file uploaded.',
'overwroteimage' => 'This is the text of an entry in the [[Special:Log|upload log]] (and Recent Changes), after hour (and date, only in the Upload log) and user name. $1 is the name of the file uploaded.',
-'uploaddisabled' => 'Title of the Special:Upload page when upload is disabled.
+'uploaddisabled' => 'Title of the [[Special:Upload]] page when upload is disabled.
See also:
* {{msg-mw|Copyuploaddisabled}}',
'copyuploaddisabled' => 'See also:
* {{msg-mw|Uploaddisabled}}',
-'uploaddisabledtext' => 'This message can have parameter $1, which contains the name of the target file. See r22243 and [https://bugzilla.wikimedia.org/show_bug.cgi?id=8818 bug 8818].',
+'uploaddisabledtext' => 'This message can have parameter $1, which contains the name of the target file. See r22243 and [[bugzilla:8818|bug 8818]].',
'php-uploaddisabledtext' => 'This means that file uploading is disabled in PHP, not upload of PHP-files.',
'uploadscripted' => 'Used as error message when uploading a file.
'upload-proto-error' => 'See also:
* {{msg-mw|Upload-proto-error|title}}
* {{msg-mw|Upload-proto-error-text|text}}',
-'upload-proto-error-text' => '"Remote upload" is explained on [http://en.wikipedia.org/wiki/Uploading_and_downloading#Remote_upload Wikipedia].
+'upload-proto-error-text' => '"Remote upload" is explained on [[w:Uploading_and_downloading#Remote_upload|Wikipedia]].
See also:
* {{msg-mw|Upload-proto-error|title}}
'lockmanager-fail-closelock' => 'Parameters:
* $1 is a resource path (e.g. "mwstore://media-public/a/ab/file.jpg").
-A "[http://en.wikipedia.org/wiki/File_locking#Lock_files lock file]" signals by its presence that some resource is locked.',
+A "[[w:File_locking#Lock_files|lock file]]" signals by its presence that some resource is locked.',
'lockmanager-fail-deletelock' => 'Parameters:
* $1 is a resource path (e.g. "mwstore://media-public/a/ab/file.jpg").
-A "[http://en.wikipedia.org/wiki/File_locking#Lock_files lock file]" signals by its presence that some resource is locked.',
+A "[[w:File_locking#Lock_files|lock file]]" signals by its presence that some resource is locked.',
'lockmanager-fail-acquirelock' => 'Parameters:
* $1 is a resource path (e.g. "mwstore://media-public/a/ab/file.jpg").',
'lockmanager-fail-openlock' => 'Parameters:
* $1 is a resource path (e.g. "mwstore://media-public/a/ab/file.jpg").
-A "[http://en.wikipedia.org/wiki/File_locking#Lock_files lock file]" signals by its presence that some resource is locked.',
+A "[[w:File_locking#Lock_files|lock file]]" signals by its presence that some resource is locked.',
'lockmanager-fail-releaselock' => 'Parameters:
* $1 is a resource path (e.g. "mwstore://media-public/a/ab/file.jpg").',
'lockmanager-fail-db-bucket' => 'The databases store what is locked by who. Parameters:
* {{msg-mw|Http-request-error}}
* {{msg-mw|Http-read-error}}
* {{msg-mw|Http-timed-out|28}}',
-'http-bad-status' => '$1 is an HTTP error code (e.g. 404), $2 is the HTTP error message (e.g. File Not Found)',
+'http-bad-status' => 'Parameters:
+* $1 - an HTTP error code (e.g. 404)
+* $2 - the HTTP error message (e.g. File Not Found)',
# Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
'upload-curl-error6' => 'See also:
{{Identical|Size}}',
'listfiles_description' => 'Column header for the result table displayed on [[Special:ListFiles]].
{{Identical|Description}}',
-'listfiles_count' => 'One of the table column headers in [[Special:Listfiles]] denoting the amount of saved versions of that file.',
+'listfiles_count' => 'One of the table column headers in [[Special:Listfiles]] denoting the amount of saved versions of that file.
+{{Identical|Version}}',
# File description page
'file-anchor-link' => '{{Identical|File}}',
* $1: Number of identical files
* $2: Name of the shown file to link to the special page "FileDuplicateSearch"',
-'sharedupload' => 'Shown on an image description page when it is used in a central repository (i.e. [http://commons.wikimedia.org/ Commons] for Wikimedia wikis).
+'sharedupload' => 'Shown on an image description page when it is used in a central repository (i.e. [[commons:|Commons]] for Wikimedia wikis).
* $1 is the name of the shared repository. On Wikimedia sites, $1 is {{msg-mw|shared-repo-name-shared}}. The default value for $1 is {{msg-mw|shared-repo}}.
'statistics-header-hooks' => 'Header of a section on [[Special:Statistics]] containing data provided by MediaWiki extensions',
'statistics-articles' => "Used in [[Special:Statistics]].
-A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [//www.mediawiki.org/wiki/Manual:Using_custom_namespaces#Content_namespaces Mediawiki].
+A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].
Possible alternatives to the word 'content' are 'subject matter' or 'wiki subject' or 'wiki purpose'.
'statistics-edits-average' => 'Used in [[Special:Statistics]]',
'statistics-views-total' => 'Used in [[Special:Statistics]]',
'statistics-views-peredit' => 'Used in [[Special:Statistics]]',
-'statistics-users' => 'Used in [[Special:Statistics]]. Do not change "Special:ListUsers"!',
+'statistics-users' => '{{doc-important|Do not translate "Special:ListUsers"}}
+Used in [[Special:Statistics]].',
'statistics-users-active' => 'Used in [[Special:Statistics]]',
'statistics-users-active-desc' => "Description shown beneath ''Active users'' in [[Special:Statistics]]
'disambiguationspage' => 'This message is the name of the template used for marking disambiguation pages. It is used by [[Special:Disambiguations]] to find all pages which link to disambiguation pages.
{{doc-important|Don\'t translate the "Template:" part!}}',
-'disambiguations-text' => "This block of text is shown on [[:Special:Disambiguations]].
+'disambiguations-text' => '{{doc-important|Do not change the link "<code><nowiki>[[MediaWiki:Disambiguationspage]]</nowiki></code>", even because it is listed as problematic. Be sure the "D" is in uppercase, so not "d".}}
+This block of text is shown on [[:Special:Disambiguations]].
-* '''Note:''' Do not change the link [[MediaWiki:Disambiguationspage]], even because it is listed as problematic. Be sure the \"D\" is in uppercase, so not \"d\".
+\'\'\'Background information:\'\'\' Beyond telling about links going to disambiguation pages, that they are generally bad, it should explain which pages in the article namespace are seen as disambiguations: [[MediaWiki:Disambiguationspage]] usually holds a list of disambiguation templates of the local wiki. Pages linking to one of them (by transclusion) will count as disambiguation pages. Pages linking to these disambiguation pages, instead to the disambiguated article itself, are listed on [[:Special:Disambiguations]].',
-* '''Background information:''' Beyond telling about links going to disambiguation pages, that they are generally bad, it should explain which pages in the article namespace are seen as disambiguations: [[MediaWiki:Disambiguationspage]] usually holds a list of disambiguation templates of the local wiki. Pages linking to one of them (by transclusion) will count as disambiguation pages. Pages linking to these disambiguation pages, instead to the disambiguated article itself, are listed on [[:Special:Disambiguations]].",
+'pageswithprop' => 'Title for [[Special:PagesWithProp]]',
+'pageswithprop-legend' => 'Legend for the input form on [[Special:PagesWithProp]]',
+'pageswithprop-text' => 'Introductory text for the input form on [[Special:PagesWithProp]]',
+'pageswithprop-prop' => 'Label for the property name input field on [[Special:PagesWithProp]]',
+'pageswithprop-submit' => 'Label for the submit button on [[Special:PagesWithProp]]',
'doubleredirects' => 'Name of [[Special:DoubleRedirects]] displayed in [[Special:SpecialPages]]',
'doubleredirectstext' => 'Shown on top of [[Special:Doubleredirects]]',
'protectedpages-cascade' => 'Option in [[Special:ProtectedPages]]',
'protectedpagestext' => 'Shown on top of [[Special:ProtectedPages]]',
'protectedtitles' => 'Name of special page displayed in [[Special:SpecialPages]]',
-'protectedtitlestext' => 'Shown on top of list of titles on [[Special:ProtectedTitles]]. If the list is empty the message [[MediaWiki:Protectedtitlesempty]] appears instead of this. See the [//www.mediawiki.org/wiki/Project:Protected_titles help page on Mediawiki] for more information.',
-'protectedtitlesempty' => 'Used on [[Special:ProtectedTitles]]. This text appears if the list of protected titles is empty. See the [//www.mediawiki.org/wiki/Project:Protected_titles help page on Mediawiki] for more information.',
+'protectedtitlestext' => 'Shown on top of list of titles on [[Special:ProtectedTitles]]. If the list is empty the message [[MediaWiki:Protectedtitlesempty]] appears instead of this. See the [[mw:Project:Protected_titles|help page on MediaWiki]] for more information.',
+'protectedtitlesempty' => 'Used on [[Special:ProtectedTitles]]. This text appears if the list of protected titles is empty. See the [[mw:Project:Protected_titles|help page on MediaWiki]] for more information.',
'listusers' => 'Name of special page displayed in [[Special:SpecialPages]]',
'listusers-editsonly' => 'Option in [[Special:ListUsers]].',
'listusers-creationsort' => 'Option in [[Special:ListUsers]].',
'categories' => 'The page name of [[Special:Categories]].
{{Identical|Categories}}',
-'categoriespagetext' => "Text displayed in [[Special:Categories]]. Do not translate or change links. In order to translate ''Unused categories'' and ''wanted categories'' see {{msg|unusedcategories}} and {{msg|wantedcategories}}.",
+'categoriespagetext' => "{{doc-important|Do not translate or change links.}}
+Text displayed in [[Special:Categories]].
+
+In order to translate ''Unused categories'' and ''wanted categories'' see {{msg|unusedcategories}} and {{msg|wantedcategories}}.",
'special-categories-sort-count' => 'This message is used on [[Special:Categories]] to sort the list by the number of members in the categories.',
# Special:DeletedContributions
'deletedcontributions-title' => 'Title of [[Special:DeletedContributions]] (extension), a special page with a list of edits to pages which were deleted. Only viewable by sysops.
{{Identical|Deleted user contributions}}',
-'sp-deletedcontributions-contribs' => 'Link to user’s contributions on [[Special:DeletedContributions]]',
+'sp-deletedcontributions-contribs' => 'Link to user’s contributions on [[Special:DeletedContributions]].
+{{Identical|Contribution}}',
# Special:LinkSearch
'linksearch' => 'Title of [[Special:LinkSearch|special page]] and legend of fieldset on that page.
'usermaildisabledtext' => 'Used as error message in [[Special:EmailUser]].
The title for this error message is {{msg-mw|Usermaildisabled}}.',
-'noemailtitle' => 'The title of the message that appears instead of Special:EmailUser after clicking the "E-mail this user" link in the sidebar, if no e-mail can be sent to the user.',
+'noemailtitle' => 'The title of the message that appears instead of [[Special:EmailUser]] after clicking the "E-mail this user" link in the sidebar, if no e-mail can be sent to the user.',
'noemailtext' => 'The text of the message that appears in [[Special:EmailUser]] after clicking the "E-mail this user" link in the sidebar, if no e-mail can be sent to the user because he has not specified or not confirmed an e-mail address.',
'nowikiemailtext' => 'This is an error message used in [[Special:Emailuser]] when called with a target user not consenting to be an e-mail recipient.',
'emailnotarget' => 'This is an error message that may be used in [[Special:Emailuser]] when called without a (valid) target user for the e-mail.',
{{Identical|Send}}',
'emailccme' => 'Used at [[Special:Preferences]] > E-mail',
'emailccsubject' => 'Subject of the carbon-copied email for the sender sent through MediaWiki.',
-'emailsent' => 'Title of Special:Emailuser when it says you it sent an email',
-'emailsenttext' => 'When you send an e-mail, Special:Emailuser says you this (Your email has been sent).',
+'emailsent' => 'Title of [[Special:EmailUser]] when it says you it sent an email',
+'emailsenttext' => 'When you send an e-mail, [[Special:EmailUser]] says you this (Your email has been sent).',
'emailuserfooter' => 'This message is appended to every email sent through the "Email user" function.
* $1: username of the sender
# User Messenger
'usermessage-summary' => 'This message is used as an edit summary for any message that is posted because of a system event. Translate "leaving a message" in the sense of: to give a message to someone; to deliver a message somewhere; to deposit.',
-'usermessage-editor' => 'The user name for the user that is the editor of system messages. See [http://translatewiki.net/wiki/Thread:Support/Message_info_please discussion on Support].',
+'usermessage-editor' => 'The user name for the user that is the editor of system messages. See [{{canonicalurl:Thread:Support/Message_info_please}} discussion on Support].',
'usermessage-template' => '{{optional}}',
# Watchlist
See also:
* {{msg-mw|Watchthispage|link text}}
* {{msg-mw|Notanarticle|error message}}',
-'notanarticle' => "A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [//www.mediawiki.org/wiki/Manual:Using_custom_namespaces#Content_namespaces Mediawiki].
+'notanarticle' => "A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].
Possible alternatives to the word 'content' are 'subject matter' or 'wiki subject' or 'wiki purpose'.
'protect-fallback' => 'This message is used as an option in the protection form on wikis were extra protection levels have been configured.',
'protect-level-autoconfirmed' => 'Used as protect level.
-See example: [http://translatewiki.net/w/i.php?title=Main_Page&action=info]',
+See example: {{canonicalurl:Main_Page|action=info}}',
'protect-level-sysop' => 'Used as protect level.
-See example: [http://translatewiki.net/w/i.php?title=Main_Page&action=info]',
+See example: {{canonicalurl:Main_Page|action=info}}',
'protect-summary-desc' => '{{Optional}}
Used in edit summary for description of a protecting restriction.
* $1 is action, taken from restriction-*
{{Identical|Other time}}',
'protect-othertime-op' => 'Used on the page protection form in the drop down menu
{{Identical|Other time}}',
-'protect-existing-expiry' => 'Shows the existing expiry time in the drop down menu of the protection form ([http://translatewiki.net/w/i.php?title=User:Raymond/test&action=unprotect example])
+'protect-existing-expiry' => 'Shows the existing expiry time in the drop down menu of the protection form ([{{canonicalurl:User:Raymond/test|action=unprotect}} example])
* $1: date and time of the existing expiry time (kept for backward compatibility purposes)
* $2: date of the existing expiry time
'protect-expiry-options' => "{{Identical|Infinite}}{{doc-important|Be careful: '''1 translation:1 english''', so the first part is the translation and the second part should stay in English.}}
Options for the duration of the page protection. Example: See e.g. [[MediaWiki:Protect-expiry-options/nl]] if you still don't know how to do it.",
-'restriction-type' => 'Used on [[Special:ProtectedPages]]. The text next to a drop-down box. See [[mw:Manual:Administrators|MediaWiki Manual]] for more information on protection.',
-'restriction-level' => 'Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. The text next to a drop-down box. See the [//www.mediawiki.org/wiki/Project:Protected_titles help page on Mediawiki] and on [http://meta.wikimedia.org/wiki/Protect Meta] for more information.',
+'restriction-type' => 'Used on [[Special:ProtectedPages]]. The text next to a drop-down box. See [[mw:Manual:Administrators|MediaWiki Manual]] for more information on protection.
+{{Identical|Permission}}',
+'restriction-level' => 'Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. The text next to a drop-down box. See the [[mw:Project:Protected_titles|help page on MediaWiki]] and on [[meta:Protect|Meta]] for more information.',
'minimum-size' => 'Used in [[Special:Protectedpages]] as a pair of radio buttons, with {{msg-mw|Maximum-size}}. There is an input box to specify the minimum bites of the projected pages listed.',
'maximum-size' => 'Used in [[Special:Protectedpages]] as a pair of radio buttons, with {{msg-mw|Minimum-size}}. There is an input box to specify the maximum bites of the projected pages listed.',
-'pagesize' => 'Used on [[Special:ProtectedPages]]. See the help page on [http://meta.wikimedia.org/wiki/Protect Meta] for more information on protection.',
+'pagesize' => 'Used on [[Special:ProtectedPages]]. See the help page on [[meta:Protect|Meta]] for more information on protection.',
# Restrictions (nouns)
'restriction-edit' => "Used on [[Special:ProtectedPages]]. Option in the 'permission' drop-down box.
'restriction-move' => "Used on [[Special:ProtectedPages]]. Option in the 'permission' drop-down box.
{{Identical|Move}}",
-'restriction-create' => 'Used on [[Special:ProtectedPages]]. An option in a drop-down box. See the help pages on [//www.mediawiki.org/wiki/Project:Protected_titles MediaWiki] and [http://meta.wikimedia.org/wiki/Protect Meta] for more information on protection.
-
+'restriction-create' => 'Used on [[Special:ProtectedPages]]. An option in a drop-down box. See the help pages on [[mw:Project:Protected_titles|MediaWiki]] and [[meta:Protect|Meta]] for more information on protection.
{{Identical|Create}}',
'restriction-upload' => '{{Identical|Upload}}',
# Restriction levels
-'restriction-level-sysop' => "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level' and in brackets after each page name entry. See the [//www.mediawiki.org/wiki/Project:Protected_titles help page on Mediawiki] and on [http://meta.wikimedia.org/wiki/Protect Meta] for more information.
+'restriction-level-sysop' => "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level' and in brackets after each page name entry. See the [[mw:Project:Protected_titles|help page on MediaWiki]] and on [[meta:Protect|Meta]] for more information.
See also:
*{{msg-mw|Restriction-level-autoconfirmed}}
*{{msg-mw|Restriction-level-all}}",
-'restriction-level-autoconfirmed' => "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level', and in brackets after each page name entry. See the [//www.mediawiki.org/wiki/Project:Protected_titles help page on Mediawiki] and on [http://meta.wikimedia.org/wiki/Protect Meta] for more information.
+'restriction-level-autoconfirmed' => "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level', and in brackets after each page name entry. See the [[mw:Project:Protected_titles|help page on MediaWiki]] and on [[meta:Protect|Meta]] for more information.
See also:
*{{msg-mw|Restriction-level-sysop}}
*{{msg-mw|Restriction-level-all}}",
-'restriction-level-all' => "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level'. See the [//www.mediawiki.org/wiki/Project:Protected_titles help page on Mediawiki] and on [http://meta.wikimedia.org/wiki/Protect Meta] for more information.
+'restriction-level-all' => "Used on [[Special:ProtectedPages]] and [[Special:ProtectedTitles]]. An option in the drop-down box 'Restriction level'. See the [[mw:Project:Protected_titles|help page on MediaWiki]] and on [[meta:Protect|Meta]] for more information.
See also:
*{{msg-mw|Restriction-level-sysop}}
'undelete-error-long' => 'Used as error message. See also:
* {{msg-mw|Undelete-error-short}}
* {{msg-mw|Undelete-error-long}}',
-'undelete-show-file-confirm' => 'A confirmation message shown on Special:Undelete when the request does not contain a valid token (e.g. when a user clicks a link received in mail).
+'undelete-show-file-confirm' => 'A confirmation message shown on [[Special:Undelete]] when the request does not contain a valid token (e.g. when a user clicks a link received in mail).
* <code>$1</code> is the name of the file being undeleted.
* <code>$2</code> is the date of the displayed revision.
* <code>$3</code> is the time of the displayed revision.
-
{{identical|Are you sure you want to view the deleted revision of the file...}}',
'undelete-show-file-submit' => '{{Identical|Yes}}',
'undelete-revisionrow' => "{{Optional}}
Parameter $1 is a page title.',
'nolinkshere-ns' => '* $1 - page title',
-'isredirect' => 'Displayed in Special:WhatLinksHere (see [{{fullurl:Special:WhatLinksHere/Project:Translator|hidelinks=1}} Special:WhatLinksHere/Project:Translator] for example).
+'isredirect' => 'Displayed in [[Special:WhatLinksHere]] (see [{{fullurl:Special:WhatLinksHere/Project:Translator|hidelinks=1}} Special:WhatLinksHere/Project:Translator] for example).
{{Identical|Redirect page}}',
'istemplate' => 'Means that a page (a template, specifically) is used as <code><nowiki>{{Page name}}</nowiki></code>.
-Displayed in Special:WhatLinksHere (see [[Special:WhatLinksHere/Template:New portal]] for example).',
+Displayed in [[Special:WhatLinksHere]] (see [[Special:WhatLinksHere/Template:New portal]] for example).',
'isimage' => 'This message is displayed on [[Special:WhatLinksHere]] for images. It means that the image is used on the page (as opposed to just being linked to like an non-image page).',
'whatlinkshere-prev' => 'This is part of the navigation message on the top and bottom of Whatlinkshere pages, where it is used as the first argument of {{msg-mw|Viewprevnext}}.
$1 is the number of items shown per page. It is not used when $1 is zero; not sure what happens when $1 is one.
Example line:
* [[Main Page]] ([[Special:WhatLinksHere/Main Page|{{int:whatlinkshere-links}}]])
-
-{{Identical|Links}}',
+{{Identical|Link}}',
'whatlinkshere-hideredirs' => 'Filter option in [[Special:WhatLinksHere]]. Parameters:
* $1 is the {{msg-mw|hide}} or {{msg-mw|show}}',
'whatlinkshere-hidetrans' => 'First filter option in [[Special:WhatLinksHere]]. Parameters:
* $1 - target username',
'unblockip' => 'Used as legend for the form in [[Special:Unblock]].',
'unblockiptext' => 'Used in the {{msg-mw|Unblockip}} form on [[Special:Unblock]].',
-'ipusubmit' => 'Used as button text on Special:BlockList?action=unblock. To see the message:
+'ipusubmit' => 'Used as button text on [{{canonicalurl:Special:BlockList|action=unblock}} Special:BlockList?action=unblock]. To see the message:
* Go to [[Special:BlockList]]
* Click "unblock" for any block (but you can only see "unblock" if you have administrator rights)
* It is now the button below the form',
{{Related|Blocklist-blocks}}',
'blocklist-rangeblocks' => 'Used as the label for the multi-select checkbox in the form on [[Special:BlockList]].
-For an explanation of "range blocks", see http://www.mediawiki.org/wiki/Help:Range_blocks
+For an explanation of "range blocks", see [[mw:Help:Range_blocks]]
{{Related|Blocklist-blocks}}',
'blocklist-timestamp' => 'This is a column header for dates and times in the table on the page [[Special:BlockList]].
{{Identical|Timestamp}}',
* {{msg-mw|Sp-contributions-uploads}}
* {{msg-mw|Sp-contributions-logs}}
* {{msg-mw|Sp-contributions-deleted}}
-* {{msg-mw|Sp-contributions-userrights}}",
+* {{msg-mw|Sp-contributions-userrights}}
+{{Identical|Block}}",
'unblocklink' => 'Used as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].
See also:
* {{msg-mw|sp-contributions-logs}}
* {{msg-mw|sp-contributions-deleted}}
* {{msg-mw|sp-contributions-userrights}}',
-'change-blocklink' => 'Used to name the link on Special:Log.
+'change-blocklink' => 'Used to name the link on [[Special:Log]].
Also used as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].
See also:
* {{msg-mw|Sorbsreason}}
* {{msg-mw|Sorbs create account_reason}}',
-'cant-see-hidden-user' => 'Used as (red) error message on Special:Block when you try to change (as sysop w/o the hideuser right) the block of a hidden user.',
+'cant-see-hidden-user' => 'Used as (red) error message on [[Special:Block]] when you try to change (as sysop without the hideuser right) the block of a hidden user.',
'ipbblocked' => 'Error message shown when a user tries to alter block settings when they are themselves blocked.',
'ipbnounblockself' => 'Error message shown when a user without the <tt>unblockself</tt> right tries to unblock themselves.',
# Export
'export' => 'Page title of [[Special:Export]], a page where a user can export pages from a wiki to a file.',
-'exporttext' => 'Main text on [[Special:Export]]. Leave the line <tt><nowiki>[[{{#Special:Export}}/{{MediaWiki:Mainpage}}]]</nowiki></tt> exactly as it is!',
+'exporttext' => '{{doc-important|Leave the line <code><nowiki>[[{{#Special:Export}}/{{MediaWiki:Mainpage}}]]</nowiki></code> exactly as it is!}}
+Main text on [[Special:Export]].',
'exportall' => 'A label of checkbox option in [[Special:Export]]',
'exportcuronly' => 'A label of checkbox option in [[Special:Export]]',
'exportnohistory' => 'Used in [[Special:Export]].',
* {{msg-mw|Import-interwiki-templates}}
* {{msg-mw|Import-interwiki-namespace}}
* {{msg-mw|Import-interwiki-rootpage}}
-* {{msg-mw|Import-interwiki-submit}}',
+* {{msg-mw|Import-interwiki-submit}}
+{{Identical|Comment}}',
'importtext' => 'Used in the Import form on [[Special:Import]].',
'importstart' => 'Used in [[Special:Import]].
# Import log
'importlogpage' => '{{doc-logpage}}',
-'importlogpagetext' => 'This text appears at the top of the [//translatewiki.net/w/i.php?title=Special:Log&type=import import log] special page.',
+'importlogpagetext' => 'This text appears at the top of the [{{canonicalurl:Special:Log|type=import}} import log] special page.',
'import-logentry-upload' => 'This is the text of an entry in the Import log (and Recent Changes), after hour (and date, only in the Import log) and sysop name:
* $1 is the name of the imported file',
'import-logentry-upload-detail' => '* $1 - number of revisions, success count',
{{Identical|Log out}}',
'tooltip-ca-talk' => "Tooltip shown when hovering over the {{msg-mw|Talk}} tab.
-A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For a technical definition of 'content namespaces' see [//www.mediawiki.org/wiki/Manual:Using_custom_namespaces#Content_namespaces Mediawiki].
+A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For a technical definition of 'content namespaces' see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].
Possible alternatives to the word 'content' are 'subject matter' or 'wiki subject' or 'wiki purpose'.
See also:
* {{msg-mw|Upload}}
* {{msg-mw|Accesskey-t-upload}}
-* {{msg-mw|Tooltip-t-upload}}',
+* {{msg-mw|Tooltip-t-upload}}
+{{Identical|Upload file}}',
'tooltip-t-specialpages' => 'The tooltip when hovering over the link "[[MediaWiki:Specialpages/{{SUBPAGENAME}}|{{int:specialpages}}]]" going to a list of all special pages available in the wiki.
See also:
* {{msg-mw|Permalink}}
* {{msg-mw|Accesskey-t-permalink}}
* {{msg-mw|Tooltip-t-permalink}}',
-'tooltip-ca-nstab-main' => 'A "content page" is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons "content pages" include pages in the file and category namespaces. On Wikinews "content pages" include pages in the Portal namespace. For technical definition of "content namespaces" see [//www.mediawiki.org/wiki/Manual:Using_custom_namespaces#Content_namespaces Mediawiki].
+'tooltip-ca-nstab-main' => 'A "content page" is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons "content pages" include pages in the file and category namespaces. On Wikinews "content pages" include pages in the Portal namespace. For technical definition of "content namespaces" see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].
Possible alternatives to the word \'content\' are \'subject matter\' or \'wiki subject\' or \'wiki purpose\'.
* $2: optional, the count of names in $1',
'others' => 'The following explanation is guesswork. This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net - to use type <nowiki>&action=credits</nowiki> at the end of any URL in the address bar).
-The message appears at the end of the list of credits given in the message [[Mediawiki:Othercontribs/{{SUBPAGENAME}}]] if the number of contributors is above a certain level.',
+The message appears at the end of the list of credits given in the message [[Mediawiki:Othercontribs/{{SUBPAGENAME}}]] if the number of contributors is above a certain level.
+{{Identical|Other}}',
'siteusers' => 'This message is shown when viewing the credits of a page (example: {{fullurl:Main Page|action=credits}}). Note that this action is disabled by default (currently enabled on translatewiki.net).
It should be in a form that fits with [[MediaWiki:Othercontribs/{{SUBPAGENAME}}|othercontribs]].
'pageinfo-title' => 'Page title for action=info. Parameters:
* $1 is the page name',
'pageinfo-not-current' => 'Error message displayed when information for an old revision is requested. Example: [{{fullurl:Project:News|oldid=4266597&action=info}}]',
-'pageinfo-header-basic' => 'Table section header in action=info.',
+'pageinfo-header-basic' => 'Table section header in action=info. See [{{canonicalurl:MediaWiki:Pageinfo-header-basic/en|action=info}} example].
+{{Identical|Basic information}}',
'pageinfo-header-edits' => 'Table section header in action=info.',
'pageinfo-header-restrictions' => 'Table section header in action=info.',
'pageinfo-header-properties' => 'Table section header in action=info.',
See also:
* {{msg-mw|Pageinfo-templates}}',
'pageinfo-toolboxlink' => "Information link for the page (like 'What links here', but to action=info for the current page instead)",
-'pageinfo-redirectsto' => 'Key for the row shown if this page is a redirect. Verb. See [http://en.wikipedia.org/w/index.php?title=Main_page&action=info example].',
+'pageinfo-redirectsto' => 'Key for the row shown if this page is a redirect. Verb. See [{{canonicalurl:w:Main_page|action=info}} example].',
'pageinfo-redirectsto-info' => 'Text to put in parentheses for the link to the action=info of the redirect target.
{{Identical|Info}}',
'pageinfo-contentpage' => 'Key for the row shown on [{{fullurl:News|action=info}} action=info] if this page is [[mw:Manual:Article count|counted as a content page]]',
# Media information
'mediawarning' => 'Shows up on file description pages if the file type is not listed in [[mw:Manual:$wgTrustedMediaFormats|Manual:$wgTrustedMediaFormats]].',
-'imagemaxsize' => 'This is used in Special:Preferences, under Files.
+'imagemaxsize' => 'This is used in [[Special:Preferences]], under Files.
See also:
* {{msg-mw|Thumbsize}}',
Parameters:
* $1 is the width of the image(s) in pixels.
* $2 is the height of the image(s) in pixels.',
-'file-info-gif-looped' => 'Part of the information provided about a [http://en.wikipedia.org/wiki/Gif .gif file] on its file description page. Looped means repeating in the context of an animated gif. It is a sequence of images, each displayed after the other, and the first one displayed after the last, in a never ending loop. For example of message in use see [[:File:Mouse10.gif]].',
-'file-info-gif-frames' => 'Part of the information provided about a [http://en.wikipedia.org/wiki/Gif .gif file] on its file description page.',
-'file-info-png-looped' => 'Part of the information provided about a [http://en.wikipedia.org/wiki/APNG .apng file] on its file description page. Looped means repeating indefinetly in the context of an animated png. It is a sequence of images, each displayed after the other, and the first one displayed after the last, in a never ending loop.',
-'file-info-png-repeat' => 'Part of the information provided about a [http://en.wikipedia.org/wiki/APNG .apng file] on its file description page. The sequence of images is repeating a limited amount of time. It is a sequence of images, each displayed after the other, and the first one displayed after the last, for $1 times.',
-'file-info-png-frames' => 'Part of the information provided about a [http://en.wikipedia.org/wiki/APNG .apng file] on its file description page.
+'file-info-gif-looped' => 'Part of the information provided about a [[w:Gif|.gif file]] on its file description page. Looped means repeating in the context of an animated gif. It is a sequence of images, each displayed after the other, and the first one displayed after the last, in a never ending loop. For example of message in use see [[:File:Mouse10.gif]].',
+'file-info-gif-frames' => 'Part of the information provided about a [[w:Gif|.gif file]] on its file description page.',
+'file-info-png-looped' => 'Part of the information provided about a [[w:APNG|.apng file]] on its file description page. Looped means repeating indefinetly in the context of an animated png. It is a sequence of images, each displayed after the other, and the first one displayed after the last, in a never ending loop.',
+'file-info-png-repeat' => 'Part of the information provided about a [[w:APNG|.apng file]] on its file description page. The sequence of images is repeating a limited amount of time. It is a sequence of images, each displayed after the other, and the first one displayed after the last, for $1 times.',
+'file-info-png-frames' => 'Part of the information provided about a [[w:APNG|.apng file]] on its file description page.
The variable $1 is the number of individual frames in an animated gif file.
'variantname-shi' => '{{optional}}',
# Metadata
-'metadata' => 'The title of a section on an image description page, with information and data about the image. For example of message in use see [http://commons.wikimedia.org/wiki/File:Titan-crystal_bar.JPG Commons].
-
+'metadata' => 'The title of a section on an image description page, with information and data about the image. For example of message in use see [[commons:File:Titan-crystal_bar.JPG|Commons]].
{{Identical|Metadata}}',
'metadata-expand' => 'On an image description page, there is mostly a table containing data (metadata) about the image. The most important data are shown, but if you click on this link, you can see more data and information. For the link to hide back the less important data, see "[[MediaWiki:Metadata-collapse/{{SUBPAGENAME}}|{{int:metadata-collapse}}]]".',
'metadata-collapse' => 'On an image description page, there is mostly a table containing data (metadata) about the image. The most important data are shown, but if you click on the link "[[MediaWiki:Metadata-expand/{{SUBPAGENAME}}|{{int:metadata-expand}}]]", you can see more data and information. This message is for the link to hide back the less important data.',
-'metadata-fields' => "'''Warning:''' Do not translate list items, only translate the text! So leave \"<tt>* make</tt>\" and the other items exactly as they are.
-
-The sentences are for explanation only and are not shown to the user.",
+'metadata-fields' => '{{doc-important|Do not translate list items, only translate the text! So leave "<code>* make</code>" and the other items exactly as they are.}}
+The sentences are for explanation only and are not shown to the user.',
'metadata-langitem' => '{{optional}}
This is used for constructing the list of translations when a metadata property is translated into multiple languages.
Similar to "metadata-langitem" but for the case where a multilingual property has a default specified that does not specify what language the default is in. $1 is the value of the property.',
# EXIF tags
-'exif-imagewidth' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-
+'exif-imagewidth' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
{{Identical|Width}}',
-'exif-imagelength' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-
+'exif-imagelength' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
{{Identical|Height}}',
-'exif-bitspersample' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-compression' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-bitspersample' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-compression' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-This field labels what the compression of the image is. It is commonly seen in Tiff images. It uses messages like {{msg-mw|exif-compression-1}} for the value. http://en.wikipedia.org/wiki/TIFF#TIFF_Compression_Tag has information about this field.
+This field labels what the compression of the image is. It is commonly seen in Tiff images. It uses messages like {{msg-mw|exif-compression-1}} for the value. [[w:TIFF#TIFF_Compression_Tag]] has information about this field.
{{Related|Exif-compression}}',
-'exif-photometricinterpretation' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-orientation' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-photometricinterpretation' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-orientation' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
For specific information on the orientation tag, see http://sylvana.net/jpegcrop/exif_orientation.html
{{Related|Exif-orientation}}',
-'exif-samplesperpixel' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-planarconfiguration' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-samplesperpixel' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-planarconfiguration' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
See also:
* {{msg-mw|Exif-planarconfiguration}}
* {{msg-mw|Exif-planarconfiguration-1}}
* {{msg-mw|Exif-planarconfiguration-2}}',
-'exif-ycbcrsubsampling' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-ycbcrpositioning' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-ycbcrsubsampling' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-ycbcrpositioning' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
{{Related|Exif-ycbcrpositioning}}',
-'exif-xresolution' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-xresolution' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This is the horizontal resolution in either dots/inch or dots/cm.',
-'exif-yresolution' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-yresolution' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This is the vertical resolution in either dots/inch or dots/cm.',
-'exif-stripoffsets' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-rowsperstrip' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-stripbytecounts' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-jpeginterchangeformat' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-jpeginterchangeformatlength' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-whitepoint' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-stripoffsets' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-rowsperstrip' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-stripbytecounts' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-jpeginterchangeformat' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-jpeginterchangeformatlength' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-whitepoint' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
'exif-primarychromaticities' => 'The chromaticity of the three primary colours of the image. Normally this tag is not necessary, since colour space is specified in the colour space information tag. This should probably be translated it as "Chromaticity of primary colours".
-Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-ycbcrcoefficients' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-referenceblackwhite' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-datetime' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-ycbcrcoefficients' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-referenceblackwhite' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-datetime' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Note, this message is also used for the XMP:ModifyDate property in XMP metadata. See page 35 of http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart1.pdf
Datetime is the time that the digital file was last changed.',
-'exif-imagedescription' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-imagedescription' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This property is the description or caption of the image. It is used for the exif ImageDescription property, the dc:description property in XMP (see http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart1.pdf ), and the iptc-iim 2:120 caption/abstract property ( http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf ).
When an image has multiple differing descriptions, mediawiki follows the MWG guidelines when deciding which to show (Which typically means Exif takes precedence).',
-'exif-make' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-make' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The Manufacturer of the digital camera (or scanner) that took the photo.',
-'exif-model' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-model' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The model of camera (or scanner) used to take the picture.',
'exif-software' => 'Short for "The software which was used to create or modify this image".
The property can come from the Exif Software tag, PNG software chunk, iptc-iim 2:65 Software field, or XMP\'s xmp:CreatorTool field.
-Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-artist' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-artist' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This message labels the author or artist of the work. Usually this means who took the photograph, or who drew the picture. The corresponding value field most commonly contains a single author, however it can contain an ordered (or unordered depending on which metadata standard is used to store the information) list of authors. Sometimes the persons position is prefixed before their name such as \"Photographer, John Smith\". The exif standard recommends multiple authors be specified by \"position, Author 1; position for author 2, Author 2's name\" however this doesn't seem to happen in practise very often. If multiple authors are specified using a non-exif standard, then a billeted (or numbered) list is used.
This property can be specified by exif Artist tag, XMP's tiff:Artist, XMP's dc:creator, iptc-iim's 2:80 byline, PNG's author textual chunk, PNG's (unofficial) artist textual chunk. XMP's photoshop:AuthorsPosition and iptc 2:85 byline-title can also affect display of this property.
-
{{Identical|Author}}",
-'exif-copyright' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-copyright' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Label for information contained in exif Copyright tag, XMP dc:rights, IPTC-iim 2:116, or PNG copyright textual chunk.
Typically the copyright statement for the photograph/drawing/video (such as ''(c) 2010 John Smith. Released under GFDL''). Sometimes contains license information. See also {{msg-mw|exif-copyrightowner}}",
-'exif-exifversion' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-exifversion' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Version of exif standard photo uses. Typically this is 2.22',
-'exif-flashpixversion' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-flashpixversion' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Version of flashpix used. Flashpix is a format used for storing some types of metadata in image. It is not as commonly used as EXIF, and mediawiki currently cannot read Flashpix data.',
-'exif-colorspace' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-colorspace' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The colorspace of the photo. This tells the computer how to make the colours in the photo be more true to the original photo. Typical values for this are sRGB or uncalibrated. This only gives information on colour information given in the exif-colorspace property. However, colour information is often stored elsewhere in the photo.
* {{msg-mw|Exif-colorspace}}
* {{msg-mw|Exif-colorspace-1|optional}}
* {{msg-mw|Exif-colorspace-65535}}',
-'exif-componentsconfiguration' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-componentsconfiguration' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This contains how the information in the picture is stored. This is most commonly Y, Cr, Cb to specify luma, red, blue. RGB is also possible to specify Red, Green, Blue.
{{Related|Exif-componentsconfiguration}}',
-'exif-compressedbitsperpixel' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-pixelydimension' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-pixelxdimension' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-usercomment' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-compressedbitsperpixel' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-pixelydimension' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-pixelxdimension' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-usercomment' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Comments by user. Sometimes used like ImageDescription when the ImageDescription contained non-ascii characters. (Technically ImageDescription is supposed to contain ascii characters. In practise utf-8 is used in ImageDescription, so this field isn't used too much.)",
-'exif-relatedsoundfile' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-relatedsoundfile' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Some cameras offer the option to record an audio "memo" for the photo they just took. If the user did that, the name of the file is labelled with this message.',
-'exif-datetimeoriginal' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-datetimeoriginal' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The date and time when the original image data was generated. For example if it was a painting from 1773, scanned in to a computer in 2007, the datetimeoriginal would be 1773 and {{msg-mw|exif-datetimedigitized}} would have the 2007 date.',
-'exif-datetimedigitized' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-datetimedigitized' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The date and time when the image was stored as digital data.',
-'exif-subsectime' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-subsectime' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
'DateTime subseconds' shows the detail of the fraction of a second (1/100s) at which the file was changed, when the tag {{msg-mw|Exif-datetime}} is recorded to the whole second.",
-'exif-subsectimeoriginal' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-subsectimeoriginal' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This tag shows the detail of the fraction of a second (1/100s) at which the file data was originally generated, when the tag {{msg-mw|Exif-datetimeoriginal}} is recorded to the whole second.',
-'exif-subsectimedigitized' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-subsectimedigitized' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This tag shows the detail of the fraction of a second (1/100s) at which the file was stored as digital data, when the tag {{msg-mw|Exif-datetimedigitized}} is recorded to the whole second.',
-'exif-exposuretime' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-exposuretime' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The exposure time. Number of (or fraction of) seconds the film was exposed to light. The value for this property is formatted using {{msg-mw|exif-exposuretime-format}}',
-'exif-exposuretime-format' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-exposuretime-format' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
*$1 is the exposure time written as a fraction of a second, for example 1/640 of a second.
*$2 is the exposure time written as a decimal, for example 0.0015625.
*'sec' is the abbreviation used in English for the unit of time 'second'.",
-'exif-fnumber' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-fnumber' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-The [http://en.wikipedia.org/wiki/F_number F number] is the relative aperture of the camera.',
+The [[w:F_number|F number]] is the relative aperture of the camera.',
'exif-fnumber-format' => "{{optional}}
Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
*$1 is a number
*f is the abbreviation used in English for 'f-number'.",
-'exif-exposureprogram' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-exposureprogram' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
How the camera figured out what exposure to use. (If it was manually set, if its optimizing for fast shutter speed, etc).
{{Related|Exif-exposureprogram}}',
-'exif-spectralsensitivity' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-spectralsensitivity' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
How sensitive each channel (colour) of the photo is to light. This tag is almost never used.',
-'exif-isospeedratings' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-isospeedratings' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The iso speed of the film used in the camera. This is basically a measure of how sensitive the film in the camera is to light.',
-'exif-shutterspeedvalue' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-shutterspeedvalue' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-[http://en.wikipedia.org/wiki/Shutter_speed Shutter speed] is the time that the camera shutter is open.
+[[w:Shutter_speed|Shutter speed]] is the time that the camera shutter is open.
This is the shutter speed measured in APEX units (negative base 2 log of shutter speed in seconds). See {{msg-mw|exif-exposuretime}} for this property in more traditional units of seconds.',
-'exif-aperturevalue' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-aperturevalue' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-The [http://en.wikipedia.org/wiki/Aperture aperture] of a camera is the hole through which light shines. This message can be translated 'Aperture width'. Note, this is measured in APEX units which is 2*log<sub>2</sub>(f-number) . See {{msg-mw|exif-fnumber}} for this value in more traditional units.",
-'exif-brightnessvalue' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+The [[w:Aperture|aperture]] of a camera is the hole through which light shines. This message can be translated 'Aperture width'. Note, this is measured in APEX units which is 2*log<sub>2</sub>(f-number) . See {{msg-mw|exif-fnumber}} for this value in more traditional units.",
+'exif-brightnessvalue' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
How intense the illumination of the scene photographed is. Measured in APEX brightness units. See Annex C of Exif standard for details on the measurement system in use.',
-'exif-exposurebiasvalue' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-exposurebiasvalue' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-Another term for [http://en.wikipedia.org/wiki/Exposure_bias 'exposure bias'] is 'exposure compensation'.",
-'exif-maxaperturevalue' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+Another term for [[w:Exposure_bias|'exposure bias']] is 'exposure compensation'.",
+'exif-maxaperturevalue' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The 'land' in a camera refers possibly to the inner surface of the barrel of the lens. An alternative phrasing for this message could perhaps be 'maximum width of the land aperture'.",
-'exif-subjectdistance' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-subjectdistance' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
The subject of a photograph is the person or thing on which the camera focuses. 'Subject distance' is the distance to the subject given in meters.",
-'exif-meteringmode' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-meteringmode' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See [http://en.wikipedia.org/wiki/Metering_mode Wikipedia article] on metering mode.
+See [[w:Metering_mode|Wikipedia article]] on metering mode.
{{Related|Exif-meteringmode}}',
-'exif-lightsource' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-lightsource' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
{{Related|Exif-lightsource}}',
-'exif-flash' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-flash' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See this [http://en.wikipedia.org/wiki/Flash_(photography) Wikipedia article] for an explanation of the term.
+See this [[w:en:Flash_(photography)|Wikipedia article]] for an explanation of the term.
See also:
* {{msg-mw|Exif-flash}}
* {{msg-mw|Exif-flash-fired-0}}
* {{msg-mw|Exif-flash-fired-1}}
{{Identical|Flash}}',
-'exif-focallength' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-focallength' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See this [http://en.wikipedia.org/wiki/Focal_length_(photography) Wikipedia article] for an explanation of the term.',
+See this [[w:en:Focal_length_(photography)|Wikipedia article]] for an explanation of the term.',
'exif-focallength-format' => "{{optional}}
Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
*$1 is a number
*mm is the abbreviation used in English for the unit of measurement of length 'millimetre'.",
-'exif-subjectarea' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-subjectarea' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
This exif property contains the position of the main subject. The first two numbers is the position of the subject in the picture in pixels from the upper left corner. If a third number is specified, it is a circle centred at the first two numbers. If four numbers are specified, the first two are coordinates of the centre of the subject as before, the third is the width of the rectangle, and the fourth is the height of the rectangle. It is rare for a photo to use this tag.',
-'exif-flashenergy' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-flashenergy' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
How bright the flash is in beam candle power seconds.',
-'exif-focalplanexresolution' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-focalplanexresolution' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Indicates the number of pixels in the image width (X) direction per FocalPlaneResolutionUnit on the camera focal plane.',
-'exif-focalplaneyresolution' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-focalplaneresolutionunit' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-focalplaneyresolution' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-focalplaneresolutionunit' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
See also:
* {{msg-mw|Exif-focalplaneresolutionunit-2}}',
-'exif-subjectlocation' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-subjectlocation' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Same as {{msg-mw|exif-subjectarea}} but only ever has two numbers as a value.',
-'exif-exposureindex' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-sensingmethod' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-exposureindex' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-sensingmethod' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
{{Related|Exif-sensingmethod}}',
-'exif-filesource' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-filesource' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
Determines if the image was recorded by a digital camera adhering to DSC standard (which is almost all digital cameras).',
-'exif-scenetype' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-scenetype' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
If the image is directly photographed (taken by a digital camera).
See also:
* {{msg-mw|Exif-scenetype}}
* {{msg-mw|Exif-scenetype-1}}',
-'exif-customrendered' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-customrendered' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See also Wikipedia on [http://en.wikipedia.org/wiki/Image_processing image processing].
+See also Wikipedia on [[w:Image_processing|image processing]].
See also:
* {{msg-mw|Exif-customrendered}}
* {{msg-mw|Exif-customrendered-0}}
* {{msg-mw|Exif-customrendered-1}}',
-'exif-exposuremode' => "Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-exposuremode' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See also Wikipedia on [http://en.wikipedia.org/wiki/Exposure_(photography) exposure in photography]. This tag shows if the photo's exposure was manually set or automatically determined.
+See also Wikipedia on [[w:en:Exposure_(photography)|exposure in photography]]. This tag shows if the photo's exposure was manually set or automatically determined.
{{Related|Exif-exposuremode}}",
-'exif-whitebalance' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-whitebalance' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See also Wikipedia on [http://en.wikipedia.org/wiki/Color_balance color balance].
+See also Wikipedia on [[w:Color_balance|color balance]].
See also:
* {{msg-mw|Exif-whitebalance}}
* {{msg-mw|Exif-whitebalance-0}}
* {{msg-mw|Exif-whitebalance-1}}',
-'exif-digitalzoomratio' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-digitalzoomratio' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See also Wikipedia on [http://en.wikipedia.org/wiki/Digital_zoom digital zoom].',
-'exif-focallengthin35mmfilm' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+See also Wikipedia on [[w:Digital_zoom|digital zoom]].',
+'exif-focallengthin35mmfilm' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
-See also Wikipedia on [http://en.wikipedia.org/wiki/Focal_length#In_photography focal length].',
+See also Wikipedia on [[w:Focal_length#In_photography|focal length]].',
'exif-scenecapturetype' => '{{Related|Exif-scenecapturetype}}',
'exif-gaincontrol' => 'Gain amplifies the signal off of the image sensor. Gain turns the brightness level up or down.
{{Related|Exif-gaincontrol}}',
{{Related|Exif-componentsconfiguration}}',
'exif-exposureprogram-0' => '{{Related|Exif-exposureprogram}}',
-'exif-exposureprogram-1' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[http://en.wikipedia.org/wiki/Mode_dial Mode dial]' for an explanation.
+'exif-exposureprogram-1' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[[w:Mode_dial|Mode dial]]' for an explanation.
{{Related|Exif-exposureprogram}}",
-'exif-exposureprogram-2' => '{{Related|Exif-exposureprogram}}',
-'exif-exposureprogram-3' => 'One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article for a definition of the term [http://en.wikipedia.org/wiki/Aperture_priority aperture priority].
+'exif-exposureprogram-2' => 'One of the exposure program types in the table of metadata on image description pages.
{{Related|Exif-exposureprogram}}',
-'exif-exposureprogram-4' => 'One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article for a definition of the term [http://en.wikipedia.org/wiki/Shutter_priority shutter priority].
+'exif-exposureprogram-3' => 'One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article for a definition of the term [[w:Aperture_priority|aperture priority]].
{{Related|Exif-exposureprogram}}',
-'exif-exposureprogram-5' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[http://en.wikipedia.org/wiki/Mode_dial Mode dial]' for an explanation.
+'exif-exposureprogram-4' => 'One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article for a definition of the term [[w:Shutter_priority|shutter priority]].
+{{Related|Exif-exposureprogram}}',
+'exif-exposureprogram-5' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[[w:Mode_dial|Mode dial]]' for an explanation.
{{Related|Exif-exposureprogram}}",
-'exif-exposureprogram-6' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[http://en.wikipedia.org/wiki/Mode_dial Mode dial]' for an explanation.
+'exif-exposureprogram-6' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[[w:Mode_dial|Mode dial]]' for an explanation.
{{Related|Exif-exposureprogram}}",
-'exif-exposureprogram-7' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[http://en.wikipedia.org/wiki/Mode_dial Mode dial]' for an explanation.
+'exif-exposureprogram-7' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[[w:Mode_dial|Mode dial]]' for an explanation.
{{Related|Exif-exposureprogram}}",
-'exif-exposureprogram-8' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[http://en.wikipedia.org/wiki/Mode_dial Mode dial]' for an explanation.
+'exif-exposureprogram-8' => "One of the exposure program types in the table of metadata on image description pages. See the Wikipedia article '[[w:Mode_dial|Mode dial]]' for an explanation.
{{Related|Exif-exposureprogram}}",
'exif-subjectdistance-value' => '$1 is a distance measured in metres. The value can, and usually does, include decimal places.',
* {{msg-mw|Exif-flash}}
* {{msg-mw|Exif-flash-fired-0}}
* {{msg-mw|Exif-flash-fired-1}}',
-'exif-flash-return-0' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-flash-return-0' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
"Strobe" and "flash" mean the same here.
* {{msg-mw|Exif-flash-return-0}}
* {{msg-mw|Exif-flash-return-2}}
* {{msg-mw|Exif-flash-return-3}}',
-'exif-flash-return-2' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-flash-return-2' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
"Strobe" and "flash" mean the same here.
* {{msg-mw|Exif-flash-return-0}}
* {{msg-mw|Exif-flash-return-2}}
* {{msg-mw|Exif-flash-return-3}}',
-'exif-flash-return-3' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+'exif-flash-return-3' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
"Strobe" and "flash" mean the same here.
* {{msg-mw|Exif-flash-mode-1}}
* {{msg-mw|Exif-flash-mode-2}}
* {{msg-mw|Exif-flash-mode-3}}',
-'exif-flash-function-1' => 'Exif is a format for storing metadata in image files. See this [http://en.wikipedia.org/wiki/Exchangeable_image_file_format Wikipedia article] and the example at the bottom of [http://commons.wikimedia.org/wiki/File:Phalacrocorax-auritus-020.jpg this page on Commons]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-flash-function-1' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
'exif-focalplaneresolutionunit-2' => 'See also:
* {{msg-mw|Exif-focalplaneresolutionunit}}',
'exif-exposuremode-0' => '{{Related|Exif-exposuremode}}',
'exif-exposuremode-1' => '{{Related|Exif-exposuremode}}',
-'exif-exposuremode-2' => "A type of exposure mode shown as part of the metadata on image description pages. The Wikipedia article on [http://en.wikipedia.org/wiki/Bracketing#Exposure_bracketing bracketing] says that 'auto bracket' is a camera exposure setting which automatically takes a series of pictures at slightly different light exposures.
+'exif-exposuremode-2' => "A type of exposure mode shown as part of the metadata on image description pages. The Wikipedia article on [[w:Bracketing#Exposure_bracketing|bracketing]] says that 'auto bracket' is a camera exposure setting which automatically takes a series of pictures at slightly different light exposures.
{{Related|Exif-exposuremode}}",
'exif-whitebalance-0' => 'See also:
'exif-subjectdistancerange-0' => '{{Related|Exif-subjectdistancerange}}
{{Identical|Unknown}}',
-'exif-subjectdistancerange-1' => 'Macro view is close-up photography. See [http://en.wikipedia.org/wiki/Macro_photography Wikipedia].
+'exif-subjectdistancerange-1' => 'Macro view is close-up photography. See [[w:Macro_photography|Wikipedia]].
{{Identical|Macro}}
{{Related|Exif-subjectdistancerange}}',
'exif-subjectdistancerange-2' => '{{Related|Exif-subjectdistancerange}}',
See: http://www.awaresystems.be/imaging/tiff/tifftags/ycbcrpositioning.html
{{Related|Exif-ycbcrpositioning}}',
-'exif-dc-contributor' => 'People who helped make the resource, but are secondary in contribution to the author.',
+'exif-dc-contributor' => 'People who helped make the resource, but are secondary in contribution to the author.
+{{Identical|Contributor}}',
'exif-dc-coverage' => '"The extent or scope of the resource" see dc:coverage in http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart2.pdf',
'exif-dc-date' => 'One or more dates associated with the image. How they are associated is not really defined. From the dc:date XMP property.',
'exif-dc-publisher' => 'One or more publisher of resource.
'exif-iimcategory-rel' => 'Displayed as part of the iimcategory field if the 3 letter code is recognized, or as part {{msg-mw|exif-subjectnewscode-value}}',
'exif-iimcategory-sci' => 'Displayed as part of the iimcategory field if the 3 letter code is recognized, or as part {{msg-mw|exif-subjectnewscode-value}}',
'exif-iimcategory-soi' => 'Displayed as part of the iimcategory field if the 3 letter code is recognized, or as part {{msg-mw|exif-subjectnewscode-value}}',
-'exif-iimcategory-spo' => 'Displayed as part of the iimcategory field if the 3 letter code is recognized, or as part {{msg-mw|exif-subjectnewscode-value}}',
+'exif-iimcategory-spo' => 'Displayed as part of the iimcategory field if the 3 letter code is recognized, or as part {{msg-mw|exif-subjectnewscode-value}}.
+{{Identical|Sport}}',
'exif-iimcategory-war' => 'Displayed as part of the iimcategory field if the 3 letter code is recognized, or as part {{msg-mw|exif-subjectnewscode-value}}',
'exif-iimcategory-wea' => 'Displayed as part of the iimcategory field if the 3 letter code is recognized, or as part {{msg-mw|exif-subjectnewscode-value}}',
# External editor support
'edit-externally' => 'Displayed on image description pages. See for example [[:Image:Yes.png#filehistory]].',
-'edit-externally-help' => 'Displayed on image description pages. See for example [[:Image:Yes.png#filehistory]].
-
-Please leave the link http://www.mediawiki.org/wiki/Manual:External_editors exactly as it is.',
+'edit-externally-help' => '{{doc-important|Please leave the link "<code>http://www.mediawiki.org/wiki/Manual:External_editors</code>" exactly as it is.}}
+Displayed on image description pages. See for example [[:Image:Yes.png#filehistory]].',
# 'all' in various places, this might be different for inflected languages
'watchlistall2' => 'Appears on [[Special:Watchlist]].
# Core parser functions
'unknown_extension_tag' => '* Description: This is an error shown when you use an unknown extension tag name. This feature allows tags like <tt><nowiki><pre></nowiki></tt> to be called with a parser like <tt><nowiki>{{#tag:pre}}</nowiki></tt>.
* Parameter $1: This is the unknown extension tag name.',
-'duplicate-defaultsort' => 'See definition of [http://en.wikipedia.org/wiki/Sorting sort key] on Wikipedia.',
+'duplicate-defaultsort' => 'See definition of [[w:Sorting|sort key]] on Wikipedia.',
# Special:Version
'version' => 'Name of special page displayed in [[Special:SpecialPages]]
{{Identical|Version}}',
'version-extensions' => 'Header on [[Special:Version]].',
'version-specialpages' => 'Part of [[Special:Version]].
-
-{{Identical|Special pages}}',
+{{Identical|Special page}}',
'version-parserhooks' => 'This message is a heading at [[Special:Version]] for extensions that modifies the parser of wikitext.',
'version-variables' => '{{Identical|Variable}}',
'version-antispam' => 'Part of [[Special:Version]].
* {{msg-mw|Specialpages}}
* {{msg-mw|Accesskey-t-specialpages}}
* {{msg-mw|Tooltip-t-specialpages}}
-{{Identical|Special pages}}',
+{{Identical|Special page}}',
'specialpages-note' => 'Footer note for the [[Special:SpecialPages]] page',
'specialpages-group-maintenance' => 'Section heading in the list of [[Special:SpecialPages|Special pages]].',
'specialpages-group-other' => 'Section heading in the list of [[Special:SpecialPages|Special pages]].',
# External image whitelist
'external_image_whitelist' => "As usual please leave all the wiki markup, including the spaces, as they are. You can translate the text, including 'Leave this line exactly as it is'. The first line of this messages has one (1) leading space.
-See definition of [http://en.wikipedia.org/wiki/Regular_expression regular expression] on Wikipedia.",
+See definition of [[w:Regular_expression|regular expression]] on Wikipedia.",
# Special:Tags
-'tags' => "Shown on [[Special:Specialpages]] for page listing the tags that the software may mark an edit with, and their meaning. For more information on tags see [//www.mediawiki.org/wiki/Manual:Tags Mediawiki].
+'tags' => "Shown on [[Special:Specialpages]] for page listing the tags that the software may mark an edit with, and their meaning. For more information on tags see [[mw:Manual:Tags|MediaWiki]].
It appears that the word 'valid' describes 'tags', not 'change'. It also appears that you could use the term 'defined' instead of 'valid', or perhaps use a phrase meaning 'Change tags in use'.",
'tag-filter' => 'Caption of a filter shown on lists of changes (e.g. [[Special:Log]], [[Special:Contributions]], [[Special:Newpages]], [[Special:Recentchanges]], [[Special:Recentchangeslinked]], page histories)',
{{Identical|Filter}}',
'tags-title' => 'The title of [[Special:Tags]]',
-'tags-intro' => 'Explanation on top of [[Special:Tags]]. For more information on tags see [//www.mediawiki.org/wiki/Manual:Tags Mediawiki].',
-'tags-tag' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [//www.mediawiki.org/wiki/Manual:Tags Mediawiki].',
-'tags-display-header' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [//www.mediawiki.org/wiki/Manual:Tags Mediawiki].',
-'tags-description-header' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [//www.mediawiki.org/wiki/Manual:Tags Mediawiki].',
-'tags-hitcount-header' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [//www.mediawiki.org/wiki/Manual:Tags Mediawiki].',
+'tags-intro' => 'Explanation on top of [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
+'tags-tag' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
+'tags-display-header' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
+'tags-description-header' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
+'tags-hitcount-header' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
'tags-edit' => '{{Identical|Edit}}
Used on [[Special:Tags]]. Verb. Used as display text on a link to create/edit a description.',
-'tags-hitcount' => 'Shown in the "{{msg-mw|Tags-hitcount-header}}" column in [[Special:Tags]]. For more information on tags see [//www.mediawiki.org/wiki/Manual:Tags Mediawiki].
+'tags-hitcount' => 'Shown in the "{{msg-mw|Tags-hitcount-header}}" column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].
* <code>$1</code> is the number of changes marked with the tag',
{{Identical|Other}}',
# SQLite database support
-'sqlite-has-fts' => 'Shown on Special:Version, $1 is version',
-'sqlite-no-fts' => 'Shown on Special:Version, $1 is version',
+'sqlite-has-fts' => 'Shown on [[Special:Version]].
+Parameters:
+* $1 - version',
+'sqlite-no-fts' => 'Shown on [[Special:Version]].
+Parameters:
+* $1 - version',
# New logging system
'logentry-delete-delete' => '{{Logentry}}',
'feedback-bugornote' => 'When feedback dialog box is opened, this introductory message in small print explains the options to report a bug or add simple feedback. We expect that people in a hurry will not read this.',
'feedback-subject' => 'Label for a text input
{{Identical|Subject}}',
-'feedback-message' => 'Label for a textarea; signature referrs to a Wikitext signature.',
+'feedback-message' => 'Label for a textarea; signature referrs to a Wikitext signature.
+{{Identical|Message}}',
'feedback-cancel' => 'Button label
{{Identical|Cancel}}',
'feedback-submit' => 'Button label
'search-interwiki-default' => '$1 результ.:',
'search-interwiki-more' => '(ещё)',
'search-relatedarticle' => 'Связанный',
-'mwsuggest-disable' => 'Отключить AJAX-подсказки',
+'mwsuggest-disable' => 'Отключить подсказки поиска',
'searcheverything-enable' => 'Поиск по всем пространствам имён',
'searchrelated' => 'связанный',
'searchall' => 'все',
Вы отвечаете за то, чтобы ссылки продолжали и далее указывать туда, куда предполагалось.
Обратите внимание, что страница '''не будет''' переименована, если уже существует страница с названием, идентичным выбранному, кроме случаев, когда такая страница является перенаправлением или пуста, и при этом не имеет истории правок.
-ÐÑ\82о ознаÑ\87аеÑ\82, Ñ\87Ñ\82о вÑ\8b можеÑ\82е пеÑ\80еименоваÑ\82Ñ\8c Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 обÑ\80аÑ\82но в Ñ\82о название, коÑ\82оÑ\80ое Ñ\83 него Ñ\82олÑ\8cко Ñ\87Ñ\82о бÑ\8bло, еÑ\81ли вÑ\8b Ñ\81делали пÑ\80еименование оÑ\88ибоÑ\87но, но вы не можете случайно затереть существующую страницу.
+ÐÑ\82о ознаÑ\87аеÑ\82, Ñ\87Ñ\82о еÑ\81ли вÑ\8b Ñ\81делали пÑ\80еименование оÑ\88ибоÑ\87но, вÑ\8b можеÑ\82е пеÑ\80еименоваÑ\82Ñ\8c Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 обÑ\80аÑ\82но в Ñ\82о название, коÑ\82оÑ\80ое Ñ\83 неÑ\91 Ñ\82олÑ\8cко Ñ\87Ñ\82о бÑ\8bло, но вы не можете случайно затереть существующую страницу.
'''Предупреждение!'''
Переименование ''популярных'' страниц может привести к масштабным и неожиданным изменениям.
-Ð\9fожалÑ\83йÑ\81Ñ\82а, пÑ\80ежде Ñ\87ем вÑ\8b пÑ\80одолжиÑ\82е, Ñ\83бедиÑ\82еÑ\81Ñ\8c, Ñ\87Ñ\82о вÑ\8b понимаете все возможные последствия.",
+Ð\9fожалÑ\83йÑ\81Ñ\82а, пÑ\80ежде Ñ\87ем пÑ\80одолжаÑ\82Ñ\8c, Ñ\83бедиÑ\82еÑ\81Ñ\8c, Ñ\87Ñ\82о понимаете все возможные последствия.",
'movepagetext-noredirectfixer' => "Воспользовавшись формой ниже, вы переименуете страницу, одновременно переместив на новое место её журнал изменений.
Старое название станет перенаправлением на новое название.
Пожалуйста, проверьте наличие [[Special:DoubleRedirects|двойных]] и [[Special:BrokenRedirects|разорванных перенаправлений]].
'pageinfo-robot-noindex' => 'Не индексируется',
'pageinfo-views' => 'Количество просмотров',
'pageinfo-watchers' => 'Число наблюдающих',
+'pageinfo-few-watchers' => 'Менее $1 {{PLURAL:$1|следящего|следящих}}',
'pageinfo-redirects-name' => 'Перенаправления на эту страницу',
'pageinfo-redirects-value' => '$1',
'pageinfo-subpages-name' => 'Подстраницы данной страницы',
Pò èssiri ca ggià canciasti cu successu la tò password o c'addumannasti na nova password timpurrània.",
'resetpass-temp-password' => 'Password timpurrània:',
+# Special:ChangeEmail
+'changeemail-submit' => 'Cancia e-mail',
+
# Edit page toolbar
'bold_sample' => 'Grassettu',
'bold_tip' => 'Grassettu',
'searchhelp-url' => 'Help:Cuntinuti',
'searchmenu-prefix' => '[[Special:PrefixIndex/$1|Visualizza li pàggini cu stu prifissu]]',
'searchprofile-articles' => 'Pàggini di cuntinutu',
-'searchprofile-project' => "Pàggini d'aiutu e dô pruggettu",
+'searchprofile-project' => "Pàggini d'ajutu e dô pruggettu",
'searchprofile-images' => 'Multimedia',
'searchprofile-everything' => 'Tuttu',
'searchprofile-advanced' => 'Avanzata',
'linksearch' => 'Lijami di fora',
'linksearch-pat' => 'Mudellu di circata:',
'linksearch-ns' => 'Namespace:',
-'linksearch-ok' => 'Cerca',
+'linksearch-ok' => 'Arriscedi',
'linksearch-text' => 'C\'è la pussibbilitati di fari usu di metacaràttiri, p\'asèmpiu "*.wikipedia.org".<br />
Protucolli suppurtati: <code>$1</code>',
'linksearch-line' => '$1 prisenti ntâ pàggina $2',
# Watchlist
'watchlist' => 'Lista taliata mia',
'mywatchlist' => 'Lista taliata mia',
+'watchlistfor2' => 'Pi $1, $2',
'nowatchlist' => "Nun hai innicatu pàggini a tèniri d'occhiu.",
'watchlistanontext' => "Pi visualizzari e canciari l'alencu di l'ossirvati spiciali è nicissariu $1.",
'watchnologin' => 'Nun hai effittuatu lu login',
'sp-contributions-search' => 'Ricerca cuntribbuti',
'sp-contributions-username' => 'Nnirizzu IP o nomu utenti:',
'sp-contributions-toponly' => "Ammuscia sulu li cuntribbuti ca sunnu l'ùrtimi rivisioni pâ pàggina",
-'sp-contributions-submit' => 'Ricerca',
+'sp-contributions-submit' => 'Risciduta',
# What links here
'whatlinkshere' => 'Chi punta ccà',
'unblocked-id' => 'Lu bloccu $1 hà statu cacciatu',
'ipblocklist' => 'Utiloizzatura bluccati',
'ipblocklist-legend' => "Atrova n'utenti bluccatu",
-'ipblocklist-submit' => 'Ricerca',
+'ipblocklist-submit' => 'Risciduta',
'infiniteblock' => 'nfinitu',
'expiringblock' => 'scadi lu $1 ê $2',
'anononlyblock' => 'sulu anònimi',
'spam_reverting' => "Ripristinata l'ùrtima virsioni priva di culligamenti a $1",
'spam_blanking' => 'Pàggina svacantata, tutti li virsioni cuntinìanu culligamenti a $1',
+# Info page
+'pageinfo-toolboxlink' => 'Nfurmazzioni ncapu la pàggina',
+
# Skin names
'skinname-standard' => 'Classicu',
'skinname-nostalgia' => 'Nustargìa',
'rightsnone' => '(nuddu)',
# Search suggestions
-'searchsuggest-search' => 'Ricerca',
+'searchsuggest-search' => 'Risciduta',
# API errors
'api-error-nomodule' => 'Erruri nternu: nun fu mpustatu lu mòdulu di carricamentu',
'newwindow' => '(otvara se u novom prozoru)',
'cancel' => 'Poništi',
'moredotdotdot' => 'Još...',
+'morenotlisted' => 'Više nije prikazano...',
'mypage' => 'Stranica',
'mytalk' => 'Razgovor',
'anontalk' => 'Razgovor za ovu IP adresu',
'gotaccount' => "Imate račun? '''$1'''.",
'gotaccountlink' => 'Prijavi se',
'userlogin-resetlink' => 'Zaboravili ste detalje vaše prijave?',
-'createaccountmail' => 'e-mailom',
+'createaccountmail' => 'Koristite privremenu slučajno stvorenu lozinku i pošaljite na dolje specificiranu e-mail adresu',
'createaccountreason' => 'Razlog:',
'badretype' => 'Lozinke koje ste unijeli se ne poklapaju.',
'userexists' => 'Uneseno korisničko ime već je u upotrebi.
# E-mail sending
'php-mail-error-unknown' => 'Nepoznata greška u PHP funkciji mail()',
'user-mail-no-addy' => 'Pokušaj slanja e-maila bez e-mail adrese.',
+'user-mail-no-body' => 'Pokušano slanje e-maila s praznim ili nerazumno kratkim sadržajem.',
# Change password dialog
'resetpass' => 'Promijeni korisničku šifru',
'changeemail-oldemail' => 'Trenutna e-mail adresa:',
'changeemail-newemail' => 'Nova e-mail adresa:',
'changeemail-none' => '(ništa)',
+'changeemail-password' => 'Tvoja šifra/lozinka za {{SITENAME}}:',
'changeemail-submit' => 'Promijeni e-mail',
'changeemail-cancel' => 'Odustani',
'''NE ŠALJITE DJELA ZAŠTIĆENA AUTORSKIM PRAVOM BEZ DOZVOLE!'''",
'longpageerror' => "'''Greška: tekst koji ste uneli je veličine {{PLURAL:$1|jedan kilobajt|$1 kilobajta|$1 kilobajta}}, što je veće od {{PLURAL:$2|dozvoljenog jednog kilobajta|dozvoljena $2 kilobajta|dozvoljenih $2 kilobajta}}.'''
Stranica ne može biti sačuvana.",
-'readonlywarning' => "'''PAŽNJA: Baza je zaključana zbog održavanja, tako da nećete moći da snimite svoje izmjene za sada.
-Možda želite da kopirate i nalijepite tekst u tekst editor i sačuvate ga za kasnije.'''
+'readonlywarning' => "'''PAŽNJA: Baza je zaključana zbog održavanja, tako da nećete moći da sačuvate svoje izmjene za sada.'''
+Možda želite da kopirate i nalijepite tekst u tekst editor i sačuvate ga za kasnije.
Administrator koji je zaključao bazu je naveo slijedeće objašnjenje: $1",
'protectedpagewarning' => "'''PAŽNJA: Ova stranica je zaključana tako da samo korisnici sa administratorskim privilegijama mogu da je mijenjaju.'''
'search-interwiki-default' => '$1 rezultati:',
'search-interwiki-more' => '(više)',
'search-relatedarticle' => 'Povezano',
-'mwsuggest-disable' => 'Onemogući AJAX prijedloge',
+'mwsuggest-disable' => 'Onemogući prijedloge pretrage',
'searcheverything-enable' => 'Pretraga u svim imenskim prostorima',
'searchrelated' => 'povezano',
'searchall' => 'sve',
'prefs-emailconfirm-label' => 'E-mail potvrda:',
'prefs-textboxsize' => 'Veličina prozora za uređivanje',
'youremail' => 'E-mail:',
-'username' => 'Korisničko ime:',
-'uid' => 'Korisnički ID:',
-'prefs-memberingroups' => 'Član {{PLURAL:$1|grupe|grupa}}:',
+'username' => 'Ime {{GENDER:$1|korisnika|korisnice}}:',
+'uid' => '{{GENDER:$1|Korisnički}} ID:',
+'prefs-memberingroups' => '{{GENDER:$2|Korisnik|Korisnica}} je član {{PLURAL:$1|grupe|grupâ}}:',
'prefs-registration' => 'Vrijeme registracije:',
'yourrealname' => 'Vaše pravo ime:',
'yourlanguage' => 'Jezik:',
'linksearch-pat' => 'Šema pretrage:',
'linksearch-ns' => 'Imenski prostor:',
'linksearch-ok' => 'Traži',
-'linksearch-text' => 'Mogu se koristiti džokeri poput "*.wikipedia.org".<br />
-Potreban je najviši domen, na primjer "*.org".<br />
-Podržani protokoli: <tt>$1</tt> (zadaje http:// ako ne navedete protokol).',
+'linksearch-text' => 'Možete koristiti džoker znakove poput "*.wikipedia.org".
+Potrebno je navesti osnovnu domenu (TLD), npr. "*.org".<br />
+Podržani {{PLURAL:$2|protokol|protokoli}}: <code>$1</code> (default je http:// ako nijedan protokol nije naveden).',
'linksearch-line' => '$1 je povezan od $2',
'linksearch-error' => 'Džokeri se mogu pojavljivati samo na početku naziva servera.',
# Special:ActiveUsers
'activeusers' => 'Spisak aktivnih korisnika',
'activeusers-intro' => 'Ovo je spisak korisnika koji su napravili neku aktivnost u {{PLURAL:$1|zadnji $1 dan|zadnja $1 dana|zadnjih $1 dana}}.',
-'activeusers-count' => '{{PLURAL:$1|nedavna $1 izmjena|nedavne $1 izmjene|nedavnih $1 izmjena}} u {{PLURAL:$3|posljednji $3 dan|posljednja $3 dana|posljednjih $3 dana}}',
+'activeusers-count' => '{{PLURAL:$1|$1 izmjena|$1 izmjene|$1 izmjena}} u {{PLURAL:$3|posljednji $3 dan|posljednja $3 dana|posljednjih $3 dana}}',
'activeusers-from' => 'Prikaži korisnike koji počinju sa:',
'activeusers-hidebots' => 'Sakrij botove',
'activeusers-hidesysops' => 'Sakrij administratore',
'usermessage-editor' => 'Sistem za poruke',
# Watchlist
-'watchlist' => 'Moj spisak praćenja',
+'watchlist' => 'Spisak praćenja',
'mywatchlist' => 'Spisak praćenja',
'watchlistfor2' => 'Za $1 $2',
'nowatchlist' => 'Nemate ništa na svom spisku praćenih članaka.',
'watchnologin' => 'Niste prijavljeni',
'watchnologintext' => 'Morate biti [[Special:UserLogin|prijavljeni]] da bi ste mijenjali spisak praćenih članaka.',
'addwatch' => 'Dodaj u popis praćenja',
-'addedwatchtext' => "Stranica \"[[:\$1]]\" je dodana [[Special:Watchlist|vašoj listi praćenih stranica]].
-Buduće promjene ove stranice i njoj pridružene stranice za razgovor će biti navedene ovdje, te će stranica izgledati '''podebljana''' u [[Special:RecentChanges|listi nedavnih]] izmjena kako bi se lakše uočila.",
+'addedwatchtext' => 'Stranica "[[:$1]]" je dodata vašem [[Special:Watchlist|spisku praćenih članaka]].
+Buduće promjene ove stranice i njoj pridružene stranice za razgovor će biti navedene ovde.',
'removewatch' => 'Ukloni sa spiska praćenja',
'removedwatchtext' => 'Stranica "[[:$1]]" je uklonjena s [[Special:Watchlist|vaše liste praćenja]].',
'watch' => 'Prati',
'enotif_subject_moved' => '{{SITENAME}} stranicu $1 {{gender:|je premijestio|je premjestila|je premjestio}} $2',
'enotif_subject_restored' => '{{SITENAME}} stranicu $1 {{gender:|je obnovio|je obnovila|je obnovio}} $2',
'enotif_subject_changed' => '{{SITENAME}} stranicu $1 {{gender:|je promijenio|je promijenila|je promijenio}} $2',
-'enotif_body_intro_deleted' => '{{SITENAME}} stranica $1 je izbrisana na $PAGEEDITDATE od {{GENDER:|korisnika|korisnice|korisnika}} $2, v. $3 za trenutnu verziju.',
+'enotif_body_intro_deleted' => 'Stranicu $1 projekta {{SITENAME}} {{GENDER:$2|obrisao|obrisala}} je dana $PAGEEDITDATE {{GENDER:$2|korisnik|korisnica}} $2, pogledajte $3.',
'enotif_body_intro_created' => '{{SITENAME}} stranica $1 je stvorena na $PAGEEDITDATE od {{GENDER:|korisnika|korisnice|korisnika}} $2, v. $3 za trenutnu verziju.',
'enotif_body_intro_moved' => '{{SITENAME}} stranica $1 je premještena na $PAGEEDITDATE od {{GENDER:|korisnika|korisnice|korisnika}} $2, v. $3 za trenutnu verziju.',
'enotif_body_intro_restored' => '{{SITENAME}} stranica $1 je obnovljena na $PAGEEDITDATE od {{GENDER:|korisnika|korisnice|korisnika}} $2, v. $3 za trenutnu verziju.',
'prot_1movedto2' => '[[$1]] premješten na [[$2]]',
'protect-badnamespace-title' => 'Nezaštitljiv imenski prostor',
'protect-badnamespace-text' => 'Stranice u ovom imenskom prostoru se ne mogu zaštititi.',
+'protect-norestrictiontypes-text' => 'Ova stranica se ne može zaštititi jer nema dostupnih oblika ograničenja.',
+'protect-norestrictiontypes-title' => 'Stranica koju nije moguće zaštititi',
'protect-legend' => 'Potvrdite zaštitu',
'protectcomment' => 'Razlog:',
'protectexpiry' => 'Ističe:',
'protect-cascadeon' => 'Ova stranica je trenutno zaštićena jer je uključena u {{PLURAL:$1|stranicu, koja ima|stranice, koje imaju|stranice, koje imaju}} uključenu prenosnu (kaskadnu) zaštitu.
Možete promijeniti stepen zaštite ove stranice, ali to neće uticati na prenosnu zaštitu.',
'protect-default' => 'Dozvoli svim korisnicima',
-'protect-fallback' => 'Potrebno je imati "$1" ovlasti',
-'protect-level-autoconfirmed' => 'Blokiraj nove i neregistrovane korisnike',
-'protect-level-sysop' => 'Samo administratori',
+'protect-fallback' => 'Dopušteno samo korisnicima s dozvolom "$1"',
+'protect-level-autoconfirmed' => 'Dopušteno samo automatski potvrđenim korisnicima',
+'protect-level-sysop' => 'Dopušteno samo administratorima',
'protect-summary-cascade' => 'prenosna (kaskadna) zaštita',
'protect-expiring' => 'ističe $1 (UTC)',
'protect-expiring-local' => 'ističe $1',
# Move page
'move-page' => 'Preusmjeravanje $1',
'move-page-legend' => 'Premjestite stranicu',
-'movepagetext' => "Korištenjem donjeg formulara možete preimenovati stranicu, preusmjerivši njenu historiju na novi naziv.
-Stari naslov će postati stranica za preusmjerenje na novi naslov.
-Možete updateirati preusmjerenja koja idu na originalni naslov automatski.
-Ako to ne učinite, budite sigurni da ste provjerili [[Special:DoubleRedirects|dupla]] ili [[Special:BrokenRedirects|mrtva preusmjerenja]].
-Odgovorni ste za to da poveznice nastave povezivati stranice kojima su namijenjene.
-
-Uzmite u obzir da stranica '''neće''' biti preusmjerena ako već postoji stranica s novim naslovom, osim ako je prazna ili ako je preusmjerenje bez prethodne historije uređivanja.
-To znači da stranicu možete ponovno preimenovati u stari naslov ako je u pitanju bila pogreška, te da ne možete presnimiti već postojeću stranicu.
-
-'''UPOZORENJE!'''
-Ovo može biti drastična i neočekivana promjena za popularnu stranicu;
-budite sigurni da ste shvatili sve posljedice prije nego što nastavite.",
+'movepagetext' => "Korištenjem ovog formulara možete preimenovati stranicu, premještajući cijelu historiju na novo ime.
+Članak pod starim imenom će postati stranica koja preusmjerava na članak pod novim imenom.
+Možete automatski izmjeniti preusmjerenje do izvornog naslova.
+Ako se ne odlučite na to, provjerite [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|neispravna preusmjeravanja]].
+Dužni ste provjeriti da svi linkovi i dalje nastave voditi na prave stranice.
+
+Imajte na umu da članak '''neće''' biti preusmjeren ukoliko već postoji članak pod imenom na koje namjeravate da preusmjerite osim u slučaju stranice za preusmjeravanje koja nema nikakvih starih izmjena.
+To znači da možete vratiti stranicu na prethodno mjesto ako pogriješite, ali ne možete zamijeniti postojeću stranicu.
+
+'''Pažnja!'''
+Ovo može biti drastična i neočekivana promjena kad su u pitanju popularne stranice;
+Molimo dobro razmislite prije nego što preimenujete stranicu.",
'movepagetext-noredirectfixer' => "Koristeći obrazac ispod ćete preimenovati stranicu i premjestiti cijelu njenu historiju na novi naziv.
Stari naziv će postati preusmjerenje na novi naziv.
Molimo provjerite da li postoje [[Special:DoubleRedirects|dvostruka]] ili [[Special:BrokenRedirects|nedovršena preusmjerenja]].
'import-error-interwiki' => 'Ne mogu da uvezem stranicu „$1“ jer je njen naziv rezervisan za spoljno povezivanje (interwiki).',
'import-error-special' => 'Ne mogu da uvezem stranicu „$1“ jer ona pripada posebnom imenskom prostoru koje ne prihvata stranice.',
'import-error-invalid' => 'Ne mogu da uvezem stranicu „$1“ jer je njen naziv neispravan.',
+'import-error-unserialize' => 'Verzija $2 stranice "$1" ne može biti pročitana/uvezena. Zapisano je da verzija koristi $3 tip sadržaja u $4 formatu.',
'import-options-wrong' => '{{PLURAL:$2|Pogrešna opcija|Pogrešne opcije}}: <nowiki>$1</nowiki>',
'import-rootpage-invalid' => 'Navedena osnovna stranica ima neispravan naslov.',
'import-rootpage-nosubpage' => 'Imenski prostor „$1“ osnovne stranice ne dozvoljava podstranice.',
'pageinfo-robot-noindex' => 'Ne može se indeksirati',
'pageinfo-views' => 'Broj pregleda',
'pageinfo-watchers' => 'Broj pratitelja stranice',
+'pageinfo-few-watchers' => 'Manje od $1 {{PLURAL:$1|pratioca|pratilaca}}',
'pageinfo-redirects-name' => 'Preusmjeravanja na ovu stranicu',
'pageinfo-subpages-name' => 'Podstranice ove stranice',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|preusmjerenje|preusmjerenja|preusmjerenja}}; $3 {{PLURAL:$3|nepreusmjerenje|nepreusmjerenja|nepreusmjerenja}})',
'pageinfo-magic-words' => '{{PLURAL:$1|Magična riječ|Magične riječi}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}} ($1)',
'pageinfo-templates' => '{{PLURAL:$1|Uključeni šablon|Uključeni šabloni}} ($1)',
+'pageinfo-transclusions' => '{{PLURAL:$1|Stranica|Stranice}} uključene u ($1)',
'pageinfo-toolboxlink' => 'Informacije o stranici',
'pageinfo-redirectsto' => 'Preusmjerava na',
'pageinfo-redirectsto-info' => 'Informacije',
'pageinfo-protect-cascading' => 'Prenosiva zaštita stranica važi odavde',
'pageinfo-protect-cascading-yes' => 'Da',
'pageinfo-protect-cascading-from' => 'Stranice sa prenosivom zaštitom od',
+'pageinfo-category-info' => 'Informacije o kategoriji',
+'pageinfo-category-pages' => 'Broj stranica',
+'pageinfo-category-subcats' => 'Broj potkategorija',
+'pageinfo-category-files' => 'Broj datoteka',
# Patrolling
'markaspatrolleddiff' => 'Označi kao patrolirano',
'minutes' => '{{PLURAL:$1|$1 minut|$1 minuta|$1 minuta}}',
'hours' => '{{PLURAL:$1|$1 sat|$1 sata|$1 sati}}',
'days' => '{{PLURAL:$1|$1 dan|$1 dana|$1 dana}}',
+'months' => '{{PLURAL:$1|$1 mjesec|$1 mjeseci}}',
+'years' => '{{PLURAL:$1|$1 godina|$1 godine|$1 godina}}',
'ago' => 'prije $1',
'just-now' => 'upravo sada',
'specialpages-group-highuse' => 'Često korištene stranice',
'specialpages-group-pages' => 'Spiskovi stranica',
'specialpages-group-pagetools' => 'Alati za stranice',
-'specialpages-group-wiki' => 'Wiki podaci i alati',
+'specialpages-group-wiki' => 'Podaci i alati',
'specialpages-group-redirects' => 'Preusmjeravanje posebnih stranica',
'specialpages-group-spam' => 'Spam alati',
'logentry-newusers-newusers' => 'Korisnički račun $1 je napravljen',
'logentry-newusers-create' => 'Korisnički račun $1 je napravljen',
'logentry-newusers-create2' => 'Korisnički račun $3 {{GENDER:|je napravio|je napravila|je napravio}} $1',
+'logentry-newusers-byemail' => 'Korisnički račun $3 je napravio $1 i lozinka/šifra je poslana putem e-maila',
'logentry-newusers-autocreate' => 'Račun $1 je samostalno otvoren',
'logentry-rights-rights' => '$1 {{GENDER:$1|je promijenio|je promijenila|je promijenio}} članstvo grupe za $3 iz $4 u $5',
'logentry-rights-rights-legacy' => '$1 {{GENDER:$1|je promenio|je promenila|je promenio}} članstvo grupe za $3',
'api-error-ok-but-empty' => 'Unutrašnja greška: nema odgovora od servera.',
'api-error-overwrite' => 'Pisanje preko postojeće datoteke nije dopušteno.',
'api-error-stashfailed' => 'Unutrašnja greška: server nije mogao da spremi privremenu datoteku.',
+'api-error-publishfailed' => 'Unutrašnja greška: server nije mogao da spremi privremenu datoteku.',
'api-error-timeout' => 'Server nije odgovorio unutar očekivanog vremena.',
'api-error-unclassified' => 'Desila se nepoznata greška',
'api-error-unknown-code' => 'Nepoznata greška: "$1"',
'allpagesprev' => 'Predchádzajúci',
'allpagesnext' => 'Ďalší',
'allpagessubmit' => 'Vykonať',
-'allpagesprefix' => 'Zobraziť stránky s predponou:',
+'allpagesprefix' => 'Zobraziť stránky začínajúce na:',
'allpagesbadtitle' => 'Zadaný názov stránky je neplatný alebo mal medzijazykový alebo interwiki prefix. Môže obsahovať jeden alebo viac znakov, ktoré nie je možné použiť v názve stránky.',
'allpages-bad-ns' => '{{SITENAME}} nemá menný priestor „$1“.',
'allpages-hide-redirects' => 'Skryť presmerovania',
'nchanges' => '$1 {{PLURAL:$1|sprememba|spremembi|spremembe|sprememb|sprememb}}',
'recentchanges' => 'Zadnje spremembe',
'recentchanges-legend' => 'Možnosti zadnjih sprememb',
-'recentchanges-summary' => 'Na tej strani lahko spremljajte najnedavnejše spremembe wikija.',
+'recentchanges-summary' => 'Na tej strani lahko spremljate najnovejše spremembe wikija.',
'recentchanges-feed-description' => 'Spremljajte zadnje spremembe wikija prek tega vira.',
'recentchanges-label-newpage' => 'S tem urejanjem je bila ustvarjena nova stran',
'recentchanges-label-minor' => 'Manjše urejanje',
'filehist-thumb' => 'Sawir yar',
'filehist-thumbtext' => 'Sawirka yar nuuciisa ahaa $1',
'filehist-user' => 'Isticmaale',
+'filehist-dimensions' => 'Cabirka',
'filehist-comment' => 'Ka hadalka',
'imagelinks' => 'Faylka lagu isticmaalay',
'linkstoimage' => 'Boggagaan soo socota ee {{PLURAL:$1|ah waxey la xiriiraan|$1 ah waxey la xiriiraan}} faylkan:',
'vector-action-protect' => 'காக்கவும்',
'vector-action-undelete' => 'நீக்கத்தை நிறுத்து',
'vector-action-unprotect' => 'காப்பை மாற்று',
-'vector-simplesearch-preference' => 'à®®à¯\87à®®à¯\8dபà®\9fà¯\8dà®\9f தà¯\87à®\9fà¯\81தலà¯\8d à®®à¯\81à®\9fிவà¯\81à®\95ளà¯\88à®\9aà¯\8d செயல்படுத்தவும் (Vector தோல் மட்டும்)',
+'vector-simplesearch-preference' => 'à®\9aாதாரண தà¯\87à®\9fà¯\81தலà¯\8d பà®\9fà¯\8dà®\9fà¯\88யதà¯\8dதà¯\88 செயல்படுத்தவும் (Vector தோல் மட்டும்)',
'vector-view-create' => 'உருவாக்கவும்',
'vector-view-edit' => 'தொகு',
'vector-view-history' => 'வரலாற்றைக் காட்டவும்',
'prot_1movedto2' => '[[$1]], [[$2]] என்றத் தலைப்புக்கு நகர்த்தப்பட்டுள்ளது.',
'protect-badnamespace-title' => 'பாதுகாக்க முடியாத பெயரிடைவெளி',
'protect-badnamespace-text' => 'இந்த பெயரிடைவெளியில் உள்ள பக்கங்கள் பாதுகாக்கப்படாது.',
+'protect-norestrictiontypes-title' => 'பாதுகாக்க முடியாத பக்கங்கள்',
'protect-legend' => 'காப்பை உறுதிப்படுத்து',
'protectcomment' => 'காரணம்:',
'protectexpiry' => 'முடிவுறுகிறது:',
'pageinfo-hidden-categories' => 'மறைக்கப்பட்ட {{PLURAL:$1|பகுப்பு|பகுப்புகள்}} ($1)',
'pageinfo-templates' => 'பயன்படுத்தப்பட்ட {{PLURAL:$1|வார்ப்புரு|வார்ப்புருக்கள்}} ($1)',
'pageinfo-toolboxlink' => 'பக்கத் தகவல்',
+'pageinfo-redirectsto' => 'வழிமாற்றவும்:',
'pageinfo-redirectsto-info' => 'தகவல்',
'pageinfo-contentpage' => 'உள்ளடக்கப் பக்கமாய்க் கணக்கிடப்பட்டது.',
'pageinfo-contentpage-yes' => 'ஆம்',
'pageinfo-protect-cascading-yes' => 'ஆம்',
+'pageinfo-category-info' => 'பகுப்புகளின் எண்ணிக்கை',
+'pageinfo-category-pages' => 'பக்கங்களின் எண்ணிக்கை',
+'pageinfo-category-files' => 'கோப்புகளின் எண்ணிக்கை',
# Skin names
'skinname-standard' => 'இயல்பான',
'tog-watchdefault' => "Hateke pájina sira-ne'ebé ha'u edita",
'tog-watchmoves' => "Hateke pájina sira-ne'ebé ha'u book",
'tog-watchdeletion' => "Hateke pájina sira-ne'ebé ha'u halakon",
+'tog-minordefault' => 'Edita hotu-hotu "ki\'ik"',
+'tog-oldsig' => 'Asinatura atuál',
'tog-watchlisthideown' => "La hatudu ha'u-nia edita iha lista hateke",
'tog-watchlisthidebots' => 'Hamsumik bot iha lista hateke',
'tog-watchlisthideminor' => "Hamsumik muda ki-ki'ik iha lista hateke",
'tog-watchlisthideliu' => 'La hatudu edita ema rejista nian iha lista hateke',
'tog-watchlisthideanons' => 'La hatudu edita ema anónimu nian iha lista hateke',
+'tog-watchlisthidepatrolled' => 'Hamsumik muda patrolada iha lista hateke',
+'tog-ccmeonemails' => "Haruka ba ha'u kopia korreiu eletróniku nian ne'ebé ha'u korreia",
'tog-showhiddencats' => "Hatudu kategoria sira-ne'ebé subar",
'underline-always' => 'Sempre',
# History pages
'currentrev' => 'Versaun atuál',
'revisionasof' => 'Versaun $1 nian',
+'revision-info' => 'Revisaun loron $4, tempu $5, husi $2',
'previousrevision' => '←Versaun tuan liu',
'nextrevision' => 'Versaun foun liu→',
'currentrevisionlink' => 'Versaun atuál',
$messages = array(
# User preference toggles
-'tog-underline' => 'à¸\82ีà¸\94à¹\80สà¹\89à¸\99à¹\83à¸\95à¹\89ลิà¸\87à¸\81à¹\8c',
+'tog-underline' => 'à¸\81ารà¸\82ีà¸\94à¹\80สà¹\89à¸\99à¹\83à¸\95à¹\89ลิà¸\87à¸\81à¹\8c:',
'tog-justify' => 'จัดย่อหน้าชิดขอบ',
'tog-hideminor' => 'ซ่อนการแก้ไขเล็กน้อยในหน้าปรับปรุงล่าสุด',
'tog-hidepatrolled' => 'ซ่อนการแก้ไขที่ตรวจแล้วในหน้าปรับปรุงล่าสุด',
'underline-default' => 'ค่าโดยปริยายของหน้าตาหรือเบราว์เซอร์',
# Font style option in Special:Preferences
-'editfont-style' => 'รูà¸\9bà¹\81à¸\9aà¸\9aà¸\95ัวอักษรในพื้นที่แก้ไข:',
+'editfont-style' => 'รูà¸\9bà¹\81à¸\9aà¸\9aà¸\8aุà¸\94à¹\81à¸\9aà¸\9aอักษรในพื้นที่แก้ไข:',
'editfont-default' => 'ค่าตั้งต้นของเบราว์เซอร์',
'editfont-monospace' => 'ชุดอักษรแบบความกว้างคงที่',
'editfont-sansserif' => 'ชุดอักษรแบบไม่มีเชิง',
'morenotlisted' => 'มีที่ยังไม่แสดงอีก...',
'mypage' => 'หน้า',
'mytalk' => 'พูดคุย',
-'anontalk' => 'พูดคุยกับไอพีนี้',
+'anontalk' => 'à¸\9eูà¸\94à¸\84ุยà¸\81ัà¸\9aà¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eีà¸\99ีà¹\89',
'navigation' => 'ป้ายบอกทาง',
'and' => ' และ',
'returnto' => 'กลับไป $1',
'tagline' => 'จาก {{SITENAME}}',
'help' => 'คำอธิบาย',
-'search' => 'สืà¸\9aà¸\84à¹\89à¸\99',
-'searchbutton' => 'สืà¸\9aà¸\84à¹\89à¸\99',
+'search' => 'à¸\84à¹\89à¸\99หา',
+'searchbutton' => 'à¸\84à¹\89à¸\99หา',
'go' => 'ไป',
'searcharticle' => 'ไป',
'history' => 'ประวัติหน้า',
'protect' => 'ล็อก',
'protect_change' => 'เปลี่ยน',
'protectthispage' => 'ล็อกหน้านี้',
-'unprotect' => 'à¹\80à¸\9bลีà¹\88ยà¸\99à¸\84à¹\88าà¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99',
+'unprotect' => 'เปลี่ยนการป้องกัน',
'unprotectthispage' => 'เปลี่ยนการป้องกันหน้านี้',
'newpage' => 'หน้าใหม่',
'talkpage' => 'อภิปรายหน้านี้',
'talkpagelinktext' => 'พูดคุย',
'specialpage' => 'หน้าพิเศษ',
'personaltools' => 'เครื่องมือส่วนตัว',
-'postcomment' => 'à¸\95à¸นใหม่',
+'postcomment' => 'สà¹\88วนใหม่',
'articlepage' => 'ดูหน้าเนื้อหา',
'talk' => 'อภิปราย',
'views' => 'ดู',
'protectedpage' => 'หน้าถูกล็อก',
'jumpto' => 'ข้ามไปยัง:',
'jumptonavigation' => 'นำทาง',
-'jumptosearch' => 'สืà¸\9aà¸\84à¹\89à¸\99',
+'jumptosearch' => 'à¸\84à¹\89à¸\99หา',
'view-pool-error' => 'ขออภัย ขณะนี้เซิร์ฟเวอร์มีภาระเกิน
ผู้ใช้พยายามเข้าดูหน้านี้มากเกินไป
กรุณารอสักครู่ก่อนที่จะเข้าดูหน้านี้อีกครั้งหนึ่ง
$1',
-'pool-timeout' => 'à¹\80à¸\81ิà¸\99à¹\80วลารà¸à¸\81ารลà¹\87à¸à¸\84',
+'pool-timeout' => 'à¹\80à¸\81ิà¸\99à¹\80วลารà¸à¸\81ารลà¹\87à¸à¸\81',
'pool-queuefull' => 'พื้นที่รองรับคิวเต็ม',
-'pool-errorunknown' => 'à¹\80à¸\81ิà¸\94à¸\84วามผิดพลาดไม่ทราบสาเหตุ',
+'pool-errorunknown' => 'à¹\80à¸\81ิà¸\94à¸\82à¹\89à¸ผิดพลาดไม่ทราบสาเหตุ',
# All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage) and the disambiguation template definition (see disambiguations).
-'aboutsite' => 'เกี่ยวกับ {{SITENAME}}',
+'aboutsite' => 'เกี่ยวกับ{{SITENAME}}',
'aboutpage' => 'Project:เกี่ยวกับ',
'copyright' => 'เนื้อหาอนุญาตให้เผยแพร่ภายใต้ $1',
'copyrightpage' => '{{ns:project}}:ลิขสิทธิ์',
'privacypage' => 'Project:นโยบายสิทธิส่วนบุคคล',
'badaccess' => 'มีข้อผิดพลาดในการใช้สิทธิ',
-'badaccess-group0' => 'à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aà¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\95ามà¸\97ีà¹\88รà¹\89à¸à¸\87à¸\82à¸',
-'badaccess-groups' => 'à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\81ารà¸\97ีà¹\88à¸\84ุà¸\93รà¹\89à¸à¸\87à¸\82à¸à¸\99ีà¹\89สà¸\87วà¸\99à¹\84วà¹\89à¹\80à¸\89à¸\9eาะà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\83à¸\99{{PLURAL:$2|à¸\81ลุà¹\88ม|à¸\81ลุà¹\88มหà¸\99ึà¹\88à¸\87à¸\81ลุà¹\88มà¹\83à¸\94 à¸\94ัà¸\87à¸\99ีà¹\89}}: $1',
+'badaccess-group0' => 'คุณไม่ได้รับอนุญาตให้ดำเนินการตามที่ขอ',
+'badaccess-groups' => 'ปฏิบัติการที่คุณขอนี้สงวนไว้เฉพาะผู้ใช้ใน{{PLURAL:$2|กลุ่ม|กลุ่มหนึ่งกลุ่มใด ดังนี้}}: $1',
'versionrequired' => 'ต้องการมีเดียวิกิรุ่น $1',
'versionrequiredtext' => 'ต้องการมีเดียวิกิรุ่น $1 สำหรับใช้งานหน้านี้ ดู[[Special:Version|หน้ารุ่น]]',
'hidetoc' => 'ซ่อน',
'collapsible-collapse' => 'ยุบ',
'collapsible-expand' => 'ขยาย',
-'thisisdeleted' => 'à¹\81สà¸\94à¸\87หรืà¸à¹\80รียà¸\81à¸\94ู $1',
+'thisisdeleted' => 'à¸\94ูหรืà¸à¸\81ูà¹\89à¸\84ืà¸\99 $1 หรืà¸à¹\84มà¹\88',
'viewdeleted' => 'ดู $1',
'restorelink' => '$1 การแก้ไขที่ถูกลบ',
'feedlinks' => 'ฟีด',
'fileexistserror' => 'ไม่สามารถเขียนไฟล์ "$1" ได้ เนื่องจากมีไฟล์อยู่แล้ว',
'unexpected' => 'ผลที่ไม่คาดคิด: "$1"="$2"',
'formerror' => 'ผิดพลาด: ไม่สามารถส่งแบบได้',
-'badarticleerror' => 'à¹\84มà¹\88สามารà¸\96à¸\94ำà¹\80à¸\99ิà¸\99à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\81ารà¸\99ี้ในหน้านี้',
+'badarticleerror' => 'à¸\81ารà¸\81ระà¸\97ำà¸\99ีà¹\89à¹\84มà¹\88สามารà¸\96à¸\97ำà¹\84à¸\94้ในหน้านี้',
'cannotdelete' => 'ไม่สามารถลบหน้าหรือไฟล์ "$1"
อาจมีผู้อื่นลบไปแล้ว',
'cannotdelete-title' => "ไม่สามารถลบหน้า ''$1''",
'delete-hook-aborted' => 'การลบถูกฮุกยกเลิก
-à¹\84มà¹\88มีà¸\84ำà¸à¸\98ิà¸\9aายสำหรัà¸\9aà¸\81ารยà¸\81à¹\80ลิà¸\81à¸\99ีà¹\89',
-'badtitle' => 'à¸\8aืà¹\88à¸à¹\84มà¹\88à¹\80หมาะสม',
-'badtitletext' => 'à¸\8aืà¹\88à¸à¸\82à¸à¸\87หà¸\99à¹\89าà¸\97ีà¹\88รà¹\89à¸à¸\87à¸\82à¸à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87 à¸à¸²à¸\88à¹\80à¸\9bà¹\87à¸\99à¸\8aืà¹\88à¸à¸§à¹\88าà¸\87 หรืà¸à¸\8aืà¹\88à¸à¸\97ีà¹\88à¸\9cิà¸\94à¸\9eลาà¸\94à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81ลิà¸\87à¸\81à¹\8cà¸\82à¹\89ามมาà¸\88าà¸\81ภาษาà¸à¸·à¹\88à¸\99
-หรืà¸à¹\84มà¹\88à¸\8aืà¹\88à¸à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¸à¸²à¸\88มีà¸\95ัวà¸à¸±à¸\81ษรà¸\97ีà¹\88à¹\84มà¹\88สามารà¸\96à¸\9bราà¸\81à¸\8fà¹\83à¸\99à¸\8aืà¹\88à¸à¸\81à¹\87à¹\84à¸\94à¹\89',
-'perfcached' => 'à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¸\96ูà¸\81à¹\80à¸\81à¹\87à¸\9aà¹\84วà¹\89à¹\83à¸\99à¹\81à¸\84à¸\8a à¹\81ละà¸à¸²à¸\88ลà¹\89าสมัย มีà¸\9cลà¸\81ารà¸\84à¹\89à¸\99หาสูà¸\87สุà¸\94 $1 รายà¸\81ารà¹\83à¸\99à¹\81à¸\84à¸\8a',
-'perfcachedts' => 'à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¸\96ูà¸\81à¹\80à¸\81à¹\87à¸\9aà¹\84วà¹\89à¹\83à¸\99หà¸\99à¹\88วยà¸\84วามà¸\88ำà¹\81à¸\84à¸\8a à¹\81ละà¹\84à¸\94à¹\89รัà¸\9aà¸\81ารà¸\9bรัà¸\9aลà¹\88าสุà¸\94à¹\80มืà¹\88ภ$1 à¸\84à¹\88าสูà¸\87สุà¸\94 $4 à¸\9cลลัà¸\9eà¸\98à¹\8cสามารà¸\96à¹\80à¸\81à¹\87à¸\9aà¹\84วà¹\89à¹\83à¸\99หà¸\99à¹\88วยà¸\84วามà¸\88ำแคชได้',
-'querypage-no-updates' => 'à¸\82à¸\93ะà¸\99ีà¹\89à¸\81ารà¸\9bรัà¸\9aà¸\9bรุà¸\87หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ระà¸\87ัà¸\9a à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\83à¸\99à¸\97ีà¹\88à¸\99ีà¹\88จะไม่รีเฟรชเป็นปัจจุบัน',
+à¹\82à¸\94ยà¹\84มà¹\88มีà¸\84ำà¸à¸\98ิà¸\9aาย',
+'badtitle' => 'à¹\83à¸\8aà¹\89à¸\8aืà¹\88à¸à¸«à¸±à¸§à¸\82à¹\89à¸à¸\99ีà¹\89à¹\84มà¹\88à¹\84à¸\94à¹\89',
+'badtitletext' => 'à¸\8aืà¹\88à¸à¸«à¸\99à¹\89าà¸\97ีà¹\88à¸\82à¸à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87 à¹\80à¸\9bà¹\87à¸\99à¸\8aืà¹\88à¸à¸§à¹\88าà¸\87 หรืà¸à¸\8aืà¹\88à¸à¸\82à¹\89ามภาษาหรืà¸à¸\82à¹\89ามวิà¸\81ิà¸\97ีà¹\88à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87
+à¸à¸²à¸\88มีà¸à¸±à¸\81à¸\82ระà¸\97ีà¹\88à¹\84มà¹\88สามารà¸\96à¹\83à¸\8aà¹\89à¹\83à¸\99à¸\8aืà¹\88à¸à¹\80รืà¹\88à¸à¸\87à¹\84à¸\94à¹\89',
+'perfcached' => 'ข้อมูลต่อไปนี้ถูกเก็บในแคช และอาจล้าสมัย มีผลการค้นหาสูงสุด $1 รายการในแคช',
+'perfcachedts' => 'à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¸\96ูà¸\81à¹\80à¸\81à¹\87à¸\9aà¹\83à¸\99à¹\81à¸\84à¸\8a à¹\81ละà¹\84à¸\94à¹\89รัà¸\9aà¸\81ารà¸\9bรัà¸\9aลà¹\88าสุà¸\94à¹\80มืà¹\88ภ$1 à¸\9cลลัà¸\9eà¸\98à¹\8cสูà¸\87สุà¸\94 $4 รายà¸\81ารสามารà¸\96à¹\80à¸\81à¹\87à¸\9aà¹\83à¸\99แคชได้',
+'querypage-no-updates' => 'à¸\82à¸\93ะà¸\99ีà¹\89à¸\81ารà¸\9bรัà¸\9aà¸\9bรุà¸\87หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ระà¸\87ัà¸\9a à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\83à¸\99à¸\97ีà¹\88à¸\99ีà¹\89จะไม่รีเฟรชเป็นปัจจุบัน',
'wrong_wfQuery_params' => 'พารามิเตอร์ที่ส่งไป wfQuery() ไม่ถูกต้อง<br />
ฟังก์ชั่น: $1<br />
คำค้น: $2',
'ns-specialprotected' => 'หน้าพิเศษไม่สามารถแก้ไขได้',
'titleprotected' => "ชื่อเรื่องนี้ถูกป้องกันมิให้สร้างโดย [[User:$1|$1]]
เหตุผลที่ให้ไว้คือ ''$2''",
-'invalidtitle-knownnamespace' => 'ชื่อที่มีเนมสเปซ "$2" กับข้อความ "$3" ไม่ถูกต้อง',
-'invalidtitle-unknownnamespace' => 'ชื่อที่ไม่ทราบเนมสเปซหมายเลข $1 กับข้อความ "$2" ไม่ถูกต้อง',
+'filereadonlyerror' => 'ไม่สามารถแก้ไขไฟล์ "$1" เพราะที่เก็บไฟล์ "$2" อยู่ในภาวะอ่านอย่างเดียว
+ผู้ดูแลระบบที่ล็อกให้คำอธิบายว่า: "$3"',
+'invalidtitle-knownnamespace' => 'ชื่อเรื่องที่มีเนมสเปซ "$2" กับข้อความ "$3" ไม่ถูกต้อง',
+'invalidtitle-unknownnamespace' => 'ชื่อเรื่องที่ไม่ทราบเนมสเปซหมายเลข $1 กับข้อความ "$2" ไม่ถูกต้อง',
'exception-nologin' => 'ไม่ได้ล็อกอิน',
-'exception-nologin-text' => 'หน้าหรือปฏิบัติการนี้กำหนดให้คุณล็อกอินเข้าสู่วิกินี้ก่อน',
+'exception-nologin-text' => 'หà¸\99à¹\89าหรืà¸à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\81ารà¸\99ีà¹\89à¸\81ำหà¸\99à¸\94à¹\83หà¹\89à¸\84ุà¸\93à¸\95à¹\89à¸à¸\87ลà¹\87à¸à¸\81à¸à¸´à¸\99à¹\80à¸\82à¹\89าสูà¹\88วิà¸\81ิà¸\99ีà¹\89à¸\81à¹\88à¸à¸\99',
# Virus scanner
-'virus-badscanner' => "à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าผิดพลาด: ไม่รู้จักตัวสแกนไวรัส: ''$1''",
+'virus-badscanner' => "à¹\82à¸\84รà¸\87à¹\81à¸\9aà¸\9aผิดพลาด: ไม่รู้จักตัวสแกนไวรัส: ''$1''",
'virus-scanfailed' => 'การสแกนล้มเหลว (โค้ด $1)',
'virus-unknownscanner' => 'ไม่รู้จักโปรแกรมป้องกันไวรัสตัวนี้:',
'logouttext' => "'''ขณะนี้คุณได้ล็อกเอาต์แล้ว'''
คุณสามารถใช้งาน {{SITENAME}} ต่อในฐานะผู้ใช้นิรนาม หรือคุณสามารถ<span class='plainlinks'>[$1 ล็อกอินกลับเข้าไป]</span>ด้วยชื่อผู้ใช้เดิมหรือชื่อผู้ใช้อื่น
-อย่างไรก็ตามอาจมีบางหน้าที่แสดงผลเสมือนคุณกำลังล็อกอินอยู่ จนกว่าคุณจะล้างแคชเบราว์เซอร์ของคุณ",
+à¸à¸¢à¹\88าà¸\87à¹\84รà¸\81à¹\87à¸\95ามà¸à¸²à¸\88มีà¸\9aาà¸\87หà¸\99à¹\89าà¸\97ีà¹\88à¹\81สà¸\94à¸\87à¸\9cลà¹\80สมืà¸à¸\99วà¹\88าà¸\84ุà¸\93à¸\81ำลัà¸\87ลà¹\87à¸à¸\81à¸à¸´à¸\99à¸à¸¢à¸¹à¹\88 à¸\88à¸\99à¸\81วà¹\88าà¸\84ุà¸\93à¸\88ะลà¹\89าà¸\87à¹\81à¸\84à¸\8aà¹\80à¸\9aราวà¹\8cà¹\80à¸\8bà¸à¸£à¹\8cà¸\82à¸à¸\87à¸\84ุà¸\93",
'welcomeuser' => 'ยินดีต้อนรับ $1!',
'welcomecreation-msg' => 'บัญชีของคุณถูกสร้างขึ้นแล้ว
อย่าลืมเปลี่ยนแปลง[[Special:Preferences|การตั้งค่าใน {{SITENAME}}]] ของคุณ',
'password-login-forbidden' => 'ห้ามใช้ชื่อผู้ใช้และรหัสผ่านนี้',
'mailmypassword' => 'อีเมลรหัสผ่านใหม่',
'passwordremindertitle' => 'รหัสผ่านชั่วคราวใหม่สำหรับ {{SITENAME}}',
-'passwordremindertext' => 'à¸\9cูà¹\89à¹\83à¸\94à¸\9cูà¹\89หà¸\99ึà¹\88à¸\87 (à¸\8bึà¹\88à¸\87à¸à¸²à¸\88à¹\80à¸\9bà¹\87à¸\99à¸\84ุà¸\93 à¸\97ีà¹\88à¹\83à¸\8aà¹\89หมายà¹\80ลà¸\82à¹\84à¸à¸\9eี $1) à¸\82à¸à¹\83หà¹\89สà¹\88à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\82à¸à¸\87 {{SITENAME}} ($4) รหัสà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวสำหรัà¸\9aà¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89 "$2" à¸\96ูà¸\81สรà¹\89าà¸\87à¸\82ึà¹\89à¸\99 à¹\81ละà¸\81ำหà¸\99à¸\94à¹\80à¸\9bà¹\87à¸\99 "$3" หาà¸\81เป็นเจตนาของคุณ คุณจำต้องล็อกอินและเลือกรหัสผ่านใหม่ ณ ขณะนี้ รหัสผ่านชั่วคราวของคุณจะหมดอายุใน $5 วัน
+'passwordremindertext' => 'à¸\9cูà¹\89à¹\83à¸\94à¸\9cูà¹\89หà¸\99ึà¹\88à¸\87 (à¸\8bึà¹\88à¸\87à¸à¸²à¸\88à¹\80à¸\9bà¹\87à¸\99à¸\84ุà¸\93 à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eี $1) à¸\82à¸à¹\83หà¹\89สà¹\88à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\82à¸à¸\87 {{SITENAME}} ($4) รหัสà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวสำหรัà¸\9aà¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89 "$2" à¸\96ูà¸\81สรà¹\89าà¸\87à¸\82ึà¹\89à¸\99 à¹\81ละà¸\81ำหà¸\99à¸\94à¹\80à¸\9bà¹\87à¸\99 "$3" หาà¸\81à¸\81ารà¸\82à¸à¸£à¸«à¸±à¸ªà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\99ีà¹\89เป็นเจตนาของคุณ คุณจำต้องล็อกอินและเลือกรหัสผ่านใหม่ ณ ขณะนี้ รหัสผ่านชั่วคราวของคุณจะหมดอายุใน $5 วัน
-หาà¸\81à¸\9aุà¸\84à¸\84ลà¸à¸·à¹\88à¸\99à¸\9aุà¸\84à¸\84ลà¹\83à¸\94ขอรหัสผ่านใหม่ หรือหากคุณจำรหัสผ่านของคุณได้แล้ว และไม่ต้องการเปลี่ยนรหัสผ่านใหม่อีกต่อไป คุณอาจละเลยข้อความนี้และใช้รหัสผ่านเดิมของคุณต่อไป',
+หาà¸\81à¹\80à¸\9bà¹\87à¸\99à¸\9aุà¸\84à¸\84ลà¸à¸·à¹\88à¸\99à¸\97ีà¹\88ขอรหัสผ่านใหม่ หรือหากคุณจำรหัสผ่านของคุณได้แล้ว และไม่ต้องการเปลี่ยนรหัสผ่านใหม่อีกต่อไป คุณอาจละเลยข้อความนี้และใช้รหัสผ่านเดิมของคุณต่อไป',
'noemail' => 'ไม่มีที่อยู่อีเมลบันทึกไว้สำหรับผู้ใช้ "$1"',
'noemailcreate' => 'คุณจำต้องใส่ที่อยู่อีเมลให้ถูกต้อง',
-'passwordsent' => 'รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¹\84à¸\94à¹\89à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bยัà¸\87à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มลà¸\97ีà¹\88ลà¸\87à¸\97ะà¹\80à¸\9aียà¸\99à¹\84วà¹\89à¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89 "$1"
-à¸\81รุà¸\93าลà¹\87à¸à¸\81à¸à¸´à¸\99à¸à¸µà¸\81à¸\84รัà¹\89à¸\87หลัà¸\87à¸\88าà¸\81à¸\84ุà¸\93à¹\84à¸\94à¹\89รัà¸\9aà¸à¸µà¹\80มล',
-'blocked-mailpassword' => 'หมายà¹\80ลà¸\82ไอพีของคุณถูกบล็อกมิให้แก้ไข ฉะนั้น จึงไม่ได้รับอนุญาตให้ใช้ฟังก์ชันขอกู้รหัสผ่านเพื่อป้องกันการกระทำผิด',
-'eauthentsent' => 'à¸à¸µà¹\80มลยืà¸\99ยัà¸\99à¹\84à¸\94à¹\89à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¸\97ีà¹\88à¸à¸µà¹\80มลà¸\97ีà¹\88à¹\84à¸\94à¹\89à¸\96ูà¸\81à¹\80สà¸\99ภà¸\81à¹\88à¸à¸\99à¸\97ีà¹\88à¸à¸µà¹\80มลà¸\88ะà¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¸\97ีà¹\88à¸\8aืà¹\88à¸à¸\9aัà¸\8dà¸\8aีà¸\99ัà¹\89à¸\99 à¸\84ุà¸\93à¸\95à¹\89à¸à¸\87à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\95ามà¸\84ำà¹\81à¸\99ะà¸\99ำà¹\83à¸\99à¸à¸µà¹\80มลà¹\80à¸\9eืà¹\88à¸à¸¢à¸·à¸\99ยัà¸\99วà¹\88าหมายà¹\80ลยà¸\9aัà¸\8dà¸\8aีà¸\99ัà¹\89à¸\99à¹\80à¸\9bà¹\87à¸\99à¸\82à¸à¸\87à¸\84ุà¸\93',
+'passwordsent' => 'รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bยัà¸\87à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มลà¸\97ีà¹\88ลà¸\87à¸\97ะà¹\80à¸\9aียà¸\99à¹\84วà¹\89à¸\82à¸à¸\87 "$1"
+กรุณาล็อกอินอีกครั้งหลังได้รับอีเมล',
+'blocked-mailpassword' => 'à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88ไอพีของคุณถูกบล็อกมิให้แก้ไข ฉะนั้น จึงไม่ได้รับอนุญาตให้ใช้ฟังก์ชันขอกู้รหัสผ่านเพื่อป้องกันการกระทำผิด',
+'eauthentsent' => 'à¸à¸µà¹\80มลยืà¸\99ยัà¸\99à¹\84à¸\94à¹\89à¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มลà¸\97ีà¹\88à¹\80สà¸\99ภà¸\81à¹\88à¸à¸\99à¸\97ีà¹\88à¸à¸µà¹\80มลà¸\88ะà¸\96ูà¸\81สà¹\88à¸\87à¹\84à¸\9bà¸\97ีà¹\88à¸\8aืà¹\88à¸à¸\9aัà¸\8dà¸\8aีà¸\99ัà¹\89à¸\99 à¸\84ุà¸\93à¸\95à¹\89à¸à¸\87à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\95ามà¸\84ำà¹\81à¸\99ะà¸\99ำà¹\83à¸\99à¸à¸µà¹\80มลà¹\80à¸\9eืà¹\88à¸à¸¢à¸·à¸\99ยัà¸\99วà¹\88าà¸\9aัà¸\8dà¸\8aีà¸\99ัà¹\89à¸\99à¹\80à¸\9bà¹\87à¸\99à¸\82à¸à¸\87à¸\84ุà¸\93à¸\88ริà¸\87 à¹\86',
'throttled-mailpassword' => 'ตัวเตือนรหัสผ่านได้ถูกส่งไปแล้วใน $1 ชั่วโมงที่ผ่านมา ตัวเตือนรหัสผ่านนี้จะถูกส่งได้หนึ่งครั้งต่อ $1 ชั่วโมงเท่านั้น เพื่อป้องกันการกระทำผิด',
-'mailerror' => 'à¹\84มà¹\88สามารà¸\96สà¹\88à¸\87à¸à¸µà¹\80มลà¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81 $1',
-'acct_creation_throttle_hit' => 'à¸\9cูà¹\89à¹\80à¸\82à¹\89าà¸\8aมà¸\97ีà¹\88à¹\83à¸\8aà¹\89หมายà¹\80ลà¸\82à¹\84à¸à¸\9eีà¸\82à¸à¸\87à¸\84ุà¸\93à¹\83à¸\99วิà¸\81ิà¸\99ีà¹\89 à¹\84à¸\94à¹\89สรà¹\89าà¸\87à¸\8aืà¹\88à¸à¸\9aัà¸\8dà¸\8aีà¹\81ลà¹\89ว $1 à¸\9aัà¸\8dà¸\8aีà¹\83à¸\99วัà¸\99à¸\97ีà¹\88à¸\9cà¹\88าà¸\99มา à¸\8bึà¹\88à¸\87à¹\80à¸\9bà¹\87à¸\99à¸\88ำà¸\99วà¸\99มาà¸\81à¸\97ีà¹\88สุดที่อนุญาตในช่วงเวลาดังกล่าว
-à¸\88ึà¸\87สà¹\88à¸\87à¸\9cลà¹\83หà¹\89à¸\9cูà¹\89à¹\80à¸\82à¹\89าà¸\8aมà¸\97ีà¹\88à¹\83à¸\8aà¹\89หมายà¹\80ลà¸\82ไอพีนี้ ไม่สามารถสร้างบัญชีได้อีกในขณะนี้',
-'emailauthenticated' => 'อีเมลของคุณได้รับการยืนยันเมื่อวันที่ $2 เวลา $3',
+'mailerror' => 'à¸\82à¹\89à¸à¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\81ารสà¹\88à¸\87à¹\80มล: $1',
+'acct_creation_throttle_hit' => 'à¸\9cูà¹\89à¹\80à¸\82à¹\89าà¸\8aมวิà¸\81ิà¸\99ีà¹\89à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eีà¸\82à¸à¸\87à¸\84ุà¸\93 à¹\84à¸\94à¹\89สรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีà¹\81ลà¹\89ว $1 à¸\9aัà¸\8dà¸\8aีà¹\83à¸\99วัà¸\99à¸\97ีà¹\88à¸\9cà¹\88าà¸\99มา à¸\8bึà¹\88à¸\87à¹\80à¸\9bà¹\87à¸\99à¸\88ำà¸\99วà¸\99สูà¸\87สุดที่อนุญาตในช่วงเวลาดังกล่าว
+à¸\88ึà¸\87สà¹\88à¸\87à¸\9cลà¹\83หà¹\89à¸\9cูà¹\89à¹\80à¸\82à¹\89าà¸\8aมà¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88ไอพีนี้ ไม่สามารถสร้างบัญชีได้อีกในขณะนี้',
+'emailauthenticated' => 'à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มลà¸\82à¸à¸\87à¸\84ุà¸\93à¹\84à¸\94à¹\89รัà¸\9aà¸\81ารยืà¸\99ยัà¸\99à¹\80มืà¹\88à¸à¸§à¸±à¸\99à¸\97ีà¹\88 $2 à¹\80วลา $3',
'emailnotauthenticated' => 'ที่อยู่อีเมลของคุณยังไม่ได้รับการยืนยัน
ไม่มีการส่งอีเมลสำหรับคุณลักษณะใด ๆ ต่อไปนี้',
'noemailprefs' => 'ระบุที่อยู่อีเมลในการตั้งค่าของคุณเพื่อให้คุณลักษณะเหล่านี้ทำงานได้',
-'emailconfirmlink' => 'ยืนยันอีเมลของคุณ',
+'emailconfirmlink' => 'ยืà¸\99ยัà¸\99à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มลà¸\82à¸à¸\87à¸\84ุà¸\93',
'invalidemailaddress' => 'ไม่สามารถรับที่อยู่อีเมลได้ เพราะดูมีรูปแบบไม่ถูกต้อง
โปรดใส่ที่อยู่ให้มีรูปแบบถูกต้อง หรือเว้นช่องนั้น',
'cannotchangeemail' => 'ไม่สามารถเปลี่ยนที่อยู่อีเมลบนวิกินี้',
'createaccount-text' => 'มีบางคนสร้างบัญชีโดยใช้ที่อยู่อีเมลของคุณบน {{SITENAME}} ($4) โดยใช้ชื่อ "$2" และรหัสผ่าน "$3" คุณควรล็อกอินเพื่อเปลี่ยนรหัสผ่านทันที
คุณอาจเพิกเฉยข้อความนี้ หากการสร้างบัญชีนี้เกิดจากความผิดพลาด',
-'usernamehasherror' => 'à¹\83à¸\99à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\95à¹\89à¸à¸\87à¹\84มà¹\88มีà¸\95ัวà¸à¸±à¸\81ษร "#"',
-'login-throttled' => 'à¸\84ุà¸\93à¹\84à¸\94à¹\89พยายามล็อกอินมากครั้งเกินไป
+'usernamehasherror' => 'à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\95à¹\89à¸à¸\87à¹\84มà¹\88มีà¸à¸±à¸\81à¸\82ระà¹\81ฮà¸\8a',
+'login-throttled' => 'à¸\97ีà¹\88à¸\9cà¹\88าà¸\99มาà¸\84ุà¸\93พยายามล็อกอินมากครั้งเกินไป
กรุณารอสักครู่แล้วลองใหม่อีกครั้ง',
'login-abort-generic' => 'การเข้าสู่ระบบของคุณไม่ประสบความสำเร็จ - ล้มเลิกแล้ว',
'loginlanguagelabel' => 'ภาษา: $1',
-'suspicious-userlogout' => 'à¸\84ำà¸\82à¸à¸\82à¸à¸\87à¸\84ุà¸\93à¹\80à¸\9eืà¹\88à¸à¸à¸à¸\81à¸\88าà¸\81ระà¸\9aà¸\9aà¸\96ูà¸\81à¸\9bà¸\8fิà¹\80สà¸\98 à¹\80à¸\9eราะà¸\94ูà¹\80หมืà¸à¸\99วà¹\88าà¸\88ะสà¹\88à¸\87มาà¸\88าà¸\81à¹\80à¸\9aราวà¹\8cà¹\80à¸\8bà¸à¸£à¹\8cหรืà¸à¸\9eรà¹\87à¸à¸\81à¸\8bีà¹\88แคชที่เสีย',
+'suspicious-userlogout' => 'à¸\84ำà¸\82à¸à¸¥à¹\87à¸à¸\81à¹\80à¸à¸²à¸\95à¹\8cà¸\82à¸à¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¸\9bà¸\8fิà¹\80สà¸\98à¹\80à¸\9eราะà¸\94ูà¹\80หมืà¸à¸\99สà¹\88à¸\87มาà¸\88าà¸\81à¹\80à¸\9aราวà¹\8cà¹\80à¸\8bà¸à¸£à¹\8cหรืà¸à¸\9eรà¹\87à¸à¸\81à¸\8bีแคชที่เสีย',
# E-mail sending
-'php-mail-error-unknown' => 'ข้อผิดพลาดไม่ทราบสาเหตุในฟังก์ชัน mail() ของพีเอชพี',
+'php-mail-error-unknown' => 'à¹\80à¸\81ิà¸\94à¸\82à¹\89à¸à¸\9cิà¸\94à¸\9eลาà¸\94à¹\84มà¹\88à¸\97ราà¸\9aสาà¹\80หà¸\95ุà¹\83à¸\99à¸\9fัà¸\87à¸\81à¹\8cà¸\8aัà¸\99 mail() à¸\82à¸à¸\87à¸\9eีà¹\80à¸à¸\8aà¸\9eี',
'user-mail-no-addy' => 'พยายามส่งอีเมลโดยไม่มีที่อยู่อีเมล',
+'user-mail-no-body' => 'พยายามส่งอีเมลที่มีเนื้อหาว่างหรือสั้นอย่างไร้เหตุผล',
# Change password dialog
'resetpass' => 'เปลี่ยนรหัสผ่าน',
'resetpass-submit-loggedin' => 'เปลี่ยนรหัสผ่าน',
'resetpass-submit-cancel' => 'ยกเลิก',
'resetpass-wrong-oldpass' => 'รหัสผ่านชั่วคราวหรือปัจจุบันไม่ถูกต้อง
-à¸\84ุà¸\93à¸à¸²à¸\88à¹\80à¸\9bลีà¹\88ยà¸\99รหัสà¸\9cà¹\88าà¸\99à¸\82à¸à¸\87à¸\84ุà¸\93à¹\84à¸\9bà¹\81ลà¹\89ว หรืà¸à¸£à¹\89à¸à¸\87à¸\82à¸à¸£à¸«à¸±à¸ªà¸\9cà¹\88าà¸\99à¸\8aัà¹\88วà¸\84ราวà¹\83หมà¹\88à¹\81ลà¹\89ว',
+คุณอาจเปลี่ยนรหัสผ่านของคุณไปแล้ว หรือขอรหัสผ่านชั่วคราวใหม่แล้ว',
'resetpass-temp-password' => 'รหัสผ่านชั่วคราว:',
# Special:PasswordReset
'passwordreset' => 'ตั้งรหัสผ่านใหม่',
-'passwordreset-text' => 'à¸\81รà¸à¸\81à¹\81à¸\9aà¸\9aà¸\99ีà¹\89à¹\80à¸\9eืà¹\88à¸à¸£à¸±à¸\9aà¸\95ัวà¹\80à¸\95ืà¸à¸\99à¸à¸µà¹\80มลà¸\82à¸à¸\87รายละà¹\80à¸à¸µà¸¢à¸\94à¸\9aัà¸\8dà¸\8aีà¸\82à¸à¸\87à¸\84ุà¸\93',
+'passwordreset-text' => 'กรอกแบบนี้เพื่อรับตัวเตือนอีเมลรายละเอียดบัญชีของคุณ',
'passwordreset-legend' => 'เปลี่ยนรหัสผ่าน',
'passwordreset-disabled' => 'การตั้งรหัสผ่านใหม่ปิดใช้งานบนวิกินี้',
'passwordreset-username' => 'ชื่อผู้ใช้:',
'passwordreset-domain' => 'โดเมน:',
'passwordreset-email' => 'ที่อยู่อีเมล:',
'passwordreset-emailtitle' => 'รายละเอียดบัญชีบน {{SITENAME}}',
+'passwordreset-emailtext-ip' => 'ใครบางคน (ซึ่งอาจเป็นคุณ ที่ใช้เลขที่อยู่ไอพี $1) ขอตัวเตือนรายละเอียดบัญชีของคุณบน {{SITENAME}} ($4) บัญชีผู้ใช้ดังกล่าวเกี่ยวข้องกับที่อยู่อีเมลนี้:
+
+$2
+
+{{PLURAL:$3|รหัสผ่านชั่วคราวนี้|รหัสผ่านชั่วคราวเหล่านี้}}จะหมดอายุใน $5 วัน
+ตอนนี้คุณควรล็อกอินและเลือกรหัสผ่านใหม่ หากบุคคลอื่นขอตัวเตือนรายละเอียดบัญชี หรือคุณจำรหัสผ่านเดิมของคุณได้แล้ว และคุณไม่ต้องการเปลี่ยนรหัสผ่านอีกต่อไป คุณอาจละเลยข้อความนี้และใช้รหัสผ่านเก่าของคุณต่อไป',
+'passwordreset-emailtext-user' => 'ผู้ใช้ $1 ขอตัวเตือนรายละเอียดบัญชีของคุณบน {{SITENAME}} ($4) {{PLURAL:$3||}}บัญชีผู้ใช้ดังกล่าวเกี่ยวข้องกับที่อยู่อีเมลนี้:
+
+$2
+
+{{PLURAL:$3|รหัสผ่านชั่วคราวนี้|รหัสผ่านชั่วคราวเหล่านี้}}จะหมดอายุใน $5 วัน
+ตอนนี้คุณควรล็อกอินและเลือกรหัสผ่านใหม่ หากบุคคลอื่นขอตัวเตือนรายละเอียดบัญชี หรือคุณจำรหัสผ่านเดิมของคุณได้แล้ว และคุณไม่ต้องการเปลี่ยนรหัสผ่านอีกต่อไป คุณอาจละเลยข้อความนี้และใช้รหัสผ่านเก่าของคุณต่อไป',
'passwordreset-emailelement' => 'ชื่อผู้ใช้: $1
รหัสผ่านชั่วคราว: $2',
'passwordreset-emailsent' => 'อีเมลแจ้งเตือนได้ถูกส่งไปแล้ว',
+'passwordreset-emailsent-capture' => 'อีเมลแจ้งเตือนได้ถูกส่งไปแล้ว ซึ่งแสดงด้านล่าง',
+'passwordreset-emailerror-capture' => 'อีเมลแจ้งเตือนถูกสร้างขึ้นแล้ว ซึ่งแสดงข้างล่าง แต่การส่งไปยังผู้ใช้ล้มเหลว: $1',
# Special:ChangeEmail
'changeemail' => 'เปลี่ยนที่อยู่อีเมล',
'showpreview' => 'แสดงตัวอย่าง',
'showlivepreview' => 'แสดงตัวอย่างทันที',
'showdiff' => 'แสดงความเปลี่ยนแปลง',
-'anoneditwarning' => "'''คำเตือน:''' คุณมิได้ล็อกอิน ที่อยู่ไอพีของคุณจะถูกบันทึกไว้ในประวัติการแก้ไขของหน้านี้",
-'anonpreviewwarning' => "'''คุณมิได้ล็อกอิน การบันทึกจะเก็บที่อยู่ไอพีของคุณในประวัติการแก้ไขของหน้านี้'''",
+'anoneditwarning' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99:''' à¸\84ุà¸\93มิà¹\84à¸\94à¹\89ลà¹\87à¸à¸\81à¸à¸´à¸\99 à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eีà¸\82à¸à¸\87à¸\84ุà¸\93à¸\88ะà¸\96ูà¸\81à¸\9aัà¸\99à¸\97ึà¸\81à¹\84วà¹\89à¹\83à¸\99à¸\9bระวัà¸\95ิà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89",
+'anonpreviewwarning' => "'''à¸\84ุà¸\93มิà¹\84à¸\94à¹\89ลà¹\87à¸à¸\81à¸à¸´à¸\99 à¸\81ารà¸\9aัà¸\99à¸\97ึà¸\81à¸\88ะà¹\80à¸\81à¹\87à¸\9aà¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eีà¸\82à¸à¸\87à¸\84ุà¸\93à¹\83à¸\99à¸\9bระวัà¸\95ิà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89'''",
'missingsummary' => "'''อย่าลืม:''' คุณยังไม่ได้ระบุคำอธิบายการแก้ไข ถ้าคุณกด \"บันทึก\" อีกครั้ง การแก้ไขของคุณจะถูกบันทึกโดยไม่มีคำอธิบายการแก้ไข",
'missingcommenttext' => 'กรุณาใส่ความเห็นด้านล่าง',
'missingcommentheader' => "'''ประกาศเตือน:''' คุณยังไม่ได้ใส่หัวข้อ/จ่าหัวสำหรับความเห็นนี้ ถ้าคุณกด \"{{int:savearticle}}\" อีกครั้ง การแก้ไขของคุณจะถูกบันทึกโดยไม่มีหัวข้อ",
'summary-preview' => 'ตัวอย่างคำอธิบายการแก้ไข:',
'subject-preview' => 'ตัวอย่างหัวข้อ:',
-'blockedtitle' => 'ผู้ใช้ถูกบล็อก',
-'blockedtext' => "'''à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89หรืà¸à¸«à¸¡à¸²à¸¢à¹\80ลà¸\82ไอพีของคุณถูกบล็อก'''
+'blockedtitle' => 'ผู้ใช้ถูกบล็อกอยู่',
+'blockedtext' => "'''à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89หรืà¸à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88ไอพีของคุณถูกบล็อก'''
การบล็อกนี้ดำเนินการโดย $1
-à¸\8bึà¹\88à¸\87ระà¸\9aุà¹\80หà¸\95ุà¸\9cลà¹\84วà¹\89วà¹\88า ''$2''
+ซึ่งระบุเหตุผลว่า ''$2''
* เริ่มการบล็อก: $8
* หมดเขตการบล็อก: $6
* ผู้ถูกบล็อก: $7
คุณสามารถติดต่อ $1 หรือ[[{{MediaWiki:Grouppage-sysop}}|ผู้ดูแลระบบ]]คนอื่นเพื่ออภิปรายการบล็อกนี้ได้
-คุณไม่สามารถใช้ 'ส่งอีเมลหาผู้ใช้รายนี้ได้' จนกว่าจะระบุที่อยู่อีเมลให้ถูกต้องใน[[Special:Preferences|การตั้งค่าบัญชี]]ของคุณ และคุณมิได้ถูกบล็อกไม่ให้ใช้ความสามารถนี้
+คุณไม่สามารถใช้คุณลักษณะ 'ส่งอีเมลหาผู้ใช้รายนี้ได้' จนกว่าจะระบุที่อยู่อีเมลให้ถูกต้องใน[[Special:Preferences|การตั้งค่าบัญชี]]ของคุณ และคุณมิได้ถูกบล็อกไม่ให้ใช้ความสามารถนี้
เลขที่อยู่ไอพีปัจจุบันของคุณคือ $3 และหมายเลขการบล็อกคือ #$5
โปรดแสดงรายละเอียดข้างต้นทั้งหมดนี้ในการอภิปรายเกี่ยวกับการบล็อกของคุณด้วย",
-'autoblockedtext' => "เลขที่อยู่ไอพีของคุณถูกบล็อกอัตโนมัติ เพราะมีผู้ใช้อื่นมาก่อน ซึ่งถูกบล็อกโดย $1
-à¹\80หà¸\95ุà¸\9cลà¸\97ีà¹\88à¹\83หà¹\89à¹\84วà¹\89à¹\83à¸\99à¸\81ารà¸\9aลà¹\87à¸à¸\81à¸\84ืà¸:
+'autoblockedtext' => "à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eีà¸\82à¸à¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¸\9aลà¹\87à¸à¸\81à¸à¸±à¸\95à¹\82à¸\99มัà¸\95ิ à¹\80à¸\9eราะมีà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸à¸·à¹\88à¸\99à¹\83à¸\8aà¹\89มาà¸\81à¹\88à¸à¸\99 à¸\8bึà¹\88à¸\87à¸\96ูà¸\81à¸\9aลà¹\87à¸à¸\81à¹\82à¸\94ย $1
+à¹\82à¸\94ยระà¸\9aุà¹\80หà¸\95ุà¸\9cลวà¹\88า
:''$2''
* เริ่มการบล็อก: $8
* สิ้นสุดการบล็อก: $6
-* ผู้ถูกบล็อกโดยเจตนา: $7
-
-คุณอาจติดต่อ $1 หรือ[[{{MediaWiki:Grouppage-sysop}}|ผู้ดูแลระบบ]]คนอื่นเพื่อหารือการบล็อกนี้
+* ผู้ถูกบล็อก: $7
คุณสามารถติดต่อ $1 หรือ[[{{MediaWiki:Grouppage-sysop}}|ผู้ดูแลระบบ]]คนอื่นเพื่อหารือการบล็อกนี้
-คุณไม่สามารถใช้คุณลักษณะ 'ส่งอีเมลหาผู้ใช้รายนี้ได้' จนกว่าจะระบุที่อยู่อีเมลที่ถูกต้องใน[[Special:Preferences|การตั้งค่าบัญชี]]ของคุณ และคุณมิได้ถูกบล็อกไม่ให้
+คุณไม่สามารถใช้คุณลักษณะ 'ส่งอีเมลหาผู้ใช้รายนี้ได้' จนกว่าจะระบุที่อยู่อีเมลที่ถูกต้องใน[[Special:Preferences|การตั้งค่าบัญชี]]ของคุณ และคุณมิได้ถูกบล็อกไม่ให้ใช้
เลขที่อยู่ไอพีปัจจุบันของคุณคือ $3 และหมายเลขการบล็อกคือ #$5
โปรดรวมรายละเอียดข้างต้นทั้งหมดในการสอบถามใด ๆ",
'blockednoreason' => 'ไม่ได้ให้เหตุผลไว้',
-'whitelistedittext' => 'à¸\84ุà¸\93à¸\95à¹\89à¸à¸\87$1à¹\80à¸\9eืà¹\88à¸à¸\97ำà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89า',
+'whitelistedittext' => 'คุณต้อง$1เพื่อแก้ไขหน้า',
'confirmedittext' => 'คุณต้องยืนยันที่อยู่อีเมลของคุณก่อนแก้ไขหน้า โปรดกำหนดที่อยู่อีเมลของคุณและทำให้ถูกต้องผ่าน[[Special:Preferences|การตั้งค่าผู้ใช้]]',
-'nosuchsectiontitle' => 'à¹\84มà¹\88à¸\9eà¸\9aหัวà¸\82à¹\89à¸à¸¢à¹\88à¸à¸¢',
-'nosuchsectiontext' => 'à¸\84ุà¸\93à¸\9eยายามà¹\81à¸\81à¹\89à¹\84à¸\82à¸\95à¸à¸\99à¸\97ีà¹\88à¹\84มà¹\88มีà¸à¸¢à¸¹à¹\88 à¸\95à¸นดังกล่าวอาจถูกย้ายหรือลบขณะที่คุณดูหน้าอยู่',
+'nosuchsectiontitle' => 'à¹\84มà¹\88à¸\9eà¸\9aสà¹\88วà¸\99',
+'nosuchsectiontext' => 'à¸\84ุà¸\93à¸\9eยายามà¹\81à¸\81à¹\89à¹\84à¸\82สà¹\88วà¸\99à¸\97ีà¹\88à¹\84มà¹\88มีà¸à¸¢à¸¹à¹\88 สà¹\88วนดังกล่าวอาจถูกย้ายหรือลบขณะที่คุณดูหน้าอยู่',
'loginreqtitle' => 'จำเป็นต้องล็อกอิน',
'loginreqlink' => 'ล็อกอิน',
'loginreqpagetext' => 'คุณต้อง$1เพื่อดูหน้าอื่น',
'newarticle' => '(ใหม่)',
'newarticletext' => "คุณตามลิงก์ไปยังหน้าที่ยังไม่มีในขณะนี้
ในการสร้างหน้า เริ่มพิมพ์ในกล่องด้านล่าง (ดูข้อมูลเพิ่มเติมใน[[{{MediaWiki:Helppage}}|หน้าคำอธิบาย]])
-à¸\96à¹\89าà¸\84ุà¸\93มาà¹\82à¸\94ยà¸à¸¸à¸\9aัà¸\95ิà¹\80หà¸\95ุ à¹\83หà¹\89à¸\81à¸\94'''à¸\96à¸à¸¢à¸«à¸¥à¸±à¸\87''' (back) à¸\97ีà¹\88เบราว์เซอร์",
-'anontalkpagetext' => "----''หà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยสำหรัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\99ิรà¸\99าม à¸\8bึà¹\88à¸\87ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89สรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89
-à¹\82à¸\94ยà¸\97าà¸\87à¹\80ราà¸\88ำà¹\80à¸\9bà¹\87à¸\99à¸\95à¹\89à¸à¸\87ระà¸\9aุà¸\95ัวà¸\95à¸\99à¸\9cà¹\88าà¸\99à¸\97าà¸\87หมายà¹\80ลà¸\82à¹\84à¸à¸\9eี
-à¸\8bึà¹\88à¸\87หมายà¹\80ลà¸\82à¹\84à¸à¸\9eีà¸\99ีà¹\89à¸à¸²à¸\88à¸\96ูà¸\81à¹\83à¸\8aà¹\89รà¹\88วมà¸\81ัà¸\99à¹\82à¸\94ยà¸\9cูà¹\89à¹\83à¸\8aà¹\89หลายคน
+à¸\96à¹\89าà¸\84ุà¸\93à¹\80à¸\82à¹\89ามาหà¸\99à¹\89าà¸\99ีà¹\89à¹\82à¸\94ยà¸\9cิà¸\94à¸\9eลาà¸\94 à¹\83หà¹\89à¸\81à¸\94à¸\9bุà¹\88ม'''à¸\96à¸à¸¢à¸«à¸¥à¸±à¸\87''' (back) à¸\82à¸à¸\87เบราว์เซอร์",
+'anontalkpagetext' => "----''หà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99หà¸\99à¹\89าà¸\84ุยà¸\81ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89สำหรัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\99ิรà¸\99ามà¸\8bึà¹\88à¸\87ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89สรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีหรืà¸à¹\84มà¹\88à¹\84à¸\94à¹\89ลà¹\87à¸à¸\81à¸à¸´à¸\99
+à¸\94ัà¸\87à¸\99ัà¹\89à¸\99à¹\80ราà¸\88ึà¸\87ระà¸\9aุà¸\95ัวà¸\95à¸\99à¹\82à¸\94ยà¹\83à¸\8aà¹\89à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eีà¹\81à¸\97à¸\99
+à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eีà¸\99ีà¹\89à¸à¸²à¸\88มีà¸\9cูà¹\89à¹\83à¸\8aà¹\89รà¹\88วมà¸\81ัà¸\99หลายคน
ถ้าคุณเป็นผู้ใช้นิรนาม และรู้สึกว่าความเห็นที่คุณได้รับไม่เกี่ยวข้องกับคุณแต่อย่างใด กรุณา[[Special:UserLogin/signup|สร้างบัญชีผู้ใช้]]หรือ[[Special:UserLogin|ล็อกอิน]] เพื่อป้องกันการสับสนกับผู้ใช้นิรนามรายอื่น''",
-'noarticletext' => 'ขณะนี้ไม่มีเนื้อหาในหน้านี้
-คุณสามารถ [[Special:Search/{{PAGENAME}}|ค้นหาชื่อหน้านี้]]ในหน้าอื่น
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ค้นหาปูมที่เกี่ยวข้อง] หรือ[{{fullurl:{{FULLPAGENAME}}|action=edit}} แก้ไขหน้านี้]</span>',
-'noarticletext-nopermission' => 'ปัจจุบันไม่มีข้อความในหน้านี้
-คุณสามารถ[[Special:Search/{{PAGENAME}}|ค้นหาชื่อบทความนี้]]ในหน้าอื่น หรือ<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ค้นหาปูมที่เกี่ยวข้อง]</span> แต่คุณไม่มีสิทธิ์สร้างหน้านี้',
+'noarticletext' => 'ปัจจุบันไม่มีเนื้อหาในหน้านี้
+คุณสามารถ[[Special:Search/{{PAGENAME}}|ค้นหาชื่อหน้านี้]]ในหน้าอื่น หรือ<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ค้นหาปูมที่เกี่ยวข้อง] หรือ[{{fullurl:{{FULLPAGENAME}}|action=edit}} แก้ไขหน้านี้]</span>',
+'noarticletext-nopermission' => 'ปัจจุบันไม่มีเนื้อหาในหน้านี้
+คุณสามารถ[[Special:Search/{{PAGENAME}}|ค้นหาชื่อหน้านี้]]ในหน้าอื่น หรือ<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ค้นหาปูมที่เกี่ยวข้อง]</span> แต่คุณไม่มีสิทธิสร้างหน้านี้',
+'missing-revision' => 'ไม่มีรุ่น #$1 ของหน้าชื่อ "{{PAGENAME}}"
+
+โดยปกติเกิดจากการเข้าลิงก์ประวัติเก่าของหน้าที่ถูกลบไปแล้ว
+ดูรายละเอียดได้ที่[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]',
'userpage-userdoesnotexist' => 'บัญชีผู้ใช้ "<nowiki>$1</nowiki>" มิได้ลงทะเบียน กรุณาตรวจสอบก่อนว่าคุณต้องการสร้างหรือแก้ไขหน้านี้',
'userpage-userdoesnotexist-view' => 'บัญชีผู้ใช้ "$1" มิได้ลงทะเบียน',
'blocked-notice-logextract' => 'ปัจจุบันเลขที่อยู่ไอพีนี้ถูกบล็อก
-รายการบล็อกล่าสุดแสดงด้านล่างนี้เพื่อการอ้างอิง:',
-'clearyourcache' => "'''หมายเหตุ:''' หลังจากบันทึกแล้ว คุณอาจจะต้องล้างแคชเว็บเบราว์เซอร์ของคุณเพื่อดูการเปลี่ยนแปลง
-* '''ไฟร์ฟอกซ์ / ซาฟารี:''' กดปุ่ม ''Shift'' ค้างไว้ขณะคลิก ''Reload'' หรือกดปุ่ม ''Ctrl-F5'' หรือ ''Ctrl-R'' (''⌘-R'' บนแมคอินทอช)
-* '''กูเกิล โครม:''' กดปุ่ม ''Ctrl-Shift-R'' (''⌘-Shift-R'' บนแมคอินทอช)
-* '''อินเทอร์เน็ตเอกซ์พลอเรอร์:''' กดปุ่ม ''Ctrl'' ค้างไว้ขณะคลิก ''Refresh'' หรือกดปุ่ม ''Ctrl-F5''
-* '''คองเคอเรอร์:''' คลิก ''Reload'' หรือกดปุ่ม ''F5''
-* '''โอเปร่า:''' ล้างแคชในเมนู ''Tools → Preferences''",
-'usercssyoucanpreview' => "'''คำแนะนำ:''' กดปุ่ม \"{{int:showpreview}}\" เพื่อทดสอบสไตล์ชีท CSS ก่อนบันทึก",
-'userjsyoucanpreview' => "'''คำแนะนำ:''' กดปุ่ม \"แสดงตัวอย่าง\" เพื่อทดสอบจาวาสคริปต์ใหม่ก่อนบันทึก",
+หน่วยบล็อกล่าสุดแสดงด้านล่างนี้เพื่อการอ้างอิง:',
+'clearyourcache' => "'''หมายเหตุ:''' หลังจากบันทึก คุณอาจต้องล้างแคชเว็บเบราว์เซอร์ของคุณเพื่อดูการเปลี่ยนแปลง
+* '''ไฟร์ฟอกซ์ / ซาฟารี:''' กดปุ่ม ''Shift'' ค้างไว้ขณะคลิก ''Reload'' หรือกด ''Ctrl-F5'' หรือ ''Ctrl-R'' (''⌘-R'' บนแมค)
+* '''กูเกิล โครม:''' กดปุ่ม ''Ctrl-Shift-R'' (''⌘-Shift-R'' บนแมค)
+* '''อินเทอร์เน็ตเอกซ์พลอเรอร์:''' กดปุ่ม ''Ctrl'' ค้างไว้ขณะคลิก ''Refresh'' หรือกด ''Ctrl-F5''
+* '''โอเปร่า:''' ล้างแคชใน ''Tools → Preferences''",
+'usercssyoucanpreview' => "'''คำแนะนำ:''' กดปุ่ม \"{{int:showpreview}}\" เพื่อทดสอบ CSS ใหม่ของคุณก่อนบันทึก",
+'userjsyoucanpreview' => "'''คำแนะนำ:''' กดปุ่ม \"{{int:showpreview}}\" เพื่อทดสอบจาวาสคริปต์ใหม่ของคุณก่อนบันทึก",
'usercsspreview' => "'''อย่าลืมว่าคุณกำลังดูตัวอย่าง CSS ผู้ใช้ของคุณ'''
'''ยังไม่ได้ถูกบันทึก!'''",
'userjspreview' => "'''อย่าลืมว่าคุณกำลังทดสอบ/ดูตัวอย่างจาวาสคริปต์ผู้ใช้ของคุณ'''
'''ยังไม่ถูกบันทึก!'''",
'sitecsspreview' => "'''พึงระลึกว่าคุณกำลังแสดงตัวอย่าง CSS นี้เท่านั้น'''
-'''มัà¸\99ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9aัà¸\99à¸\97ึà¸\81!'''",
+'''ยังไม่ได้ถูกบันทึก!'''",
'sitejspreview' => "'''พึงระลึกว่าคุณกำลังแสดงตัวอย่างโค้ดจาวาสคริปต์นี้เท่านั้น'''
-'''มัà¸\99ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9aัà¸\99à¸\97ึà¸\81!'''",
-'userinvalidcssjstitle' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99:''' à¹\84มà¹\88มีหà¸\99à¹\89าà¸\95า \"\$1\" หà¸\99à¹\89า .css à¹\81ละ .js à¸\97ีà¹\88à¸\9bรัà¸\9aà¹\81à¸\95à¹\88à¸\87à¹\80à¸à¸\87 à¹\83à¸\8aà¹\89à¸\95ัวà¸\9eิมà¸\9eà¹\8cà¹\80ลà¹\87à¸\81à¸\97ัà¹\89à¸\87หมà¸\94 à¹\80à¸\8aà¹\88à¸\99 à¹\83à¸\8aà¹\89 {{ns:user}}:Foo/vector.css à¹\81à¸\97à¸\99à¸\97ีà¹\88à¸\88ะà¹\80à¸\9bà¹\87à¸\99 {{ns:user}}:Foo/Vector.css",
-'updated' => '(à¸\9bรัà¸\9aà¸\9bรุà¸\87à¹\81ลà¹\89ว)',
-'note' => "'''à¸\84ำà¹\81à¸\99ะà¸\99ำ:'''",
-'previewnote' => "'''พึงระลึกว่านี่เป็นเพียงตัวอย่างเท่านั้น'''
+'''ยังไม่ได้ถูกบันทึก!'''",
+'userinvalidcssjstitle' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99:''' à¹\84มà¹\88มีหà¸\99à¹\89าà¸\95า \"\$1\" หà¸\99à¹\89า .css à¹\81ละ .js à¸\97ีà¹\88à¸\9bรัà¸\9aà¹\81à¸\95à¹\88à¸\87à¹\80à¸à¸\87 à¹\83à¸\8aà¹\89à¸\95ัวà¹\80ลà¹\87à¸\81à¸\97ัà¹\89à¸\87หมà¸\94 à¹\80à¸\8aà¹\88à¸\99 {{ns:user}}:Foo/vector.css มิà¹\83à¸\8aà¹\88 {{ns:user}}:Foo/Vector.css",
+'updated' => '(ปรับแล้ว)',
+'note' => "'''หมายà¹\80หà¸\95ุ:'''",
+'previewnote' => "'''à¸\9eึà¸\87ระลึà¸\81วà¹\88าà¸\99ีà¹\88à¹\80à¸\9bà¹\87à¸\99à¹\80à¸\9eียà¸\87à¸\81ารà¹\81สà¸\94à¸\87à¸\95ัวà¸à¸¢à¹\88าà¸\87à¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99'''
การเปลี่ยนแปลงของคุณยังไม่ได้ถูกบันทึก!",
'continue-editing' => 'ไปยังพื้นที่แก้ไข',
-'previewconflict' => 'à¸\81ารà¹\81สà¸\94à¸\87à¸\9cลสà¹\88วà¸\99à¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99à¸\95ัวà¸à¸¢à¹\88าà¸\87à¸\82à¸à¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\94à¹\89าà¸\99à¸\9aà¸\99 à¸\96à¹\89าà¸\81à¸\94à¸\9aัà¸\99à¸\97ึà¸\81à¸\81ารà¹\81สà¸\94à¸\87à¸\9cลà¸\88ะà¹\81สà¸\94à¸\87à¹\83à¸\99ลัà¸\81ษà¸\93ะà¸\99ีà¹\89à¸\97ัà¸\99à¸\97ี',
-'session_fail_preview' => "'''à¸\82à¸à¸à¸ ัย à¹\84มà¹\88สามารà¸\96à¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\95à¹\88à¸à¹\84à¸\94à¹\89 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\80à¸\8aืà¹\88à¸à¸¡à¸\95à¹\88à¸à¸ªà¸¹à¸\8dหาย
-à¹\83หà¹\89à¸\97à¸\94ลà¸à¸\87à¹\81à¸\81à¹\89à¹\84à¸\82à¸à¸µà¸\81à¸\84รัà¹\89à¸\87หà¸\99ึà¹\88à¸\87 à¸\96à¹\89ายัà¸\87à¹\84มà¹\88สามารà¸\96à¸\97ำà¹\84à¸\94à¹\89 à¹\83หà¹\89ลà¸à¸\87ลà¹\87à¸à¸\81à¹\80à¸à¸²à¸\95à¹\8cà¹\81ละลà¹\87à¸à¸\81à¸à¸´à¸\99à¸\81ลัà¸\9aมาà¸à¸µà¸\81à¸\84รัà¹\89à¸\87'''",
-'session_fail_preview_html' => "'''à¸\82à¸à¸à¸ ัย à¹\84มà¹\88สามารà¸\96à¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\95à¹\88à¸à¹\84à¸\94à¹\89 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\80à¸\8aืà¹\88à¸à¸¡à¸\95à¹\88à¸สูญหาย'''
+'previewconflict' => 'à¸\81ารà¹\81สà¸\94à¸\87à¸\95ัวà¸à¸¢à¹\88าà¸\87à¸\99ีà¹\89สะà¸\97à¹\89à¸à¸\99à¸\82à¹\89à¸à¸\84วามà¹\83à¸\99à¸\9eืà¹\89à¸\99à¸\97ีà¹\88à¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¹\89à¸à¸\84วามสà¹\88วà¸\99à¸\9aà¸\99à¸\8bึà¹\88à¸\87à¸\88ะà¸\9bราà¸\81à¸\8fหาà¸\81à¸\84ุà¸\93à¹\80ลืà¸à¸\81à¸\9aัà¸\99à¸\97ึà¸\81',
+'session_fail_preview' => "'''à¸\82à¸à¸à¸ ัย à¹\84มà¹\88สามารà¸\96à¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\95à¹\88à¸à¹\84à¸\94à¹\89 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\8aà¹\88วà¸\87à¹\80วลาสืà¹\88à¸à¸ªà¸²à¸£à¸ªà¸¹à¸\8dหาย'''
+à¹\82à¸\9bรà¸\94à¸\97à¸\94ลà¸à¸\87à¸à¸µà¸\81à¸\84รัà¹\89à¸\87 หาà¸\81ยัà¸\87à¹\80สียà¸à¸¢à¸¹à¹\88 ลà¸à¸\87[[Special:UserLogout|ลà¹\87à¸à¸\81à¹\80à¸à¸²à¸\95à¹\8c]]à¹\81ละลà¹\87à¸à¸\81à¸à¸´à¸\99à¸\81ลัà¸\9aมา",
+'session_fail_preview_html' => "'''à¸\82à¸à¸à¸ ัย à¹\84มà¹\88สามารà¸\96à¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\95à¹\88à¸à¹\84à¸\94à¹\89 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\8aà¹\88วà¸\87à¹\80วลาสืà¹\88à¸à¸ªà¸²à¸£สูญหาย'''
-''à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81 {{SITENAME}} à¹\83à¸\8aà¹\89รูà¸\9bà¹\81à¸\9aà¸\9aà¹\80à¸à¸\8aà¸\97ีà¹\80à¸à¹\87มà¹\81à¸à¸¥à¸¥à¹\89วà¸\99 à¸\81ารà¹\81สà¸\94à¸\87à¸\95ัวà¸à¸¢à¹\88าà¸\87à¸\88ะà¸\96ูà¸\81à¸\8bà¹\88à¸à¸\99à¹\84วà¹\89à¹\80à¸\9eืà¹\88à¸à¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99à¸\81ารà¹\82à¸\95มตีด้วยจาวาสคริปต์''
+''à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81 {{SITENAME}} à¹\80à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¹\80à¸à¸\8aà¸\97ีà¹\80à¸à¹\87มà¹\81à¸à¸¥à¸¥à¹\89วà¸\99 à¸\81ารà¹\81สà¸\94à¸\87à¸\95ัวà¸à¸¢à¹\88าà¸\87à¸\88ะà¸\96ูà¸\81à¸\8bà¹\88à¸à¸\99à¹\84วà¹\89à¹\80à¸\9eืà¹\88à¸à¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99à¸\81ารà¹\82à¸\88มตีด้วยจาวาสคริปต์''
-'''à¸\96à¹\89าà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\84รัà¹\89à¸\87à¸\99ีà¹\89à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87 à¹\83หà¹\89à¸\97à¸\94ลà¸à¸\87à¹\81à¸\81à¹\89à¹\84à¸\82à¸à¸µà¸\81à¸\84รัà¹\89à¸\87หà¸\99ึà¹\88à¸\87 à¸\96à¹\89ายัà¸\87à¹\84มà¹\88สามารà¸\96à¸\97ำà¹\84à¸\94à¹\89 à¹\83หà¹\89ลà¸à¸\87[[Special:UserLogout|ลà¹\87à¸à¸\81à¹\80à¸à¸²à¸\95à¹\8c]]à¹\81ละลà¹\87à¸à¸\81à¸à¸´à¸\99à¸\81ลัà¸\9aมาà¸à¸µà¸\81à¸\84รัà¹\89à¸\87'''",
-'token_suffix_mismatch' => "'''à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9bà¸\8fิà¹\80สà¸\98 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¹\80à¸\84รืà¹\88à¸à¸\87ลูà¸\81à¸\82à¹\88ายà¸\97ีà¹\88à¸\84ุà¸\93à¹\83à¸\8aà¹\89à¸à¸¢à¸¹à¹\88à¹\84à¸\94à¹\89à¸\97ำลายรูà¸\9bà¹\81à¸\9aà¸\9aà¹\80à¸\84รืà¹\88à¸à¸\87หมายวรรà¸\84à¸\95à¸à¸\99à¹\83à¸\99à¸\95ราสารà¸\9bระà¸\88ำà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82 (edit token)'''
-ระà¸\9aà¸\9aà¹\84มà¹\88รัà¸\9aà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93à¹\80à¸\9eืà¹\88à¸à¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99à¸\84วามà¸\9cิà¸\94à¸\9eลาà¸\94à¸\82à¸à¸\87à¸\82à¹\89à¸à¸¡à¸¹à¸¥
-à¹\83à¸\99à¸\9aาà¸\87à¸\84รัà¹\89à¸\87à¸\9bัà¸\8dหาà¸\99ีà¹\89à¸\88ะà¹\80à¸\81ิà¸\94à¸\82ึà¹\89à¸\99à¸\96à¹\89าคุณใช้บริการเว็บพร็อกซีนิรนามที่มีบั๊ก",
+'''หาà¸\81à¸\99ีà¹\88à¹\80à¸\9bà¹\87à¸\99à¸\84วามà¸\9eยายามà¹\81à¸\81à¹\89à¹\84à¸\82à¹\82à¸\94ยà¸\8aà¸à¸\9a à¹\82à¸\9bรà¸\94ลà¸à¸\87à¸à¸µà¸\81à¸\84รัà¹\89à¸\87หà¸\99ึà¹\88à¸\87''' หาà¸\81ยัà¸\87à¹\80สียà¸à¸¢à¸¹à¹\88 ลà¸à¸\87[[Special:UserLogout|ลà¹\87à¸à¸\81à¹\80à¸à¸²à¸\95à¹\8c]]à¹\81ละลà¹\87à¸à¸\81à¸à¸´à¸\99à¸\81ลัà¸\9aมา",
+'token_suffix_mismatch' => "'''à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¸\9bà¸\8fิà¹\80สà¸\98 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¹\80à¸\84รืà¹\88à¸à¸\87ลูà¸\81à¸\82à¹\88ายà¸\97ีà¹\88à¸\84ุà¸\93à¹\83à¸\8aà¹\89à¸\97ำà¹\83หà¹\89à¸à¸±à¸\81à¸\82ระà¹\80à¸\84รืà¹\88à¸à¸\87หมายวรรà¸\84à¸\95à¸à¸\99à¹\83à¸\99à¸\95ราสารà¸\9bระà¸\88ำà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82 (edit token) à¹\80สีย'''
+à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\99ีà¹\89à¸\96ูà¸\81à¸\9bà¸\8fิà¹\80สà¸\98à¹\80à¸\9eืà¹\88à¸à¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99à¸\81ารวิà¸\9aัà¸\95ิà¸\82à¸à¸\87à¸\82à¹\89à¸à¸\84วามหà¸\99à¹\89า
+à¸\9aาà¸\87à¸\84รัà¹\89à¸\87à¹\80à¸\81ิà¸\94à¸\9bัà¸\8dหาà¸\99ีà¹\89à¸\82ึà¹\89à¸\99à¹\80มืà¹\88à¸คุณใช้บริการเว็บพร็อกซีนิรนามที่มีบั๊ก",
'edit_form_incomplete' => "'''แบบแก้ไขบางส่วนไปไม่ถึงเซิร์ฟเวอร์ ตรวจสอบอีกครั้งว่าการแก้ไขของคุณยังอยู่และลองอีกครั้ง'''",
'editing' => 'กำลังแก้ไข $1',
'creating' => 'กำลังสร้าง $1',
'editingsection' => 'กำลังแก้ไข $1 (เฉพาะส่วน)',
-'editingcomment' => 'à¸\81ำลัà¸\87à¹\81à¸\81à¹\89à¹\84à¸\82 $1 (à¸\95à¸นใหม่)',
+'editingcomment' => 'à¸\81ำลัà¸\87à¹\81à¸\81à¹\89à¹\84à¸\82 $1 (สà¹\88วนใหม่)',
'editconflict' => 'แก้ไขชนกัน: $1',
'explainconflict' => "ใครบางคนได้เปลี่ยนแปลงหน้านี้ตั้งแต่คุณกำลังแก้ไข
พื้นที่ข้อความส่วนบนมีข้อความหน้าที่มีอยู่ในปัจจุบัน
'rev-deleted-comment' => '(คำอธิบายอย่างย่อถูกลบออก)',
'rev-deleted-user' => '(ชื่อผู้ใช้ถูกลบออก)',
'rev-deleted-event' => '(ปฏิบัติการปูมถูกลบออก)',
-'rev-deleted-user-contribs' => '[à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89หรืà¸à¸«à¸¡à¸²à¸¢à¹\80ลà¸\82ไอพีถูกลบแล้ว - การแก้ไขถูกซ่อนจากรายการแก้ไข]',
-'rev-deleted-text-permission' => "รุà¹\88à¸\99à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89'''à¸\96ูà¸\81ลà¸\9a'''
+'rev-deleted-user-contribs' => '[à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89หรืà¸à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88ไอพีถูกลบแล้ว - การแก้ไขถูกซ่อนจากรายการแก้ไข]',
+'rev-deleted-text-permission' => "รุ่นหน้านี้'''ถูกลบ'''
รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]",
-'rev-deleted-text-unhide' => "รุà¹\88à¸\99à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89'''à¸\96ูà¸\81ลà¸\9a'''
+'rev-deleted-text-unhide' => "รุ่นหน้านี้'''ถูกลบ'''
รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]
คุณยังสามารถ[$1 ดูรุ่นนี้]ได้ถ้าคุณต้องการดำเนินต่อ",
-'rev-suppressed-text-unhide' => "รุà¹\88à¸\99à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89'''à¸\96ูà¸\81ยัà¸\9aยัà¹\89à¸\87'''
+'rev-suppressed-text-unhide' => "รุ่นหน้านี้'''ถูกยับยั้ง'''
รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ปูมการยับยั้ง]
คุณยังสามารถ[$1 ดูรุ่นนี้]ได้ถ้าคุณต้องการดำเนินต่อ",
-'rev-deleted-text-view' => "รุà¹\88à¸\99à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89'''à¸\96ูà¸\81ลà¸\9a'''
+'rev-deleted-text-view' => "รุ่นหน้านี้'''ถูกลบ'''
คุณสามารถดูรุ่นนี้ได้ รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]",
-'rev-suppressed-text-view' => "รุà¹\88à¸\99à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89'''à¸\96ูà¸\81ยัà¸\9aยัà¹\89à¸\87'''
+'rev-suppressed-text-view' => "รุ่นหน้านี้'''ถูกยับยั้ง'''
คุณสามารถดูรุ่นนี้ได้ รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ปูมการยับยั้ง]",
-'rev-deleted-no-diff' => "à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¹\80รียà¸\81à¸\94ูà¸\84วามà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลงนี้ เพราะมีบางรุ่น'''ถูกลบ'''
+'rev-deleted-no-diff' => "à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¹\80รียà¸\81à¸\94ูà¸\9cลà¸\95à¹\88างนี้ เพราะมีบางรุ่น'''ถูกลบ'''
รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]",
-'rev-suppressed-no-diff' => "à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¸\94ูà¸\84วามà¹\81à¸\95à¸\81à¸\95à¹\88าà¸\87ระหวà¹\88าà¸\87รุà¹\88à¸\99à¸\97ีà¹\88à¹\80ลืà¸à¸\81à¹\84à¸\94à¹\89 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81มีà¸\84วามà¹\81à¸\95à¸\81à¸\95à¹\88าà¸\87ระหวà¹\88าà¸\87รุà¹\88à¸\99ที่'''ถูกลบ'''",
-'rev-deleted-unhide-diff' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87รายà¸\81ารà¸\84วามà¹\81à¸\95à¸\81ต่างนี้'''ถูกลบ'''
+'rev-suppressed-no-diff' => "à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¸\94ูà¸\9cลà¸\95à¹\88าà¸\87à¸\99ีà¹\89à¹\84à¸\94à¹\89 à¹\80à¸\9eราะมีà¸\9cลà¸\95à¹\88าà¸\87หà¸\99ึà¹\88à¸\87ที่'''ถูกลบ'''",
+'rev-deleted-unhide-diff' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87à¸\9cลต่างนี้'''ถูกลบ'''
รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]
-à¸\84ุà¸\93ยัà¸\87สามารà¸\96[$1 à¸\94ูà¸\84วามà¹\81à¸\95à¸\81ต่างนี้]ได้ถ้าคุณต้องการดำเนินต่อ",
-'rev-suppressed-unhide-diff' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87รายà¸\81ารà¸\84วามà¹\81à¸\95à¸\81ต่างนี้'''ถูกยับยั้ง'''
+à¸\84ุà¸\93ยัà¸\87สามารà¸\96[$1 à¸\94ูà¸\9cลต่างนี้]ได้ถ้าคุณต้องการดำเนินต่อ",
+'rev-suppressed-unhide-diff' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87à¸\9cลต่างนี้'''ถูกยับยั้ง'''
รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ปูมการยับยั้ง]
-à¸\84ุà¸\93ยัà¸\87สามารà¸\96[$1 à¸\94ูà¸\84วามà¹\81à¸\95à¸\81ต่างนี้]ได้ถ้าคุณต้องการดำเนินต่อ",
-'rev-deleted-diff-view' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87รายà¸\81ารà¸\84วามà¹\81à¸\95à¸\81ต่างนี้'''ถูกลบ'''
-à¸\84ุà¸\93สามารà¸\96à¸\94ูà¸\84วามà¹\81à¸\95à¸\81ต่างนี้ได้ รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]",
-'rev-suppressed-diff-view' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87รายà¸\81ารà¸\84วามà¹\81à¸\95à¸\81ต่างนี้'''ถูกยับยั้ง'''
-à¸\84ุà¸\93สามารà¸\96à¸\94ูà¸\84วามà¹\81à¸\95à¸\81ต่างนี้ได้ รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ปูมการยับยั้ง]",
+à¸\84ุà¸\93ยัà¸\87สามารà¸\96[$1 à¸\94ูà¸\9cลต่างนี้]ได้ถ้าคุณต้องการดำเนินต่อ",
+'rev-deleted-diff-view' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87à¸\9cลต่างนี้'''ถูกลบ'''
+à¸\84ุà¸\93สามารà¸\96à¸\94ูà¸\9cลต่างนี้ได้ รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]",
+'rev-suppressed-diff-view' => "รุà¹\88à¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87à¸\9cลต่างนี้'''ถูกยับยั้ง'''
+à¸\84ุà¸\93สามารà¸\96à¸\94ูà¸\9cลต่างนี้ได้ รายละเอียดพบได้ใน[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ปูมการยับยั้ง]",
'rev-delundel' => 'แสดง/ซ่อน',
'rev-showdeleted' => 'แสดง',
'revisiondelete' => 'ลบ/กู้คืนรุ่น',
'revdelete-nooldid-title' => 'ไม่มีรุ่นที่ต้องการ',
'revdelete-nooldid-text' => 'คุณมิได้เจาะจงรุ่นเป้าหมายเพื่อดำเนินการฟังก์ชันนี้ หรือไม่มีรุ่นที่เจาะจง หรือคุณกำลังพยายามซ่อนรุ่นปัจจุบันอย่างใดอย่างหนึ่ง',
'revdelete-nologtype-title' => 'ไม่ได้ระบุประเภทของปูม',
-'revdelete-nologtype-text' => 'à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89à¹\80à¸\88าะà¸\88à¸\87à¸\9bระà¹\80ภà¸\97à¸\82à¸à¸\87à¸\9bูมà¹\80à¸\9eืà¹\88à¸à¸\94ำà¹\80à¸\99ิà¸\99à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\81ารà¸\99ีà¹\89à¸\95à¹\88à¸',
-'revdelete-nologid-title' => 'à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\83à¸\99รายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82ไม่ถูกต้อง',
-'revdelete-nologid-text' => 'à¸\84ุà¸\93มิà¹\84à¸\94à¹\89à¹\80à¸\88าะà¸\88à¸\87รายà¸\81ารà¸\9bูมà¹\80à¸\9bà¹\89าหมายà¹\80à¸\9eืà¹\88à¸à¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\9fัà¸\87à¸\81à¹\8cà¸\8aัà¸\99à¸\99ีà¹\89 หรืà¸à¹\84มà¹\88มีรายà¸\81ารที่เจาะจงอย่างใดอย่างหนึ่ง',
+'revdelete-nologtype-text' => 'à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89à¹\80à¸\88าะà¸\88à¸\87à¸\9bระà¹\80ภà¸\97à¸\82à¸à¸\87à¸\9bูมà¸\97ีà¹\88à¸\88ะà¸\94ำà¹\80à¸\99ิà¸\99à¸\9bà¸\8fิà¸\9aัà¸\95ิà¸\81ารà¸\99ีà¹\89',
+'revdelete-nologid-title' => 'หà¸\99à¹\88วยà¸\9bูมไม่ถูกต้อง',
+'revdelete-nologid-text' => 'à¸\84ุà¸\93มิà¹\84à¸\94à¹\89à¹\80à¸\88าะà¸\88à¸\87รายà¸\81ารà¸\9bูมà¹\80à¸\9bà¹\89าหมายà¹\80à¸\9eืà¹\88à¸à¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\9fัà¸\87à¸\81à¹\8cà¸\8aัà¸\99à¸\99ีà¹\89 หรืà¸à¹\84มà¹\88มีหà¸\99à¹\88วยที่เจาะจงอย่างใดอย่างหนึ่ง',
'revdelete-no-file' => 'ไม่มีไฟล์ที่ระบุ',
'revdelete-show-file-confirm' => 'คุณแน่ใจที่จะดูรุ่นที่ถูกลบของไฟล์ "<nowiki>$1</nowiki>" เมื่อวันที่ $2 เวลา $3 หรือไม่',
'revdelete-show-file-submit' => 'ใช่',
'logdelete-selected' => "'''{{PLURAL:$1|เหตุการณ์ปูมที่เลือก|เหตุการณ์ปูมที่เลือก}} :'''",
'revdelete-text' => "'''รุ่นการปรับปรุงและเหตุการณ์ที่ถูกลบยังปรากฏในประวัติและปูมของหน้า แต่สาธารณะไม่สามารถเข้าถึงเนื้อหาบางส่วนได้'''
ผู้ดูแลระบบคนอื่นบน {{SITENAME}} ยังสามารถเข้าถึงเนื้อหาที่ถูกซ่อน และสามารถกู้คืนอีกครั้งในลักษณะเดิมเช่นนี้ เว้นแต่จะมีการกำหนดการจำกัดเพิ่มเติม",
-'revdelete-confirm' => 'à¸\81รุà¸\93ายืà¸\99ยัà¸\99วà¹\88าà¸\84ุà¸\93มีà¹\80à¸\88à¸\95à¸\99าลà¸\9aà¸\88ริà¸\87 à¹\81ละà¹\80à¸\82à¹\89าà¹\83à¸\88à¸\9cลà¸\81ระà¸\97à¸\9a และกระทำภายใต้[[{{MediaWiki:Policy-url}}|นโยบาย]]',
+'revdelete-confirm' => 'à¸\81รุà¸\93ายืà¸\99ยัà¸\99วà¹\88าà¸\84ุà¸\93มีà¹\80à¸\88à¸\95à¸\99าลà¸\9aà¸\88ริà¸\87 à¹\81ละà¹\80à¸\82à¹\89าà¹\83à¸\88à¸\9cลลัà¸\9eà¸\98à¹\8c และกระทำภายใต้[[{{MediaWiki:Policy-url}}|นโยบาย]]',
'revdelete-suppress-text' => "การระงับควรใช้ '''เฉพาะ''' กรณีต่อไปนี้:
* ข้อมูลที่อาจหมิ่นประมาท
* ข้อมูลส่วนบุคคลที่ไม่เหมาะสม
'revdelete-hide-image' => 'ซ่อนเนื้อหาไฟล์',
'revdelete-hide-name' => 'ซ่อนปฏิบัติการและเป้าหมาย',
'revdelete-hide-comment' => 'ซ่อนคำอธิบายอย่างย่อ',
-'revdelete-hide-user' => 'à¸\8bà¹\88à¸à¸\99à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89/หมายà¹\80ลà¸\82ไอพีผู้เขียน',
+'revdelete-hide-user' => 'à¸\8bà¹\88à¸à¸\99à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89/à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88ไอพีผู้เขียน',
'revdelete-hide-restricted' => 'ระงับข้อมูลจากผู้ดูแลระบบเช่นเดียวกับผู้ใช้อื่น',
'revdelete-radio-same' => '(ไม่เปลี่ยนแปลง)',
'revdelete-radio-set' => 'ใช่',
'revdelete-show-no-access' => 'เกิดความผิดพลาดในการแสดงรุ่นเมื่อวันที่ $2 เวลา $1: ฉบับปรับปรุงนี้ถูกกำหนดให้ "ถูกจำกัด"
คุณไม่มีสิทธิเข้าถึงรุ่นดังกล่าว',
'revdelete-modify-no-access' => 'เกิดความผิดพลาดในการแก้ไขรุ่นการแก้ไขเมื่อวันที่ $2 เวลา $1: รุ่นการแก้ไขนี้ถูกกำหนดให้ "ถูกจำกัด"
-à¸\84ุà¸\93à¹\84มà¹\88มีสิà¸\97à¸\98ิà¹\8cà¹\80à¸\82à¹\89าà¸\96ึà¸\87รุà¹\88à¸\99à¸\94ัà¸\87à¸\81ลà¹\88าว',
-'revdelete-modify-missing' => 'à¹\80à¸\81ิà¸\94à¸\84วามà¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\89à¸\9aัà¸\9aà¸\9bรัà¸\87à¸\9bรุà¸\87หมายเลข $1: รายการนี้สูญหายจากฐานข้อมูล!',
-'revdelete-no-change' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99:''' รุà¹\88à¸\99à¹\80มืà¹\88à¸à¸§à¸±à¸\99à¸\97ีà¹\88 $2 à¹\80วลา $1 มีà¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¸\97ัศà¸\99วิสัยà¸\95ามà¸\97ีà¹\88à¸\82à¸à¸à¸¢à¸¹à¹\88à¹\81ลà¹\89ว",
-'revdelete-concurrent-change' => 'à¹\80à¸\81ิà¸\94à¸\84วามà¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82รุà¹\88à¸\99à¹\80มืà¹\88à¸à¸§à¸±à¸\99à¸\97ีà¹\88 $2 à¹\80วลา $1: มีผู้อื่นเปลี่ยนสถานะของรุ่นขณะที่คุณพยายามแก้ไข
+คุณไม่มีสิทธิเข้าถึงรุ่นดังกล่าว',
+'revdelete-modify-missing' => 'à¹\80à¸\81ิà¸\94à¸\82à¹\89à¸à¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82รุà¹\88à¸\99หมายเลข $1: รายการนี้สูญหายจากฐานข้อมูล!',
+'revdelete-no-change' => "'''คำเตือน:''' รุ่นเมื่อวันที่ $2 เวลา $1 ตั้งค่าทัศนวิสัยตามที่ขออยู่แล้ว",
+'revdelete-concurrent-change' => 'à¹\80à¸\81ิà¸\94à¸\82à¹\89à¸à¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82รุà¹\88à¸\99à¹\80มืà¹\88à¸à¸§à¸±à¸\99à¸\97ีà¹\88 $2 à¹\80วลา $1: à¸\94ูà¹\80หมืà¸à¸\99มีผู้อื่นเปลี่ยนสถานะของรุ่นขณะที่คุณพยายามแก้ไข
กรุณาตรวจสอบปูม',
-'revdelete-only-restricted' => 'à¹\80à¸\81ิà¸\94à¸\84วามผิดพลาดในการซ่อนรุ่นเมื่อวันที่ $2 เวลา $1: คุณไม่สามารถยับยั้งผู้ดูแลระบบมิให้ดูรุ่นนี้ได้โดยไม่เลือกตัวเลือกทัศนวิสัยอื่นด้วย',
+'revdelete-only-restricted' => 'à¹\80à¸\81ิà¸\94à¸\82à¹\89à¸ผิดพลาดในการซ่อนรุ่นเมื่อวันที่ $2 เวลา $1: คุณไม่สามารถยับยั้งผู้ดูแลระบบมิให้ดูรุ่นนี้ได้โดยไม่เลือกตัวเลือกทัศนวิสัยอื่นด้วย',
'revdelete-reason-dropdown' => '*เหตุผลการลบทั่วไป
** ละเมิดลิขสิทธิ์
** ความเห็นไม่เหมาะสมหรือข้อมูลส่วนบุคคล
# History merging
'mergehistory' => 'ประวัติการรวมหน้า',
-'mergehistory-header' => 'หà¸\99à¹\89าà¸\99ีà¹\89à¹\84วà¹\89à¹\83หà¹\89à¸\84ุà¸\93à¹\83à¸\8aà¹\89รวมรุà¹\88à¸\99à¸\95à¹\88าà¸\87à¹\86 à¹\83à¸\99à¸\9bระวัà¸\95ิà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87หà¸\99à¹\89าà¸\95à¹\89à¸\99à¸\97าà¸\87 à¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¹\83หมà¹\88.
-à¸\81à¹\88à¸à¸\99à¸\94ำà¹\80à¸\99ิà¸\99à¸\81าร à¸\84วรà¹\83หà¹\89à¹\81à¸\99à¹\88à¹\83à¸\88à¸\81à¹\88à¸à¸\99วà¹\88าà¸\81ารà¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\99ีà¹\89à¸\88ะà¹\84มà¹\88à¸\97ำà¹\83หà¹\89à¸\84วามà¸\84วามà¸\95à¹\88à¸à¹\80à¸\99ืà¹\88à¸à¸\87à¸\82à¸à¸\87à¸\9bระวัà¸\95ิหà¸\99à¹\89าà¹\80à¸\81à¹\88าà¹\86 à¹\80สียà¹\84à¸\9b.',
+'mergehistory-header' => 'หà¸\99à¹\89าà¸\99ีà¹\89à¹\84วà¹\89à¹\83หà¹\89à¸\84ุà¸\93à¹\83à¸\8aà¹\89รวมรุà¹\88à¸\99à¹\83à¸\99à¸\9bระวัà¸\95ิà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87หà¸\99à¹\89าà¸\95à¹\89à¸\99à¸\97าà¸\87หà¸\99ึà¹\88à¸\87à¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¹\83หมà¹\88
+à¸\81à¹\88à¸à¸\99à¸\94ำà¹\80à¸\99ิà¸\99à¸\81าร à¸\84วรà¹\83หà¹\89à¹\81à¸\99à¹\88à¹\83à¸\88à¸\81à¹\88à¸à¸\99วà¹\88าà¸\81ารà¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\99ีà¹\89ยัà¸\87รัà¸\81ษาà¸\84วามà¸\95à¹\88à¸à¹\80à¸\99ืà¹\88à¸à¸\87à¸\82à¸à¸\87à¸\9bระวัà¸\95ิหà¸\99à¹\89าà¹\80à¸\81à¹\88า',
'mergehistory-box' => 'รวมรุ่นของหน้าทั้งสอง:',
'mergehistory-from' => 'หน้าต้นทาง:',
'mergehistory-into' => 'หน้าปลายทาง:',
'mergehistory-fail' => 'ไม่สามารถรวมประวัติการแก้ไขได้ โปรดตรวจสอบค่าตัวแปรหน้าและเวลาอีกครั้ง',
'mergehistory-no-source' => 'ไม่มีหน้าต้นทาง $1 อยู่ในสารบบ',
'mergehistory-no-destination' => 'ไม่มีหน้าปลายทาง $1 อยู่ในสารบบ',
-'mergehistory-invalid-source' => 'หัวà¹\80รืà¹\88à¸à¸\87à¸\82องหน้าต้นทางต้องสมเหตุสมผล',
-'mergehistory-invalid-destination' => 'à¸\8aืà¹\88à¸à¹\80รืà¹\88à¸à¸\87à¸\82à¸à¸\87หà¸\99à¹\89าà¸\9bลายà¸\97าà¸\87à¸\95à¹\89à¸à¸\87สมà¹\80หà¸\95ุสมà¸\9cล',
-'mergehistory-autocomment' => 'ยà¹\89าย [[:$1]] à¹\84à¸\9bยัà¸\87 [[:$2]]',
-'mergehistory-comment' => 'ยà¹\89าย [[:$1]] à¹\84à¸\9bยัà¸\87 [[:$2]]: $3',
+'mergehistory-invalid-source' => 'à¸\8aืà¹\88à¸à¹\80รืà¹\88องหน้าต้นทางต้องสมเหตุสมผล',
+'mergehistory-invalid-destination' => 'ชื่อเรื่องหน้าปลายทางต้องสมเหตุสมผล',
+'mergehistory-autocomment' => 'รวม [[:$1]] à¹\80à¸\82à¹\89าà¸\81ัà¸\9a [[:$2]]',
+'mergehistory-comment' => 'รวม [[:$1]] à¹\80à¸\82à¹\89าà¸\81ัà¸\9a [[:$2]]: $3',
'mergehistory-same-destination' => 'หน้าต้นทางและปลายทางเป็นหน้าเดียวกันไม่ได้',
'mergehistory-reason' => 'เหตุผล:',
# Merge log
'mergelog' => 'ปูมการรวมหน้า',
-'pagemerge-logentry' => 'ยà¹\89าย [[$1]] à¹\84à¸\9bยัà¸\87 [[$2]] (รุ่นขึ้นอยู่กับ $3)',
+'pagemerge-logentry' => 'รวม [[$1]] à¹\80à¸\82à¹\89าà¸\81ัà¸\9a [[$2]] (รุ่นขึ้นอยู่กับ $3)',
'revertmerge' => 'ยกเลิกการรวมหน้า',
-'mergelogpagetext' => 'à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\99ีà¹\89à¹\81สà¸\94à¸\87รายà¸\81ารลà¹\88าสุà¸\94à¸\82à¸à¸\87à¸\81ารรวมà¸\9bระวัà¸\95ิหà¸\99à¹\89าหà¸\99ึà¹\88à¸\87à¹\80à¸\82à¹\89าà¸\81ัà¸\9aà¸à¸µà¸\81หà¸\99à¹\89าหà¸\99ึà¹\88à¸\87',
+'mergelogpagetext' => 'à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99รายà¸\81ารà¸\81ารรวมà¸\9bระวัà¸\95ิà¸\82à¸à¸\87หà¸\99à¹\89าหà¸\99ึà¹\88à¸\87à¹\80à¸\82à¹\89าà¸\81ัà¸\9aà¸\82à¸à¸\87à¸à¸µà¸\81หà¸\99à¹\89าหà¸\99ึà¹\88à¸\87ลà¹\88าสุà¸\94',
# Diffs
'history-title' => 'ประวัติรุ่นปรับปรุงของ "$1"',
-'difference-title' => 'à¸\84วามà¹\81à¸\95à¸\81ต่างระหว่างรุ่นของ "$1"',
-'difference-title-multipage' => 'à¸\84วามà¹\81à¸\95à¸\81ต่างระหว่างหน้า "$1" และ "$2"',
-'difference-multipage' => '(à¸\84วามà¹\81à¸\95à¸\81à¸\95à¹\88าà¸\87ระหวà¹\88าà¸\87หà¸\99à¹\89าà¸\95à¹\88าà¸\87 à¹\86)',
+'difference-title' => 'à¸\9cลต่างระหว่างรุ่นของ "$1"',
+'difference-title-multipage' => 'à¸\9cลต่างระหว่างหน้า "$1" และ "$2"',
+'difference-multipage' => '(à¸\9cลà¸\95à¹\88าà¸\87ระหวà¹\88าà¸\87หà¸\99à¹\89า)',
'lineno' => 'แถว $1:',
'compareselectedversions' => 'เปรียบเทียบสองรุ่นที่เลือก',
'showhideselectedversions' => 'แสดง/ซ่อนรุ่นที่เลือก',
'editundo' => 'ย้อน',
-'diff-multi' => '(มิได้แสดง $1 รุ่นระหว่างรุ่นที่เปรียบเทียบโดย{{PLURAL:$2|ผู้ใช้คนหนึ่ง|ผู้ใช้ $2 คน}})',
-'diff-multi-manyusers' => '(มิได้แสดง $1 รุ่นระหว่างรุ่นที่เปรียบเทียบโดยผู้ใช้กว่า $2 คน)',
+'diff-multi' => '(มิได้แสดง $1 รุ่นระหว่างกลางโดย{{PLURAL:$2|ผู้ใช้คนหนึ่ง|ผู้ใช้ $2 คน}})',
+'diff-multi-manyusers' => '(มิได้แสดง $1 รุ่นระหว่างกลางโดยผู้ใช้กว่า $2 คน)',
+'difference-missing-revision' => 'ไม่พบรุ่น{{PLURAL:$2|รุ่น| $2 รุ่น}}ของผลต่างนี้ ($1)
+
+โดยปกติเกิดจากการเข้าลิงก์ผลต่างของหน้าที่ถูกลบไปแล้ว
+ดูรายละเอียดได้ที่[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ปูมการลบ]',
# Search results
'searchresults' => 'ผลการค้นหา',
'searchresults-title' => 'ผลการค้นหาสำหรับ "$1"',
-'searchresulttext' => 'สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการค้น {{SITENAME}} ดูที่ [[{{MediaWiki:Helppage}}|{{int:help}}]]',
-'searchsubtitle' => 'à¸\84ุà¸\93à¹\84à¸\94à¹\89สืà¸\9aà¸\84à¹\89à¸\99หา \'\'\'[[:$1]]\'\'\' ([[Special:Prefixindex/$1|à¸\97ุà¸\81หà¸\99à¹\89าà¸\97ีà¹\88à¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99à¸\94à¹\89วย "$1"]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|à¸\97ุà¸\81หà¸\99à¹\89าà¸\97ีà¹\88à¹\82ยà¸\87มาà¸\97ีà¹\88 "$1"]])',
-'searchsubtitleinvalid' => "à¸\84à¹\89à¸\99หาà¹\80à¸\81ีà¹\88ยวà¸\81ัà¸\9a '''$1'''",
-'toomanymatches' => 'พบตรงกันมากเกินไป กรุณาใช้คำค้นหาอื่น',
+'searchresulttext' => 'สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการค้นหา {{SITENAME}} ดูที่ [[{{MediaWiki:Helppage}}|{{int:help}}]]',
+'searchsubtitle' => 'คุณได้ค้นหา \'\'\'[[:$1]]\'\'\' ([[Special:Prefixindex/$1|ทุกหน้าที่ขึ้นต้นด้วย "$1"]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|ทุกหน้าที่โยงมาที่ "$1"]])',
+'searchsubtitleinvalid' => "à¸\84ุà¸\93à¹\84à¸\94à¹\89à¸\84à¹\89à¸\99หาà¸\84ำวà¹\88า '''$1'''",
+'toomanymatches' => 'à¸\9eà¸\9aà¸\95รà¸\87à¸\81ัà¸\99มาà¸\81à¹\80à¸\81ิà¸\99à¹\84à¸\9b à¸\81รุà¸\93าลà¸à¸\87à¹\83à¸\8aà¹\89à¸\84ำà¸\84à¹\89à¸\99หาà¸à¸·à¹\88à¸\99',
'titlematches' => 'พบชื่อเรื่องหน้าตรงกัน',
'notitlematches' => 'ไม่พบชื่อเรื่องหน้าตรงกัน',
'textmatches' => 'พบคำนี้ในหน้า',
'searchmenu-exists' => "'''มีหน้าชื่อ \"[[:\$1]]\" บนวิกินี้'''",
'searchmenu-new' => "'''สร้างหน้า \"[[:\$1]]\" บนวิกินี้'''",
'searchhelp-url' => 'Help:สารบัญ',
-'searchmenu-prefix' => '[[Special:PrefixIndex/$1|สืà¸\9aà¸\84à¹\89à¸\99หน้าที่มีคำขึ้นต้นนี้]]',
+'searchmenu-prefix' => '[[Special:PrefixIndex/$1|à¸\84à¹\89à¸\99à¸\94ูหน้าที่มีคำขึ้นต้นนี้]]',
'searchprofile-articles' => 'หน้าเนื้อหา',
'searchprofile-project' => 'คำอธิบายและหน้าโครงการ',
'searchprofile-images' => 'มัลติมีเดีย',
'search-interwiki-default' => '$1 ผลลัพธ์:',
'search-interwiki-more' => '(เพิ่มเติม)',
'search-relatedarticle' => 'สัมพันธ์',
-'mwsuggest-disable' => 'ยà¸\81à¹\80ลิà¸\81à¸\81ารà¹\81à¸\99ะà¸\99ำà¹\83à¸\99ลัà¸\81ษà¸\93ะà¹\80à¸à¹\81à¸\88à¹\87à¸\81à¸\8bà¹\8c',
-'searcheverything-enable' => 'สืà¸\9aà¸\84à¹\89à¸\99à¹\83à¸\99à¹\80à¸\99มสà¹\80à¸\9bà¸\8bà¸\97ัà¹\89à¸\87หมà¸\94',
+'mwsuggest-disable' => 'à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¹\80สà¸\99à¸à¹\81à¸\99ะà¸\81ารà¸\84à¹\89à¸\99หา',
+'searcheverything-enable' => 'à¸\84à¹\89à¸\99หาà¹\83à¸\99à¸\97ุà¸\81à¹\80à¸\99มสà¹\80à¸\9bà¸\8b',
'searchrelated' => 'สัมพันธ์',
'searchall' => 'ทั้งหมด',
-'showingresults' => "à¹\81สà¸\94à¸\87 $1 รายà¸\81าร à¹\80ริà¹\88มà¸\95à¹\89à¸\99à¸\88าà¸\81รายการที่ '''$2'''",
-'showingresultsnum' => "à¹\81สà¸\94à¸\87 $3 รายà¸\81าร à¹\80ริà¹\88มà¸\95à¹\89à¸\99à¸\88าà¸\81รายการที่ '''$2'''",
-'showingresultsheader' => "{{PLURAL:$5|à¸\9cลà¸\81ารสืà¸\9aà¸\84à¹\89à¸\99 '''$1''' à¸\88าà¸\81 '''$3'''|à¸\9cลà¸\81ารสืà¸\9aà¸\84à¹\89à¸\99 '''$1 - $2''' จาก '''$3'''}} สำหรับ '''$4'''",
-'nonefound' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99''': มีà¹\80à¸\9eียà¸\87à¸\9aาà¸\87à¹\80à¸\99มสà¹\80à¸\9bà¸\8bà¸\97ีà¹\88à¸\88ะà¸\96ูà¸\81à¸\84à¹\89à¸\99โดยปริยาย
-ลà¸à¸\87à¹\80ลืà¸à¸\81à¸\84ำà¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99à¸\81ารà¸\84à¹\89à¸\99หาà¸\94à¹\89วย ''all:'' สำหรัà¸\9aà¸\84à¹\89à¸\99à¹\80à¸\99ืà¹\89à¸à¸«à¸²à¸\97ัà¹\89à¸\87หมà¸\94 (รวมหà¸\99à¹\89าà¸à¸ ิà¸\9bราย à¹\81มà¹\88à¹\81à¸\9aà¸\9a ฯลฯ) หรืà¸à¹\80ลืà¸à¸\81เนมสเปซที่ต้องการ",
-'search-nonefound' => 'à¹\84มà¹\88มีà¸\9cลลัà¸\9eà¸\98à¹\8cà¸\95ามà¸\84ำà¸\84à¹\89à¸\99à¸\97ีà¹\88à¸\81ำหà¸\99à¸\94',
+'showingresults' => "à¹\81สà¸\94à¸\87 $1 รายà¸\81าร à¹\80ริà¹\88มà¸\95ัà¹\89à¸\87à¹\81à¸\95à¹\88รายการที่ '''$2'''",
+'showingresultsnum' => "à¹\81สà¸\94à¸\87 $3 รายà¸\81าร à¹\80ริà¹\88มà¸\95ัà¹\89à¸\87à¹\81à¸\95à¹\88รายการที่ '''$2'''",
+'showingresultsheader' => "{{PLURAL:$5|à¸\9cลà¸\81ารà¸\84à¹\89à¸\99หา '''$1''' à¸\88าà¸\81 '''$3'''|à¸\9cลà¸\81ารà¸\84à¹\89à¸\99หา '''$1 - $2''' จาก '''$3'''}} สำหรับ '''$4'''",
+'nonefound' => "'''à¸\84ำà¹\80à¸\95ืà¸à¸\99''': มีà¹\80à¸\9eียà¸\87à¸\9aาà¸\87à¹\80à¸\99มสà¹\80à¸\9bà¸\8bà¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99à¸\97ีà¹\88à¸\88ะà¸\96ูà¸\81à¸\84à¹\89à¸\99หาโดยปริยาย
+ลà¸à¸\87à¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99à¸\81ารà¸\84à¹\89à¸\99หาà¸\94à¹\89วย ''all:'' à¹\80à¸\9eืà¹\88à¸à¸\84à¹\89à¸\99หาà¹\80à¸\99ืà¹\89à¸à¸«à¸²à¸\97ัà¹\89à¸\87หมà¸\94 (รวมหà¸\99à¹\89าà¸à¸ ิà¸\9bราย à¹\81มà¹\88à¹\81à¸\9aà¸\9a ฯลฯ) หรืà¸à¹\83à¸\8aà¹\89à¸\84ำà¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99à¹\80à¸\9bà¹\87à¸\99เนมสเปซที่ต้องการ",
+'search-nonefound' => 'à¹\84มà¹\88มีà¸\9cลลัà¸\9eà¸\98à¹\8cà¸\95รà¸\87à¸\81ัà¸\9aà¸\84ำà¸\84à¹\89à¸\99',
'powersearch' => 'ค้นหาระดับสูง',
'powersearch-legend' => 'ค้นหาระดับสูง',
'powersearch-ns' => 'ค้นหาในเนมสเปซ:',
'powersearch-togglelabel' => 'เลือก:',
'powersearch-toggleall' => 'ทั้งหมด',
'powersearch-togglenone' => 'ไม่เลือก',
-'search-external' => 'à¸\84à¹\89à¸\99หาà¸\88าà¸\81ภายà¸\99à¸à¸\81',
-'searchdisabled' => 'ระà¸\9aà¸\9aà¸\81ารà¸\84à¹\89à¸\99หาà¹\83à¸\99 {{SITENAME}} à¹\84มà¹\88à¹\80à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99 à¸\84ุà¸\93สามารà¸\96à¸\84à¹\89à¸\99หาà¹\83à¸\99à¸\81ูà¹\80à¸\81ิลหรืà¸à¹\80à¸\8bิรà¹\8cà¸\8aà¹\80à¸à¸\99à¸\88ิà¸\99à¸à¸·à¹\88à¸\99 à¹\82à¸\9bรà¸\94à¸\97ราà¸\9aวà¹\88าเนื้อหาของ {{SITENAME}} บนเซิร์ชเอนจินอาจเป็นข้อมูลเก่า',
+'search-external' => 'ค้นหาภายนอก',
+'searchdisabled' => 'à¸\81ารà¸\84à¹\89à¸\99หา {{SITENAME}} à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99 à¸\84ุà¸\93สามารà¸\96à¸\84à¹\89à¸\99หาà¸\9cà¹\88าà¸\99à¸\81ูà¹\80à¸\81ิลหรืà¸à¹\80à¸\8bิรà¹\8cà¸\8aà¹\80à¸à¸\99à¸\88ิà¸\99à¸à¸·à¹\88à¸\99à¹\83à¸\99à¹\80วลาà¹\84มà¹\88à¸\99าà¸\99 à¹\82à¸\9bรà¸\94à¸\97ราà¸\9aวà¹\88าà¸\94ัà¸\8aà¸\99ีเนื้อหาของ {{SITENAME}} บนเซิร์ชเอนจินอาจเป็นข้อมูลเก่า',
# Quickbar
'qbsettings' => 'แถบพิเศษ',
'qbsettings-none' => 'ไม่มี',
-'qbsettings-fixedleft' => 'à¸à¸¢à¸¹à¹\88ทางซ้าย',
-'qbsettings-fixedright' => 'à¸à¸¢à¸¹à¹\88ทางขวา',
+'qbsettings-fixedleft' => 'à¸\95รึà¸\87à¹\84วà¹\89ทางซ้าย',
+'qbsettings-fixedright' => 'à¸\95รึà¸\87à¹\84วà¹\89ทางขวา',
'qbsettings-floatingleft' => 'ด้านซ้าย',
'qbsettings-floatingright' => 'ด้านขวา',
'prefs-datetime' => 'วันที่และเวลา',
'prefs-labs' => 'คุณสมบัติทดลอง',
'prefs-user-pages' => 'หน้าผู้ใช้',
-'prefs-personal' => 'รายละà¹\80à¸à¸µà¸¢à¸\94ผู้ใช้',
+'prefs-personal' => 'à¹\82à¸\9eรà¹\84à¸\9fลà¹\8cผู้ใช้',
'prefs-rc' => 'ปรับปรุงล่าสุด',
'prefs-watchlist' => 'รายการเฝ้าดู',
'prefs-watchlist-days' => 'จำนวนวันที่แสดงในรายการเฝ้าดู:',
'prefs-resetpass' => 'เปลี่ยนรหัสผ่าน',
'prefs-changeemail' => 'เปลี่ยนที่อยู่อีเมล',
'prefs-setemail' => 'ตั้งที่อยู่อีเมล',
-'prefs-email' => 'à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าอีเมล',
+'prefs-email' => 'à¸\95ัวà¹\80ลืà¸à¸\81อีเมล',
'prefs-rendering' => 'รูปลักษณ์',
'saveprefs' => 'บันทึก',
'resetprefs' => 'ล้างการเปลี่ยนแปลงที่ยังไม่บันทึก',
'prefs-edit-boxsize' => 'ขนาดหน้าจอกล่องแก้ไข',
'rows' => 'แถว:',
'columns' => 'คอลัมน์:',
-'searchresultshead' => 'สืà¸\9aà¸\84à¹\89à¸\99',
-'resultsperpage' => 'รายà¸\81ารต่อหน้า:',
-'stub-threshold' => 'à¸\82ีà¸\94à¹\81à¸\9aà¹\88à¸\87สำหรัà¸\9a <a href="#" class="stub">รูà¸\9bà¹\81à¸\9aà¸\9aà¹\82à¸\84รà¸\87</a> (à¸\84วามยาวà¸\9aà¸\97à¸\84วาม):',
-'stub-threshold-disabled' => 'à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99',
+'searchresultshead' => 'à¸\84à¹\89à¸\99หา',
+'resultsperpage' => 'à¸\81ารà¹\80à¸\9bิà¸\94à¸\94ูต่อหน้า:',
+'stub-threshold' => 'à¸\82ีà¸\94à¹\81à¸\9aà¹\88à¸\87สำหรัà¸\9a <a href="#" class="stub">ลิà¸\87à¸\81à¹\8cà¹\82à¸\84รà¸\87</a> (à¹\84à¸\9aà¸\95à¹\8c):',
+'stub-threshold-disabled' => 'ปิดใช้งาน',
'recentchangesdays' => 'จำนวนวันที่แสดงในปรับปรุงล่าสุด:',
'recentchangesdays-max' => 'มากสุด $1 วัน',
'recentchangescount' => 'จำนวนการแก้ไขที่แสดงโดยปริยาย:',
'prefs-custom-css' => 'สไตล์ชีตปรับแต่งเอง',
'prefs-custom-js' => 'จาวาสคริปต์ปรับแต่งเอง',
'prefs-common-css-js' => 'CSS / จาวาสคริปต์ที่ใช้ร่วมกันกับทุกหน้าตา:',
-'prefs-reset-intro' => 'à¸\84ุà¸\93สามารà¸\96à¹\83à¸\8aà¹\89หà¸\99à¹\89าà¸\99ีà¹\89à¸\95ัà¹\89à¸\87à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¸\82à¸à¸\87à¸\84ุà¸\93à¸\81ลัà¸\9aà¹\80à¸\9bà¹\87à¸\99à¸\84à¹\88าà¸\95ัà¹\89à¸\87à¸\95à¹\89à¸\99à¸\82à¸à¸\87à¹\84à¸\8bà¸\95à¹\8cใหม่
-à¹\80มืà¹\88à¸à¸¥à¹\89าà¸\87à¹\81ลà¹\89วà¸\88ะà¹\84มà¹\88สามารà¸\96ยà¹\89à¸à¸\99กลับได้',
+'prefs-reset-intro' => 'à¸\84ุà¸\93สามารà¸\96à¹\83à¸\8aà¹\89หà¸\99à¹\89าà¸\99ีà¹\89à¸\95ัà¹\89à¸\87à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¸\82à¸à¸\87à¸\84ุà¸\93à¸\81ลัà¸\9aà¹\84à¸\9bยัà¸\87à¸\84à¹\88าà¸\95ัà¹\89à¸\87à¸\95à¹\89à¸\99à¸\82à¸à¸\87à¹\80วà¹\87à¸\9aใหม่
+à¸\8bึà¹\88à¸\87à¹\84มà¹\88สามารà¸\96à¸\97ำกลับได้',
'prefs-emailconfirm-label' => 'การยืนยันอีเมล:',
-'prefs-textboxsize' => 'à¸\82à¸\99าà¸\94à¸\82à¸à¸\87หà¸\99à¹\89าà¸\95à¹\88าà¸\87à¹\81à¸\81à¹\89à¹\84à¸\82',
+'prefs-textboxsize' => 'ขนาดหน้าต่างแก้ไข',
'youremail' => 'อีเมล:',
'username' => '{{GENDER:$1|ชื่อผู้ใช้}}:',
'uid' => 'รหัสประจำตัว{{GENDER:$1|ผู้ใช้}}:',
'prefs-memberingroups' => '{{GENDER:$2|สมาชิก}}ใน{{PLURAL:$1|กลุ่ม|กลุ่ม}}:',
-'prefs-registration' => 'วัà¸\99à¹\80วลาà¸\97ีà¹\88ลงทะเบียน:',
+'prefs-registration' => 'à¹\80วลาลงทะเบียน:',
'yourrealname' => 'ชื่อจริง:',
'yourlanguage' => 'ภาษา:',
'yourvariant' => 'อักษรต่างรูปของเนื้อหา:',
'yournick' => 'ลายเซ็น:',
-'prefs-help-signature' => 'à¸\84วามà¹\80หà¹\87à¸\99à¹\83à¸\99หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\84วรà¸\88ะลà¸\87ลายà¹\80à¸\8bà¹\87à¸\99à¸\94à¹\89วย "<nowiki>~~~~</nowiki>" à¸\8bึà¹\88à¸\87à¸\88ะà¸\96ูà¸\81à¹\81à¸\9bลà¸\87à¹\80à¸\9bà¹\87à¸\99ลายà¹\80à¸\8bà¹\87à¸\99และตราเวลา',
-'badsig' => 'ลายà¹\80à¸\8bà¹\87à¸\99à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¸\9cิà¸\94à¸\9eลาà¸\94 à¸\81รุà¸\93าà¸\95รวà¸\88สà¸à¸\9aà¸\84ำสัà¹\88à¸\87เอชทีเอ็มแอล',
+'prefs-help-signature' => 'à¸\84วามà¹\80หà¹\87à¸\99à¹\83à¸\99หà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\84วรลà¸\87ลายà¹\80à¸\8bà¹\87à¸\99à¸\94à¹\89วย "<nowiki>~~~~</nowiki>" à¸\8bึà¹\88à¸\87à¸\88ะà¸\96ูà¸\81à¹\81à¸\9bลà¸\87à¹\80à¸\9bà¹\87à¸\99ลายà¹\80à¸\8bà¹\87à¸\99à¸\82à¸à¸\87à¸\84ุà¸\93และตราเวลา',
+'badsig' => 'ลายà¹\80à¸\8bà¹\87à¸\99à¸\94ิà¸\9aà¹\84มà¹\88สมà¹\80หà¸\95ุสมà¸\9cล à¸\95รวà¸\88สà¸à¸\9aà¸\9bà¹\89ายระà¸\9aุเอชทีเอ็มแอล',
'badsiglength' => 'ลายเซ็นของคุณยาวเกินไป ต้องยาวไม่เกิน $1 ตัวอักษร',
'yourgender' => 'เพศ:',
'gender-unknown' => 'ไม่ระบุ',
'gender-male' => 'ชาย',
'gender-female' => 'หญิง',
-'prefs-help-gender' => 'à¹\80à¸\9bà¹\87à¸\99à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\80สริม: à¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¸\8bà¸à¸\9fà¸\95à¹\8cà¹\81วรà¹\8cà¹\81ยà¸\81à¹\81ยะà¹\80à¸\9eศà¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89 à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\99ีà¹\89à¸\88ะà¹\80à¸\9bà¹\87à¸\99à¸\97ีà¹\88à¹\80à¸\9bิà¸\94à¹\80à¸\9cย',
+'prefs-help-gender' => 'à¹\80à¸\9bà¹\87à¸\99à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\80สริม: à¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¸\8bà¸à¸\9fà¸\95à¹\8cà¹\81วรà¹\8cà¹\81ยà¸\81à¹\81ยะà¹\80à¸\9eศà¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89 à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\99ีà¹\89à¸\88ะà¹\80à¸\9bิà¸\94à¹\80à¸\9cยà¸\95à¹\88à¸à¸ªà¸²à¸\98ารà¸\93ะ',
'email' => 'อีเมล',
-'prefs-help-realname' => 'à¹\84มà¹\88à¸\88ำà¹\80à¸\9bà¹\87à¸\99à¸\95à¹\89à¸à¸\87à¹\83à¸\8aà¹\89à¸\8aืà¹\88à¸à¸\88ริà¸\87 à¸\96à¹\89าà¸\84ุà¸\93à¹\80ลืà¸à¸\81à¸\97ีà¹\88à¸\88ะà¹\83à¸\8aà¹\89à¸\8aืà¹\88à¸à¸\88ริà¸\87 à¸\88ะà¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¹\80à¸\81ียรà¸\95ิà¹\81à¸\81à¹\88à¸\87าà¸\99à¸\82à¸à¸\87à¸\84ุà¸\93',
-'prefs-help-email' => 'à¹\84มà¹\88à¸\95à¹\89à¸à¸\87à¹\83สà¹\88à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มล à¹\81à¸\95à¹\88à¸\88ำà¹\80à¸\9bà¹\87à¸\99สำหรัà¸\9aà¸\81ารà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¹\80มืà¹\88à¸à¸\84ุà¸\93ลืมรหัสà¸\9cà¹\88าà¸\99à¸\82à¸à¸\87à¸\84ุà¸\93',
+'prefs-help-realname' => 'ไม่จำเป็นต้องใช้ชื่อจริง ถ้าคุณเลือกใช้ชื่อจริง จะใช้เพื่อให้เกียรติแก่งานของคุณ',
+'prefs-help-email' => 'à¹\84มà¹\88à¸\88ำà¹\80à¸\9bà¹\87à¸\99à¸\95à¹\89à¸à¸\87à¹\83สà¹\88à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มล à¹\81à¸\95à¹\88à¸\88ำà¹\80à¸\9bà¹\87à¸\99สำหรัà¸\9aà¸\81ารà¸\95ัà¹\89à¸\87รหัสà¸\9cà¹\88าà¸\99à¹\83หมà¹\88à¹\80มืà¹\88à¸à¸\84ุà¸\93ลืมรหัสà¸\9cà¹\88าà¸\99',
'prefs-help-email-others' => 'คุณยังสามารถเลือกให้ผู้อื่นติดต่อคุณโดยอีเมลผ่านลิงก์บนหน้าผู้ใช้หรือหน้าพูดคุยกับผู้ใช้ของคุณ
ที่อยู่อีเมลของคุณไม่ถูกเปิดเผยเมื่อผู้ใช้อื่นติดต่อคุณ',
'prefs-help-email-required' => 'ต้องการที่อยู่อีเมล',
'prefs-info' => 'ข้อมูลเบื้องต้น',
-'prefs-i18n' => 'ระà¸\9aà¸\9aภาษาหรืà¸à¹\80à¸\82à¸\95à¸\9eืà¹\89à¸\99à¸\97ีà¹\88',
+'prefs-i18n' => 'สาà¸\81ลวิวัà¸\95à¸\99à¹\8c',
'prefs-signature' => 'ลายเซ็น',
'prefs-dateformat' => 'รูปแบบวันที่',
'prefs-timeoffset' => 'ส่วนต่างเวลา',
-'prefs-advancedediting' => 'à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าขั้นสูง',
-'prefs-advancedrc' => 'à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าขั้นสูง',
-'prefs-advancedrendering' => 'à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าขั้นสูง',
-'prefs-advancedsearchoptions' => 'à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าขั้นสูง',
-'prefs-advancedwatchlist' => 'à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าขั้นสูง',
-'prefs-displayrc' => 'à¸\84à¹\88าà¸\81ารà¹\81สà¸\94à¸\87à¸\9cล',
-'prefs-displaysearchoptions' => 'à¸\84à¹\88าà¸\81ารà¹\81สà¸\94à¸\87à¸\9cล',
-'prefs-displaywatchlist' => 'à¸\84à¹\88าà¸\81ารà¹\81สà¸\94à¸\87à¸\9cล',
-'prefs-diffs' => 'à¹\81à¸\95à¸\81ต่าง',
+'prefs-advancedediting' => 'à¸\95ัวà¹\80ลืà¸à¸\81ขั้นสูง',
+'prefs-advancedrc' => 'à¸\95ัวà¹\80ลืà¸à¸\81ขั้นสูง',
+'prefs-advancedrendering' => 'à¸\95ัวà¹\80ลืà¸à¸\81ขั้นสูง',
+'prefs-advancedsearchoptions' => 'à¸\95ัวà¹\80ลืà¸à¸\81ขั้นสูง',
+'prefs-advancedwatchlist' => 'à¸\95ัวà¹\80ลืà¸à¸\81ขั้นสูง',
+'prefs-displayrc' => 'à¸\95ัวà¹\80ลืà¸à¸\81à¸\9cลà¹\81สà¸\94à¸\87',
+'prefs-displaysearchoptions' => 'à¸\95ัวà¹\80ลืà¸à¸\81à¸\9cลà¹\81สà¸\94à¸\87',
+'prefs-displaywatchlist' => 'à¸\95ัวà¹\80ลืà¸à¸\81à¸\9cลà¹\81สà¸\94à¸\87',
+'prefs-diffs' => 'à¸\9cลต่าง',
# User preference: e-mail validation using jQuery
'email-address-validity-valid' => 'ที่อยู่อีเมลดูถูกต้อง',
'userrights-editusergroup' => 'แก้ไขกลุ่มผู้ใช้',
'saveusergroups' => 'ตกลง',
'userrights-groupsmember' => 'สมาชิกในกลุ่ม:',
-'userrights-groupsmember-auto' => 'สมาà¸\8aิà¸\81à¹\82à¸\94ยà¸\99ัยของ:',
-'userrights-groups-help' => 'คุณสามารถเปลี่ยนแปลงกลุ่มที่ผู้ใช้รายนี้อยู่ใน:
-* à¸\81ลà¹\88à¸à¸\87à¸\97ีà¹\88à¸\96ูà¸\81à¹\80ลืà¸à¸\81หมายà¸\84วามวà¹\88าผู้ใช้อยู่ในกลุ่มนั้น
-* à¸\81ลà¹\88à¸à¸\87à¸\97ีà¹\88à¹\84มà¹\88à¸\96ูà¸\81à¹\80ลืà¸à¸\81หมายà¸\84วามวà¹\88าผู้ใช้ไม่ได้อยู่ในกลุ่มนั้น
-* à¹\80à¸\84รืà¹\88à¸à¸\87หมาย * à¸\8aีà¹\89วà¹\88าà¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¹\80à¸à¸²à¸\81ลุà¹\88มà¸\99ัà¹\89à¸\99à¸à¸à¸\81à¹\84à¸\94à¹\89à¹\80มืà¹\88à¸à¹\83à¸\94à¸\81à¹\87à¸\95ามà¸\97ีà¹\88คุณเพิ่มกลุ่มนั้นไปแล้ว หรือกลับกัน',
+'userrights-groupsmember-auto' => 'สมาà¸\8aิà¸\81à¹\82à¸\94ยà¸\9bริยายของ:',
+'userrights-groups-help' => 'คุณสามารถเปลี่ยนแปลงกลุ่มที่ผู้ใช้รายนี้อยู่:
+* à¸\81ลà¹\88à¸à¸\87à¸\97ีà¹\88มีà¹\80à¸\84รืà¹\88à¸à¸\87หมายà¸\96ูà¸\81 หมายà¸\84วามวà¹\88า ผู้ใช้อยู่ในกลุ่มนั้น
+* à¸\81ลà¹\88à¸à¸\87à¸\97ีà¹\88à¹\84มà¹\88มีà¹\80à¸\84รืà¹\88à¸à¸\87หมายà¸\96ูà¸\81 หมายà¸\84วามวà¹\88า ผู้ใช้ไม่ได้อยู่ในกลุ่มนั้น
+* à¹\80à¸\84รืà¹\88à¸à¸\87หมาย * à¸\8aีà¹\89วà¹\88าà¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¸\99ำà¸\81ลุà¹\88มà¸\99ัà¹\89à¸\99à¸à¸à¸\81à¹\84à¸\94à¹\89à¹\80มืà¹\88à¸คุณเพิ่มกลุ่มนั้นไปแล้ว หรือกลับกัน',
'userrights-reason' => 'เหตุผล:',
-'userrights-no-interwiki' => 'à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aสิà¸\97à¸\98ิà¹\83à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82สิà¸\97à¸\98ิà¸\82à¸à¸\87ผู้ใช้บนวิกิอื่น',
-'userrights-nodatabase' => 'ไม่มีฐานข้อมูล $1 อยู่ หรือ ฐานข้อมูลอยู่บนเครื่องอื่น',
+'userrights-no-interwiki' => 'à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aสิà¸\97à¸\98ิà¹\81à¸\81à¹\89à¹\84à¸\82สิà¸\97à¸\98ิผู้ใช้บนวิกิอื่น',
+'userrights-nodatabase' => 'ไม่มีฐานข้อมูล $1 อยู่ หรือฐานข้อมูลอยู่บนเครื่องอื่น',
'userrights-nologin' => 'คุณต้อง[[Special:UserLogin|ล็อกอิน]]ด้วยบัญชีผู้ดูแลระบบก่อน จึงจะกำหนดสิทธิผู้ใช้ได้',
'userrights-notallowed' => 'บัญชีของคุณไม่ได้รับอนุญาตให้เพิ่มหรือลดสิทธิของผู้ใช้',
'userrights-changeable-col' => 'กลุ่มที่คุณสามารถเปลี่ยนได้',
# Groups
'group' => 'กลุ่ม:',
-'group-user' => 'ผู้ใช้ใหม่',
+'group-user' => 'ผู้ใช้',
'group-autoconfirmed' => 'ผู้ใช้ทั่วไป',
'group-bot' => 'บอต',
-'group-sysop' => 'ผู้ดูแล',
+'group-sysop' => 'ผู้ดูแลระบบ',
'group-bureaucrat' => 'ผู้ดูแลสิทธิแต่งตั้ง',
-'group-suppress' => 'à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\94ัà¸\9aสูà¸\87',
+'group-suppress' => 'à¸\9cูà¹\89à¸\94ูà¹\81ลà¸\9bระวัà¸\95ิ',
'group-all' => '(ทั้งหมด)',
-'group-user-member' => '{{GENDER:$1|ผู้ใช้ใหม่}}',
+'group-user-member' => '{{GENDER:$1|ผู้ใช้}}',
'group-autoconfirmed-member' => '{{GENDER:$1|ผู้ใช้ทั่วไป}}',
'group-bot-member' => '{{GENDER:$1|บอต}}',
'group-sysop-member' => '{{GENDER:$1|ผู้ดูแลระบบ}}',
'group-bureaucrat-member' => '{{GENDER:$1|ผู้ดูแลสิทธิแต่งตั้ง}}',
-'group-suppress-member' => '{{GENDER:$1|oversight}}',
+'group-suppress-member' => '{{GENDER:$1|ผู้ดูแลประวัติ}}',
'grouppage-user' => '{{ns:project}}:ผู้ใช้',
'grouppage-autoconfirmed' => '{{ns:project}}:ผู้ใช้ทั่วไป',
'grouppage-bot' => '{{ns:project}}:บอต',
'grouppage-sysop' => '{{ns:project}}:ผู้ดูแล',
'grouppage-bureaucrat' => '{{ns:project}}:ผู้ดูแลสิทธิแต่งตั้ง',
-'grouppage-suppress' => '{{ns:project}}:à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\94ัà¸\9aสูà¸\87',
+'grouppage-suppress' => '{{ns:project}}:à¸\9cูà¹\89à¸\94ูà¹\81ลà¸\9bระวัà¸\95ิ',
# Rights
'right-read' => 'อ่านหน้า',
'right-createpage' => 'สร้างหน้า (ที่ไม่ใช่หน้าอภิปราย)',
'right-createtalk' => 'สร้างหน้าอภิปราย',
'right-createaccount' => 'สร้างบัญชีผู้ใช้ใหม่',
-'right-minoredit' => 'ทำเครื่องหมายการแก้ไขเล็กน้อย',
+'right-minoredit' => 'à¸\97ำà¹\80à¸\84รืà¹\88à¸à¸\87หมายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80ลà¹\87à¸\81à¸\99à¹\89à¸à¸¢',
'right-move' => 'ย้ายหน้า',
'right-move-subpages' => 'ย้ายหน้าพร้อมหน้าย่อย',
'right-move-rootuserpages' => 'ย้ายหน้าผู้ใช้หลัก',
'right-upload_by_url' => 'อัปโหลดไฟล์จากยูอาร์แอล',
'right-purge' => 'ล้างแคชของเว็บไซต์โดยไม่มีการยืนยัน',
'right-autoconfirmed' => 'แก้ไขหน้าที่ถูกกึ่งล็อก',
-'right-bot' => 'à¸\81ำหà¸\99à¸\94วà¹\88าà¹\80à¸\9bà¹\87à¸\99à¸\81ระà¸\9aวà¸\99à¸\81ารà¸à¸±à¸\95à¹\82à¸\99มัà¸\95ิ',
-'right-nominornewtalk' => 'à¹\84มà¹\88มีà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80ลà¹\87à¸\81à¸\99à¹\89à¸à¸¢à¸\97ีà¹\88หà¸\99à¹\89าสà¸\99à¸\97à¸\99าà¸\97ีà¹\88à¸\97ำà¹\83หà¹\89à¸\81ารà¹\80à¸\95ืà¸à¸\99ข้อความใหม่ปรากฏ',
+'right-bot' => 'กำหนดเป็นกระบวนการอัตโนมัติ',
+'right-nominornewtalk' => 'à¹\84มà¹\88มีà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80ลà¹\87à¸\81à¸\99à¹\89à¸à¸¢à¹\83à¸\99หà¸\99à¹\89าà¸à¸ ิà¸\9bรายà¸\97ีà¹\88à¸\97ำà¹\83หà¹\89à¸\81ารà¹\81à¸\88à¹\89à¸\87ข้อความใหม่ปรากฏ',
'right-apihighlimits' => 'ใช้ข้อจำกัดที่สูงขึ้นในคำสั่งเอพีไอ',
'right-writeapi' => 'ใช้การเขียนเอพีไอ',
'right-delete' => 'ลบหน้า',
'right-bigdelete' => 'ลบหน้าที่มีประวัติขนาดใหญ่',
-'right-deletelogentry' => 'ลà¸\9aà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99รายà¸\81ารปูมที่เจาะจง',
-'right-deleterevision' => 'ลà¸\9aà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99รุà¹\88à¸\99à¸\97ีà¹\88à¹\80à¸\88าะà¸\88à¸\87à¸\82à¸à¸\87หà¸\99à¹\89าà¸\95à¹\88าà¸\87 à¹\86',
-'right-deletedhistory' => 'à¸\94ูรายà¸\81ารประวัติที่ถูกลบ โดยไม่มีข้อความที่เกี่ยวข้อง',
-'right-deletedtext' => 'à¹\80รียà¸\81à¸\94ูà¸\82à¹\89à¸à¸\84วามà¸\97ีà¹\88à¸\96ูà¸\81ลà¸\9aà¹\81ละà¸\84วามเปลี่ยนแปลงระหว่างรุ่นที่ถูกลบ',
+'right-deletelogentry' => 'ลà¸\9aà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99หà¸\99à¹\88วยปูมที่เจาะจง',
+'right-deleterevision' => 'ลà¸\9aà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99รุà¹\88à¸\99à¸\88ำà¹\80à¸\9eาะà¸\82à¸à¸\87หà¸\99à¹\89า',
+'right-deletedhistory' => 'à¸\94ูหà¸\99à¹\88วยประวัติที่ถูกลบ โดยไม่มีข้อความที่เกี่ยวข้อง',
+'right-deletedtext' => 'à¸\94ูà¸\82à¹\89à¸à¸\84วามà¸\97ีà¹\88à¸\96ูà¸\81ลà¸\9aà¹\81ละà¸\81ารเปลี่ยนแปลงระหว่างรุ่นที่ถูกลบ',
'right-browsearchive' => 'ค้นหาหน้าที่ถูกลบ',
-'right-undelete' => 'à¹\80รียà¸\81คืนหน้า',
+'right-undelete' => 'à¸\81ูà¹\89คืนหน้า',
'right-suppressrevision' => 'ดูและกู้คืนรุ่นที่ซ่อนจากผู้ดูแลระบบ',
'right-suppressionlog' => 'ดูปูมส่วนตัว',
-'right-block' => 'à¸\9aลà¹\87à¸à¸\81à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸à¸·à¹\88à¸\99มิà¹\83หà¹\89แก้ไข',
-'right-blockemail' => 'à¸\9aลà¹\87à¸à¸\81à¸\9cูà¹\89à¹\83à¸\8aà¹\89มิà¹\83ห้ส่งอีเมล',
-'right-hideuser' => 'à¸\9aลà¹\87à¸à¸\81à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\81ละà¸\8bà¹\88à¸à¸\99à¹\84มà¹\88à¹\83หà¹\89à¸\9cูà¹\89à¸à¸·à¹\88à¸\99เห็น',
-'right-ipblock-exempt' => 'à¸\9cà¹\88าà¸\99à¸\81ารà¸\9aลà¹\87à¸à¸\81หมายà¹\80ลà¸\82à¹\84à¸à¸\9eี à¸\9aลà¹\87à¸à¸\81à¹\81à¸\9aà¸\9aà¸à¸±à¸\95à¹\82à¸\99มัà¸\95ิ à¹\81ละà¸\9aลà¹\87à¸à¸\81à¹\80à¸\9bà¹\87à¸\99ช่วง',
-'right-proxyunbannable' => 'à¸\9cà¹\88าà¸\99à¸\81ารà¸\9aลà¹\87à¸à¸\81à¹\81à¸\9aà¸\9aอัตโนมัติของพร็อกซี',
-'right-unblockself' => 'ยà¸\81à¹\80ลิà¸\81à¸\81ารบล็อกตนเอง',
+'right-block' => 'à¸\9aลà¹\87à¸à¸\81มิà¹\83หà¹\89à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸à¸·à¹\88à¸\99แก้ไข',
+'right-blockemail' => 'à¸\9aลà¹\87à¸à¸\81มิà¹\83หà¹\89à¸\9cูà¹\89à¹\83à¸\8a้ส่งอีเมล',
+'right-hideuser' => 'à¸\9aลà¹\87à¸à¸\81à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89 à¸\8bà¹\88à¸à¸\99à¹\84มà¹\88à¹\83หà¹\89สาà¸\98ารà¸\93ะเห็น',
+'right-ipblock-exempt' => 'à¸à¹\89à¸à¸¡à¸\81ารà¸\9aลà¹\87à¸à¸\81à¹\80ลà¸\82à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¹\84à¸à¸\9eี à¸\9aลà¹\87à¸à¸\81à¸à¸±à¸\95à¹\82à¸\99มัà¸\95ิ à¹\81ละà¸\9aลà¹\87à¸à¸\81ช่วง',
+'right-proxyunbannable' => 'à¹\80ลีà¹\88ยà¸\87à¸\81ารà¸\9aลà¹\87à¸à¸\81อัตโนมัติของพร็อกซี',
+'right-unblockself' => 'à¸\9bลà¸\94บล็อกตนเอง',
'right-protect' => 'เปลี่ยนระดับการล็อกและแก้ไขหน้าที่ถูกล็อก',
-'right-editprotected' => 'à¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\97ีà¹\88à¸\96ูà¸\81ลà¹\87à¸à¸\81 (ที่ไม่ล็อกแบบสืบทอด)',
-'right-editinterface' => 'à¹\81à¸\81à¹\89à¹\84à¸\82à¸à¸´à¸\99à¹\80à¸\95à¸à¸£à¹\8cà¹\80à¸\9fà¸\8bà¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89',
-'right-editusercssjs' => 'แก้ไข CSS และ JS ของผู้ใช้คนอื่น',
-'right-editusercss' => 'แก้ไข CSS ของผู้ใช้คนอื่น',
-'right-edituserjs' => 'แก้ไข JS ของผู้ใช้คนอื่น',
-'right-rollback' => 'ยà¹\89à¸à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89ลà¹\88าสุà¸\94à¸\97ีà¹\88à¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¹\82à¸\94ยà¹\80à¸\89à¸\9eาะà¸à¸¢à¹\88าà¸\87รวà¸\94à¹\80รà¹\87ว',
+'right-editprotected' => 'หà¸\99à¹\89าà¸\97ีà¹\88à¸\96ูà¸\81ลà¹\87à¸à¸\81à¹\80à¸\95à¹\87มà¸\97ีà¹\88 (ที่ไม่ล็อกแบบสืบทอด)',
+'right-editinterface' => 'แก้ไขอินเตอร์เฟซผู้ใช้',
+'right-editusercssjs' => 'แก้ไขไฟล์ CSS และจาวาสคริปต์ของผู้ใช้อื่น',
+'right-editusercss' => 'แก้ไขไฟล์ CSS ของผู้ใช้อื่น',
+'right-edituserjs' => 'แก้ไขไฟล์จาวาสคริปต์ของผู้ใช้อื่น',
+'right-rollback' => 'ย้อนการแก้ไขของผู้ใช้ล่าสุดที่แก้ไขหน้าเฉพาะอย่างรวดเร็ว',
'right-markbotedits' => 'ทำเครื่องหมายการย้อนว่าเป็นการแก้ไขโดยบอต',
-'right-noratelimit' => 'à¹\84มà¹\88มีà¸\9cลà¸\81ระà¸\97à¸\9aà¸\88าà¸\81à¸\81ารà¸\88ำà¸\81ัà¸\94สิà¸\97à¸\98ิà¸\95ามà¹\80วลา',
+'right-noratelimit' => 'à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aà¸\9cลà¸\81ระà¸\97à¸\9aà¸\88าà¸\81à¸\82ีà¸\94à¸\88ำà¸\81ัà¸\94à¸à¸±à¸\95รา',
'right-import' => 'นำเข้าหน้าจากวิกิอื่น',
'right-importupload' => 'นำเข้าหน้าจากไฟล์ที่อัปโหลด',
'right-patrol' => 'ทำเครื่องหมายการแก้ไขของผู้อื่นว่าตรวจสอบแล้ว',
-'right-autopatrol' => 'à¸\95ัà¹\89à¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\95à¸\99à¹\80à¸à¸\87วà¹\88าตรวจสอบแล้วอัตโนมัติ',
+'right-autopatrol' => 'à¹\83หà¹\89à¸\97ำà¹\80à¸\84รืà¹\88à¸à¸\87หมายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\95à¸\99à¹\80à¸à¸\87à¹\80à¸\9bà¹\87à¸\99ตรวจสอบแล้วอัตโนมัติ',
'right-patrolmarks' => 'ดูการเปลี่ยนแปลงล่าสุดของการทำเครื่องหมายตรวจสอบ',
'right-unwatchedpages' => 'ดูรายการหน้าที่ไม่มีผู้เฝ้าดู',
-'right-mergehistory' => 'รวมà¸\9bระวัà¸\95ิà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89า',
+'right-mergehistory' => 'รวมประวัติหน้า',
'right-userrights' => 'แก้ไขสิทธิผู้ใช้ทั้งหมด',
'right-userrights-interwiki' => 'แก้ไขสิทธิผู้ใช้ของผู้ใช้บนวิกิอื่น',
'right-siteadmin' => 'ล็อกและปลดล็อกฐานข้อมูล',
'right-passwordreset' => 'ดูอีเมลตั้งรหัสผ่านใหม่',
# Special:Log/newusers
-'newuserlogpage' => 'à¸\9bูมà¸\81ารสรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89',
-'newuserlogpagetext' => 'à¸\99ีà¹\88à¸\84ืà¸à¸\9bูมà¸\81ารสรà¹\89าà¸\87à¸\9aัà¸\8dà¸\8aีà¸\9cูà¹\89à¹\83à¸\8aà¹\89',
+'newuserlogpage' => 'ปูมการสร้างผู้ใช้',
+'newuserlogpagetext' => 'นี่คือปูมการสร้างผู้ใช้',
# User rights log
'rightslog' => 'ปูมสิทธิผู้ใช้',
'action-createpage' => 'สร้างหน้า',
'action-createtalk' => 'สร้างหน้าอภิปราย',
'action-createaccount' => 'สร้างบัญชีผู้ใช้นี้',
-'action-minoredit' => 'เป็นการแก้ไขเล็กน้อย',
+'action-minoredit' => 'à¸\97ำà¹\80à¸\84รืà¹\88à¸à¸\87หมายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\80ลà¹\87à¸\81à¸\99à¹\89à¸à¸¢',
'action-move' => 'ย้ายหน้านี้',
'action-move-subpages' => 'ย้ายหน้านี้ รวมทั้งหน้าย่อย',
'action-move-rootuserpages' => 'ย้ายหน้าผู้ใช้หลัก',
'action-deletedhistory' => 'ดูประวัติที่ถูกลบของหน้านี้',
'action-browsearchive' => 'ค้นหาหน้าที่ถูกลบ',
'action-undelete' => 'กู้คืนหน้านี้',
-'action-suppressrevision' => 'à¸\95รวà¸\88à¸\94ูและกู้คืนรุ่นที่ซ่อนอยู่นี้',
-'action-suppressionlog' => 'ดูปูมส่วนตัว',
+'action-suppressrevision' => 'à¸\97à¸\9aà¸\97วà¸\99และกู้คืนรุ่นที่ซ่อนอยู่นี้',
+'action-suppressionlog' => 'ดูปูมส่วนตัวนี้',
'action-block' => 'บล็อกผู้ใช้รายนี้มิให้แก้ไข',
'action-protect' => 'เปลี่ยนระดับการล็อกสำหรับหน้านี้',
+'action-rollback' => 'ย้อนการแก้ไขของผู้ใช้ล่าสุดที่แก้ไขหน้าเฉพาะอย่างรวดเร็ว',
'action-import' => 'นำเข้าหน้านี้จากวิกิอื่น',
-'action-importupload' => 'à¸\99ำà¹\80à¸\82à¹\89าหà¸\99à¹\89าà¸\99ีà¹\89à¸\88าà¸\81à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸à¸±à¸\9bà¹\82หลà¸\94à¹\81ลà¹\89ว',
-'action-patrol' => 'ทำเครื่องหมายการแก้ไขของผู้ใช้อื่นว่าตรวจแล้ว',
-'action-autopatrol' => 'ทำเครื่องหมายการแก้ไขของคุณว่าตรวจแล้ว',
+'action-importupload' => 'à¸\99ำà¹\80à¸\82à¹\89าหà¸\99à¹\89าà¸\99ีà¹\89à¸\88าà¸\81à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8c',
+'action-patrol' => 'à¸\97ำà¹\80à¸\84รืà¹\88à¸à¸\87หมายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸à¸·à¹\88à¸\99วà¹\88าà¸\95รวà¸\88สà¸à¸\9aà¹\81ลà¹\89ว',
+'action-autopatrol' => 'à¸\97ำà¹\80à¸\84รืà¹\88à¸à¸\87หมายà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\84ุà¸\93วà¹\88าà¸\95รวà¸\88สà¸à¸\9aà¹\81ลà¹\89ว',
'action-unwatchedpages' => 'ดูรายการหน้าที่ไม่มีผู้เฝ้าดู',
'action-mergehistory' => 'รวมประวัติหน้านี้',
'action-userrights' => 'แก้ไขสิทธิผู้ใช้ทั้งหมด',
-'action-userrights-interwiki' => 'à¹\81à¸\81à¹\89à¹\84à¸\82สิà¸\97à¸\98ิà¸\9cูà¹\89à¹\83à¸\8aà¹\89สำหรัà¸\9aวิà¸\81ิà¸\99ีà¹\89',
+'action-userrights-interwiki' => 'à¹\81à¸\81à¹\89à¹\84à¸\82สิà¸\97à¸\98ิà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\9aà¸\99วิà¸\81ิà¸à¸·à¹\88à¸\99',
'action-siteadmin' => 'ล็อกหรือปลดล็อกฐานข้อมูล',
'action-sendemail' => 'ส่งอีเมล',
'nchanges' => '$1 การแก้ไข',
'recentchanges' => 'ปรับปรุงล่าสุด',
'recentchanges-legend' => 'ตัวเลือกปรับปรุงล่าสุด',
-'recentchanges-summary' => 'à¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99รายà¸\81ารลà¹\88าสุà¸\94à¸\97ีà¹\88มีà¸\81ารà¸\9bรัà¸\9aà¸\9bรุà¸\87',
-'recentchanges-feed-description' => 'à¸\9fีà¸\94à¸\99ีà¹\89à¹\81สà¸\94à¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87ลà¹\88าสุà¸\94',
-'recentchanges-label-newpage' => 'à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99à¸\81ารสรà¹\89าà¸\87หà¸\99à¹\89าà¹\83หมà¹\88',
+'recentchanges-summary' => 'à¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99รายà¸\81ารà¸\81ารà¸\9bรัà¸\9aà¸\9bรุà¸\87ลà¹\88าสุà¸\94à¸\9aà¸\99วิà¸\81ิà¸\99ีà¹\89',
+'recentchanges-feed-description' => 'à¸\95ิà¸\94à¸\95ามà¸\81ารà¸\9bรัà¸\9aà¸\9bรุà¸\87ลà¹\88าสุà¸\94à¹\83à¸\99วิà¸\81ิà¸\99ีà¹\89à¹\83à¸\99à¸\9fีà¸\94à¸\99ีà¹\89',
+'recentchanges-label-newpage' => 'การแก้ไขนี้สร้างหน้าใหม่',
'recentchanges-label-minor' => 'เป็นการแก้ไขเล็กน้อย',
'recentchanges-label-bot' => 'การแก้ไขนี้กระทำโดยบอต',
'recentchanges-label-unpatrolled' => 'การแก้ไขนี้ยังไม่ได้ตรวจสอบ',
'rcnote' => "รายการด้านล่างคือการแก้ไข {{PLURAL:$1|'''1''' รายการ|ล่าสุด '''$1''' รายการ}} ในช่วง '''$2''' วันที่ผ่านมา จนถึง $5, $4",
-'rcnotefrom' => "à¹\81สà¸\94à¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¸\95ัà¹\89à¸\87à¹\81à¸\95à¹\88 '''$2''' (à¹\81สà¸\94à¸\87 '''$1''' รายการ)",
-'rclistfrom' => 'แสดงการเปลี่ยนแปลงตั้งแต่ $1',
+'rcnotefrom' => "à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¸\95ัà¹\89à¸\87à¹\81à¸\95à¹\88 '''$2''' (มาà¸\81สุà¸\94 '''$1''' รายการ)",
+'rclistfrom' => 'à¹\81สà¸\94à¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¹\83หมà¹\88à¹\80ริà¹\88มà¸\95ัà¹\89à¸\87à¹\81à¸\95à¹\88 $1',
'rcshowhideminor' => '$1การแก้ไขเล็กน้อย',
'rcshowhidebots' => '$1บอต',
'rcshowhideliu' => '$1ผู้ใช้ล็อกอิน',
'rc_categories_any' => 'ใด ๆ',
'rc-change-size-new' => '$1 ไบต์หลังปรับปรุง',
'newsectionsummary' => '/* $1 */ หัวข้อใหม่',
-'rc-enhanced-expand' => 'à¹\81สà¸\94à¸\87รายละà¹\80à¸à¸µà¸¢à¸\94 (à¸\95à¹\89à¸à¸\87à¹\83à¸\8aà¹\89à¸\88าวาสà¸\84ริà¸\9bà¸\95à¹\8c)',
+'rc-enhanced-expand' => 'แสดงรายละเอียด (จาวาสคริปต์)',
'rc-enhanced-hide' => 'ซ่อนรายละเอียด',
'rc-old-title' => 'เดิมถูกสร้างในชื่อ "$1"',
'recentchangeslinked-toolbox' => 'การปรับปรุงที่เกี่ยวโยง',
'recentchangeslinked-title' => 'การปรับปรุงที่โยงมายัง "$1"',
'recentchangeslinked-noresult' => 'ไม่มีการเปลี่ยนแปลงในหน้าที่ถูกโยงไป ในช่วงเวลาที่กำหนด',
-'recentchangeslinked-summary' => "หà¸\99à¹\89าà¸\99ีà¹\89à¹\81สà¸\94à¸\87รายการปรับปรุงล่าสุดของหน้าที่ถูกโยงไป (หรือไปยังหน้าต่าง ๆ ของหมวดหมู่ที่กำหนด) โดยหน้าที่อยู่ใน[[Special:Watchlist|รายการเฝ้าดู]]แสดงเป็น'''ตัวหนา'''",
+'recentchangeslinked-summary' => "หà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9bà¹\87à¸\99รายการปรับปรุงล่าสุดของหน้าที่ถูกโยงไป (หรือไปยังหน้าต่าง ๆ ของหมวดหมู่ที่กำหนด) โดยหน้าที่อยู่ใน[[Special:Watchlist|รายการเฝ้าดู]]แสดงเป็น'''ตัวหนา'''",
'recentchangeslinked-page' => 'ชื่อหน้า:',
'recentchangeslinked-to' => 'แสดงการเปลี่ยนแปลงที่เชื่อมโยงมายังหน้านี้แทน',
'upload' => 'อัปโหลดไฟล์',
'uploadbtn' => 'อัปโหลดไฟล์',
'reuploaddesc' => 'ยกเลิกการอัปโหลดและกลับไปยังแบบอัปโหลด',
-'upload-tryagain' => 'สà¹\88à¸\87à¸\84ำà¸à¸\98ิà¸\9aายà¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\9bรัà¸\9aà¹\81à¸\95à¹\88à¸\87แล้ว',
+'upload-tryagain' => 'สà¹\88à¸\87à¸\84ำà¸à¸\98ิà¸\9aายà¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\94ัà¸\94à¹\81à¸\9bรแล้ว',
'uploadnologin' => 'ไม่ได้ล็อกอิน',
'uploadnologintext' => 'ต้อง[[Special:UserLogin|ล็อกอิน]]ก่อนจึงจะอัปโหลดไฟล์ได้',
'upload_directory_missing' => 'ไดเรกทอรีสำหรับอัปโหลด ($1) หายไป และเว็บเซิร์ฟเวอร์ไม่สามารถสร้างได้',
-'upload_directory_read_only' => 'à¹\84มà¹\88สามารà¸\96à¹\80à¸\81à¹\87à¸\9aà¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\83à¸\99à¹\84à¸\94à¹\80รà¸\81à¸\97à¸à¸£à¸µ ($1) à¸\9bัà¸\8dหาà¹\80à¸\81ิà¸\94à¸\97ีà¹\88à¹\80วà¹\87à¸\9aà¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วà¸à¸£à¹\8c',
-'uploaderror' => 'à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\80à¸\81ิà¸\94à¸\82à¹\89à¸à¸\9cิà¸\94à¸\9eลาà¸\94',
+'upload_directory_read_only' => 'à¹\80วà¹\87à¸\9aà¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วà¸à¸£à¹\8cà¹\84มà¹\88สามารà¸\96à¹\80à¸\81à¹\87à¸\9aà¸\82à¹\89à¸à¸¡à¸¹à¸¥à¹\83à¸\99à¹\84à¸\94à¹\80รà¸\81à¸\97à¸à¸£à¸µ ($1)',
+'uploaderror' => 'การอัปโหลดผิดพลาด',
'upload-recreate-warning' => "'''คำเตือน: ไฟล์ชื่อนั้นถูกลบหรือเปลี่ยนชื่อแล้ว'''
ปูมการลบและปูมการย้ายของหน้านี้ถูกนำมาไว้ด้านล่างเพื่อความสะดวก:",
'uploadtext' => "กรุณาใช้แบบด้านล่างในการอัปโหลดไฟล์
-สำหรัà¸\9aà¸\81ารà¸\94ูหรืà¸à¸\81ารà¸\84à¹\89à¸\99หาà¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¹\80à¸\84ยà¸à¸±à¸\9bà¹\82หลà¸\94à¸\81à¹\88à¸à¸\99หà¸\99à¹\89าà¸\99ีà¹\89 à¹\83หà¹\89à¹\84à¸\9bà¸\97ีà¹\88[[Special:FileList|รายà¸\8aืà¹\88à¸ไฟล์ที่ถูกอัปโหลด]] การอัปโหลดและการอัปโหลดซ้ำดูได้ที่[[Special:Log/upload|ปูมการอัปโหลด]] และการลบไฟล์ดูได้ที่[[Special:Log/delete|ปูมการลบ]]
+สำหรัà¸\9aà¸\81ารà¸\94ูหรืà¸à¸\81ารà¸\84à¹\89à¸\99หาà¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¹\80à¸\84ยà¸à¸±à¸\9bà¹\82หลà¸\94à¸\81à¹\88à¸à¸\99หà¸\99à¹\89าà¸\99ีà¹\89 à¹\83หà¹\89à¹\84à¸\9bà¸\97ีà¹\88[[Special:FileList|รายà¸\81ารไฟล์ที่ถูกอัปโหลด]] การอัปโหลดและการอัปโหลดซ้ำดูได้ที่[[Special:Log/upload|ปูมการอัปโหลด]] และการลบไฟล์ดูได้ที่[[Special:Log/delete|ปูมการลบ]]
ถ้าต้องการแทรกไฟล์ลงในหน้าหนึ่ง ๆ ให้ใช้คำสั่งหนึ่งในรูปแบบต่อไปนี้
* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' เพื่อใช้รูปขนาดเต็ม
* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|ข้อความอธิบาย]]</nowiki></code>''' เพื่อใช้รูปย่อขนาดกว้าง 200 พิกเซลในกล่องที่จัดชิดซ้าย โดยมี \"ข้อความอธิบาย\" เป็นคำบรรยายใต้ภาพ
* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' สำหรับการเชื่อมโยงไฟล์โดยตรง โดยไม่ปรากฏไฟล์นั้นออกมา",
-'upload-permitted' => 'à¸\8aà¸\99ิà¸\94à¸\82à¸à¸\87à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89: $1',
-'upload-preferred' => 'à¸\8aà¸\99ิà¸\94à¸\82à¸à¸\87à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\84วรà¹\83à¸\8aà¹\89: $1',
-'upload-prohibited' => 'à¸\8aà¸\99ิà¸\94à¸\82à¸à¸\87à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¹\84มà¹\88à¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\83à¸\8aà¹\89: $1',
+'upload-permitted' => 'à¸\8aà¸\99ิà¸\94à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸à¸\99ุà¸\8dาà¸\95: $1',
+'upload-preferred' => 'ชนิดไฟล์ที่ควรใช้: $1',
+'upload-prohibited' => 'à¸\8aà¸\99ิà¸\94à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¹\84มà¹\88à¸à¸\99ุà¸\8dาà¸\95: $1',
'uploadlog' => 'ปูมการอัปโหลด',
'uploadlogpage' => 'ปูมการอัปโหลด',
-'uploadlogpagetext' => 'รายการแสดงไฟล์ที่อัปโหลดล่าสุด',
+'uploadlogpagetext' => 'ด้านล่างเป็นรายการการอัปโหลดไฟล์ล่าสุด
+ดูภาพรวมที่ [[Special:NewFiles|แกลอรีไฟล์ใหม่]]',
'filename' => 'ชื่อไฟล์',
'filedesc' => 'รายละเอียดไฟล์',
'fileuploadsummary' => 'รายละเอียดไฟล์:',
-'filereuploadsummary' => 'à¹\84à¸\9fลà¹\8cà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87:',
+'filereuploadsummary' => 'à¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¹\84à¸\9fลà¹\8c:',
'filestatus' => 'สถานะลิขสิทธิ์:',
'filesource' => 'แหล่งที่มา:',
'uploadedfiles' => 'ไฟล์ที่อัปโหลดแล้ว',
'ignorewarning' => 'บันทึกไฟล์โดยละเลยคำเตือน',
-'ignorewarnings' => 'à¹\84มà¹\88à¹\81สà¸\94à¸\87à¸\84ำà¹\80à¸\95ืà¸à¸\99',
+'ignorewarnings' => 'ละà¹\80ลยà¸\84ำà¹\80à¸\95ืà¸à¸\99à¸\97ัà¹\89à¸\87หมà¸\94',
'minlength1' => 'ชื่อไฟล์ต้องมีตัวอักษรอย่างน้อยหนึ่งตัว',
-'illegalfilename' => 'à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8c "$1" มีà¸\95ัวà¸à¸±à¸\81ษรà¸\97ีà¹\88à¹\84มà¹\88à¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¸\9bราà¸\81à¸\8fà¹\83à¸\99à¸\8aืà¹\88ภà¸\81รุà¸\93าà¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¹\81ละอัปโหลดอีกครั้ง',
+'illegalfilename' => 'à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8c "$1" มีà¸à¸±à¸\81à¸\82ระà¸\97ีà¹\88à¹\84มà¹\88à¸à¸\99ุà¸\8dาà¸\95à¹\83à¸\99à¸\8aืà¹\88à¸à¹\80รืà¹\88à¸à¸\87หà¸\99à¹\89า à¸\81รุà¸\93าà¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¹\81ละลà¸à¸\87อัปโหลดอีกครั้ง',
'filename-toolong' => 'ชื่อไฟล์ไม่อาจยาวกว่า 240 ไบต์',
'badfilename' => 'ชื่อไฟล์ถูกเปลี่ยนเป็น "$1"',
-'filetype-mime-mismatch' => 'นามสกุลไฟล์ ".$1" ไม่ตรงกับชนิด MIME ของแฟ้มที่ตรวจพบ ($2)',
+'filetype-mime-mismatch' => 'นามสกุลไฟล์ ".$1" ไม่ตรงกับชนิดไมม์ของไฟล์ที่ตรวจพบ ($2)',
'filetype-badmime' => 'ไม่อนุญาตให้อัปโหลดไฟล์ที่เป็นไมม์ชนิด "$1"',
-'filetype-bad-ie-mime' => 'ไม่สามารถอัปโหลดไฟล์นี้เนื่องจาก Internet Explorer จะตรวจจับว่าเป็น "$1" ซึ่งเป็นชนิดไฟล์ที่ไม่อนุญาตและอาจเป็นอันตราย',
+'filetype-bad-ie-mime' => 'ไม่สามารถอัปโหลดไฟล์นี้เนื่องจากอินเทอร์เน็ตเอกซ์พลอเรอร์จะตรวจจับว่าเป็น "$1" ซึ่งเป็นชนิดไฟล์ที่ไม่อนุญาตและอาจเป็นอันตราย',
'filetype-unwanted-type' => "{{PLURAL:\$3|ไฟล์|ไฟล์}}ชนิด '''\".\$1\"''' เป็นไฟล์ที่ไม่สามารถอัปโหลดได้ ไฟล์ที่สามารถใช้ได้ ได้แก่ \$2",
'filetype-banned-type' => '\'\'\'".$1"\'\'\' {{PLURAL: $4|เป็นชนิดไฟล์ที่ไม่อนุญาต|เป็นชนิดไฟล์ที่ไม่อนุญาต}}
-{{PLURAL: $3|ชนิดไฟล์|ชนิดไฟล์}}ที่อนุญาตคือ $2',
+{{PLURAL:$3|ชนิดไฟล์|ชนิดไฟล์}}ที่อนุญาตคือ $2',
'filetype-missing' => 'นามสกุลไฟล์หายไป (เช่น ".jpg")',
-'empty-file' => 'à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\84ุà¸\93สà¹\88à¸\87มาà¸\99ัà¹\89à¸\99à¹\84มà¹\88มีà¸\82à¹\89à¸à¸¡à¸¹à¸¥',
+'empty-file' => 'à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\84ุà¸\93สà¹\88à¸\87มาà¸\99ัà¹\89à¸\99วà¹\88าà¸\87',
'file-too-large' => 'ไฟล์ที่คุณส่งมามีขนาดใหญ่เกินไป',
'filename-tooshort' => 'ชื่อไฟล์สั้นเกินไป',
-'filetype-banned' => 'à¹\84à¸\9fลà¹\8cà¸\9bระà¹\80ภà¸\97นี้ถูกห้าม',
+'filetype-banned' => 'à¹\84à¸\9fลà¹\8cà¸\8aà¸\99ิà¸\94นี้ถูกห้าม',
'verification-error' => 'ไฟล์นี้ไม่ผ่านการพิสูจน์ยืนยันไฟล์',
'hookaborted' => 'สิ่งที่คุณพยายามปรับเปลี่ยนถูกยกเลิกโดยส่วนขยาย',
'illegal-filename' => 'ชื่อไฟล์นี้ไม่ได้รับอนุญาต',
'unknown-error' => 'เกิดข้อผิดพลาดไม่ทราบสาเหตุ',
'tmp-create-error' => 'ไม่สามารถสร้างไฟล์ชั่วคราว',
'tmp-write-error' => 'เกิดข้อผิดพลาดในการเขียนไฟล์ชั่วคราว',
-'large-file' => 'ไฟล์ไม่ควรมีขนาดใหญ่กว่า $1 ไฟล์นี้มีขนาด $2',
-'largefileserver' => 'à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89มีà¸\82à¸\99าà¸\94à¹\83หà¸\8dà¹\88à¸\81วà¹\88าà¸\84à¹\88าà¸\97ีà¹\88à¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\83à¸\8aà¹\89à¹\84à¸\94à¹\89',
-'emptyfile' => 'à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸à¸±à¸\9bà¹\82หลà¸\94มาà¹\80หมืà¸à¸\99à¹\84à¸\9fลà¹\8cวà¹\88าà¸\87 à¸à¸²à¸\88à¹\80à¸\81ิà¸\94à¸\88าà¸\81à¸\9bัà¸\8dหาà¸\9eิมà¸\9eà¹\8cà¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¸\9cิà¸\94 à¸\81รุà¸\93าà¸\95รวà¸\88สà¸à¸\9aà¹\84à¸\9fลà¹\8cà¸à¸µà¸\81à¸\84รัà¹\89à¸\87 à¹\81ละà¹\81à¸\99à¹\88à¹\83à¸\88วà¹\88าà¸\95à¹\89à¸à¸\87à¸\81ารà¸\97ีà¹\88à¸\88ะà¸à¸±à¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89',
-'windows-nonascii-filename' => 'วิà¸\81ิà¸\99ีà¹\89à¹\84มà¹\88รà¸à¸\87รัà¸\9aà¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88มีà¸\95ัวà¸à¸±à¸\81ษรพิเศษ',
+'large-file' => 'à¹\81à¸\99ะà¸\99ำวà¹\88าà¹\84à¸\9fลà¹\8cà¹\84มà¹\88à¸\84วรมีà¸\82à¸\99าà¸\94à¹\83หà¸\8dà¹\88à¸\81วà¹\88า $1 à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89มีà¸\82à¸\99าà¸\94 $2',
+'largefileserver' => 'à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89มีà¸\82à¸\99าà¸\94à¹\83หà¸\8dà¹\88à¸\81วà¹\88าà¸\97ีà¹\88à¹\80à¸\8bิรà¹\8cà¸\9fà¹\80วà¸à¸£à¹\8cà¸à¸\99ุà¸\8dาà¸\95',
+'emptyfile' => 'à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\84ุà¸\93à¸à¸±à¸\9bà¹\82หลà¸\94à¹\80หมืà¸à¸\99à¹\80à¸\9bà¹\87à¸\99à¹\84à¸\9fลà¹\8cวà¹\88าà¸\87 à¸à¸²à¸\88à¹\80à¸\81ิà¸\94à¸\88าà¸\81à¸\9bัà¸\8dหาà¸\9eิมà¸\9eà¹\8cà¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¸\9cิà¸\94 à¸\81รุà¸\93าà¸\95รวà¸\88สà¸à¸\9aวà¹\88า à¸\84ุà¸\93à¸\95à¹\89à¸à¸\87à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89à¸\88ริà¸\87 à¹\86',
+'windows-nonascii-filename' => 'วิà¸\81ิà¸\99ีà¹\89à¹\84มà¹\88รà¸à¸\87รัà¸\9aà¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88มีà¸à¸±à¸\81à¸\82ระพิเศษ',
'fileexists' => 'มีไฟล์ชื่อนี้อยู่แล้ว กรุณาตรวจสอบ <strong>[[:$1]]</strong> หากคุณไม่แน่ใจว่าต้องการเปลี่ยนแปลงไฟล์นี้หรือไม่ [[$1|thumb]]',
-'filepageexists' => 'หà¸\99à¹\89าà¸\84ำà¸à¸\98ิà¸\9aายสำหรัà¸\9aà¹\84à¸\9fลà¹\8cà¸\99ีà¹\89à¹\84à¸\94à¹\89à¸\96ูà¸\81สรà¹\89าà¸\87à¹\84วà¹\89à¹\81ลà¹\89วà¸\97ีà¹\88 <strong>[[:$1]]</strong> à¹\81à¸\95à¹\88à¹\84à¸\9fลà¹\8cà¸\8aืà¹\88à¸à¸\99ีà¹\89à¹\84มà¹\88มีà¸à¸¢à¸¹à¹\88à¹\83à¸\99à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99
-สาระสำà¸\84ัà¸\8dà¸\97ีà¹\88à¸\84ุà¸\93à¸\9aัà¸\99à¸\97ึกจะไม่ปรากฏบนหน้าคำอธิบาย
-à¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89สาระสำà¸\84ัà¸\8dปรากฏขึ้น คุณจำเป็นต้องแก้ไขด้วยตนเอง
+'filepageexists' => 'หน้าคำอธิบายสำหรับไฟล์นี้ได้ถูกสร้างแล้วที่ <strong>[[:$1]]</strong> แต่ไฟล์ชื่อนี้ไม่มีอยู่ในปัจจุบัน
+à¸\84ำà¸à¸\98ิà¸\9aายà¸à¸¢à¹\88าà¸\87ยà¹\88à¸à¸\97ีà¹\88à¸\84ุà¸\93à¸\81รà¸กจะไม่ปรากฏบนหน้าคำอธิบาย
+à¹\80à¸\9eืà¹\88à¸à¹\83หà¹\89à¸\84ำà¸à¸\98ิà¸\9aายà¸à¸¢à¹\88าà¸\87ยà¹\88à¸ปรากฏขึ้น คุณจำเป็นต้องแก้ไขด้วยตนเอง
[[$1|thumb]]',
-'fileexists-extension' => 'à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¹\82หลà¸\94มีà¸\8aืà¹\88à¸à¹\83à¸\81ลà¹\89à¹\80à¸\84ียà¸\87: [[$2|thumb]]
+'fileexists-extension' => 'มีà¹\84à¸\9fลà¹\8cà¸\8aืà¹\88à¸à¸\84ลà¹\89ายà¸\81ัà¸\99: [[$2|thumb]]
* ชื่อไฟล์ที่กำลังอัปโหลด: <strong>[[:$1]]</strong>
-* ชื่อไฟล์ที่มีอยู่แล้ว: <strong>[[:$2]]</strong>
-à¸\81รุà¸\93าà¹\80ลืà¸à¸\81à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¹\83หมà¹\88',
-'fileexists-thumbnail-yes' => "ไฟล์นี้ดูเหมือนจะเป็นภาพที่ถูกลดขนาดมา ''(รูปย่อ)''
+* ชื่อไฟล์ที่มีอยู่: <strong>[[:$2]]</strong>
+à¸\81รุà¸\93าà¹\80ลืà¸à¸\81à¸\8aืà¹\88à¸à¸à¸·à¹\88à¸\99',
+'fileexists-thumbnail-yes' => "ไฟล์นี้ดูเหมือนจะเป็นภาพที่ถูกลดขนาด ''(รูปย่อ)''
[[$1|thumb]]
กรุณาตรวจสอบไฟล์ <strong>[[:$1]]</strong>
-à¸\96à¹\89าà¸\95รวà¸\88สà¸à¸\9aà¹\81ลà¹\89วà¹\81ละà¸\9eà¸\9aวà¹\88าà¹\80à¸\9bà¹\87à¸\99ภาà¸\9eà¹\80à¸\94ียวà¸\81ัà¸\99à¸\81ัà¸\9aภาà¸\9eต้นฉบับ ไฟล์นั้นไม่จำเป็นต้องอัปโหลดเพิ่ม",
+à¸\96à¹\89าà¸\95รวà¸\88สà¸à¸\9aà¹\81ลà¹\89วà¹\81ละà¸\9eà¸\9aวà¹\88าà¹\80à¸\9bà¹\87à¸\99ภาà¸\9eà¸\82à¸\99าà¸\94à¹\80à¸\94ียวà¸\81ัà¸\9aต้นฉบับ ไฟล์นั้นไม่จำเป็นต้องอัปโหลดเพิ่ม",
'file-thumbnail-no' => "ชื่อไฟล์ขึ้นต้นด้วย <strong>$1</strong>
-ภาพนี้ดูเหมือนว่าจะเป็นภาพที่ถูกลดขนาดมา ''(thumbnail)''
-ถ้าคุณมีไฟล์ต้นฉบับขนาดใหญ่กว่านี้ กรุณาอัปโหลดไฟล์ต้นฉบับ หรือเปลี่ยนชื่อไฟล์ด้วย",
-'fileexists-forbidden' => 'ไฟล์ชื่อนี้มีอยู่แล้วในระบบ และไม่สามารถอัปโหลดทับได้
-หากคุณยังคงต้องการอัปโหลดไฟล์ของคุณ กรุณาย้อนกลับและใช้ชื่อใหม่ [[ไฟล์:$1|thumb|center|$1]]',
+ภาพนี้ดูเหมือนว่าจะเป็นภาพที่ถูกลดขนาด ''(thumbnail)''
+ถ้าคุณมีภาพนี้ในความละเอียดเต็ม ให้อัปโหลดภาพนี้ มิฉะนั้นแล้วโปรดเปลี่ยนชื่อไฟล์",
+'fileexists-forbidden' => 'มีไฟล์ชื่อนี้แล้ว และไม่สามารถเขียนทับได้
+หากคุณยังต้องการอัปโหลดไฟล์ของคุณ กรุณาย้อนกลับและใช้ชื่อใหม่
+[[ไฟล์:$1|thumb|center|$1]]',
'fileexists-shared-forbidden' => 'ไฟล์ที่ใช้ชื่อนี้มีอยู่แล้วในระบบเก็บไฟล์ในส่วนกลาง
ถ้าคุณยังคงต้องการอัปโหลดไฟล์ของคุณ กรุณาย้อนกลับไปตั้งชื่อใหม่
[[File:$1|thumb|center|$1]]',
'file-exists-duplicate' => 'ไฟล์นี้ซ้ำกับ{{PLURAL:$1|ไฟล์|ไฟล์}}ต่อไปนี้:',
-'file-deleted-duplicate' => 'à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\95รà¸\87à¸\81ัà¸\9aà¸\8aืà¹\88à¸à¸\99ีà¹\89 ([[:$1]]) à¹\80à¸\84ยà¸\96ูà¸\81ลà¸\9aà¹\84à¸\9bà¸\81à¹\88à¸à¸\99หà¸\99à¹\89า
+'file-deleted-duplicate' => 'à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¹\80หมืà¸à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89 ([[:$1]]) à¹\80à¸\84ยà¸\96ูà¸\81ลà¸\9aà¹\84à¸\9bà¸\81à¹\88à¸à¸\99หà¸\99à¹\89าà¸\99ีà¹\89à¹\81ลà¹\89ว
คุณควรตรวจสอบว่าประวัติการลบของไฟล์ก่อนดำเนินการอัปโหลดใหม่',
'uploadwarning' => 'คำเตือนการอัปโหลด',
'uploadwarning-text' => 'กรุณาแก้ไขคำอธิบายไฟล์ด้านล่างนี้ แล้วลองใหม่อีกครั้ง',
'savefile' => 'บันทึกไฟล์',
'uploadedimage' => 'อัปโหลด "[[$1]]"',
'overwroteimage' => 'อัปโหลดรุ่นใหม่ของ "[[$1]]"',
-'uploaddisabled' => 'à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99อัปโหลด',
-'copyuploaddisabled' => 'à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\82à¸\94ย URL à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99à¹\84วà¹\89',
-'uploadfromurl-queued' => 'à¸\81ารà¸à¸±à¸\9eà¹\82หลà¸\94à¸\82à¸à¸\87à¸\84ุà¸\93à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\88ัà¸\94à¹\83à¸\99คิวแล้ว',
-'uploaddisabledtext' => 'à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8cà¸\96ูà¸\81à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99',
-'php-uploaddisabledtext' => 'à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8cà¸\96ูà¸\81à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99à¹\83à¸\99 PHP
+'uploaddisabled' => 'à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารอัปโหลด',
+'copyuploaddisabled' => 'à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\82à¸\94ยยูà¸à¸²à¸£à¹\8cà¹\81à¸à¸¥',
+'uploadfromurl-queued' => 'à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¸\82à¸à¸\87à¸\84ุà¸\93à¸\96ูà¸\81à¸\88ัà¸\94คิวแล้ว',
+'uploaddisabledtext' => 'à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8c',
+'php-uploaddisabledtext' => 'à¹\80à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\84à¸\9fลà¹\8cà¹\83à¸\99à¸\9eีà¹\80à¸à¸\8aà¸\9eี
กรุณาตรวจสอบการตั้งค่า file_uploads',
'uploadscripted' => 'ไฟล์นี้มีส่วนประกอบของโค้ดเอชทีเอ็มแอลหรือสคริปต์ ซึ่งอาจก่อให้เกิดความผิดพลาดในการแสดงผลของเว็บเบราว์เซอร์',
'uploadvirus' => 'ไฟล์นี้มีไวรัส! รายละเอียด: $1',
'upload-source' => 'ไฟล์ต้นทาง',
'sourcefilename' => 'ชื่อไฟล์ต้นทาง:',
-'sourceurl' => 'URL ที่มา:',
-'destfilename' => 'à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\95à¹\89à¸à¸\87à¸\81าร:',
+'sourceurl' => 'ยูอาร์แอลที่มา:',
+'destfilename' => 'à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¸\9bลายà¸\97าà¸\87:',
'upload-maxfilesize' => 'ขนาดไฟล์ที่ใหญ่ที่สุดที่อนุญาต: $1',
'upload-description' => 'คำอธิบายไฟล์',
'upload-options' => 'ตัวเลือกอัปโหลด',
'watchthisupload' => 'เฝ้าดูไฟล์นี้',
-'filewasdeleted' => 'à¹\84à¸\9fลà¹\8cà¹\83à¸\99à¸\8aืà¹\88à¸à¸\99ีà¹\89à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸à¸±à¸\9bà¹\82หลà¸\94à¸\81à¹\88à¸à¸\99หà¸\99à¹\89าà¹\81ละà¸\96ูà¸\81ลà¸\9aà¹\84à¸\9bà¹\81ลà¹\89ว à¸\81รุà¸\93าà¸\95รวà¸\88สà¸à¸\9a $1 à¸\81à¹\88à¸à¸\99à¸\97ีà¹\88à¸\88ะà¸à¸±à¸\9bà¹\82หลà¸\94à¹\83หมà¹\88อีกครั้ง',
-'filename-bad-prefix' => "à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\84ุà¸\93à¸\81ำลัà¸\87à¸\88ะà¸à¸±à¸\9bà¹\82หลà¸\94à¹\80à¸\82à¹\89ามาà¸\99ีà¹\89มีà¸\8aืà¹\88à¸à¸\97ีà¹\88à¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99à¸\94à¹\89วย '''\"\$1\"''' à¸\8bึà¹\88à¸\87à¹\80à¸\9bà¹\87à¸\99à¸\8aืà¹\88à¸à¸\97ีà¹\88à¹\84มà¹\88สืà¹\88à¸à¸\84วามหมายà¹\83à¸\94 à¹\86 à¸\97ีà¹\88à¹\82à¸\94ยà¸\9bà¸\81à¸\95ิà¹\81ลà¹\89วà¸\8aืà¹\88à¸à¸\99ีà¹\89à¸\88ะà¸\96ูà¸\81à¸\95ัà¹\89à¸\87à¹\82à¸\94ยà¸\81ลà¹\89à¸à¸\87à¸\96à¹\88ายรูà¸\9bà¸\94ิà¸\88ิà¸\97ัลà¸à¸±à¸\95à¹\82à¸\99มัà¸\95ิ à¸\81รุà¸\93าà¸\95ัà¹\89à¸\87à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¹\83หมà¹\88à¸\97ีà¹\88สื่อความหมายกว่าเดิม",
+'filewasdeleted' => 'à¹\84à¸\9fลà¹\8cà¸\8aืà¹\88à¸à¸\99ีà¹\89à¸\96ูà¸\81à¸à¸±à¸\9bà¹\82หลà¸\94à¸\81à¹\88à¸à¸\99หà¸\99à¹\89าà¹\81ละà¸\96ูà¸\81ลà¸\9aà¹\84à¸\9bà¹\81ลà¹\89ว à¸\81รุà¸\93าà¸\95รวà¸\88สà¸à¸\9a $1 à¸\81à¹\88à¸à¸\99à¸à¸±à¸\9bà¹\82หลà¸\94อีกครั้ง',
+'filename-bad-prefix' => "à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¸\97ีà¹\88à¸\84ุà¸\93à¸\81ำลัà¸\87à¸à¸±à¸\9bà¹\82หลà¸\94à¸\82à¹\89à¸\99à¸\95à¹\89à¸\99à¸\94à¹\89วย '''\"\$1\"''' à¸\8bึà¹\88à¸\87à¹\80à¸\9bà¹\87à¸\99à¸\8aืà¹\88à¸à¸\97ีà¹\88à¹\84มà¹\88สืà¹\88à¸à¸\84วามหมายà¹\83à¸\94 à¹\86 à¸\97ีà¹\88à¹\82à¸\94ยà¸\9bà¸\81à¸\95ิà¹\81ลà¹\89วà¸\81ลà¹\89à¸à¸\87à¸\96à¹\88ายรูà¸\9bà¸\94ิà¸\88ิà¸\97ัลà¸\95ัà¹\89à¸\87à¹\83หà¹\89à¸à¸±à¸\95à¹\82à¸\99มัà¸\95ิ à¸\81รุà¸\93าà¸\95ัà¹\89à¸\87à¸\8aืà¹\88à¸à¹\84à¸\9fลà¹\8cà¹\83หมà¹\88à¹\83หà¹\89สื่อความหมายกว่าเดิม",
'upload-success-subj' => 'อัปโหลดสำเร็จ',
'upload-success-msg' => 'การอัปโหลดของคุณจาก [$2] สำเร็จแล้ว และสามารถใช้ไฟล์ได้ที่นี่: [[:{{ns:file}}:$1]]',
'upload-failure-subj' => 'ปัญหาการอัปโหลด',
$1',
'upload-warning-subj' => 'คำเตือนการอัปโหลด',
-'upload-warning-msg' => 'à¸\9eà¸\9aà¸\9bัà¸\8dหาà¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¸\82à¸à¸\87à¸\84ุà¸\93à¸\88าà¸\81 [$2] à¸\84ุà¸\93à¸à¸²à¸\88à¸\81ลัà¸\9aà¹\84à¸\9bยัà¸\87[[Special:Upload/stash/$1|à¸\9fà¸à¸£à¹\8cมอัปโหลด]]เพื่อแก้ไขปัญหานี้',
+'upload-warning-msg' => 'à¸\9eà¸\9aà¸\9bัà¸\8dหาà¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¸\82à¸à¸\87à¸\84ุà¸\93à¸\88าà¸\81 [$2] à¸\84ุà¸\93à¸à¸²à¸\88à¸\81ลัà¸\9aà¹\84à¸\9bยัà¸\87[[Special:Upload/stash/$1|à¹\81à¸\9aà¸\9aอัปโหลด]]เพื่อแก้ไขปัญหานี้',
'upload-proto-error' => 'โพรโทคอลไม่ถูกต้อง',
'upload-proto-error-text' => 'การอัปโหลดโดยตรงจากเว็บต้องการยูอาร์แอลที่ขึ้นต้นด้วย <code>http://</code> หรือ <code>ftp://</code>',
'upload-file-error' => 'เกิดความผิดพลาดภายใน',
-'upload-file-error-text' => 'เกิดความผิดพลาดภายใน จากปัญหาการสร้างไฟล์ชั่วคราวที่เซิร์ฟเวอร์ กรุณาติดต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]]',
-'upload-misc-error' => 'à¹\80à¸\81ิà¸\94à¸\9bัà¸\8dหาà¸à¸±à¸\9bà¹\82หลà¸\94',
-'upload-misc-error-text' => 'à¹\80à¸\81ิà¸\94à¸\9bัà¸\8dหาระหวà¹\88าà¸\87à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94 à¸\81รุà¸\93าà¸\95รวà¸\88สà¸à¸\9aวà¹\88ายูà¸à¸²à¸£à¹\8cà¹\81à¸à¸¥à¸\99ัà¹\89à¸\99à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87 à¸\96à¹\89ายัà¸\87à¸\84à¸\87มีà¸\9bัà¸\8dหาà¹\83หà¹\89à¸\95ิà¸\94à¸\95à¹\88à¸à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9a',
-'upload-too-many-redirects' => 'URL ที่ระบุมีการเปลี่ยนทางมากเกินไป',
+'upload-file-error-text' => 'เกิดความผิดพลาดภายในขณะพยายามสร้างไฟล์ชั่วคราวบนเซิร์ฟเวอร์ กรุณาติดต่อ[[Special:ListUsers/sysop|ผู้ดูแลระบบ]]',
+'upload-misc-error' => 'à¹\80à¸\81ิà¸\94à¸\84วามà¸\9cิà¸\94à¸\9eลาà¸\94à¹\83à¸\99à¸\81ารà¸à¸±à¸\9bà¹\82หลà¸\94à¹\82à¸\94ยà¹\84มà¹\88à¸\97ราà¸\9aสาà¹\80หà¸\95ุ',
+'upload-misc-error-text' => 'à¹\80à¸\81ิà¸\94à¸\84วามà¸\9cิà¸\94à¸\9eลาà¸\94à¹\84มà¹\88à¸\97ราà¸\9aสาà¹\80หà¸\95ุระหวà¹\88าà¸\87à¸à¸±à¸\9bà¹\82หลà¸\94 à¸\81รุà¸\93าà¸\95รวà¸\88สà¸à¸\9aวà¹\88ายูà¸à¸²à¸£à¹\8cà¹\81à¸à¸¥à¸\99ัà¹\89à¸\99à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87à¹\81ละà¹\80à¸\82à¹\89าà¸\96ึà¸\87à¹\84à¸\94à¹\89 à¹\81ละลà¸à¸\87à¸à¸µà¸\81à¸\84รัà¹\89à¸\87 à¸\96à¹\89ายัà¸\87มีà¸\9bัà¸\8dหา à¹\83หà¹\89à¸\95ิà¸\94à¸\95à¹\88à¸[[Special:ListUsers/sysop|à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9a]]',
+'upload-too-many-redirects' => 'ยูอาร์แอลที่ระบุมีการเปลี่ยนทางมากเกินไป',
'upload-unknown-size' => 'ไม่ทราบขนาด',
-'upload-http-error' => 'เกิดข้อผิดพลาด HTTP: $1',
+'upload-http-error' => 'เกิดข้อผิดพลาดเอชทีทีพี: $1',
+'upload-copy-upload-invalid-domain' => 'การอัปโหลดสำเนาไม่สามารถทำได้จากโดเมนนี้',
# File backend
'backend-fail-backup' => 'ไม่สามารถสำรองข้อมูลไฟล์ $1.',
-'backend-fail-notexists' => 'à¹\84มà¹\88à¸\9eà¸\9aà¹\84à¸\9fลà¹\8c $1 à¸\97ีà¹\88à¸\95à¹\89à¸à¸\87à¸\81าร',
+'backend-fail-notexists' => 'à¹\84มà¹\88มีà¹\84à¸\9fลà¹\8c $1',
'backend-fail-delete' => 'ไม่สามารถลบไฟล์ $1 ได้',
'backend-fail-alreadyexists' => 'มีไฟล์ "$1" อยู่แล้ว',
'backend-fail-store' => 'ไม่สามารถเก็บไฟล์ "$1" ที่ "$2" ได้',
เซิร์ฟเวอร์ของคุณอาจไม่ได้ถูกตั้งให้ส่งข้อมูลนี้
หรือเซิร์ฟเวอร์อาจเป็นแบบ CGI-based และไม่สนับสนุนข้อมูล img_auth
ดูที่ https://www.mediawiki.org/wiki/Manual:Image_Authorization',
-'img-auth-notindir' => 'à¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸\97ีà¹\88รà¹\89à¸à¸\87à¸\82à¸à¹\84มà¹\88à¹\84à¸\94à¹\89à¸à¸¢à¸¹à¹\88à¹\83à¸\99à¹\84à¸\94à¹\80รà¹\87à¸\81à¸\97à¸à¸£à¸µà¸à¸±à¸\9eà¹\82หลà¸\94à¸\97ีà¹\88à¸\81ำหà¸\99à¸\94à¹\84à¹\89วà¹\89',
+'img-auth-notindir' => 'ที่อยู่ที่ร้องขอไม่ได้อยู่ในไดเร็กทอรีอัพโหลดที่กำหนดไว้',
'img-auth-badtitle' => 'ไม่สามารถสร้างชื่อเรื่องที่ถูกต้องจาก "$1" ได้',
-'img-auth-nologinnWL' => 'à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89ลà¸\87à¸\8aืà¹\88à¸à¹\80à¸\82à¹\89าà¹\83à¸\8aà¹\89และ "$1" ไม่ได้อยู่ในรายชื่อผู้ใช้ที่ดี (whitelist)',
+'img-auth-nologinnWL' => 'à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89ลà¹\87à¸à¸\81à¸à¸´à¸\99และ "$1" ไม่ได้อยู่ในรายชื่อผู้ใช้ที่ดี (whitelist)',
'img-auth-nofile' => 'ไม่มีไฟล์ "$1"',
'img-auth-isdir' => 'คุณกำลังพยายามเข้าถึงไดเร็กทอรี "$1"
ซึ่งคุณสามารถเข้าถึงได้เฉพาะไฟล์เท่านั้น',
'upload-curl-error28' => 'เวลาอัปโหลดถูกตัด',
'upload-curl-error28-text' => 'เว็บไซต์นี้ใช้เวลานานเกินไปในการเชื่อมต่อ กรุณาตรวจสอบว่าเว็บนี้ยังใช้งานได้ตามปกติ หรืออาจจะรอสักครู่แล้วลองอัปโหลดใหม่',
-'license' => 'ลิà¸\82สิà¸\97à¸\98ิà¹\8c:',
-'license-header' => 'à¸\81ารà¸à¸\99ุà¸\8dาà¸\95à¹\82à¸\94ยà¹\80à¸\88à¹\89าà¸\82à¸à¸\87ลิà¸\82สิà¸\97à¸\98ิà¹\8c',
+'license' => 'à¸\81ารà¸à¸\99ุà¸\8dาà¸\95à¹\83à¸\8aà¹\89สิà¸\97à¸\98ิ:',
+'license-header' => 'à¸\81ารà¸à¸\99ุà¸\8dาà¸\95à¹\83à¸\8aà¹\89สิà¸\97à¸\98ิ',
'nolicense' => 'ไม่ได้เลือก',
'license-nopreview' => '(ไม่สามารถแสดงตัวอย่าง)',
-'upload_source_url' => ' (ยูà¸à¸²à¸£à¹\8cà¹\81à¸à¸¥à¸\97ีà¹\88à¸\9aุà¸\84à¸\84ลà¸\97ัà¹\88วà¹\84à¸\9bสามารถเข้าถึงได้)',
+'upload_source_url' => ' (ยูà¸à¸²à¸£à¹\8cà¹\81à¸à¸¥à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87à¸\97ีà¹\88สาà¸\98ารà¸\93ะสามารถเข้าถึงได้)',
'upload_source_file' => ' (ไฟล์จากคอมพิวเตอร์คุณ)',
# Special:ListFiles
'filehist-comment' => 'ความเห็น',
'filehist-missing' => 'ไฟล์หายไป',
'imagelinks' => 'การใช้ไฟล์',
-'linkstoimage' => '$1 หน้าลิงก์มายังไฟล์นี้:',
-'linkstoimage-more' => 'à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89มีà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87มาà¸\81à¸\81วà¹\88า $1 à¹\81หà¹\88à¸\87
-รายà¸\81ารà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¹\81สà¸\94à¸\87à¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87 $1 à¹\81หà¹\88à¸\87แรกที่มายังไฟล์นี้เท่านั้น
-à¸\94ูà¹\80à¸\9eิà¹\88มà¹\84à¸\94à¹\89à¸\97ีà¹\88[[Special:WhatLinksHere/$2|รายà¸\8aืà¹\88à¸เต็ม]]',
-'nolinkstoimage' => 'à¹\84มà¹\88มีหà¸\99à¹\89าà¸\97ีà¹\88ลิà¸\87à¸\81à¹\8cมาไฟล์นี้',
-'morelinkstoimage' => 'à¸\94ู[[Special:WhatLinksHere/$1|หà¸\99à¹\89าà¸\97ีà¹\88ลิà¸\87à¸\81à¹\8c]]มายังไฟล์นี้เพิ่มเติม',
-'linkstoimage-redirect' => '$1 (à¹\81à¸\9fà¹\89มเปลี่ยนทาง) $2',
-'duplicatesoffile' => '$1 ไฟล์ต่อไปนี้ เป็นไฟล์เดียวกับไฟล์นี้ ([[Special:FileDuplicateSearch/$2|รายละเอียดเพิ่ม]]):',
+'linkstoimage' => 'มี $1 หน้าเชื่อมโยงมายังไฟล์นี้:',
+'linkstoimage-more' => 'à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89มีหà¸\99à¹\89าà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87มาà¸\81วà¹\88า $1 หà¸\99à¹\89า
+รายà¸\81ารà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¹\81สà¸\94à¸\87à¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87 $1 หà¸\99à¹\89าแรกที่มายังไฟล์นี้เท่านั้น
+à¸\94ูà¹\80à¸\9eิà¹\88มà¹\84à¸\94à¹\89à¸\97ีà¹\88[[Special:WhatLinksHere/$2|รายà¸\81ารเต็ม]]',
+'nolinkstoimage' => 'à¹\84มà¹\88มีหà¸\99à¹\89าà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87มายัà¸\87ไฟล์นี้',
+'morelinkstoimage' => 'à¸\94ู[[Special:WhatLinksHere/$1|à¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87]]มายังไฟล์นี้เพิ่มเติม',
+'linkstoimage-redirect' => '$1 (à¹\84à¸\9fลà¹\8cเปลี่ยนทาง) $2',
+'duplicatesoffile' => '$1 ไฟล์ต่อไปนี้ เป็นไฟล์เดียวกับไฟล์นี้ ([[Special:FileDuplicateSearch/$2|รายละเอียดเพิ่มเติม]]):',
'sharedupload' => 'ไฟล์นี้มาจาก $1 และอาจมีการใช้ในโครงการอื่น',
-'sharedupload-desc-there' => 'ไฟล์นี้มาจาก $1 และอาจถูกใช้บนโครงการอื่น ๆ
-กรุณาดู [หน้าคำอธิบายของไฟล์ $2] สำหรับข้อมูลเพิ่มเติม',
+'sharedupload-desc-there' => 'ไฟล์นี้มาจาก $1 และอาจถูกใช้บนโครงการอื่น
+กรุณาดู[หน้าคำอธิบายไฟล์ $2] สำหรับข้อมูลเพิ่มเติม',
'sharedupload-desc-here' => 'ไฟล์นี้มาจาก $1 และอาจมีใช้ในโครงการอื่น
-à¸\84ำà¸à¸\98ิà¸\9aายà¹\83à¸\99[$2 หà¸\99à¹\89าà¹\84à¸\9fลà¹\8c]à¹\84à¸\94à¹\89แสดงไว้ข้างล่างนี้',
-'sharedupload-desc-edit' => 'à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89มาà¸\88าà¸\81 $1 à¹\81ละà¸à¸²à¸\88มีà¸\81ารà¹\83à¸\8aà¹\89à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89à¹\83à¸\99à¹\82à¸\84รà¸\87à¸\81ารà¸à¸·à¹\88à¸\99 à¹\86 à¸à¸µà¸\81
-หากคุณต้องการแก้ไขคำอธิบาย ให้ดำเนินการ[$2 ที่นี่]',
-'sharedupload-desc-create' => 'ไฟล์นี้มาจาก $1 และอาจมีการใช้ไฟล์นี้ในโครงการอื่น ๆ อีก
-หากคุณต้องการแก้ไขคำอธิบาย ให้ดำเนินการ[$2 ที่นี่]',
+à¸\84ำà¸à¸\98ิà¸\9aายà¹\83à¸\99[$2 หà¸\99à¹\89าà¸\84ำà¸à¸\98ิà¸\9aายà¹\84à¸\9fลà¹\8c]แสดงไว้ข้างล่างนี้',
+'sharedupload-desc-edit' => 'à¹\84à¸\9fลà¹\8cà¸\99ีà¹\89มาà¸\88าà¸\81 $1 à¹\81ละà¸à¸²à¸\88มีà¹\83à¸\8aà¹\89à¹\83à¸\99à¹\82à¸\84รà¸\87à¸\81ารà¸à¸·à¹\88à¸\99
+หากคุณต้องการแก้ไขคำอธิบาย ให้ดำเนินการบน[$2 หน้าคำอธิบายไฟล์]',
+'sharedupload-desc-create' => 'ไฟล์นี้มาจาก $1 และอาจมีการใช้ไฟล์นี้ในโครงการอื่น
+หากคุณต้องการแก้ไขคำอธิบาย ให้ดำเนินการบน[$2 หน้าคำอธิบายไฟล์]',
'filepage-nofile' => 'ไม่มีไฟล์ชื่อนี้',
'filepage-nofile-link' => 'ไม่มีไฟล์ชื่อนี้ แต่คุณสามารถ[$1 อัปโหลด]ได้',
'uploadnewversion-linktext' => 'อัปโหลดรุ่นใหม่ของไฟล์นี้',
# File deletion
'filedelete' => 'ลบ $1',
'filedelete-legend' => 'ลบไฟล์',
-'filedelete-intro' => "à¸\84ุà¸\93à¸\81ำลัà¸\87à¸\88ะลà¸\9aà¹\84à¸\9fลà¹\8c '''[[Media:$1|$1]]''' à¹\84à¸\9bà¸\9eรà¹\89à¸à¸¡à¸\81ัà¸\9aà¸\9bระวัà¸\95ิของไฟล์นี้",
+'filedelete-intro' => "à¸\84ุà¸\93à¸\81ำลัà¸\87ลà¸\9aà¹\84à¸\9fลà¹\8c '''[[Media:$1|$1]]''' à¸\9eรà¹\89à¸à¸¡à¸\81ัà¸\9aà¸\9bระวัà¸\95ิà¸\97ัà¹\89à¸\87หมà¸\94ของไฟล์นี้",
'filedelete-intro-old' => "คุณกำลังลบ '''[[Media:$1|$1]]''' รุ่น [$4 $3, $2]",
'filedelete-comment' => 'เหตุผล:',
'filedelete-submit' => 'ลบ',
** ละเมิดลิขสิทธิ์
** ไฟล์ซ้ำ',
'filedelete-edit-reasonlist' => 'แก้ไขเหตุผลการลบ',
-'filedelete-maintenance' => 'à¸\9bิà¸\94à¸\81ารลà¸\9aà¹\81ละà¹\80รียà¸\81à¸\84ืà¸\99à¹\84à¸\9fลà¹\8cà¹\84วà¹\89à¸\8aัà¹\88วà¸\84ราว à¹\83à¸\99ระหวà¹\88าà¸\87à¸\81ารà¸\8bà¹\88à¸à¸¡à¸\9aำรุà¸\87',
+'filedelete-maintenance' => 'à¸\81ารลà¸\9aà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99à¹\84à¸\9fลà¹\8cà¹\83à¸\8aà¹\89à¸\87าà¸\99à¹\84มà¹\88à¹\84à¸\94à¹\89à¸\8aัà¹\88วà¸\84ราวระหวà¹\88าà¸\87à¸\81ารà¸\9aำรุà¸\87รัà¸\81ษา',
'filedelete-maintenance-title' => 'ไม่สามารถลบไฟล์',
# MIME search
'mimesearch' => 'ค้นหาตามชนิดไมม์',
-'mimesearch-summary' => 'หน้านี้แสดงไฟล์ตามการแบ่งของชนิดไมม์ (MIME) ของแต่ละไฟล์ ใส่ค่า: contenttype/subtype เช่น <code>image/jpeg</code>.',
+'mimesearch-summary' => 'หน้านี้แสดงไฟล์ตามการแบ่งของชนิดไมม์ของแต่ละไฟล์
+ใส่ค่า: contenttype/subtype เช่น <code>image/jpeg</code>',
'mimetype' => 'ชนิดไมม์:',
'download' => 'ดาวน์โหลด',
# Unused templates
'unusedtemplates' => 'แม่แบบไม่ได้ใช้',
-'unusedtemplatestext' => 'หà¸\99à¹\89าà¸\99ีà¹\89à¹\81สà¸\94à¸\87รายà¸\81ารà¸\9aà¸\97à¸\84วามà¸\97ัà¹\89à¸\87หมà¸\94à¹\83à¸\99à¹\80à¸\99มสà¹\80à¸\9bà¸\8b {{ns:template}} à¸\8bึà¹\88à¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¸\96ูà¸\81รวมà¸à¸¢à¸¹à¹\88à¹\83à¸\99หà¸\99à¹\89าà¸à¸·à¹\88à¸\99 à¸\81à¹\88à¸à¸\99à¸\97ีà¹\88à¸\88ะลà¸\9aสà¹\88วà¸\99à¸\99ีà¹\89à¹\83หà¹\89à¸\97ำà¸\81ารà¸\95รวà¸\88สà¸à¸\9aหà¸\99à¹\89าà¸\97ีà¹\88ลิà¸\87à¸\81à¹\8cมาà¸\81à¹\88à¸à¸\99à¸\97ุà¸\81à¸\84รัà¹\89à¸\87',
-'unusedtemplateswlh' => 'ลิà¸\87à¸\81à¹\8cมา',
+'unusedtemplatestext' => 'หà¸\99à¹\89าà¸\99ีà¹\89à¹\81สà¸\94à¸\87รายà¸\81ารหà¸\99à¹\89าà¸\97ัà¹\89à¸\87หมà¸\94à¹\83à¸\99à¹\80à¸\99มสà¹\80à¸\9bà¸\8b {{ns:template}} à¸\8bึà¹\88à¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¸\96ูà¸\81รวมà¸à¸¢à¸¹à¹\88à¹\83à¸\99หà¸\99à¹\89าà¸à¸·à¹\88à¸\99 à¸à¸¢à¹\88าลืมà¸\95รวà¸\88สà¸à¸\9aà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87มายัà¸\87à¹\81มà¹\88à¹\81à¸\9aà¸\9aà¸à¸·à¹\88à¸\99à¸\81à¹\88à¸à¸\99ลà¸\9a',
+'unusedtemplateswlh' => 'à¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¸à¸·à¹\88à¸\99',
# Random page
'randompage' => 'สุ่มหน้า',
'statistics-views-total-desc' => 'ไม่นับรวมจำนวนการเข้าชมหน้าที่ไม่มีอยู่และหน้าพิเศษ',
'statistics-views-peredit' => 'จำนวนการเข้าดูต่อการแก้ไข:',
'statistics-users' => '[[Special:ListUsers|ผู้ใช้]]ลงทะเบียน',
-'statistics-users-active' => 'à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88ยัà¸\87à¹\81à¸\81à¹\89à¹\84à¸\82à¸à¸¢à¸¹à¹\88',
+'statistics-users-active' => 'à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88ยัà¸\87มีà¸\84วามà¹\80à¸\84ลืà¹\88à¸à¸\99à¹\84หว',
'statistics-users-active-desc' => 'ผู้ใช้ที่ดำเนินปฏิบัติการในช่วง $1 วันที่ผ่านมา',
'statistics-mostpopular' => 'หน้าที่มีการเข้าชมมากที่สุด',
-'disambiguations' => 'หà¸\99à¹\89าà¸\97ีà¹\88à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¸\81ัà¸\9aหน้าแก้ความกำกวม',
+'disambiguations' => 'หà¸\99à¹\89าà¸\97ีà¹\88à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84à¸\9bยัà¸\87หน้าแก้ความกำกวม',
'disambiguationspage' => 'Template:แก้กำกวม',
-'disambiguations-text' => "หà¸\99à¹\89าà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89มีà¸à¸¢à¹\88าà¸\87à¸\99à¹\89à¸à¸¢à¸«à¸\99ึà¹\88à¸\87ลิà¸\87à¸\81à¹\8cà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84à¸\9bยัà¸\87'''หà¸\99à¹\89าà¸\84วามà¸\81ำà¸\81วม'''
-à¸\8bึà¹\88à¸\87à¸à¸²à¸\88à¸\95à¹\89à¸à¸\87ลิà¸\87à¸\81à¹\8cà¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¸\97ีà¹\88à¹\80หมาะสมแทน<br />
-หà¸\99à¹\89าà¹\83à¸\94à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\81มà¹\88à¹\81à¸\9aà¸\9aà¸\97ีà¹\88ลิà¸\87à¸\81à¹\8cมาà¸\88าà¸\81 [[MediaWiki:Disambiguationspage]] หà¸\99à¹\89าà¹\80หลà¹\88าà¸\99ัà¹\89à¸\99à¸\88ะà¸\96ูà¸\81à¸\99ัà¸\9aรวมเป็นหน้าความกำกวม",
+'disambiguations-text' => "หà¸\99à¹\89าà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89มีà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84à¸\9bยัà¸\87'''หà¸\99à¹\89าà¸\84วามà¸\81ำà¸\81วม'''à¸à¸¢à¹\88าà¸\87à¸\99à¹\89à¸à¸¢à¸«à¸\99ึà¹\88à¸\87à¹\81หà¹\88à¸\87
+à¸\8bึà¹\88à¸\87à¸à¸²à¸\88à¸\95à¹\89à¸à¸\87à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¸\97ีà¹\88à¹\80หมาะสมà¸\81วà¹\88าแทน<br />
+หà¸\99à¹\89าà¹\83à¸\94à¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\81มà¹\88à¹\81à¸\9aà¸\9aà¸\97ีà¹\88à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87มาà¸\88าà¸\81 [[MediaWiki:Disambiguationspage]] à¸\88ะà¸\96ูà¸\81à¸\99ัà¸\9aเป็นหน้าความกำกวม",
'doubleredirects' => 'หน้าเปลี่ยนทางซ้ำซ้อน',
-'doubleredirectstext' => 'หน้านี้แสดงรายการชื่อที่เปลี่ยนทางไปยังหน้าเปลี่ยนทางอื่น
-แต่ละแถวคือลิงก์ของการเปลี่ยนทางครั้งแรกและครั้งที่สอง พร้อมกับหน้าปลายทางของการเปลี่ยนทางครั้งที่สอง ซึ่งควรแก้ไขการเปลี่ยนทางครั้งแรกเป็นหน้าปลายทางดังกล่าว
-รายการที่ <del>ขีดฆ่า</del> คือรายการที่แก้ไขแล้ว',
-'double-redirect-fixed-move' => '[[$1]] ถูกเปลี่ยนชื่อแล้ว และเปลี่ยนทางไปยัง [[$2]]',
+'doubleredirectstext' => 'หน้านี้แสดงรายการหน้าที่เปลี่ยนทางไปยังหน้าเปลี่ยนทางอื่น
+แต่ละแถวมีการเชื่อมโยงไปยังการเปลี่ยนทางครั้งแรกและครั้งที่สอง เช่นเดียวกับเป้าหมายของการเปลี่ยนทางครั้งที่สอง ซึ่งมักเป็นหน้าเป้าหมาย "ที่แท้จริง" ที่การเปลี่ยนแปลงครั้งแรกควรชี้ไป
+หน่วยที่<del>ขีดฆ่า</del> คือ รายการที่ได้แก้ไขแล้ว',
+'double-redirect-fixed-move' => '[[$1]] ถูกเปลี่ยนชื่อแล้ว
+ขณะนี้เปลี่ยนทางไปยัง [[$2]]',
'double-redirect-fixed-maintenance' => 'การแก้ไขการเปลี่ยนทางซ้ำซ้อนจาก [[$1]] ไปยัง [[$2]]',
-'double-redirect-fixer' => 'Redirect fixer',
+'double-redirect-fixer' => 'ผู้ซ่อมหน้าเปลี่ยนทาง',
'brokenredirects' => 'หน้าเปลี่ยนทางเสีย',
-'brokenredirectstext' => 'หà¸\99à¹\89าà¹\80à¸\9bลีà¹\88ยà¸\99à¸\97าà¸\87à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¸\97ีà¹\88à¹\84มà¹\88มี:',
+'brokenredirectstext' => 'หà¸\99à¹\89าà¹\80à¸\9bลีà¹\88ยà¸\99à¸\97าà¸\87à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84à¸\9bยัà¸\87หà¸\99à¹\89าà¸\97ีà¹\88ยัà¸\87à¹\84มà¹\88à¸\96ูà¸\81สรà¹\89าà¸\87:',
'brokenredirects-edit' => 'แก้ไข',
'brokenredirects-delete' => 'ลบ',
'withoutinterwiki' => 'หน้าที่ไม่มีลิงก์ข้ามภาษา',
'withoutinterwiki-summary' => 'หน้าต่อไปนี้ไม่มีลิงก์ข้ามไปภาษาอื่น',
-'withoutinterwiki-legend' => 'à¸\84ำà¸\99ำหà¸\99à¹\89า',
+'withoutinterwiki-legend' => 'à¸\84ำà¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99',
'withoutinterwiki-submit' => 'แสดง',
-'fewestrevisions' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82น้อยสุด',
+'fewestrevisions' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีรุà¹\88à¸\99น้อยสุด',
# Miscellaneous special pages
'nbytes' => '$1 ไบต์',
'ncategories' => '$1 หมวดหมู่',
-'nlinks' => '$1 {{PLURAL:$1|ลิงก์|ลิงก์}}',
+'ninterwikis' => '$1 ลิงก์ข้ามโครงการ',
+'nlinks' => '$1 ลิงก์',
'nmembers' => '$1 หน้า',
-'nrevisions' => '$1 à¸\84รัà¹\89à¸\87',
+'nrevisions' => '$1 รุà¹\88à¸\99',
'nviews' => '$1 ครั้ง',
'nimagelinks' => 'ใช้ใน $1 {{PLURAL: $1|หน้า|หน้า}}',
'ntransclusions' => 'ใช้ใน $1 {{PLURAL: $1|หน้า|หน้า}}',
-'specialpage-empty' => 'à¹\84มà¹\88มีหà¸\99à¹\89าà¸\97ีà¹\88à¹\80รียà¸\81à¸\94ู',
+'specialpage-empty' => 'à¹\84มà¹\88มีà¸\9cลลัà¸\9eà¸\98à¹\8cรายà¸\87าà¸\99à¸\99ีà¹\89',
'lonelypages' => 'หน้าสุดทาง',
'lonelypagestext' => 'หน้าต่อไปนี้ไม่มีการเชื่อมโยงหรือถูกรวมไว้ในหน้าอื่นใน {{SITENAME}}',
'uncategorizedpages' => 'หน้าที่ไม่ได้จัดหมวดหมู่',
'popularpages' => 'หน้าที่มีการเข้าดูมาก',
'wantedcategories' => 'หมวดหมู่ที่ต้องการ',
'wantedpages' => 'หน้าที่ต้องการ',
-'wantedpages-badtitle' => 'ชื่อเรื่อง $1 ไม่ถูกต้องในรายการผลลัพธ์',
+'wantedpages-badtitle' => 'ชื่อเรื่องไม่สมเหตุสมผลในเซตผลลัพธ์: $1',
'wantedfiles' => 'ไฟล์ที่ต้องการ',
'wantedtemplates' => 'แม่แบบที่ต้องการ',
-'mostlinked' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีà¸\81ารลิà¸\87à¸\81à¹\8cหามาà¸\81',
-'mostlinkedcategories' => 'หมวà¸\94หมูà¹\88à¸\97ีà¹\88มีà¸\81ารà¹\82ยà¸\87หามาà¸\81',
-'mostlinkedtemplates' => 'à¹\81มà¹\88à¹\81à¸\9aà¸\9aà¸\97ีà¹\88à¹\83à¸\8aà¹\89มาà¸\81',
-'mostcategories' => 'หน้าที่มีหมวดหมู่มาก',
-'mostimages' => 'ภาà¸\9eà¸\97ีà¹\88à¹\83à¸\8aà¹\89มาà¸\81',
-'mostinterwikis' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีลิà¸\87à¸\81à¹\8cà¸\82à¹\89ามภาษามากที่สุด',
-'mostrevisions' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82มาà¸\81',
-'prefixindex' => 'หà¸\99à¹\89าà¸\97ัà¹\89à¸\87หมà¸\94à¸\95ามà¸\94ัà¸\8aà¸\99ีคำขึ้นต้น',
-'prefixindex-namespace' => 'à¸\97ุà¸\81หà¸\99à¹\89าà¸\97ีà¹\88มีà¸\84ำà¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99 ($1 à¹\80à¸\99มสà¹\80à¸\9bà¸\8b)',
-'shortpages' => 'หน้าสั้นมาก',
-'longpages' => 'หน้ายาวมาก',
+'mostlinked' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87หามาà¸\81à¸\97ีà¹\88สุà¸\94',
+'mostlinkedcategories' => 'หมวà¸\94หมูà¹\88à¸\97ีà¹\88มีà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87หามาà¸\81à¸\97ีà¹\88สุà¸\94',
+'mostlinkedtemplates' => 'à¹\81มà¹\88à¹\81à¸\9aà¸\9aà¸\97ีà¹\88มีà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87หามาà¸\81à¸\97ีà¹\88สุà¸\94',
+'mostcategories' => 'หน้าที่มีหมวดหมู่มากที่สุด',
+'mostimages' => 'ภาà¸\9eà¸\97ีà¹\88มีà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87หามาà¸\81à¸\97ีà¹\88สุà¸\94',
+'mostinterwikis' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีลิà¸\87à¸\81à¹\8cà¸\82à¹\89ามà¹\82à¸\84รà¸\87à¸\81ารมากที่สุด',
+'mostrevisions' => 'หà¸\99à¹\89าà¸\97ีà¹\88มีรุà¹\88à¸\99มาà¸\81à¸\97ีà¹\88สุà¸\94',
+'prefixindex' => 'à¸\97ุà¸\81หà¸\99à¹\89าà¸\9eรà¹\89à¸à¸¡คำขึ้นต้น',
+'prefixindex-namespace' => 'à¸\97ุà¸\81หà¸\99à¹\89าà¸\9eรà¹\89à¸à¸¡à¸\84ำà¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99 (à¹\80à¸\99มสà¹\80à¸\9bà¸\8b $1)',
+'shortpages' => 'หน้าสั้น',
+'longpages' => 'หน้ายาว',
'deadendpages' => 'หน้าสุดทาง',
-'deadendpagestext' => 'หà¸\99à¹\89าà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¹\84มà¹\88à¹\84à¸\94à¹\89ลิà¸\87à¸\81à¹\8cไปหน้าอื่นใน {{SITENAME}}',
-'protectedpages' => 'หน้าถูกล็อก',
-'protectedpages-indef' => 'à¸\81ารลà¹\87à¸à¸\81à¹\81à¸\9aà¸\9aà¹\84มà¹\88à¸\88ำà¸\81ัดเท่านั้น',
+'deadendpagestext' => 'หà¸\99à¹\89าà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¹\84มà¹\88à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87ไปหน้าอื่นใน {{SITENAME}}',
+'protectedpages' => 'หà¸\99à¹\89าà¸\97ีà¹\88à¸\96ูà¸\81ลà¹\87à¸à¸\81',
+'protectedpages-indef' => 'à¸\81ารลà¹\87à¸à¸\81à¹\81à¸\9aà¸\9aà¹\84มà¹\88มีà¸\81ำหà¸\99ดเท่านั้น',
'protectedpages-cascade' => 'การล็อกแบบสืบทอดเท่านั้น',
-'protectedpagestext' => 'หà¸\99à¹\89าà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81หà¹\89ามà¹\81à¸\81à¹\89à¹\84à¸\82หรืà¸à¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸',
-'protectedpagesempty' => 'à¹\84มà¹\88มีหà¸\99à¹\89าà¹\83à¸\94à¸\97ีà¹\88à¸\96ูà¸\81ลà¹\87à¸à¸\81à¸\95ามà¸\84à¹\88าà¸\97ีà¹\88à¹\80ลืà¸à¸\81',
+'protectedpagestext' => 'หà¸\99à¹\89าà¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81มิà¹\83หà¹\89ยà¹\89ายหรืà¸à¹\81à¸\81à¹\89à¹\84à¸\82',
+'protectedpagesempty' => 'à¸\82à¸\93ะà¸\99ีà¹\89à¹\84มà¹\88มีหà¸\99à¹\89าà¹\83à¸\94à¸\96ูà¸\81ลà¹\87à¸à¸\81à¸\95ามà¸\9eารามิà¹\80à¸\95à¸à¸£à¹\8cà¹\80หลà¹\88าà¸\99ีà¹\89',
'protectedtitles' => 'ชื่อเรื่องที่ถูกป้องกัน',
'protectedtitlestext' => 'ชื่อเรื่องต่อไปนี้ถูกป้องกันมิให้สร้าง',
-'protectedtitlesempty' => 'à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\84มà¹\88มีหัวà¹\80รืà¹\88à¸à¸\87à¸\97ีà¹\88à¹\84à¸\94à¹\89รัà¸\9aà¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99à¸\94à¹\89วยà¸\84à¹\88าà¸\95à¹\88à¸à¹\84à¸\9bนี้',
+'protectedtitlesempty' => 'à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¹\84มà¹\88มีหัวà¹\80รืà¹\88à¸à¸\87à¸\97ีà¹\88à¹\84à¸\94à¹\89รัà¸\9aà¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99à¸\94à¹\89วยà¸\9eารามิà¹\80à¸\95à¸à¸£à¹\8cà¹\80หลà¹\88านี้',
'listusers' => 'รายนามผู้ใช้',
'listusers-editsonly' => 'แสดงเฉพาะผู้ใช้ที่มีการแก้ไข',
'listusers-creationsort' => 'เรียงลำดับตามวันสร้าง',
'move' => 'เปลี่ยนชื่อ',
'movethispage' => 'เปลี่ยนชื่อหน้านี้',
'unusedimagestext' => 'ไฟล์ต่อไปนี้มีอยู่ แต่ไม่มีการเรียกใช้ในหน้าใด ๆ เลย
-หมายà¹\80หà¸\95ุวà¹\88า à¹\80วà¹\87à¸\9aà¹\84วà¸\95à¹\8cà¸à¸·à¹\88à¸\99à¸à¸²à¸\88ลิà¸\87à¸\81à¹\8cมายัà¸\87à¹\84à¸\9fลà¹\8cà¸\94à¹\89วยยูà¸à¸²à¸£à¹\8cà¹\81à¸à¸¥à¹\82à¸\94ยà¸\95รà¸\87 à¸\89ะà¸\99ัà¹\89à¸\99à¸\88ึà¸\87à¸à¸²à¸\88ยัà¸\87มีà¸\8aืà¹\88à¸อยู่ที่นี่แม้จะมีการใช้อย่างต่อเนื่อง',
-'unusedcategoriestext' => 'หมวดหมู่ต่อไปนี้ยังมีอยู่ถึงแม้ว่าจะไม่มีว่าไม่มีหน้าไหนหรือบทความไหนใช้ส่วนนี้',
-'notargettitle' => 'à¹\84มà¹\88à¸\9eà¸\9aหà¸\99à¹\89าà¸\9bลายà¸\97าà¸\87',
+หมายà¹\80หà¸\95ุวà¹\88า à¹\80วà¹\87à¸\9aà¹\84à¸\8bà¸\95à¹\8cà¸à¸·à¹\88à¸\99à¸à¸²à¸\88à¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87มายัà¸\87à¹\84à¸\9fลà¹\8cà¸\94à¹\89วยยูà¸à¸²à¸£à¹\8cà¹\81à¸à¸¥à¹\82à¸\94ยà¸\95รà¸\87 à¸\89ะà¸\99ัà¹\89à¸\99à¸\88ึà¸\87à¸\8aืà¹\88à¸à¸à¸²à¸\88ยัà¸\87à¹\81สà¸\94à¸\87รายà¸\81ารอยู่ที่นี่แม้จะมีการใช้อย่างต่อเนื่อง',
+'unusedcategoriestext' => 'หมวดหมู่ต่อไปนี้ยังมีอยู่ แม้ไม่มีหน้าอื่นหรือหมวดหมู่ใดใช้ส่วนนี้',
+'notargettitle' => 'à¹\84มà¹\88à¸\9eà¸\9aà¹\80à¸\9bà¹\89าหมาย',
'notargettext' => 'คุณมิได้ระบุหน้าหรือผู้ใช้เป้าหมายที่จะดำเนินการฟังก์ชันนี้',
'nopagetitle' => 'ไม่มีหน้าเป้าหมายดังกล่าว',
'nopagetext' => 'หน้าเป้าหมายที่คุณระบุไม่มีอยู่',
'pager-newer-n' => 'ใหม่กว่า $1',
'pager-older-n' => 'เก่ากว่า $1',
-'suppress' => 'Oversight',
-'querypage-disabled' => 'หà¸\99à¹\89าà¸\9eิà¹\80ศษà¸\99ีà¹\89à¸\96ูà¸\81à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\94à¹\89วยà¹\80หà¸\95ุà¸\9cลà¸\94à¹\89าà¸\99à¸\9bระสิà¸\97à¸\98ิภาà¸\9e',
+'suppress' => 'ผู้ดูแลประวัติ',
+'querypage-disabled' => 'หà¸\99à¹\89าà¸\9eิà¹\80ศษà¸\99ีà¹\89à¸\96ูà¸\81à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81มีà¸\9bระสิà¸\97à¸\98ิภาà¸\9eà¸\95à¹\88ำ',
# Book sources
-'booksources' => 'à¸\84à¹\89à¸\99หาหนังสือ',
-'booksources-search-legend' => 'ค้นหาหนังสือ',
+'booksources' => 'à¹\81หลà¹\88à¸\87หนังสือ',
+'booksources-search-legend' => 'à¸\84à¹\89à¸\99หาà¹\81หลà¹\88à¸\87หà¸\99ัà¸\87สืà¸',
'booksources-go' => 'ค้นหา',
-'booksources-text' => 'รายà¸\81ารà¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\81สà¸\94à¸\87à¹\80วà¹\87à¸\9aà¹\84à¸\8bà¸\95à¹\8cà¸\97ีà¹\88à¸\82ายหà¸\99ัà¸\87สืà¸à¹\83หมà¹\88หรืà¸à¸«à¸\99ัà¸\87สืà¸à¹\83à¸\8aà¹\89à¹\81ลà¹\89ว à¸\8bึà¹\88à¸\87à¸à¸²à¸\88มีà¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\82à¸à¸\87หà¸\99ัà¸\87สืà¸à¸\97ีà¹\88à¸\84ุà¸\93à¸\81ำลัà¸\87à¸\84à¹\89à¸\99หา:',
+'booksources-text' => 'à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9bà¹\87à¸\99รายà¸\81ารà¸\81ารà¹\80à¸\8aืà¹\88à¸à¸¡à¹\82ยà¸\87à¹\84à¸\9bยัà¸\87à¹\80วà¹\87à¸\9aà¹\84à¸\8bà¸\95à¹\8cà¸à¸·à¹\88à¸\99à¸\97ีà¹\88à¸\82ายหà¸\99ัà¸\87สืà¸à¹\83หมà¹\88à¹\81ละหà¸\99ัà¸\87สืà¸à¹\83à¸\8aà¹\89à¹\81ลà¹\89ว à¹\81ละà¸à¸²à¸\88มีสารสà¸\99à¹\80à¸\97ศà¹\80à¸\9eิà¹\88มà¹\80à¸\95ิมà¹\80à¸\81ีà¹\88ยวà¸\81ัà¸\9aหà¸\99ัà¸\87สืà¸à¸\97ีà¹\88à¸\84ุà¸\93à¸\81ำลัà¸\87มà¸à¸\87หา:',
'booksources-invalid-isbn' => 'รหัส ISBN ที่ให้ไว้ไม่ถูกต้อง กรุณาตรวจสอบจากต้นฉบับอีกครั้ง',
# Special:Log
'alllogstext' => 'การแสดงผลรวมปูมที่มีทั้งหมดของ {{SITENAME}}
คุณสามารถค้นหาให้ละเอียดขึ้นโดยเลือกประเภทปูม ชื่อผู้ใช้หรือหน้าที่ต้องการ (ไวต่ออักษรใหญ่เล็ก)',
'logempty' => 'ไม่พบรายการตรงกันในปูม',
-'log-title-wildcard' => 'à¸\84à¹\89à¸\99หาà¸\8aืà¹\88à¸à¹\80รืà¹\88à¸à¸\87à¸\94à¹\89วยà¸\84ำà¸\82ึà¹\89à¸\99à¸\95à¹\89à¸\99',
-'showhideselectedlogentries' => 'à¹\81สà¸\94à¸\87/à¸\8bà¹\88à¸à¸\99รายà¸\81ารปูมที่เลือก',
+'log-title-wildcard' => 'à¸\84à¹\89à¸\99หาà¸\8aืà¹\88à¸à¹\80รืà¹\88à¸à¸\87à¸\94à¹\89วยà¸\82à¹\89à¸à¸\84วามà¸\99ีà¹\89',
+'showhideselectedlogentries' => 'à¹\81สà¸\94à¸\87/à¸\8bà¹\88à¸à¸\99หà¸\99à¹\88วยปูมที่เลือก',
# Special:AllPages
'allpages' => 'ทุกหน้า',
'alphaindexline' => '$1 ถึง $2',
'nextpage' => 'ถัดไป ($1)',
'prevpage' => 'ก่อนหน้า ($1)',
-'allpagesfrom' => 'à¹\80ริà¹\88มà¹\81สà¸\94à¸\87à¸\9cลจาก:',
-'allpagesto' => 'à¸\88à¸\9aà¸\81ารà¹\81สà¸\94à¸\87à¸\9cลที่:',
+'allpagesfrom' => 'à¹\81สà¸\94à¸\87หà¸\99à¹\89าà¹\82à¸\94ยà¹\80ริà¹\88มจาก:',
+'allpagesto' => 'à¹\81สà¸\94à¸\87หà¸\99à¹\89าà¸\88à¸\9aที่:',
'allarticles' => 'ทุกหน้า',
-'allinnamespace' => 'หน้าทุกหน้า ($1 เนมสเปซ)',
-'allnotinnamespace' => 'หน้าทุกหน้า (ไม่อยู่ใน $1 เนมสเปซ)',
+'allinnamespace' => 'หน้าทุกหน้า (เนมสเปซ $1)',
+'allnotinnamespace' => 'หน้าทุกหน้า (ไม่อยู่ในเนมสเปซ $1)',
'allpagesprev' => 'ก่อนหน้า',
'allpagesnext' => 'ถัดไป',
-'allpagessubmit' => 'à¸\84à¹\89à¸\99หา',
+'allpagessubmit' => 'à¸\94ู',
'allpagesprefix' => 'แสดงหน้าที่ขึ้นต้นด้วย:',
'allpagesbadtitle' => 'ชื่อเรื่องนี้ไม่ถูกต้อง อาจสะกดผิด ลิงก์มาจากภาษาอื่นหรือวิกิอื่น หรือมีตัวอักษรที่ไม่สามารถใช้เป็นชื่อเรื่องได้',
'allpages-bad-ns' => '{{SITENAME}} ไม่มีเนมสเปซ "$1"',
# Special:Categories
'categories' => 'หมวดหมู่',
-'categoriespagetext' => '{{PLURAL:$1|หมวà¸\94หมูà¹\88à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89}}มีหà¸\99à¹\89าหรืà¸à¸ªà¸·à¹\88à¸à¸\95à¹\88าà¸\87ๆ
+'categoriespagetext' => '{{PLURAL:$1|หมวà¸\94หมูà¹\88à¸\99ีà¹\89|หมวà¸\94หมูà¹\88à¸\95à¹\88à¸à¹\84à¸\9bà¸\99ีà¹\89}}มีหà¸\99à¹\89าหรืà¸à¸ªà¸·à¹\88à¸à¸\95à¹\88าà¸\87 ๆ
[[Special:UnusedCategories|หมวดหมู่ที่ไม่ได้ใช้]]จะไม่แสดงในที่นี้
-ดูเพิ่มที่[[Special:WantedCategories|หมวดหมู่ที่ต้องการ]]',
-'categoriesfrom' => 'à¹\81สà¸\94à¸\87หมวà¸\94หมูà¹\88à¹\82à¸\94ยà¹\80ริà¹\88มà¸\88าà¸\81:',
+ดูเพิ่มที่ [[Special:WantedCategories|หมวดหมู่ที่ต้องการ]]',
+'categoriesfrom' => 'แสดงหมวดหมู่เริ่มจาก:',
'special-categories-sort-count' => 'เรียงตามจำนวน',
'special-categories-sort-abc' => 'เรียงตามตัวอักษร',
'sp-deletedcontributions-contribs' => 'เรื่องที่เขียน',
# Special:LinkSearch
-'linksearch' => 'à¸\84à¹\89à¸\99หาลิà¸\87à¸\81à¹\8cà¸\88าà¸\81ภายà¸\99à¸à¸\81à¹\80วà¹\87à¸\9aà¹\84à¸\8bà¸\95à¹\8c',
+'linksearch' => 'à¸\84à¹\89à¸\99หาลิà¸\87à¸\81à¹\8cภายà¸\99à¸à¸\81',
'linksearch-pat' => 'รูปแบบการค้นหา:',
'linksearch-ns' => 'เนมสเปซ:',
-'linksearch-ok' => 'สืà¸\9aà¸\84à¹\89à¸\99',
-'linksearch-text' => 'à¸à¸±à¸\81à¸\82ระà¸\95ัวà¹\81à¸\97à¸\99à¹\80à¸\8aà¹\88à¸\99 "*.wikipedia.org" สามารà¸\96à¹\83à¸\8aà¹\89ได้
+'linksearch-ok' => 'à¸\84à¹\89à¸\99หา',
+'linksearch-text' => 'สามารà¸\96à¹\83à¸\8aà¹\89à¸\95ัวà¹\81à¸\97à¸\99à¹\80à¸\8aà¹\88à¸\99 "*.wikipedia.org" ได้
ต้องการโดเมนระดับบนสุดเป็นอย่างน้อย เช่น "*.org"<br />
-à¹\82à¸\9eรà¹\82à¸\97à¸\84à¸à¸¥à¸\97ีà¹\88รà¸à¸\87รัà¸\9a: <code>$1</code> (à¸\84à¹\88าà¹\82à¸\94ยà¸\9bริยายà¹\80à¸\9bà¹\89น http:// หากไม่ระบุโพรโทคอล)',
+à¹\82à¸\9eรà¹\82à¸\97à¸\84à¸à¸¥à¸\97ีà¹\88รà¸à¸\87รัà¸\9a: <code>$1</code> (à¸\84à¹\88าà¹\82à¸\94ยà¸\9bริยายà¹\80à¸\9bà¹\87น http:// หากไม่ระบุโพรโทคอล)',
'linksearch-line' => '$1 ถูกลิงก์จาก $2',
-'linksearch-error' => 'à¹\80à¸\84รืà¹\88à¸à¸\87หมายà¹\81à¸\97à¸\99à¸à¸±à¸\81à¸\82ระ (wildcard) à¸à¸¢à¸¹à¹\88หà¸\99à¹\89าà¸\8aืà¹\88à¸à¹\82ฮสà¸\95à¹\8cà¹\84à¸\94à¹\89เท่านั้น',
+'linksearch-error' => 'à¸à¸±à¸\81à¸\82ระà¸\95ัวà¹\81à¸\97à¸\99à¸à¸¢à¸¹à¹\88à¹\84à¸\94à¹\89à¹\80à¸\89à¸\9eาะหà¸\99à¹\89าà¸\8aืà¹\88à¸à¹\82ฮสà¸\95à¹\8cเท่านั้น',
# Special:ListUsers
-'listusersfrom' => 'à¹\81สà¸\94à¸\87à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\82à¸\94ยà¹\80ริà¹\88มà¸\95à¹\89à¸\99จาก:',
+'listusersfrom' => 'à¹\81สà¸\94à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\80ริà¹\88มจาก:',
'listusers-submit' => 'แสดง',
-'listusers-noresult' => 'à¹\84มà¹\88à¸\9eà¸\9aà¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88à¸\95à¹\89à¸à¸\87à¸\81าร',
+'listusers-noresult' => 'à¹\84มà¹\88à¸\9eà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89',
'listusers-blocked' => '(ถูกบล็อก)',
# Special:ActiveUsers
-'activeusers' => 'รายà¸\81ารà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\9bระà¸\88ำ',
-'activeusers-intro' => 'à¸\99ีà¹\88à¸\84ืà¸à¸£à¸²à¸¢à¸\99ามà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88มีà¸\81ิà¸\88à¸\81รรมà¹\83à¸\94 à¹\86 à¹\83à¸\99 $1 วันที่ผ่านมา',
+'activeusers' => 'รายà¸\81ารà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88มีà¸\84วามà¹\80à¸\84ลืà¹\88à¸à¸\99à¹\84หว',
+'activeusers-intro' => 'à¸\99ีà¹\88à¸\84ืà¸à¸£à¸²à¸¢à¸\81ารà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88มีà¸\81ิà¸\88à¸\81รรมà¹\83à¸\94 à¹\86 à¹\83à¸\99à¸\8aà¹\88วà¸\87 $1 วันที่ผ่านมา',
'activeusers-count' => '{{PLURAL:$1|ปฏิบัติการล่าสุด|ปฏิบัติการล่าสุด $1 รายการ}} ในช่วง $3 วันที่ผ่านมา',
-'activeusers-from' => 'à¹\81สà¸\94à¸\87à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\82à¸\94ยเริ่มจาก:',
+'activeusers-from' => 'à¹\81สà¸\94à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89เริ่มจาก:',
'activeusers-hidebots' => 'ซ่อนบอต',
'activeusers-hidesysops' => 'ซ่อนผู้ดูแลระบบ',
-'activeusers-noresult' => 'à¹\84มà¹\88à¸\9eà¸\9aà¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89',
+'activeusers-noresult' => 'ไม่พบผู้ใช้',
# Special:ListGroupRights
-'listgrouprights' => 'สิทธิของกลุ่มผู้ใช้',
-'listgrouprights-summary' => 'รายชื่อกลุ่มผู้ใช้ต่อไปนี้ถูกกำหนดไว้บน {{SITENAME}} โดยมีสิทธิการเข้าถึงที่เกี่ยวข้อง และอาจมี[[{{MediaWiki:Listgrouprights-helppage}}|ข้อมูลเพิ่มเติม]]เกี่ยวกับสิทธิของแต่ละบุคคล',
-'listgrouprights-key' => '* <span class="listgrouprights-granted">สิทธิ์ที่ถูกให้</span>
-* <span class="listgrouprights-revoked">สิทธิ์ที่ถูกยกเลิก</span>',
+'listgrouprights' => 'สิทธิกลุ่มผู้ใช้',
+'listgrouprights-summary' => 'ด้านล่างเป็นรายการกลุ่มผู้ใช้ที่นิยามบนวิกินี้ และสิทธิการเข้าถึงที่เกี่ยวข้อง
+อาจมี[[{{MediaWiki:Listgrouprights-helppage}}|ข้อมูลเพิ่มเติม]]เกี่ยวกับสิทธิหนึ่ง ๆ',
+'listgrouprights-key' => '* <span class="listgrouprights-granted">สิทธิที่ได้รับแต่งตั้ง</span>
+* <span class="listgrouprights-revoked">สิทธิที่ถูกเพิกถอน</span>',
'listgrouprights-group' => 'กลุ่ม',
'listgrouprights-rights' => 'สิทธิ',
-'listgrouprights-helppage' => 'Help:สิà¸\97à¸\98ิà¸\82à¸à¸\87à¸\81ลุà¹\88ม',
-'listgrouprights-members' => '(รายà¸\8aืà¹\88à¸สมาชิก)',
-'listgrouprights-addgroup' => 'สามารà¸\96à¹\80à¸\9eิà¹\88ม{{PLURAL:$2|à¸\81ลุà¹\88มà¸\99ีà¹\89|à¸\81ลุà¹\88มà¹\80หลà¹\88าà¸\99ีà¹\89}}à¹\84à¸\94à¹\89: $1',
-'listgrouprights-removegroup' => 'สามารà¸\96ลà¸\9a{{PLURAL:$2|à¸\81ลุà¹\88มà¸\99ีà¹\89|à¸\81ลุà¹\88มà¹\80หลà¹\88าà¸\99ีà¹\89}}à¹\84à¸\94à¹\89: $1',
-'listgrouprights-addgroup-all' => 'สามารà¸\96à¹\80à¸\9eิà¹\88มà¸\81ลุà¹\88มà¸\97ัà¹\89à¸\87หมà¸\94à¹\84à¸\94à¹\89',
-'listgrouprights-removegroup-all' => 'สามารà¸\96ลà¸\9aà¸\81ลุà¹\88มà¸\97ัà¹\89à¸\87หมà¸\94à¹\84à¸\94à¹\89',
-'listgrouprights-addgroup-self' => 'à¹\80à¸\9eิà¹\88ม{{PLURAL:$2|à¸\81ลุà¹\88ม|à¸\81ลุà¹\88ม}}à¹\80à¸\82à¹\89าà¹\84à¸\9bà¹\83à¸\99à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89: $1',
-'listgrouprights-removegroup-self' => 'ลà¸\9a{{PLURAL:$2|à¸\81ลุà¹\88ม|à¸\81ลุà¹\88ม}}à¸à¸à¸\81à¸\88าà¸\81à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89: $1',
-'listgrouprights-addgroup-self-all' => 'à¹\80à¸\9eิà¹\88มà¸\97ุà¸\81à¸\81ลุà¹\88มà¹\80à¸\82à¹\89าà¹\84à¸\9bà¹\83à¸\99à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89นี้',
-'listgrouprights-removegroup-self-all' => 'ลà¸\9aà¸\97ุà¸\81à¸\81ลุà¹\88มà¸à¸à¸\81à¸\88าà¸\81à¸\8aืà¹\88à¸à¸\9cูà¹\89à¹\83à¸\8aà¹\89นี้',
+'listgrouprights-helppage' => 'Help:สิทธิกลุ่ม',
+'listgrouprights-members' => '(รายà¸\81ารสมาชิก)',
+'listgrouprights-addgroup' => 'à¹\80à¸\9eิà¹\88ม{{PLURAL:$2|à¸\81ลุà¹\88มà¸\99ีà¹\89|à¸\81ลุà¹\88มà¹\80หลà¹\88าà¸\99ีà¹\89}}: $1',
+'listgrouprights-removegroup' => 'à¸\99ำ{{PLURAL:$2|à¸\81ลุà¹\88มà¸\99ีà¹\89|à¸\81ลุà¹\88มà¹\80หลà¹\88าà¸\99ีà¹\89}}à¸à¸à¸\81: $1',
+'listgrouprights-addgroup-all' => 'à¹\80à¸\9eิà¹\88มà¸\81ลุà¹\88มà¸\97ัà¹\89à¸\87หมà¸\94',
+'listgrouprights-removegroup-all' => 'à¸\99ำà¸\81ลุà¹\88มà¸\97ัà¹\89à¸\87หมà¸\94à¸à¸à¸\81',
+'listgrouprights-addgroup-self' => 'à¹\80à¸\9eิà¹\88ม{{PLURAL:$2|à¸\81ลุà¹\88ม|à¸\81ลุà¹\88ม}}à¹\80à¸\82à¹\89าà¹\84à¸\9bà¹\83à¸\99à¸\9aัà¸\8dà¸\8aี: $1',
+'listgrouprights-removegroup-self' => 'ลà¸\9a{{PLURAL:$2|à¸\81ลุà¹\88ม|à¸\81ลุà¹\88ม}}à¸à¸à¸\81à¸\88าà¸\81à¸\9aัà¸\8dà¸\8aี: $1',
+'listgrouprights-addgroup-self-all' => 'à¹\80à¸\9eิà¹\88มà¸\97ุà¸\81à¸\81ลุà¹\88มà¹\80à¸\82à¹\89าà¹\84à¸\9bà¹\83à¸\99à¸\9aัà¸\8dà¸\8aีนี้',
+'listgrouprights-removegroup-self-all' => 'à¸\99ำà¸\97ุà¸\81à¸\81ลุà¹\88มà¸à¸à¸\81à¸\88าà¸\81à¸\9aัà¸\8dà¸\8aีนี้',
# E-mail user
-'mailnologin' => 'à¹\84มà¹\88มีà¸\81ารสà¹\88à¸\87à¸à¸µà¹\80มล',
-'mailnologintext' => 'à¸\95à¹\89à¸à¸\87à¸\81ารà¸\97ำ[[Special:UserLogin|ลà¹\87à¸à¸\81à¸à¸´à¸\99]]à¹\81ละà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¸à¸µà¹\80มลà¹\83à¸\99สà¹\88วà¸\99[[Special:Preferences|à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88า]] à¹\80à¸\9eืà¹\88à¸à¸\88ะสà¹\88à¸\87à¸à¸µà¹\80มลหาà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\84à¸\99อื่น',
+'mailnologin' => 'à¹\84มà¹\88มีà¸\97ีà¹\88à¸à¸¢à¸¹à¹\88สà¹\88à¸\87',
+'mailnologintext' => 'à¸\84ุà¸\93à¸\95à¹\89à¸à¸\87[[Special:UserLogin|ลà¹\87à¸à¸\81à¸à¸´à¸\99]]à¹\81ละมีà¸\97ีà¹\88à¸à¸¢à¸¹à¹\88à¸à¸µà¹\80มลà¸\97ีà¹\88สมà¹\80หà¸\95ุสมà¸\9cลà¹\83à¸\99[[Special:Preferences|à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88า]]à¸\82à¸à¸\87à¸\84ุà¸\93 à¹\83à¸\99à¸\81ารสà¹\88à¸\87à¸à¸µà¹\80มลหาà¸\9cูà¹\89à¹\83à¸\8aà¹\89อื่น',
'emailuser' => 'ส่งอีเมลหาผู้ใช้นี้',
'emailuser-title-target' => 'ส่งอีเมลหา{{GENDER:$1|ผู้ใช้}}',
'emailuser-title-notarget' => 'อีเมลผู้ใช้',
'emailpage' => 'อีเมลผู้ใช้',
-'emailpagetext' => 'à¸\84ุà¸\93สามารà¸\96à¹\83à¸\8aà¹\89à¹\81à¸\9aà¸\9aà¸\9fà¸à¸£à¹\8cมà¸\94à¹\89าà¸\99ลà¹\88าà¸\87สà¹\88à¸\87à¸à¸µà¹\80มลหา{{GENDER:$1|à¸\9cูà¹\89à¹\83à¸\8aà¹\89}}à¸\99ีà¹\89
+'emailpagetext' => 'คุณสามารถใช้แบบด้านล่างส่งอีเมลหา{{GENDER:$1|ผู้ใช้}}นี้
ที่อยู่อีเมลที่คุณกรอกใน[[Special:Preferences|การตั้งค่าส่วนตัวของคุณ]]จะปรากฏเป็นที่อยู่ "จาก" ของอีเมล ซึ่งผู้รับสามารถตอบกลับคุณได้โดยตรง',
'usermailererror' => 'การส่งอีเมลผิดพลาด:',
'defemailsubject' => 'อีเมล {{SITENAME}} จากผู้ใช้ "$1"',
-'usermaildisabled' => 'สà¹\88à¸\87à¸à¸µà¹\80มลหาà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\9bิà¸\94à¸\81ารà¹\83à¸\8aà¹\89à¸\87าà¸\99',
-'usermaildisabledtext' => 'à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96สà¹\88à¸\87à¸à¸µà¹\80มลà¹\84à¸\9bหาà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸à¸·à¹\88à¸\99à¸\9aà¸\99วิà¸\81ิà¸\99ีà¹\89',
+'usermaildisabled' => 'à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\87าà¸\99à¸\81ารสà¹\88à¸\87à¸à¸µà¹\80มลหาà¸\9cูà¹\89à¹\83à¸\8aà¹\89',
+'usermaildisabledtext' => 'คุณไม่สามารถส่งอีเมลหาผู้ใช้อื่นบนวิกินี้',
'noemailtitle' => 'ไม่มีที่อยู่อีเมล',
'noemailtext' => 'ผู้ใช้คนนี้ระบุที่อยู่อีเมลไม่ถูกต้อง',
'nowikiemailtitle' => 'ไม่อนุญาตให้ใช้อีเมล',
'nowikiemailtext' => 'ผู้ใช้คนนี้เลือกไม่รับอีเมลจากผู้ใช้อื่น',
'emailnotarget' => 'ไม่มีชื่อผู้ใช้ของผู้รับหรือชื่อผู้ใช้ไม่ถูกต้อง',
'emailtarget' => 'กรอกชื่อผู้ใช้ของผู้รับ',
-'emailusername' => 'ชื่อผู้ใช้ :',
+'emailusername' => 'ชื่อผู้ใช้:',
'emailusernamesubmit' => 'ส่ง',
'email-legend' => 'ส่งอีเมลถึงผู้ใช้ {{SITENAME}} อีกคน',
'emailfrom' => 'จาก:',
'watchnologin' => 'ไม่ได้ล็อกอิน',
'watchnologintext' => 'ต้อง[[Special:UserLogin|ล็อกอิน]]เพื่อแก้ไขรายการเฝ้าดูของคุณ',
'addwatch' => 'เพิ่มเข้ารายการเฝ้าดู',
-'addedwatchtext' => 'หà¸\99à¹\89า "[[:$1]]" à¸\96ูà¸\81à¹\80à¸\9eิà¹\88มà¹\80à¸\82à¹\89า[[Special:Watchlist|รายà¸\81ารà¹\80à¸\9dà¹\89าà¸\94ู]]à¸\82à¸à¸\87à¸\84ุà¸\93 à¸\96à¹\89ามีà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89 à¹\81ละหà¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\97ีà¹\88à¹\80à¸\81ีà¹\88ยวà¸\82à¹\89à¸à¸\87à¸\88ะà¹\81สà¸\94à¸\87รายการด้านล่าง',
+'addedwatchtext' => 'หà¸\99à¹\89า "[[:$1]]" à¹\84à¸\94à¹\89à¹\80à¸\9eิà¹\88มลà¸\87à¹\83à¸\99[[Special:Watchlist|รายà¸\81ารà¹\80à¸\9dà¹\89าà¸\94ู]]à¸\82à¸à¸\87à¸\84ุà¸\93à¹\81ลà¹\89ว à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¹\83à¸\99หà¸\99à¹\89าà¸\99ีà¹\89หรืà¸à¸«à¸\99à¹\89าà¸\9eูà¸\94à¸\84ุยà¸\97ีà¹\88à¹\80à¸\81ีà¹\88ยวà¸\82à¹\89à¸à¸\87à¸\88ะà¹\81สà¸\94à¸\87à¹\83à¸\99รายการด้านล่าง',
'removewatch' => 'นำออกจากรายการเฝ้าดู',
'removedwatchtext' => 'หน้า "[[:$1]]" ถูกนำออกจาก[[Special:Watchlist|รายการเฝ้าดูของคุณ]]',
'watch' => 'เฝ้าดู',
'unwatch' => 'เลิกเฝ้าดู',
'unwatchthispage' => 'เลิกเฝ้าดูหน้านี้',
'notanarticle' => 'ไม่ใช่หน้าเนื้อหา',
-'notvisiblerev' => 'รุà¹\88à¸\99à¸\94ัà¸\87à¸\81ลà¹\88าวà¸\96ูà¸\81ลà¸\9aà¹\80รียà¸\9aรà¹\89à¸à¸¢แล้ว',
-'watchnochange' => 'à¹\84มà¹\88มีหà¸\99à¹\89าà¸\97ีà¹\88à¸\84ุà¸\93à¹\80à¸\9dà¹\89าà¸\94ูà¸\96ูà¸\81à¹\81à¸\81à¹\89à¹\84à¸\82ในระยะเวลาที่แสดง',
+'notvisiblerev' => 'รุà¹\88à¸\99ลà¹\88าสุà¸\94à¹\82à¸\94ยà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸à¸µà¸\81à¸\84à¸\99à¸\96ูà¸\81ลà¸\9aแล้ว',
+'watchnochange' => 'à¹\84มà¹\88มีà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¸\97ีà¹\88à¸\84ุà¸\93à¹\80à¸\9dà¹\89าà¸\94ูในระยะเวลาที่แสดง',
'watchlist-details' => 'มี $1 หน้าในรายการเฝ้าดูของคุณ ไม่รวมหน้าอภิปราย',
'wlheader-enotif' => '* แจ้งเตือนผ่านอีเมลถูกเปิดใช้งาน',
'wlheader-showupdated' => "* หน้าที่มีการเปลี่ยนแปลงตั้งแต่การเข้าชมครั้งล่าสุดของคุณแสดงใน'''ตัวหนา'''",
'watchmethod-recent' => 'ตรวจสอบการปรับปรุงล่าสุดกับหน้าเฝ้าดู',
'watchmethod-list' => 'ตรวจสอบหน้าเฝ้าดูกับการแก้ไขล่าสุด',
'watchlistcontains' => 'รายการเฝ้าดูของคุณมี $1 หน้า',
-'iteminvalidname' => "à¹\80à¸\81ิà¸\94à¸\9bัà¸\8dหาà¸\8aืà¹\88à¸à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87à¸\81ัà¸\9a '$1'...",
-'wlnote' => "à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82{{PLURAL:$1|สุà¸\94à¸\97à¹\89าย|ล่าสุด '''$1''' รายการ}} ใน{{PLURAL:$2|ชั่วโมง|ช่วง '''$2''' ชั่วโมง}}ที่ผ่านมา จนถึง $3, $4",
-'wlshowlast' => 'แสดงล่าสุดใน $1 ชั่วโมง $2 วัน $3',
+'iteminvalidname' => "à¹\80à¸\81ิà¸\94à¸\9bัà¸\8dหาà¸\81ัà¸\9aรายà¸\81าร '$1' à¸\8aืà¹\88à¸à¹\84มà¹\88à¸\96ูà¸\81à¸\95à¹\89à¸à¸\87...",
+'wlnote' => "à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82{{PLURAL:$1|ลà¹\88าสุà¸\94|ล่าสุด '''$1''' รายการ}} ใน{{PLURAL:$2|ชั่วโมง|ช่วง '''$2''' ชั่วโมง}}ที่ผ่านมา จนถึง $3, $4",
+'wlshowlast' => 'แสดง $1 ชั่วโมง $2 วันล่าสุด $3',
'watchlist-options' => 'ตัวเลือกรายการเฝ้าดู',
# Displayed when you click the "watch" button and it is in the process of watching
'watching' => 'เฝ้าดู...',
'unwatching' => 'เลิกเฝ้าดู...',
+'watcherrortext' => 'เกิดข้อผิดพลาดขณะเปลี่ยนแปลงการตั้งค่ารายการเฝ้าดูของคุณ เพราะ "$1"',
'enotif_mailer' => 'แจ้งการแก้ไขจาก {{SITENAME}}',
'enotif_reset' => 'ทำเครื่องหมายว่าชมทุกหน้าแล้ว',
'enotif_impersonal_salutation' => 'ผู้ใช้งาน {{SITENAME}}',
-'enotif_subject_deleted' => '{{SITENAME}} หน้า $1 ถูกลบแล้วโดย {{gender:$2|$2}}',
-'enotif_subject_created' => '{{SITENAME}} หน้า $1 ถูกสร้างแล้วโดย {{gender:$2|$2}}',
-'enotif_subject_moved' => '{{SITENAME}} หน้า $1 ได้ย้ายแล้วโดย {{gender:$2|$2}}',
-'enotif_subject_changed' => '{{SITENAME}} หน้า $1 ได้เปลี่ยนแล้วโดย {{gender:$2|$2}}',
-'enotif_lastvisited' => 'ดู $1 สำหรับการเปลี่ยนแปลงทั้งหมดตั้งแต่ครั้งล่าสุดที่คุณเข้าชม',
+'enotif_subject_deleted' => 'หน้า $1 บน {{SITENAME}} ถูกลบโดย {{gender:$2|$2}}',
+'enotif_subject_created' => 'หน้า $1 บน {{SITENAME}} ถูกสร้างโดย {{gender:$2|$2}}',
+'enotif_subject_moved' => 'หน้า $1 บน {{SITENAME}} ถูกย้ายโดย {{gender:$2|$2}}',
+'enotif_subject_restored' => 'หน้า $1 บน {{SITENAME}} ถูก{{GENDER:$2|กู้คืน}}โดย $2',
+'enotif_subject_changed' => 'หน้า $1 บน {{SITENAME}} มีการเปลี่ยนแปลงโดย {{gender:$2|$2}}',
+'enotif_body_intro_deleted' => 'หน้า $1 บน {{SITENAME}} ถูก{{GENDER:$2|ลบ}}เมื่อ $PAGEEDITDATE โดย $2 ดู $3',
+'enotif_body_intro_created' => 'หน้า $1 บน {{SITENAME}} ถูก{{GENDER:$2|สร้าง}}เมื่อ $PAGEEDITDATE โดย $2 ดูรุ่นปัจจุบันที่ $3',
+'enotif_body_intro_moved' => 'หน้า $1 บน {{SITENAME}} ถูก{{GENDER:$2|เปลี่ยนชื่อ}}เมื่อ $PAGEEDITDATE โดย $2 ดูรุ่นปัจจุบันที่ $3',
+'enotif_body_intro_restored' => 'หน้า $1 บน {{SITENAME}} ถูก{{GENDER:$2|กู้คืน}}เมื่อ $PAGEEDITDATE โดย $2 ดูรุ่นปัจจุบันที่ $3',
+'enotif_body_intro_changed' => 'หน้า $1 บน {{SITENAME}} ถูก{{GENDER:$2|เปลี่ยนแปลง}}เมื่อ $PAGEEDITDATE โดย $2 ดูรุ่นปัจจุบันที่ $3',
+'enotif_lastvisited' => 'ดู $1 สำหรับการเปลี่ยนแปลงทั้งหมดตั้งแต่คุณเข้าชมครั้งล่าสุด',
'enotif_lastdiff' => 'ดู $1 เพื่อดูการเปลี่ยนแปลงนี้',
'enotif_anon_editor' => 'ผู้ใช้นิรนาม $1',
'enotif_body' => 'เรียน $WATCHINGUSERNAME
'deletepage' => 'ลบหน้า',
'confirm' => 'ยืนยัน',
'excontent' => "เนื้อหาเดิม: '$1'",
-'excontentauthor' => "à¹\80à¸\99ืà¹\89à¸à¸«à¸²à¹\80à¸\94ิม: '$1' (à¹\81ละมีà¸\9cูà¹\89à¹\80à¸\82ียà¸\99à¸\84à¸\99à¹\80à¸\94ียว à¸\84ืภ'[[Special:Contributions/$2|$2]]')",
+'excontentauthor' => "เนื้อหาเดิม: '$1' (และผู้เขียนคนเดียว คือ '[[Special:Contributions/$2|$2]]')",
'exbeforeblank' => "เนื้อหาก่อนถูกทำว่างคือ: '$1'",
'exblank' => 'หน้าว่าง',
'delete-confirm' => 'ลบ "$1"',
'delete-legend' => 'ลบ',
-'historywarning' => 'คำเตือน: หน้าที่คุณกำลังจะลบ มีประวัติการแก้ไขโดยประมาณ $1 {{PLURAL:$1|รุ่น}}:',
+'historywarning' => "'''คำเตือน:'''' หน้าที่คุณกำลังลบมีประวัติการแก้ไขประมาณ $1 {{PLURAL:$1|รุ่น}}:",
'confirmdeletetext' => 'คุณกำลังลบหน้า รวมทั้งประวัติทั้งหมดของหน้า
-à¸\81รุà¸\93ายืà¸\99ยัà¸\99วà¹\88าà¸\84ุà¸\93à¹\80à¸\88à¸\95à¸\99า à¹\81ละà¸\84ุà¸\93à¹\80à¸\82à¹\89าà¹\83à¸\88à¸\9cลà¸\81ระà¸\97à¸\9a à¹\81ละà¸\81ารà¸\81ระà¸\97ำà¸\99ีà¹\89สà¸à¸\94à¸\84ลà¹\89à¸à¸\87à¸\81ัà¸\9a[[{{MediaWiki:Policy-url}}|à¸\99à¹\82ยà¸\9aาย]]',
+กรุณายืนยันว่าคุณเจตนา เข้าใจผลกระทบ และการกระทำนี้สอดคล้องกับ[[{{MediaWiki:Policy-url}}|นโยบาย]]',
'actioncomplete' => 'ปฏิบัติการสำเร็จ',
'actionfailed' => 'ปฏิบัติการล้มเหลว',
'deletedtext' => '"$1" ถูกลบ
'rollback-success' => 'ย้อนรุ่นที่แก้ไขโดย $1 ไปยังรุ่นล่าสุดโดย $2',
# Edit tokens
-'sessionfailure-title' => 'Session นี้ล้มเหลว',
-'sessionfailure' => 'เหมือนจะมีปัญหาเกี่ยวการล็อกอินในช่วงเวลานี้ เกิดจากทางระบบป้องกันการลักลอบการขโมยล็อกอิน กรุณาย้อนกลับไปหน้าก่อนหน้า และลองโหลดใหม่อีกครั้ง',
+'sessionfailure-title' => 'ช่วงเวลาสื่อสารล้มเหลว',
+'sessionfailure' => 'ดูเหมือนมีปัญหากับช่วงเวลาสื่อสารล็อกอินของคุณ
+การกระทำนี้ถูกยกเลิกเป็นการป้องกันการลักลอบช่วงเวลาสื่อสารไว้ก่อน
+กลับไปหน้าที่แล้ว โหลดหน้าใหม่ แล้วลองอีกครั้ง',
# Protect
'protectlogpage' => 'ปูมการล็อก',
-'protectlogtext' => 'à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\99ีà¹\89à¸\84ืà¸à¸£à¸²à¸¢à¸\81ารà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99หน้า
-à¸\94ู[[Special:ProtectedPages|รายà¸\81ารหà¸\99à¹\89าà¸\97ีà¹\88à¸\96ูà¸\81à¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99]]สำหรัà¸\9aà¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99หà¸\99à¹\89าในปัจจุบัน',
-'protectedarticle' => 'à¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99 "[[$1]]"',
-'modifiedarticleprotection' => 'à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81สำหรัà¸\9a "[[$1]]"',
-'unprotectedarticle' => 'ยà¸\81à¹\80ลิà¸\81à¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99จาก "[[$1]]" แล้ว',
+'protectlogtext' => 'à¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¹\80à¸\9bà¹\87à¸\99รายà¸\81ารà¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87à¸\81ารลà¹\87à¸à¸\81หน้า
+à¸\94ู[[Special:ProtectedPages|รายà¸\81ารหà¸\99à¹\89าà¸\97ีà¹\88à¸\96ูà¸\81ลà¹\87à¸à¸\81]]สำหรัà¸\9aà¸\81ารลà¹\87à¸à¸\81หà¸\99à¹\89าà¸\97ีà¹\88มีà¸\9cลà¸à¸¢à¸¹à¹\88ในปัจจุบัน',
+'protectedarticle' => 'ลà¹\87à¸à¸\81 "[[$1]]"',
+'modifiedarticleprotection' => 'à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81à¸\82à¸à¸\87 "[[$1]]"',
+'unprotectedarticle' => 'ยà¸\81à¹\80ลิà¸\81à¸\81ารลà¹\87à¸à¸\81จาก "[[$1]]" แล้ว',
'movedarticleprotection' => 'ย้ายการตั้งค่าการล็อกจาก "[[$2]]" ไปยัง "[[$1]]"',
'protect-title' => 'กำลังล็อกหน้า "$1"',
-'protect-title-notallowed' => 'à¸\94ูระà¸\94ัà¸\9aà¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99ของ "$1"',
+'protect-title-notallowed' => 'à¸\94ูระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81ของ "$1"',
'prot_1movedto2' => '[[$1]] ถูกเปลี่ยนชื่อเป็น [[$2]]',
-'protect-badnamespace-title' => 'à¹\80à¸\99มสà¹\80à¸\9bà¸\8bà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99ไม่ได้',
+'protect-badnamespace-title' => 'à¹\80à¸\99มสà¹\80à¸\9bà¸\8bลà¹\87à¸à¸\81ไม่ได้',
'protect-badnamespace-text' => 'หน้าในเนมสเปซนี้ไม่สามารถป้องกันได้',
+'protect-norestrictiontypes-text' => 'หน้านี้ไม่สามารถถูกล็อก เพราะไม่มีประเภทการจำกัดที่ใช้ได้',
+'protect-norestrictiontypes-title' => 'หน้าที่ล็อกไม่ได้',
'protect-legend' => 'ยืนยันการล็อก',
'protectcomment' => 'เหตุผล:',
'protectexpiry' => 'หมดอายุ:',
'protect_expiry_invalid' => 'เวลาหมดอายุไม่ถูกต้อง',
'protect_expiry_old' => 'เวลาหมดอายุผ่านมาแล้ว',
-'protect-unchain-permissions' => 'à¸\9bลà¸\94ลà¹\87à¸à¸\81à¸\95ัวà¹\80ลืà¸à¸\81à¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99อื่น ๆ',
-'protect-text' => "à¸\94ูà¹\81ละà¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81สำหรัà¸\9aหà¸\99à¹\89า '''$1'''.",
-'protect-locked-blocked' => "à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81หà¸\99à¹\89าà¸\82à¸\93ะà¸\97ีà¹\88à¸\96ูà¸\81à¸\9aลà¹\87à¸à¸\81à¹\84à¸\94à¹\89 à¸\94ูระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81à¸\82à¸à¸\87หà¸\99à¹\89า '''$1''':",
-'protect-locked-dblock' => "à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81หà¸\99à¹\89าà¹\84à¸\94à¹\89à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\90าà¸\99à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\96ูà¸\81ลà¹\87à¸à¸\81 à¸\94ูระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81à¸\82à¸à¸\87หà¸\99à¹\89า '''$1''':",
-'protect-locked-access' => "à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81หà¸\99à¹\89าà¹\84à¸\94à¹\89 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\84ุà¸\93à¹\84มà¹\88มีสิà¸\97à¸\98ิ à¸\94ูระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81à¸\82à¸à¸\87หà¸\99à¹\89า '''$1''':",
-'protect-cascadeon' => 'หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¹\80à¸\9bà¹\87à¸\99สà¹\88วà¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87{{PLURAL:$1|หà¸\99à¹\89า|หà¸\99à¹\89า}}à¸\97ีà¹\88à¸\96ูà¸\81ล็อกแบบสืบทอด
+'protect-unchain-permissions' => 'à¸\9bลà¸\94ลà¹\87à¸à¸\81à¸\95ัวà¹\80ลืà¸à¸\81à¸\81ารลà¹\87à¸à¸\81อื่น ๆ',
+'protect-text' => "à¸\97ีà¹\88à¸\99ีà¹\88à¸\84ุà¸\93สามารà¸\96à¸\94ูà¹\81ละà¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81à¸\82à¸à¸\87หà¸\99à¹\89า '''$1''' à¹\84à¸\94à¹\89",
+'protect-locked-blocked' => "à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81หà¸\99à¹\89าà¸\82à¸\93ะà¸\97ีà¹\88à¸\96ูà¸\81à¸\9aลà¹\87à¸à¸\81à¹\84à¸\94à¹\89 à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¸\82à¸à¸\87หà¸\99à¹\89า '''$1''' à¸\84ืà¸:",
+'protect-locked-dblock' => "à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81à¹\84à¸\94à¹\89à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\90าà¸\99à¸\82à¹\89à¸à¸¡à¸¹à¸¥à¸\96ูà¸\81ลà¹\87à¸à¸\81 à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¸\82à¸à¸\87หà¸\99à¹\89า '''$1''' à¸\84ืà¸:",
+'protect-locked-access' => "à¸\9aัà¸\8dà¸\8aีà¸\82à¸à¸\87à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aà¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\80à¸\9bลีà¹\88ยà¸\99à¹\81à¸\9bลà¸\87ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81หà¸\99à¹\89า à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99à¸\82à¸à¸\87หà¸\99à¹\89า '''$1''' à¸\84ืà¸:",
+'protect-cascadeon' => 'หà¸\99à¹\89าà¸\99ีà¹\89à¸\96ูà¸\81ลà¹\87à¸à¸\81à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¹\80à¸\9bà¹\87à¸\99สà¹\88วà¸\99หà¸\99ึà¹\88à¸\87à¸\82à¸à¸\87{{PLURAL:$1|หà¸\99à¹\89า|หà¸\99à¹\89า}}à¸\97ีà¹\88à¹\80à¸\9bิà¸\94à¸\81ารล็อกแบบสืบทอด
คุณสามารถเปลี่ยนระดับการล็อกได้ แต่จะไม่มีผลต่อการล็อกแบบสืบทอด',
'protect-default' => 'อนุญาตผู้ใช้ทั้งหมด',
'protect-fallback' => 'อนุญาตเฉพาะผู้ใช้ที่มีสิทธิ "$1"',
-'protect-level-autoconfirmed' => 'à¸\9aลà¹\87à¸à¸\81à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\83หมà¹\88à¹\81ละà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\84มà¹\88ลà¸\87à¸\97ะà¹\80à¸\9aียà¸\99',
+'protect-level-autoconfirmed' => 'à¸à¸\99ุà¸\8dาà¸\95à¹\80à¸\89à¸\9eาะà¸\9cูà¹\89à¹\83à¸\8aà¹\89ยืà¸\99ยัà¸\99à¸à¸±à¸\95à¹\82à¸\99มัà¸\95ิ',
'protect-level-sysop' => 'อนุญาตเฉพาะผู้ดูแลระบบ',
'protect-summary-cascade' => 'สืบทอด',
'protect-expiring' => 'หมดอายุ $1 (UTC)',
'protect-expiring-local' => 'หมดอายุ $1',
'protect-expiry-indefinite' => 'ไม่มีกำหนด',
'protect-cascade' => 'ล็อกหน้าที่เป็นส่วนหนึ่งของหน้านี้ (ล็อกแบบสืบทอด)',
-'protect-cantedit' => 'à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารà¸\9bà¹\89à¸à¸\87à¸\81ัà¸\99à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89 à¹\80à¸\99ืà¹\88à¸à¸\87à¸\88าà¸\81à¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aสิà¸\97à¸\98ิà¹\83à¸\99à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82สิà¹\88à¸\87à¸\99ัà¹\89à¸\99',
+'protect-cantedit' => 'à¸\84ุà¸\93à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81à¸\82à¸à¸\87หà¸\99à¹\89าà¸\99ีà¹\89 à¹\80à¸\9eราะà¸\84ุà¸\93à¹\84มà¹\88à¹\84à¸\94à¹\89รัà¸\9aà¸à¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\81à¸\81à¹\89à¹\84à¸\82ระà¸\94ัà¸\9aà¸\81ารลà¹\87à¸à¸\81',
'protect-othertime' => 'ระยะเวลาอื่น:',
'protect-othertime-op' => 'ระยะเวลาอื่น',
'protect-existing-expiry' => 'ระยะเวลาการป้องกัน: $3, $2',
-'protect-otherreason' => 'เหตุผลอื่นเพิ่มเติม:',
-'protect-otherreason-op' => 'สาà¹\80หà¸\95ุอื่น',
+'protect-otherreason' => 'เหตุผลอื่น/เพิ่มเติม:',
+'protect-otherreason-op' => 'à¹\80หà¸\95ุà¸\9cลอื่น',
'protect-dropdown' => '* เหตุผลการป้องกันทั่วไป
** การก่อกวนจำนวนมาก
** สแปมจำนวนมาก
'restriction-upload' => 'อัปโหลด',
# Restriction levels
-'restriction-level-sysop' => 'ลà¹\87à¸à¸\81à¹\80à¸\95à¹\87มà¸\97ีà¹\88',
-'restriction-level-autoconfirmed' => 'ลà¹\87à¸à¸\81à¸\9cูà¹\89à¹\84มà¹\88ลà¹\87à¸à¸\81à¸à¸´à¸\99',
-'restriction-level-all' => 'ระดับ',
+'restriction-level-sysop' => 'ลà¹\87à¸à¸\81สมà¸\9aูรà¸\93à¹\8c',
+'restriction-level-autoconfirmed' => 'à¸\81ึà¹\88à¸\87ลà¹\87à¸à¸\81',
+'restriction-level-all' => 'à¸\97ุà¸\81ระà¸\94ัà¸\9a',
# Undelete
'undelete' => 'ดูหน้าที่ถูกลบ',
'undeletepage' => 'ดูและกู้คืนหน้าที่ถูกลบ',
-'undeletepagetitle' => "'''ต่อไปนี้เป็นรุ่นการแก้ไขของ [[:$1|$1]] ที่ถูกลบ'''",
-'viewdeletedpage' => 'หน้าที่ถูกลบ',
-'undeletepagetext' => '{{PLURAL:$1|หน้า|หน้า}}ต่อไปนี้ถูกลบไปแล้ว แต่ยังคงอยู่ในกรุซึ่งสามารถเรียกคืนได้ กรุข้อมูลอาจถูกลบเป็นระยะ',
-'undelete-fieldset-title' => 'กู้คืนรุ่นต่าง ๆ',
+'undeletepagetitle' => "'''ต่อไปนี้เป็นรุ่นการแก้ไขที่ถูกลบของ [[:$1|$1]]'''",
+'viewdeletedpage' => 'ดูหน้าที่ถูกลบ',
+'undeletepagetext' => '{{PLURAL:$1||$1 }}หน้าต่อไปนี้ถูกลบไปแล้ว แต่เนื้อหายังคงอยู่ในกรุและสามารถกู้คืนได้
+กรุอาจถูกลบเป็นระยะได้',
+'undelete-fieldset-title' => 'กู้คืนรุ่น',
'undeleteextrahelp' => "ถ้าต้องการกู้ประวัติของหน้าคืนทั้งหมด ไม่ต้องเลือกกล่องใดเลย แล้วกดปุ่ม '''''กู้คืน'''''
ถ้าต้องการกู้ประวัติคืนเฉพาะบางส่วน ให้เลือกกล่องที่มีประวัติส่วนที่ต้องการกู้ แล้วกด'''''กู้คืน'''''
กด '''''ล้างค่า''''' เพื่อลบค่าในกล่องความเห็นและกล่องตัวเลือกทั้งหมด",
'undeleterevisions' => '$1 รุ่นการแก้ไขถูกเก็บไว้',
'undeletehistory' => 'เมื่อคุณกู้หน้าใดหน้าหนึ่ง รุ่นทั้งหมดจะถูกกู้คืนไปยังประวัติ หากมีหน้าใหม่ในชื่อเดียวกันถูกสร้างขึ้นหลังจากการลบ รุ่นที่กู้คืนนั้นจะปรากฏในประวัติที่มีมาก่อน',
-'undeleterevdel' => 'จะกู้คืนไม่ได้หากการกู้คืนนั้นส่งผลให้รุ่นล่าสุดของหน้าหรือไฟล์ถูกลบไปบางส่วน ในกรณีเช่นนั้น คุณต้องไม่เลือกหรือแสดงรุ่นใหม่สุดที่ถูกลบไปก่อน',
-'undeletehistorynoadmin' => 'หน้านี้ถูกลบก่อนหน้านี้ โดยสาเหตุการลบและรายชื่อผู้ร่วมแก้ไขก่อนหน้าแสดงผลด้านล่าง สำหรับข้อมูลที่ถูกลบจะดูได้เฉพาะผู้ดูแลระบบ',
+'undeleterevdel' => 'จะกู้คืนไม่ได้หากการกู้คืนนั้นส่งผลให้รุ่นล่าสุดของหน้าหรือไฟล์ถูกลบไปบางส่วน
+ในกรณีเช่นนั้น คุณต้องไม่เลือกหรือแสดงรุ่นใหม่สุดที่ถูกลบไปก่อน',
+'undeletehistorynoadmin' => 'หน้านี้ถูกลบไปแล้ว
+มีสาเหตุการลบแสดงไว้ในคำอธิบายอย่างย่อข้างล่าง ร่วมกับรายละเอียดผู้ใช้ที่เคยแก้ไขหน้านี้ก่อนลบ
+ข้อความแท้จริงของรุ่นที่ถูกลบดูได้เฉพาะผู้ดูแลระบบ',
'undelete-revision' => 'รุ่นที่ถูกลบของหน้า $1 (ตั้งแต่ $4 เมื่อ $5) โดย $3:',
'undeleterevision-missing' => 'รุ่นไม่ถูกต้องหรือสูญหาย
คุณอาจมีลิงก์เสีย หรือรุ่นอาจถูกกู้คืนหรือนำออกจากกรุ',
'undelete-nodiff' => 'ไม่พบรุ่นก่อนหน้า',
'undeletebtn' => 'กู้คืน',
'undeletelink' => 'ดู/กู้คืน',
-'undeleteviewlink' => 'à¹\80รียà¸\81à¸\94ู',
-'undeletereset' => 'ลà¹\89าà¸\87à¸\84à¹\88า',
-'undeleteinvert' => 'à¸\81ลัà¸\9aà¸\84à¹\88าà¸\97ีà¹\88เลือก',
+'undeleteviewlink' => 'ดู',
+'undeletereset' => 'à¸\95ัà¹\89à¸\87à¹\83หมà¹\88',
+'undeleteinvert' => 'à¸\81ลัà¸\9aà¸\81ารเลือก',
'undeletecomment' => 'เหตุผล:',
'undeletedrevisions' => '$1 รุ่นการแก้ไขถูกกู้คืน',
'undeletedrevisions-files' => '$1 รุ่น และ $2 ไฟล์ถูกกู้คืน',
'undelete-header' => 'ดู [[Special:Log/delete|ปูมการลบ]] สำหรับหน้าที่ถูกลบล่าสุด',
'undelete-search-title' => 'ค้นหาหน้าที่ถูกลบ',
'undelete-search-box' => 'ค้นหาหน้าที่ถูกลบ',
-'undelete-search-prefix' => 'à¸\84à¹\89à¸\99หาหà¸\99à¹\89าà¸\97ีà¹\88à¹\80ริà¹\88มต้นด้วย:',
-'undelete-search-submit' => 'สืà¸\9aà¸\84à¹\89à¸\99',
+'undelete-search-prefix' => 'à¸\84à¹\89à¸\99หาหà¸\99à¹\89าà¸\97ีà¹\88à¸\82ึà¹\89à¸\99ต้นด้วย:',
+'undelete-search-submit' => 'à¸\84à¹\89à¸\99หา',
'undelete-no-results' => 'ไม่พบหน้าที่ตรงกันในกรุการลบ',
-'undelete-filename-mismatch' => 'ไม่สามารถกู้คืนไฟล์ $1: ชื่อไฟล์ไม่ถูกต้อง',
-'undelete-bad-store-key' => 'ไม่สามารถกู้คืนไฟล์ $1: ไม่มีไฟล์ก่อนที่จะถูกลบ',
-'undelete-cleanup-error' => 'เกิดปัญหาการลบไฟล์เก่า "$1"',
-'undelete-missing-filearchive' => 'ไม่สามารถกู้คืนไฟล์เก่ารุ่น $1 เพราะไม่มีไฟล์อยู่ในฐานข้อมูล ไฟล์อาจถูกกู้คืนไปแล้ว',
-'undelete-error' => 'เกิดข้อผิดพลาด ไม่สามารถลบหน้าเวปได้',
-'undelete-error-short' => 'เกิดปัญหาในการกู้คืนไฟล์: $1',
-'undelete-error-long' => 'เกิดความผิดพลาดระหว่างการลบไฟล์:
+'undelete-filename-mismatch' => 'ไม่สามารถกู้คืนรุ่นไฟล์ที่มีตราเวลา $1: ชื่อไฟล์ไม่ตรง',
+'undelete-bad-store-key' => 'ไม่สามารถกู้คืนรุ่นไฟล์ที่มีตราเวลา $1: ไฟล์สูญหายก่อนถูกลบ',
+'undelete-cleanup-error' => 'เกิดความผิดพลาดในการลบไฟล์กรุที่ไม่ใช้แล้ว "$1"',
+'undelete-missing-filearchive' => 'ไม่สามารถกู้คืนไฟล์เก่าหมายเลข $1 เพราะไม่มีในฐานข้อมูล
+ไฟล์อาจถูกกู้คืนไปแล้ว',
+'undelete-error' => 'เกิดข้อผิดพลาดในการกู้คืนหน้า',
+'undelete-error-short' => 'เกิดข้อผิดพลาดในการกู้คืนไฟล์: $1',
+'undelete-error-long' => 'เกิดข้อผิดพลาดขณะกู้คืนไฟล์:
$1',
-'undelete-show-file-confirm' => 'à¹\81à¸\99à¹\88à¹\83à¸\88หรืà¸à¹\84มà¹\88วà¹\88าà¸\84ุà¸\93à¸\95à¹\89à¸à¸\87à¸\81ารà¸\88ะà¸\94ูรุà¹\88à¸\99à¸\97ีà¹\88à¸\96ูà¸\81ลà¸\9aà¹\84à¸\9b สำหรัà¸\9aไฟล์ "<nowiki>$1</nowiki>" ตั้งแต่ $2 เมื่อ $3',
+'undelete-show-file-confirm' => 'à¸\84ุà¸\93à¹\81à¸\99à¹\88à¹\83à¸\88หรืà¸à¸§à¹\88าà¸\95à¹\89à¸à¸\87à¸\81ารà¸\94ูรุà¹\88à¸\99à¸\97ีà¹\88à¸\96ูà¸\81ลà¸\9aà¸\82à¸à¸\87ไฟล์ "<nowiki>$1</nowiki>" ตั้งแต่ $2 เมื่อ $3',
'undelete-show-file-submit' => 'ใช่',
# Namespace form on various pages
'month' => 'จากเดือน (และก่อนหน้า):',
'year' => 'จากปี (และก่อนหน้า):',
-'sp-contributions-newbies' => 'à¹\81สà¸\94à¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\9cูà¹\89à¹\83à¸\8aà¹\89ใหม่เท่านั้น',
-'sp-contributions-newbies-sub' => 'สำหรัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89ใหม่',
+'sp-contributions-newbies' => 'à¹\81สà¸\94à¸\87à¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¸\82à¸à¸\87à¸\9aัà¸\8dà¸\8aีใหม่เท่านั้น',
+'sp-contributions-newbies-sub' => 'สำหรัà¸\9aà¸\9aัà¸\8dà¸\8aีใหม่',
'sp-contributions-newbies-title' => 'เรื่องที่เขียนโดยบัญชีใหม่',
'sp-contributions-blocklog' => 'ปูมการบล็อก',
'sp-contributions-deleted' => 'การแก้ไขที่ถูกลบ',
'ipb-change-block' => 'บล็อกผู้ใช้อีกครั้งด้วยการตั้งค่าเหล่านี้',
'ipb-confirm' => 'ยืนยันการบล็อก',
'badipaddress' => 'เลขที่อยู่ไอพีไม่ถูกต้อง',
-'blockipsuccesssub' => 'à¸\9aลà¹\87à¸à¸\81สำà¹\80รà¹\87à¸\88',
-'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] à¸\96ูà¸\81à¸\9aลà¹\87à¸à¸\81<br />
-ดู[[Special:BlockList|รายการบล็อก]]เพื่อทบทวนการบล็อก',
+'blockipsuccesssub' => 'à¸\9aลà¹\87à¸à¸\81à¹\80รียà¸\9aรà¹\89à¸à¸¢',
+'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] à¹\84à¸\94à¹\89à¸\96ูà¸\81à¸\9aลà¹\87à¸à¸\81à¹\81ลà¹\89ว<br />
+ดู[[Special:BlockList|รายการบล็อก]]เพื่อทบทวนการบล็อกดังกล่าว',
'ipb-blockingself' => 'คุณกำลังบล็อกตัวเอง! แน่ใจแล้วหรือว่าต้องการทำอย่างนั้น',
+'ipb-confirmhideuser' => 'คุณกำลังบล็อกผู้ใช้โดยเป็นผู้ใช้ "ซ่อนผู้ใช้" ซึ่งจะระงับชื่อผู้ใช้ในรายการและหน่วยปูมทั้งหมด คุณแน่ใจหรือว่าต้องการดำเนินการเช่นนั้น',
'ipb-edit-dropdown' => 'แก้ไขสาเหตุการบล็อก',
'ipb-unblock-addr' => 'เลิกบล็อก $1',
'ipb-unblock' => 'เลิกบล็อกผู้ใช้หรือเลขที่อยู่ไอพี',
'blocklist-userblocks' => 'ซ่อนบล็อกบัญชี',
'blocklist-tempblocks' => 'ซ่อนบล็อกชั่วคราว',
'blocklist-addressblocks' => 'ซ่อนบล็อกไอพีเดียว',
+'blocklist-rangeblocks' => 'ซ่อนการบล็อกช่วง',
'blocklist-timestamp' => 'ตราเวลา',
'blocklist-target' => 'เป้าหมาย',
'blocklist-expiry' => 'หมดอายุ',
# Move page
'move-page' => 'ย้าย $1',
'move-page-legend' => 'เปลี่ยนชื่อ',
-'movepagetext' => "à¸\81ารà¹\83à¸\8aà¹\89à¹\81à¸\9aà¸\9aà¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\88ะà¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¸«à¸\99à¹\89า à¹\81ละยà¹\89ายà¸\9bระวัà¸\95ิà¸\97ัà¹\89à¸\87หมà¸\94à¹\84à¸\9bยัà¸\87à¸\8aืà¹\88à¸à¹\80รืà¹\88à¸à¸\87ใหม่
+'movepagetext' => "à¸\81ารà¹\83à¸\8aà¹\89à¹\81à¸\9aà¸\9aà¸\94à¹\89าà¸\99ลà¹\88าà¸\87à¸\88ะสà¹\88à¸\87à¸\9cลà¹\80à¸\9bลีà¹\88ยà¸\99à¸\8aืà¹\88à¸à¸«à¸\99à¹\89า à¹\81ละยà¹\89ายà¸\9bระวัà¸\95ิà¸\97ัà¹\89à¸\87หมà¸\94à¹\84à¸\9bยัà¸\87à¸\8aืà¹\88à¸ใหม่
ชื่อเรื่องเก่าจะกลายเป็นหน้าเปลี่ยนทางไปยังชื่อเรื่องใหม่
คุณสามารถปรับให้หน้าเปลี่ยนทางที่ชี้ไปยังชื่อเรื่องเดิมได้อัตโนมัติ
แต่หากคุณเลือกไม่ทำเช่นนั้น ให้แน่ใจว่าตรวจสอบ[[Special:DoubleRedirects|หน้าเปลี่ยนทางซ้ำซ้อน]]หรือ[[Special:BrokenRedirects|หน้าเปลี่ยนทางที่เสีย]]
คุณเป็นผู้รับผิดชอบเพื่อให้แน่ใจว่าลิงก์ต่าง ๆ ยังชี้ไปยังที่ที่สมควร
-โปรดทราบว่าหน้าดังกล่าวจะ'''ไม่'''ถูกย้าย ถ้ามีหน้าที่ใช้ชื่อเรื่องใหม่อยู่แล้ว เว้นแต่เป็นหน้าเปลี่ยนทาง และไม่มีประวัติการแก้ไขในอดีต
+à¹\82à¸\9bรà¸\94à¸\97ราà¸\9aวà¹\88าหà¸\99à¹\89าà¸\94ัà¸\87à¸\81ลà¹\88าวà¸\88ะ'''à¹\84มà¹\88'''à¸\96ูà¸\81ยà¹\89าย à¸\96à¹\89ามีหà¸\99à¹\89าà¸\97ีà¹\88à¹\83à¸\8aà¹\89à¸\8aืà¹\88à¸à¹\80รืà¹\88à¸à¸\87à¹\83หมà¹\88à¸à¸¢à¸¹à¹\88à¹\81ลà¹\89ว à¹\80วà¹\89à¸\99à¹\81à¸\95à¹\88หà¸\99à¹\89าà¸\99ัà¹\89à¸\99à¹\80à¸\9bà¹\87à¸\99หà¸\99à¹\89าà¹\80à¸\9bลีà¹\88ยà¸\99à¸\97าà¸\87 à¹\81ละà¹\84มà¹\88มีà¸\9bระวัà¸\95ิà¸\81ารà¹\81à¸\81à¹\89à¹\84à¸\82à¹\83à¸\99à¸à¸\94ีà¸\95
ซึ่งหมายความว่า คุณสามารถเปลี่ยนชื่อหน้ากลับเป็นชื่อเดิมได้หากคุณทำผิดพลาด และคุณไม่สามารถเขียนทับหน้าที่มีอยู่แล้วได้
'''คำเตือน!'''
# Namespace 8 related
'allmessages' => 'ข้อความของระบบ',
'allmessagesname' => 'ชื่อ',
-'allmessagesdefault' => 'ข้อความตั้งต้น',
+'allmessagesdefault' => 'à¸\82à¹\89à¸à¸\84วามà¸\95ามà¸\84à¹\88าà¸\95ัà¹\89à¸\87à¸\95à¹\89à¸\99',
'allmessagescurrent' => 'ข้อความปัจจุบัน',
'allmessagestext' => 'รายการข้อความของระบบ อยู่ในเนมสเปซมีเดียวิกิ
กรุณาไปที่ [//www.mediawiki.org/wiki/Localisation มีเดียวิกิ] และ [//translatewiki.new translatewiki.net] ถ้าคุณยังอยากที่จะแปลข้อความของระบบมีเดียวิกิ',
'notacceptable' => 'เซิร์ฟเวอร์ของวิกิไม่สามารถให้ข้อมูลในรูปแบบที่ไคลเอนต์สามารถอ่านได้',
# Attribution
-'anonymous' => '{{PLURAL:$1|ผู้ใช้}}นิรนามของ {{SITENAME}}',
+'anonymous' => 'ผู้ใช้นิรนามของ{{SITENAME}}',
'siteuser' => 'ผู้ใช้ $1 จาก {{SITENAME}}',
'anonuser' => 'ผู้ใช้นิรนามจาก {{SITENAME}} $1',
'lastmodifiedatby' => 'แก้ไขล่าสุดเมื่อเวลา $2 $1 โดย $3',
'spambot_username' => 'กวาดล้างมีเดียวิกิสแปม',
'spam_reverting' => 'ย้อนกลับไปรุ่นก่อนหน้าที่ไม่มีลิงก์ไปยังเว็บ $1',
'spam_blanking' => 'รุ่นการปรับปรุงทุกรุ่นประกอบไปด้วยลิงก์ไปยังเว็บ $1 (ทำหน้าว่าง)',
+'spam_deleting' => 'ทุกรุ่นที่มีลิงก์ไปยัง $1 กำลังลบ',
# Info page
'pageinfo-title' => 'ข้อมูลสำหรับ "$1"',
'showhidebots' => '($1 บอต)',
'noimages' => 'ไม่มีให้ดู',
'ilsubmit' => 'สืบค้น',
-'bydate' => 'วันที่',
+'bydate' => 'à¸\95ามวัà¸\99à¸\97ีà¹\88',
'sp-newimages-showfrom' => 'แสดงภาพใหม่เริ่มต้นจาก $2, $1',
# Video information, used by Language::formatTimePeriod() to format lengths in the above messages
'version-entrypoints' => 'URL-адреса точки входу',
'version-entrypoints-header-entrypoint' => 'Точка входу',
'version-entrypoints-header-url' => 'URL',
+'version-entrypoints-articlepath' => '[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Шлях до статей]',
+'version-entrypoints-scriptpath' => '[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Шлях до скриптів]',
# Special:FilePath
'filepath' => 'Шлях до файлу',
'last' => 'trước',
'page_first' => 'đầu',
'page_last' => 'cuối',
-'histlegend' => 'Chọn so sánh: đánh dấu để chọn các phiên bản để so sánh rồi nhấn enter hoặc nút ở dưới.<br />
-Chú giải: (hiện) = khác với phiên bản hiện hành,
-(trước) = khác với phiên bản trước, n = sửa đổi nhỏ.',
+'histlegend' => "Chọn so sánh: Đánh dấu để chọn các phiên bản để so sánh rồi nhấn Enter hoặc nút ở dưới.<br />
+Chú giải: '''({{int:cur}})''' = khác với phiên bản hiện hành, '''({{int:last}})''' = khác với phiên bản trước, '''{{int:minoreditletter}}''' = sửa đổi nhỏ.",
'history-fieldset-title' => 'Tìm trong lịch sử',
'history-show-deleted' => 'Chỉ bị xóa',
'histfirst' => 'Cũ nhất',
'search-interwiki-default' => '$1 kết quả:',
'search-interwiki-more' => '(thêm)',
'search-relatedarticle' => 'Liên quan',
-'mwsuggest-disable' => 'Tắt gợi ý bằng AJAX',
+'mwsuggest-disable' => 'Tắt gợi ý tìm kiếm',
'searcheverything-enable' => 'Tìm trong tất cả không gian tên',
'searchrelated' => 'có liên quan',
'searchall' => 'tất cả',
Nếu bạn chọn không cập nhật, hãy nhớ kiểm tra [[Special:DoubleRedirects|đổi hướng kép]] hoặc [[Special:BrokenRedirects|đổi hướng đến trang không tồn tại]].
Bạn phải chịu trách nhiệm đảm bảo các liên kết đó tiếp tục trỏ đến nơi chúng cần đến.
-Chú ý rằng trang sẽ '''không''' bị di chuyển nếu đã có một trang tại tên mới, trừ khi nó là trang đổi hướng và không có lịch sử sửa đổi trước đây.
+Chú ý rằng trang sẽ '''không''' bị di chuyển nếu đã có một trang tại tên mới, trừ khi trang tại tên mới là trang đổi hướng và không có lịch sử sửa đổi trước đây.
Điều này có nghĩa là bạn có thể đổi tên trang lại như cũ nếu bạn có nhầm lẫn, và bạn không thể ghi đè lên một trang đã có sẵn.
'''CẢNH BÁO!'''
'pageinfo-robot-noindex' => 'Không thể ghi chỉ mục',
'pageinfo-views' => 'Số lần xem',
'pageinfo-watchers' => 'Số người theo dõi trang',
+'pageinfo-few-watchers' => 'Không tới $1 người theo dõi',
'pageinfo-redirects-name' => 'Số trang đổi hướng đến trang này',
'pageinfo-redirects-value' => '$1',
'pageinfo-subpages-name' => 'Số trang con của trang này',
'gotaccount' => '¿Mayda kana akawnt? $1.',
'gotaccountlink' => 'Sakob',
'userlogin-resetlink' => 'Nangalimot han imo detalye han pagsakob?',
-'createaccountmail' => 'Ha e-mail',
+'createaccountmail' => 'Gamiti hin temporaryo nga bisan ano nag password ngan igpadangat ngada ha e-mail address nga nakasurat ha ubos',
'createaccountreason' => 'Rason:',
'badretype' => 'Diri naangay an mga tigaman-pagsulod nga im ginbutang',
'userexists' => 'An agnay hiton gumaramit nga im ginbutang in gingamit na.
'passwordremindertitle' => 'Bag-o nga diri-pirmihan nga tigaman-pagsulod para han {{SITENAME}}',
'noemail' => 'Waray e-mail nga adres nga ginrekord para han nágámit "$1".',
'noemailcreate' => 'Kinahanglan nim maghatag hin may hinungdan nga e-mail address',
+'passwordsent' => 'Uska bag-o nga password in ginpadangat ha e-mail address nga nakarehistro kan "$1".
+Alayon paglog-in utro kahuman mo makarawat ini.',
+'blocked-mailpassword' => 'An imo IP address in ginpugong ha pag-edit, ngan tungod hini in diri gintutugotan paggamit han password recovery function para malikyan an abuso.',
+'eauthentsent' => 'Uska kompirmasyon nga e-mail in ginpadangan ha gin-ngaranan nga e-mail address.
+San-o matagan pa hin iba nga e-mail para ha imo akawnt, kinahanglan mo sundon an mga surundan nga nakasurat ha e-mail, para makompirma nga imo gud ito akawnt.',
'mailerror' => 'Sayop han pagpadangat hin surat: $1',
'emailauthenticated' => 'Ginpamatuod an imo e-mail adres han $2 ha $3.',
'emailconfirmlink' => 'Igkompirma an imo e-mail address',
'oldpassword' => 'Daan nga tigaman-pagsulod:',
'newpassword' => 'Bag-o nga tigaman-pagsulod:',
'retypenew' => 'Utroha pagbutang an bag-o nga tigaman-pagsulod:',
+'resetpass_submit' => 'Igbutang an password ngan log in',
'resetpass_success' => 'Malinamposon nga nasalyuan na an imo tigaman-pagsulod!
Ikaw in naglalog-in yana...',
'resetpass_forbidden' => 'Diri mababalyoan an mga tigaman-pagsulod',
'edit-already-exists' => 'Diri nakakahimo hin bag-o nga pakli.
Aada na ito.',
'defaultmessagetext' => 'Aada-nga-daan nga teksto han mensahe',
+'invalid-content-data' => 'Sayop nga sulod nga datos',
'content-not-allowed-here' => 'An sulod nga "$1" in diri gintutugotan ha pakli nga [[$2]]',
# Content models
'rev-showdeleted' => 'igpakita',
'revisiondelete' => 'Pagpara/pagtanggal han pagpara nga mga rebisyon',
'revdelete-nologtype-title' => 'Waray ginhatag nga klase hit talaan',
+'revdelete-nologid-title' => 'Sayop nga log entry',
'revdelete-show-file-confirm' => 'Sigurado ka nga gusto mo makita an ginpara nga pagliwat han file "<nowiki>$1</nowiki>" tikang $2 ha $3?',
'revdelete-show-file-submit' => 'Oo',
'revdelete-hide-text' => 'Tagoon an rebisyon han teksto',
'january-gen' => 'יאנואר',
'february-gen' => 'פעברואר',
'march-gen' => 'מערץ',
-'april-gen' => 'אפריל',
+'april-gen' => 'אַפּריל',
'may-gen' => 'מיי',
'june-gen' => 'יוני',
'july-gen' => 'יולי',
'prevpage' => 'פֿריִערדיקער בלאַט ($1)',
'allpagesfrom' => 'ווייזן בלעטער אנגעהויבן פון:',
'allpagesto' => 'ווייזן בלעטער ביז:',
-'allarticles' => '×\90Ö·×\9c×¢ ×\90ַר×\98×\99ק×\9c×¢×\9f',
-'allinnamespace' => 'אלע בלעטער ($1 נאָמענטייל )',
-'allnotinnamespace' => 'אלע בלעטער (נישט אין נאמענטייל $1)',
+'allarticles' => '×\90Ö·×\9c×¢ ×\91×\9c×¢×\98ער',
+'allinnamespace' => 'אַלע בלעטער ($1 נאָמענטייל )',
+'allnotinnamespace' => 'אַלע בלעטער (נישט אין $1 נאָמענטייל)',
'allpagesprev' => 'פריערדיגע',
'allpagesnext' => 'נעקסט',
'allpagessubmit' => 'גיי',
'usermessage-editor' => 'Sìstẹ́mú olúránṣẹ́',
# Watchlist
-'watchlist' => 'Ìmójútó mi',
+'watchlist' => 'Ìmójútó',
'mywatchlist' => 'Ìmójútó',
'watchlistfor2' => 'Fún $1 $2',
'nowatchlist' => 'Ẹ kò ní ohun kankan nínú ìmójútó yín.',
'protect-default' => 'Ẹ gba gbogbo àwọn oníṣe láàyè',
'protect-fallback' => 'Ìyọ̀nda "$1" pọn dandan',
'protect-level-autoconfirmed' => 'Dínà àwọn oníṣe tuntun àti tíkòforúkọ sílẹ́',
-'protect-level-sysop' => 'Alámùójútó nìkan',
+'protect-level-sysop' => 'Gba àwọn alámùójútó nìkan láyè',
'protect-summary-cascade' => 'títẹ̀léra',
'protect-expiring' => 'parí ní $1 (UTC)',
'protect-expiring-local' => 'yíò parí ní $1',
'pageinfo-protect-cascading' => 'Àbò bẹ̀rẹ̀ láti ibí',
'pageinfo-protect-cascading-yes' => 'Bẹ́ẹ̀ni',
'pageinfo-protect-cascading-from' => 'Àbò bẹ̀rẹ̀ láti',
+'pageinfo-category-pages' => 'Iye àwọn ojúewé',
+'pageinfo-category-files' => 'Iye àwọn fáìlì',
# Patrolling
'markaspatrolleddiff' => 'Ìṣààmí sí bíi sísọ́',
'specialpages-group-highuse' => 'Àwọn ojúewé ìlò gíga',
'specialpages-group-pages' => 'Àkójọ àwọn ojúewé',
'specialpages-group-pagetools' => 'Àwọn irinṣẹ́ ojúewé',
-'specialpages-group-wiki' => 'Àwọn irinṣẹ́ àti dátà wiki',
+'specialpages-group-wiki' => 'Àwọn irinṣẹ́ àti dátà',
'specialpages-group-redirects' => 'Ìtúnjúwe àwọn ojúewé pàtàkì',
'specialpages-group-spam' => 'Irínṣẹ́ spam',
'history-fieldset-title' => '浏览历史',
'history-show-deleted' => '仅被删除的',
'histfirst' => '最早',
-'histlast' => '最后',
+'histlast' => '最新',
'historysize' => '($1字节)',
'historyempty' => '(空)',
define( 'MEDIAWIKI', true );
$wgCommandLineMode = true;
+
# Turn off output buffering if it's on
- @ob_end_flush();
+ while( ob_get_level() > 0 ) {
+ ob_end_flush();
+ }
$this->validateParamsAndArgs();
}
doc:
php mwdocgen.php --all
- @echo 'Doc generation done. Look at ./docs/html/'
+ ./mwjsduck-gen
+ @echo 'PHP documentation (by Doxygen) in ./docs/html/'
+ @echo 'JS documentation (by JSDuck) in ./docs/js/'
man:
php mwdocgen.php --all --generate-man
--- /dev/null
+--
+-- Creates the pp_propname_page index on page_props
+--
+CREATE UNIQUE INDEX /*i*/pp_propname_page ON /*_*/page_props (pp_propname, pp_page);
$username = wfMessage( 'spambot_username' )->text();
$wgUser = User::newFromName( $username );
if ( !$wgUser ) {
- $this->error( "Invalid username", true );
+ $this->error( "Invalid username specified in 'spambot_username' message: $username", true );
}
// Create the user if necessary
if ( !$wgUser->getId() ) {
foreach ( $srcPathsRel as $srcPathRel ) {
$srcPaths[] = $src->getRootStoragePath() . "/$backendRel/$srcPathRel";
}
+ $t_start = microtime( true );
$fsFiles = $src->getLocalReferenceMulti( array( 'srcs' => $srcPaths, 'latest' => 1 ) );
+ $ellapsed_ms = floor( ( microtime( true ) - $t_start ) * 1000 );
+ $this->output( "\nDownloaded these file(s) [{$ellapsed_ms}ms]:\n" .
+ implode( "\n", $srcPaths ) . "\n\n" );
}
// Determine what files need to be copied over...
* @ingroup Maintenance
*/
class DeleteArchivedFilesImplementation {
- static public function doDelete( $output, $force ) {
+ public static function doDelete( $output, $force ) {
# Data should come off the master, wrapped in a transaction
$dbw = wfGetDB( DB_MASTER );
$dbw->begin( __METHOD__ );
* purgeRedundantText(). See Maintenance for a description of
* those methods.
*/
- static public function doDelete( $maint ) {
+ public static function doDelete( $maint ) {
$dbw = wfGetDB( DB_MASTER );
$dbw->begin( __METHOD__ );
// Potentially debug globals
$maintenance->globals();
+ // Perform deferred updates.
+ DeferredUpdates::doUpdates( 'commit' );
+
// log profiling info
wfLogProfilingData();
+
+ // Commit and close up!
+ $factory = wfGetLBFactory();
+ $factory->commitMasterChanges();
+ $factory->shutdown();
} catch ( MWException $mwe ) {
echo( $mwe->getText() );
exit( 1 );
* @ingroup Maintenance
*/
-$initialTime = microtime( true );
$wgProfiler = array( 'class' => 'ProfilerSimpleText' );
error_reporting( E_ALL );
/**
** Randomly returns one element of the input array.
*/
- static public function chooseInput( array $input ) {
+ public static function chooseInput( array $input ) {
$randindex = wikiFuzz::randnum( count( $input ) - 1 );
return $input[$randindex];
}
* @param $start int
* @return int
*/
- static public function randnum( $finish, $start = 0 ) {
+ public static function randnum( $finish, $start = 0 ) {
return mt_rand( $start, $finish );
}
* Returns a mix of random text and random wiki syntax.
* @return string
*/
- static private function randstring() {
+ private static function randstring() {
$thestring = "";
for ( $i = 0; $i < 40; $i++ ) {
* or random data from "other".
* @return string
*/
- static private function makestring() {
+ private static function makestring() {
$what = wikiFuzz::randnum( 2 );
if ( $what == 0 ) {
return wikiFuzz::randstring();
* @param $matches
* @return string
*/
- static private function stringEscape( $matches ) {
+ private static function stringEscape( $matches ) {
return sprintf( "\\x%02x", ord( $matches[1] ) );
}
* @param $str string
* @return string
*/
- static public function makeTitleSafe( $str ) {
+ public static function makeTitleSafe( $str ) {
$legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
return preg_replace_callback(
"/([^$legalTitleChars])/", 'wikiFuzz::stringEscape',
** Returns a string of fuzz text.
* @return string
*/
- static private function loop() {
+ private static function loop() {
switch ( wikiFuzz::randnum( 3 ) ) {
case 1: // an opening tag, with parameters.
$string = "";
* Returns one of the three styles of random quote: ', ", and nothing.
* @return string
*/
- static private function getRandQuote() {
+ private static function getRandQuote() {
switch ( wikiFuzz::randnum( 3 ) ) {
case 1 : return "'";
case 2 : return "\"";
* @param $maxtypes int
* @return string
*/
- static public function makeFuzz( $maxtypes = 2 ) {
+ public static function makeFuzz( $maxtypes = 2 ) {
$page = "";
for ( $k = 0; $k < $maxtypes; $k++ ) {
$page .= wikiFuzz::loop();
--- /dev/null
+<?php
+/**
+ * Print serialized output of MediaWiki config vars
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ * @author Tim Starling
+ * @author Antoine Musso
+ */
+
+require_once( __DIR__ . '/Maintenance.php' );
+
+/**
+ * Print serialized output of MediaWiki config vars
+ *
+ * @ingroup Maintenance
+ */
+class GetConfiguration extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Get serialized MediaWiki site configuration";
+ $this->addOption( 'settings', 'Space-separated list of wg* variables', true, true );
+ $this->addOption( 'format', 'PHP or JSON', true, true );
+ $this->addOption( 'wiki', 'Wiki ID', true, true );
+ }
+
+ public function execute() {
+ $res = array();
+ foreach ( explode( ' ', $this->getOption( 'settings' ) ) as $name ) {
+ if ( !preg_match( '/^wg[A-Z]/', $name ) ) {
+ throw new MWException( "Variable '$name' does start with 'wg'." );
+ } elseif ( !isset( $GLOBALS[$name] ) ) {
+ throw new MWException( "Variable '$name' is not set." );
+ } elseif ( !$this->isAllowedVariable( $GLOBALS[$name] ) ) {
+ throw new MWException( "Variable '$name' includes non-array, non-scalar, items." );
+ }
+ $res[$name] = $GLOBALS[$name];
+ }
+
+ $out = null;
+ switch( $this->getOption( 'format' ) ) {
+ case 'PHP':
+ $out = serialize( $res );
+ break;
+ case 'JSON':
+ $out = FormatJson::encode( $res );
+ break;
+ default:
+ throw new MWException( "Invalid serialization format given." );
+ }
+ if ( !is_string( $out ) ) {
+ throw new MWException( "Failed to serialize the requested settings." );
+ }
+
+ $this->output( $out . "\n" );
+ }
+
+ private function isAllowedVariable( $value ) {
+ if ( is_array( $value ) ) {
+ foreach ( $value as $k => $v ) {
+ if ( !$this->isAllowedVariable( $v ) ) {
+ return false;
+ }
+ }
+ return true;
+ } elseif ( is_scalar( $value ) ) {
+ return true;
+ }
+ return false;
+ }
+}
+
+$maintClass = "GetConfiguration";
+require_once( RUN_MAINTENANCE_IF_MAIN );
--- /dev/null
+# See also:
+# - https://github.com/senchalabs/jsduck/wiki/Tags
+# - https://github.com/senchalabs/jsduck/wiki/Custom-tags
+require 'jsduck/meta_tag'
+
+class ContextTag < JsDuck::MetaTag
+ def initialize
+ @name = 'context'
+ end
+
+ # @param tags All matches of this tag on one class.
+ def to_html(tags)
+ return '<h3 class="pa">Context</h3>' + render_long_context(tags.last)
+ end
+
+ def render_long_context(tag)
+ if tag =~ /\A([^\s]+)/m
+ name = $1
+ return format("`this` : {@link #{name}}")
+ end
+ end
+end
+
+class SeeTag < JsDuck::MetaTag
+ def initialize
+ @name = 'see'
+ @multiline = true
+ end
+
+ # @param tags All matches of this tag on one class.
+ def to_html(tags)
+ doc = []
+ doc << '<h3 class="pa">Related</h3>'
+ doc << [
+ '<ul>',
+ tags.map {|tag| render_long_see(tag) },
+ '</ul>',
+ ]
+ doc
+ end
+
+ def render_long_see(tag)
+ if tag =~ /\A([^\s]+)( .*)?\Z/m
+ name = $1
+ doc = $2 ? ': ' + $2 : ''
+ return [
+ '<li>',
+ format("{@link #{name}} #{doc}"),
+ '</li>'
+ ]
+ end
+ end
+end
--- /dev/null
+[
+ {
+ "name": "MediaWiki",
+ "groups": [
+ {
+ "name": "Base",
+ "classes": [
+ "mw",
+ "mw.Map",
+ "mw.Message",
+ "mw.loader",
+ "mw.html",
+ "mw.html.Cdata",
+ "mw.html.Raw"
+ ]
+ },
+ {
+ "name": "General",
+ "classes": [
+ "mw.Title",
+ "mw.notification",
+ "mw.util",
+ "mw.plugin.notify"
+ ]
+ },
+ {
+ "name": "API",
+ "classes": ["mw.Api*"]
+ }
+ ]
+ },
+ {
+ "name": "jQuery",
+ "groups": [
+ {
+ "name": "Core",
+ "classes": ["jQuery", "jQuery.Event", "jQuery.Promise", "jQuery.Deferred", "jQuery.jqXHR"]
+ },
+ {
+ "name": "Plugins",
+ "classes": ["jQuery.plugin.*"]
+ }
+ ]
+ },
+ {
+ "name": "Misc",
+ "groups": [
+ {
+ "name": "Native",
+ "classes": ["Array", "Boolean", "Date", "Function", "Number", "Object", "RegExp", "String"]
+ }
+ ]
+ }
+]
--- /dev/null
+{
+ "--title": "MediaWiki Code Documentation",
+ "--categories": "./categories.json",
+ "--meta-tags": "./MetaTags.rb",
+ "--warnings": ["-no_doc"],
+ "--builtin-classes": true,
+ "--output": "../../docs/js",
+ "--": [
+ "./external.js",
+ "../../resources/mediawiki/mediawiki.js",
+ "../../resources/mediawiki/mediawiki.util.js",
+ "../../resources/mediawiki/mediawiki.Title.js",
+ "../../resources/mediawiki/mediawiki.notify.js",
+ "../../resources/mediawiki/mediawiki.notification.js",
+ "../../resources/mediawiki.api",
+ "../../resources/jquery/jquery.localize.js"
+ ]
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>MediaWiki Examples</title>
+ <script>
+ function loadInlineExample(code, options, callback) {
+ try {
+ document.body.innerHTML = '';
+ eval(code);
+ callback && callback(true);
+ } catch (e) {
+ document.body.innerHTML = document.createTextNode(e);
+ callback && callback(false, e);
+ }
+ }
+ </script>
+</head>
+<body></body>
+</html>
--- /dev/null
+/**
+ * @class jQuery
+ */
+
+/**
+ * @method ajax
+ * @return {jqXHR}
+ */
+
+/**
+ * @class jQuery.Event
+ */
+
+/**
+ * @class jQuery.Promise
+ */
+
+/**
+ * @class jQuery.Deferred
+ * @mixins jQuery.Promise
+ */
+
+/**
+ * @class jQuery.jqXHR
+ * @alternateClassName jqXHR
+ */
. "\n\n";
}
if ( !$ucdallPresent ) {
- $error = "Unable to find ucd.all.grouped.xml. "
+ $error .= "Unable to find ucd.all.grouped.xml. "
. "Download it, unzip, and specify its location with --data-dir=<DIR>. "
. "\n\n";
}
* @ingroup MaintenanceLanguage
*/
-require_once( __DIR__ . '/../Maintenance.php' );
-
require_once( __DIR__ . '/../../includes/normal/UtfNormalUtil.php' );
+require_once( __DIR__ . '/../Maintenance.php' );
+
/**
* Generates normalizer data files for Arabic and Malayalam.
* For NFC see includes/normal.
'deadendpages-summary',
'protectedpages-summary',
'disambiguations-summary',
+ 'pageswithprop-summary',
'doubleredirects-summary',
'lonelypages-summary',
'unusedtemplates-summary',
'disambiguationspage',
'disambiguations-text',
),
+ 'pageswithprop' => array(
+ 'pageswithprop',
+ 'pageswithprop-summary',
+ 'pageswithprop-text',
+ 'pageswithprop-prop',
+ 'pageswithprop-ok',
+ ),
'doubleredirects' => array(
'doubleredirects',
'doubleredirects-summary',
'randomredirect' => 'Random redirect',
'statistics' => 'Statistics',
'disambiguations' => '',
+ 'pageswithprop' => '',
'doubleredirects' => '',
'brokenredirects' => '',
'withoutinterwiki' => '',
* @ingroup MaintenanceLanguage
*/
+if ( PHP_SAPI != 'cli' ) {
+ die( "Run me from the command line please.\n" );
+}
+
if ( !isset( $argv[1] ) ) {
print "Usage: php {$argv[0]} <filename>\n";
exit( 1 );
--- /dev/null
+#!/usr/bin/env sh
+jsduck --config=$(cd $(dirname $0)/..; pwd)/maintenance/jsduck/config.json && echo 'JSDuck execution finished.'
}
public function execute() {
- global $wgMemc;
+ global $wgMemc, $wgJobTypesExcludedFromDefaultQueue;
$type = false; // job type required/picked
+
if ( $this->hasOption( 'types' ) ) {
$types = explode( ' ', $this->getOption( 'types' ) );
} elseif ( $this->hasOption( 'type' ) ) {
$types = array( $this->getOption( 'type' ) );
} else {
- $types = JobQueueGroup::singleton()->getDefaultQueueTypes();
+ $types = false;
}
// Handle any required periodic queue maintenance
$this->executeReadyPeriodicTasks();
- $memcKey = 'jobqueue:dbs:v3';
- $pendingDbInfo = $wgMemc->get( $memcKey );
-
- // If the cache entry wasn't present, is stale, or in .1% of cases otherwise,
- // regenerate the cache. Use any available stale cache if another process is
- // currently regenerating the pending DB information.
- if ( !is_array( $pendingDbInfo )
- || ( time() - $pendingDbInfo['timestamp'] ) > 300 // 5 minutes
- || mt_rand( 0, 999 ) == 0
- ) {
- if ( $wgMemc->add( "$memcKey:rebuild", 1, 1800 ) ) { // lock
- $pendingDbInfo = array(
- 'pendingDBs' => $this->getPendingDbs(),
- 'timestamp' => time()
- );
- for ( $attempts=1; $attempts <= 25; ++$attempts ) {
- if ( $wgMemc->add( "$memcKey:lock", 1, 60 ) ) { // lock
- $wgMemc->set( $memcKey, $pendingDbInfo );
- $wgMemc->delete( "$memcKey:lock" ); // unlock
- break;
- }
- }
- $wgMemc->delete( "$memcKey:rebuild" ); // unlock
- }
- }
-
- if ( !is_array( $pendingDbInfo ) || !$pendingDbInfo['pendingDBs'] ) {
+ // Get all the queues with jobs in them
+ $pendingDBs = JobQueueAggregator::singleton()->getAllReadyWikiQueues();
+ if ( !count( $pendingDBs ) ) {
return; // no DBs with jobs or cache is both empty and locked
}
- $pendingDBs = $pendingDbInfo['pendingDBs']; // convenience
do {
$again = false;
// Flatten the tree of candidates into a flat list so that a random
// item can be selected, weighing each queue (type/db tuple) equally.
foreach ( $pendingDBs as $type => $dbs ) {
- if ( in_array( $type, $types ) ) {
+ if (
+ ( is_array( $types ) && in_array( $type, $types ) ) ||
+ ( $types === false && !in_array( $type, $wgJobTypesExcludedFromDefaultQueue ) )
+ ) {
foreach ( $dbs as $db ) {
$candidates[] = array( $type, $db );
}
list( $type, $db ) = $candidates[ mt_rand( 0, count( $candidates ) - 1 ) ];
if ( !$this->checkJob( $type, $db ) ) { // queue is actually empty?
- $pendingDBs = $this->delistDB( $pendingDBs, $db, $type );
- // Update the cache to remove the outdated information.
- // Make sure that this does not race (especially with full rebuilds).
- if ( $wgMemc->add( "$memcKey:lock", 1, 60 ) ) { // lock
- $curInfo = $wgMemc->get( $memcKey );
- if ( is_array( $curInfo ) ) {
- $curInfo['pendingDBs'] =
- $this->delistDB( $curInfo['pendingDBs'], $db, $type );
- $wgMemc->set( $memcKey, $curInfo );
- // May as well make use of this newer information
- $pendingDBs = $curInfo['pendingDBs'];
- }
- $wgMemc->delete( "$memcKey:lock" ); // unlock
- }
+ $pendingDBs[$type] = array_diff( $pendingDBs[$type], $db );
+ JobQueueAggregator::singleton()->notifyQueueEmpty( $db, $type );
$again = true;
}
} while ( $again );
}
}
- /**
- * Remove a type/DB entry from the list of queues with jobs
- *
- * @param $pendingDBs array
- * @param $db string
- * @param $type string
- * @return Array
- */
- private function delistDB( array $pendingDBs, $db, $type ) {
- $pendingDBs[$type] = array_diff( $pendingDBs[$type], array( $db ) );
- return $pendingDBs;
- }
-
/**
* Check if the specified database has a job of the specified type in it.
* The type may be false to indicate "all".
return !JobQueueGroup::singleton( $dbName )->get( $type )->isEmpty();
}
- /**
- * Get all databases that have a pending job
- * @return array
- */
- private function getPendingDbs() {
- global $wgLocalDatabases;
-
- $pendingDBs = array(); // (job type => (db list))
- foreach ( $wgLocalDatabases as $db ) {
- foreach ( JobQueueGroup::singleton( $db )->getQueuesWithJobs() as $type ) {
- $pendingDBs[$type][] = $db;
- }
- }
-
- return $pendingDBs;
- }
-
/**
* Do all ready periodic jobs for all databases every 5 minutes (and .1% of the time)
* @return integer
);
ALTER TABLE page_props ADD CONSTRAINT page_props_pk PRIMARY KEY (pp_page,pp_propname);
CREATE INDEX page_props_propname ON page_props (pp_propname);
+CREATE UNIQUE INDEX pp_propname_page ON page_props (pp_propname,pp_page);
CREATE TABLE archive (
ar_namespace SMALLINT NOT NULL,
do {
$job = ( $type === false )
? $group->pop( JobQueueGroup::TYPE_DEFAULT, JobQueueGroup::USE_CACHE )
- : $group->get( $type )->pop(); // job from a single queue
+ : $group->pop( $type ); // job from a single queue
if ( $job ) { // found a job
- // Perform the job (logging success/failure and runtime)...
- $t = microtime( true );
$this->runJobsLog( $job->toString() . " STARTING" );
- $status = $job->run();
- if ( !is_bool( $status ) ) {
- wfWarn( $job->getType() . " job failed to return a boolean." );
- $status = true; // sanity
+ // Run the job...
+ $t = microtime( true );
+ try {
+ $status = $job->run();
+ $error = $job->getLastError();
+ } catch ( MWException $e ) {
+ $status = false;
+ $error = get_class( $e ) . ': ' . $e->getMessage();
}
- if ( $status ) {
+ $timeMs = intval( ( microtime( true ) - $t ) * 1000 );
+
+ // Mark the job as done on success or when the job cannot be retried
+ if ( $status !== false || !$job->allowRetries() ) {
$group->ack( $job ); // done
}
- $t = microtime( true ) - $t;
- $timeMs = intval( $t * 1000 );
if ( !$status ) {
- $this->runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" );
+ $this->runJobsLog( $job->toString() . " t=$timeMs error={$error}" );
} else {
$this->runJobsLog( $job->toString() . " t=$timeMs good" );
}
+
// Break out if we hit the job count or wall time limits...
if ( $maxJobs && ++$n >= $maxJobs ) {
break;
- }
- if ( $maxTime && ( time() - $startTime ) > $maxTime ) {
+ } elseif ( $maxTime && ( time() - $startTime ) > $maxTime ) {
break;
}
+
// Don't let any slaves/backups fall behind...
$group->get( $job->getType() )->waitForBackups();
}
public function __construct() {
parent::__construct();
$this->mDescription = "Send SQL queries to a MediaWiki database";
+ $this->addOption( 'cluster', 'Use an external cluster by name', false, true );
}
public function execute() {
- $dbw = wfGetDB( DB_MASTER );
- if ( $this->hasArg() ) {
- $fileName = $this->getArg();
- $file = fopen( $fileName, 'r' );
+ // Get a DB handle (with this wiki's DB select) from the appropriate load balancer
+ if ( $this->hasOption( 'cluster' ) ) {
+ $lb = wfGetLBFactory()->getExternalLB( $this->getOption( 'cluster' ) );
+ $dbw = $lb->getConnection( DB_MASTER ); // master for external LB
+ } else {
+ $dbw = wfGetDB( DB_MASTER ); // master for primary LB for this wiki
+ }
+ if ( $this->hasArg( 0 ) ) {
+ $file = fopen( $this->getArg( 0 ), 'r' );
if ( !$file ) {
$this->error( "Unable to open input file", true );
}
$this->error( $e, $doDie );
}
}
+ wfWaitForSlaves();
}
/**
blob_id integer UNSIGNED NOT NULL AUTO_INCREMENT,
blob_text longblob,
PRIMARY KEY (blob_id)
-) ENGINE=MyISAM MAX_ROWS=100000000 AVG_ROW_LENGTH=100000;
-
+) ENGINE=InnoDB;
) /*$wgDBTableOptions*/;
CREATE UNIQUE INDEX /*i*/pp_page_propname ON /*_*/page_props (pp_page,pp_propname);
+CREATE UNIQUE INDEX /*i*/pp_propname_page ON /*_*/page_props (pp_propname,pp_page);
-- A table to log updates, one text key row per update.
require_once( __DIR__ . '/includes/WebStart.php' );
-if( $wgRequest->getVal( 'ctype' ) == 'application/xml' ) {
+if ( $wgRequest->getVal( 'ctype' ) == 'application/xml' ) {
// Makes testing tweaks about a billion times easier
$ctype = 'application/xml';
} else {
'method' => 'get',
'template' => $searchPage->getCanonicalURL( 'search={searchTerms}' ) );
-if( $wgEnableAPI ) {
+if ( $wgEnableAPI ) {
// JSON interface for search suggestions.
// Supported in Firefox 2 and later.
$urls[] = array(
// general way than overriding the whole search engine...
wfRunHooks( 'OpenSearchUrls', array( &$urls ) );
-foreach( $urls as $attribs ) {
+foreach ( $urls as $attribs ) {
print Xml::element( 'Url', $attribs );
}
require ( __DIR__ . '/includes/WebStart.php' );
}
-
header( 'Content-Type: text/html; charset=utf-8' );
?>
<!DOCTYPE html>
<html>
<head>
-<meta charset="UTF-8">
-<title>Profiling data</title>
-<style>
- /* noc.wikimedia.org/base.css */
-
- * {
- margin: 0;
- padding: 0;
- }
-
- body {
- padding: 0.5em 1em;
- background: #fff;
- font: 14px/1.6 sans-serif;
- color: #333;
- }
+ <meta charset="UTF-8">
+ <title>Profiling data</title>
+ <style>
+ /* noc.wikimedia.org/base.css */
+
+ * {
+ margin: 0;
+ padding: 0;
+ }
- p, ul, ol, table {
- margin: 0.5em 0;
- }
+ body {
+ padding: 0.5em 1em;
+ background: #fff;
+ font: 14px/1.6 sans-serif;
+ color: #333;
+ }
- a {
- color: #0645AD;
- text-decoration: none;
- }
+ p, ul, ol, table {
+ margin: 0.5em 0;
+ }
- a:hover {
- text-decoration: underline;
- }
+ a {
+ color: #0645AD;
+ text-decoration: none;
+ }
- /*!
- * Bootstrap v2.1.1
- *
- * Copyright 2012 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- */
-
- table {
- max-width: 100%;
- background-color: transparent;
- border-collapse: collapse;
- border-spacing: 0;
- }
+ a:hover {
+ text-decoration: underline;
+ }
- .table {
- width: 100%;
- margin-bottom: 20px;
- }
+ /*!
+ * Bootstrap v2.1.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+ table {
+ max-width: 100%;
+ background-color: transparent;
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
- .table th,
- .table td {
- padding: 0.1em;
- text-align: left;
- vertical-align: top;
- border-top: 1px solid #ddd;
- }
+ .table {
+ width: 100%;
+ margin-bottom: 20px;
+ }
- .table th {
- font-weight: bold;
- }
+ .table th,
+ .table td {
+ padding: 0.1em;
+ text-align: left;
+ vertical-align: top;
+ border-top: 1px solid #ddd;
+ }
- .table thead th {
- vertical-align: bottom;
- }
+ .table th {
+ font-weight: bold;
+ }
- .table thead:first-child tr:first-child th,
- .table thead:first-child tr:first-child td {
- border-top: 0;
- }
+ .table thead th {
+ vertical-align: bottom;
+ }
- .table tbody + tbody {
- border-top: 2px solid #ddd;
- }
+ .table thead:first-child tr:first-child th,
+ .table thead:first-child tr:first-child td {
+ border-top: 0;
+ }
- .table-condensed th,
- .table-condensed td {
- padding: 4px 5px;
- }
+ .table tbody + tbody {
+ border-top: 2px solid #ddd;
+ }
- .table-striped tbody tr:nth-child(odd) td,
- .table-striped tbody tr:nth-child(odd) th {
- background-color: #f9f9f9;
- }
+ .table-condensed th,
+ .table-condensed td {
+ padding: 4px 5px;
+ }
- .table-hover tbody tr:hover td,
- .table-hover tbody tr:hover th {
- background-color: #f5f5f5;
- }
+ .table-striped tbody tr:nth-child(odd) td,
+ .table-striped tbody tr:nth-child(odd) th {
+ background-color: #f9f9f9;
+ }
- hr {
- margin: 20px 0;
- border: 0;
- border-top: 1px solid #eee;
- border-bottom: 1px solid #fff;
- }
+ .table-hover tbody tr:hover td,
+ .table-hover tbody tr:hover th {
+ background-color: #f5f5f5;
+ }
-</style>
+ hr {
+ margin: 20px 0;
+ border: 0;
+ border-top: 1px solid #eee;
+ border-bottom: 1px solid #fff;
+ }
+ </style>
</head>
<body>
<?php
$dbr = wfGetDB( DB_SLAVE );
-if( !$dbr->tableExists( 'profiling' ) ) {
+if ( !$dbr->tableExists( 'profiling' ) ) {
echo '<p>No <code>profiling</code> table exists, so we can\'t show you anything.</p>'
. '<p>If you want to log profiling data, enable <code>$wgProfileToDatabase</code>'
. ' in your LocalSettings.php and run <code>maintenance/update.php</code> to'
}
$expand = array();
-if ( isset( $_REQUEST['expand'] ) )
- foreach( explode( ',', $_REQUEST['expand'] ) as $f )
+if ( isset( $_REQUEST['expand'] ) ) {
+ foreach ( explode( ',', $_REQUEST['expand'] ) as $f ) {
$expand[$f] = true;
+ }
+}
class profile_point {
var $name;
$extet = " <a id=\"{$anchor}\" href=\"{$url}#{$anchor}\">[–]</a>";
}
?>
- <tr>
- <th><div style="margin-left: <?php echo (int)$indent; ?>em;">
- <?php echo htmlspecialchars( str_replace( ',', ', ', $this->name() ) ) . $extet ?>
- </div></th>
+ <tr>
+ <th>
+ <div style="margin-left: <?php echo (int)$indent; ?>em;">
+ <?php echo htmlspecialchars( str_replace( ',', ', ', $this->name() ) ) . $extet ?>
+ </div>
+ </th>
<td class="mw-profileinfo-timep"><?php echo @wfPercent( $this->time() / self::$totaltime * 100 ); ?></td>
<td class="mw-profileinfo-memoryp"><?php echo @wfPercent( $this->memory() / self::$totalmemory * 100 ); ?></td>
<td class="mw-profileinfo-count"><?php echo $this->count(); ?></td>
<td class="mw-profileinfo-mpc"><?php echo round( sprintf( '%.2f', $this->memoryPerCall() / 1024 ), 2 ); ?></td>
<td class="mw-profileinfo-tpr"><?php echo @round( sprintf( '%.2f', $this->time() / self::$totalcount ), 2 ); ?></td>
<td class="mw-profileinfo-mpr"><?php echo @round( sprintf( '%.2f', $this->memory() / self::$totalcount / 1024 ), 2 ); ?></td>
- </tr>
+ </tr>
<?php
if ( $ex ) {
foreach ( $this->children as $child ) {
}
};
-function compare_point(profile_point $a, profile_point $b) {
+function compare_point( profile_point $a, profile_point $b ) {
global $sort;
switch ( $sort ) {
- case 'name':
- return strcmp( $a->name(), $b->name() );
- case 'time':
- return $a->time() > $b->time() ? -1 : 1;
- case 'memory':
- return $a->memory() > $b->memory() ? -1 : 1;
- case 'count':
- return $a->count() > $b->count() ? -1 : 1;
- case 'time_per_call':
- return $a->timePerCall() > $b->timePerCall() ? -1 : 1;
- case 'memory_per_call':
- return $a->memoryPerCall() > $b->memoryPerCall() ? -1 : 1;
- case 'calls_per_req':
- return $a->callsPerRequest() > $b->callsPerRequest() ? -1 : 1;
- case 'time_per_req':
- return $a->timePerRequest() > $b->timePerRequest() ? -1 : 1;
- case 'memory_per_req':
- return $a->memoryPerRequest() > $b->memoryPerRequest() ? -1 : 1;
+ case 'name':
+ return strcmp( $a->name(), $b->name() );
+ case 'time':
+ return $a->time() > $b->time() ? -1 : 1;
+ case 'memory':
+ return $a->memory() > $b->memory() ? -1 : 1;
+ case 'count':
+ return $a->count() > $b->count() ? -1 : 1;
+ case 'time_per_call':
+ return $a->timePerCall() > $b->timePerCall() ? -1 : 1;
+ case 'memory_per_call':
+ return $a->memoryPerCall() > $b->memoryPerCall() ? -1 : 1;
+ case 'calls_per_req':
+ return $a->callsPerRequest() > $b->callsPerRequest() ? -1 : 1;
+ case 'time_per_req':
+ return $a->timePerRequest() > $b->timePerRequest() ? -1 : 1;
+ case 'memory_per_req':
+ return $a->memoryPerRequest() > $b->memoryPerRequest() ? -1 : 1;
}
}
$sorts = array( 'time', 'memory', 'count', 'calls_per_req', 'name',
'time_per_call', 'memory_per_call', 'time_per_req', 'memory_per_req' );
$sort = 'time';
-if ( isset( $_REQUEST['sort'] ) && in_array( $_REQUEST['sort'], $sorts ) )
+if ( isset( $_REQUEST['sort'] ) && in_array( $_REQUEST['sort'], $sorts ) ) {
$sort = $_REQUEST['sort'];
+}
$res = $dbr->select( 'profiling', '*', array(), 'profileinfo.php', array( 'ORDER BY' => 'pf_name ASC' ) );
-if (isset( $_REQUEST['filter'] ) )
+if ( isset( $_REQUEST['filter'] ) ) {
$filter = $_REQUEST['filter'];
-else
+} else {
$filter = '';
+}
?>
<form method="get" action="profileinfo.php">
-<p>
-<input type="text" name="filter" value="<?php echo htmlspecialchars($filter); ?>">
-<input type="hidden" name="sort" value="<?php echo htmlspecialchars($sort); ?>">
-<input type="hidden" name="expand" value="<?php echo htmlspecialchars(implode(",", array_keys($expand))); ?>">
-<input type="submit" value="Filter">
-</p>
+ <p>
+ <input type="text" name="filter" value="<?php echo htmlspecialchars( $filter ); ?>">
+ <input type="hidden" name="sort" value="<?php echo htmlspecialchars( $sort ); ?>">
+ <input type="hidden" name="expand" value="<?php echo htmlspecialchars( implode( ",", array_keys( $expand ) ) ); ?>">
+ <input type="submit" value="Filter">
+ </p>
</form>
<table class="mw-profileinfo-table table table-striped table-hover">
<thead>
- <tr>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'name' ); ?>">Name</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'time' ); ?>">Time (%)</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'memory' ); ?>">Memory (%)</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'count' ); ?>">Count</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'calls_per_req' ); ?>">Calls/req</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_call' ); ?>">ms/call</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_call' ); ?>">kb/call</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_req' ); ?>">ms/req</a></th>
- <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_req' ); ?>">kb/req</a></th>
- </tr>
+ <tr>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'name' ); ?>">Name</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'time' ); ?>">Time (%)</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'memory' ); ?>">Memory (%)</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'count' ); ?>">Count</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'calls_per_req' ); ?>">Calls/req</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_call' ); ?>">ms/call</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_call' ); ?>">kb/call</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'time_per_req' ); ?>">ms/req</a></th>
+ <th><a href="<?php echo getEscapedProfileUrl( false, 'memory_per_req' ); ?>">kb/req</a></th>
+ </tr>
</thead>
<tbody>
-<?php
-profile_point::$totaltime = 0.0;
-profile_point::$totalcount = 0;
-profile_point::$totalmemory = 0.0;
-
-function getEscapedProfileUrl( $_filter = false, $_sort = false, $_expand = false ) {
- global $filter, $sort, $expand;
-
- if ( $_expand === false )
- $_expand = $expand;
-
- return htmlspecialchars(
- '?' .
- wfArrayToCgi( array(
- 'filter' => $_filter ? $_filter : $filter,
- 'sort' => $_sort ? $_sort : $sort,
- 'expand' => implode( ',', array_keys( $_expand ) )
- ) )
- );
-}
+ <?php
+ profile_point::$totaltime = 0.0;
+ profile_point::$totalcount = 0;
+ profile_point::$totalmemory = 0.0;
-$points = array();
-$queries = array();
-$sqltotal = 0.0;
-
-$last = false;
-foreach( $res as $o ) {
- $next = new profile_point( $o->pf_name, $o->pf_count, $o->pf_time, $o->pf_memory );
- if( $next->name() == '-total' ) {
- profile_point::$totaltime = $next->time();
- profile_point::$totalcount = $next->count();
- profile_point::$totalmemory = $next->memory();
- }
- if ( $last !== false ) {
- if ( preg_match( '/^'.preg_quote( $last->name(), '/' ).'/', $next->name() ) ) {
- $last->add_child($next);
- continue;
+ function getEscapedProfileUrl( $_filter = false, $_sort = false, $_expand = false ) {
+ global $filter, $sort, $expand;
+
+ if ( $_expand === false ) {
+ $_expand = $expand;
+ }
+
+ return htmlspecialchars(
+ '?' .
+ wfArrayToCgi( array(
+ 'filter' => $_filter ? $_filter : $filter,
+ 'sort' => $_sort ? $_sort : $sort,
+ 'expand' => implode( ',', array_keys( $_expand ) )
+ ) )
+ );
+ }
+
+ $points = array();
+ $queries = array();
+ $sqltotal = 0.0;
+
+ $last = false;
+ foreach ( $res as $o ) {
+ $next = new profile_point( $o->pf_name, $o->pf_count, $o->pf_time, $o->pf_memory );
+ if ( $next->name() == '-total' ) {
+ profile_point::$totaltime = $next->time();
+ profile_point::$totalcount = $next->count();
+ profile_point::$totalmemory = $next->memory();
+ }
+ if ( $last !== false ) {
+ if ( preg_match( '/^' . preg_quote( $last->name(), '/' ) . '/', $next->name() ) ) {
+ $last->add_child( $next );
+ continue;
+ }
+ }
+ $last = $next;
+ if ( preg_match( '/^query: /', $next->name() ) || preg_match( '/^query-m: /', $next->name() ) ) {
+ $sqltotal += $next->time();
+ $queries[] = $next;
+ } else {
+ $points[] = $next;
}
}
- $last = $next;
- if ( preg_match( '/^query: /', $next->name() ) || preg_match( '/^query-m: /', $next->name() ) ) {
- $sqltotal += $next->time();
- $queries[] = $next;
- } else {
- $points[] = $next;
- }
-}
-$s = new profile_point( 'SQL Queries', 0, $sqltotal, 0, 0 );
-foreach ( $queries as $q )
- $s->add_child($q);
-$points[] = $s;
+ $s = new profile_point( 'SQL Queries', 0, $sqltotal, 0, 0 );
+ foreach ( $queries as $q )
+ $s->add_child( $q );
+ $points[] = $s;
-usort( $points, 'compare_point' );
+ usort( $points, 'compare_point' );
-foreach ( $points as $point ) {
- if ( strlen( $filter ) && !strstr( $point->name(), $filter ) )
- continue;
+ foreach ( $points as $point ) {
+ if ( strlen( $filter ) && !strstr( $point->name(), $filter ) ) {
+ continue;
+ }
- $point->display( $expand );
-}
-?>
+ $point->display( $expand );
+ }
+ ?>
</tbody>
</table>
<hr>
-<p>Total time: <code><?php printf('%5.02f', profile_point::$totaltime); ?></code></p>
-<p>Total memory: <code><?php printf('%5.02f', profile_point::$totalmemory / 1024 ); ?></code></p>
-<hr>
+<p>Total time: <code><?php printf( '%5.02f', profile_point::$totaltime ); ?></code></p>
+
+<p>Total memory: <code><?php printf( '%5.02f', profile_point::$totalmemory / 1024 ); ?></code></p>
+<hr />
</body>
</html>
'scripts' => 'resources/jquery/jquery.client.js',
'targets' => array( 'desktop', 'mobile' ),
),
- 'jquery.collapsibleTabs' => array(
- 'scripts' => 'resources/jquery/jquery.collapsibleTabs.js',
- 'dependencies' => 'jquery.delayedBind',
- ),
'jquery.color' => array(
'scripts' => 'resources/jquery/jquery.color.js',
'dependencies' => 'jquery.colorUtil',
/* MediaWiki Language */
'mediawiki.language' => array(
- 'scripts' => 'resources/mediawiki.language/mediawiki.language.js',
+ 'scripts' => array(
+ 'resources/mediawiki.language/mediawiki.language.js',
+ 'resources/mediawiki.language/mediawiki.language.numbers.js'
+ ),
'languageScripts' => array(
'bs' => 'resources/mediawiki.language/languages/bs.js',
'dsb' => 'resources/mediawiki.language/languages/dsb.js',
),
'dependencies' => array(
'mediawiki.language.data',
- 'mediawiki.cldr'
+ 'mediawiki.cldr',
),
'targets' => array( 'desktop', 'mobile' ),
),
+++ /dev/null
-/**
- * Collapsible tabs jQuery Plugin
- */
-( function ( $ ) {
- $.fn.collapsibleTabs = function ( options ) {
- // return if the function is called on an empty jquery object
- if ( !this.length ) {
- return this;
- }
- // Merge options into the defaults
- var $settings = $.extend( {}, $.collapsibleTabs.defaults, options );
-
- this.each( function () {
- var $el = $( this );
- // add the element to our array of collapsible managers
- $.collapsibleTabs.instances = ( $.collapsibleTabs.instances.length === 0 ?
- $el : $.collapsibleTabs.instances.add( $el ) );
- // attach the settings to the elements
- $el.data( 'collapsibleTabsSettings', $settings );
- // attach data to our collapsible elements
- $el.children( $settings.collapsible ).each( function () {
- $.collapsibleTabs.addData( $( this ) );
- } );
- } );
-
- // if we haven't already bound our resize hanlder, bind it now
- if ( !$.collapsibleTabs.boundEvent ) {
- $( window )
- .delayedBind( '500', 'resize', function ( ) {
- $.collapsibleTabs.handleResize();
- } );
- }
- // call our resize handler to setup the page
- $.collapsibleTabs.handleResize();
- return this;
- };
- $.collapsibleTabs = {
- instances: [],
- boundEvent: null,
- defaults: {
- expandedContainer: '#p-views ul',
- collapsedContainer: '#p-cactions ul',
- collapsible: 'li.collapsible',
- shifting: false,
- expandCondition: function ( eleWidth ) {
- return ( $( '#left-navigation' ).position().left + $( '#left-navigation' ).width() )
- < ( $( '#right-navigation' ).position().left - eleWidth );
- },
- collapseCondition: function () {
- return ( $( '#left-navigation' ).position().left + $( '#left-navigation' ).width() )
- > $( '#right-navigation' ).position().left;
- }
- },
- addData: function ( $collapsible ) {
- var $settings = $collapsible.parent().data( 'collapsibleTabsSettings' );
- if ( $settings !== null ) {
- $collapsible.data( 'collapsibleTabsSettings', {
- expandedContainer: $settings.expandedContainer,
- collapsedContainer: $settings.collapsedContainer,
- expandedWidth: $collapsible.width(),
- prevElement: $collapsible.prev()
- } );
- }
- },
- getSettings: function ( $collapsible ) {
- var $settings = $collapsible.data( 'collapsibleTabsSettings' );
- if ( $settings === undefined ) {
- $.collapsibleTabs.addData( $collapsible );
- $settings = $collapsible.data( 'collapsibleTabsSettings' );
- }
- return $settings;
- },
- /**
- * @param {jQuery.Event} e
- */
- handleResize: function () {
- $.collapsibleTabs.instances.each( function () {
- var $el = $( this ),
- data = $.collapsibleTabs.getSettings( $el );
-
- if ( data.shifting ) {
- return;
- }
-
- // if the two navigations are colliding
- if ( $el.children( data.collapsible ).length > 0 && data.collapseCondition() ) {
-
- $el.trigger( 'beforeTabCollapse' );
- // move the element to the dropdown menu
- $.collapsibleTabs.moveToCollapsed( $el.children( data.collapsible + ':last' ) );
- }
-
- // if there are still moveable items in the dropdown menu,
- // and there is sufficient space to place them in the tab container
- if ( $( data.collapsedContainer + ' ' + data.collapsible ).length > 0
- && data.expandCondition( $.collapsibleTabs.getSettings( $( data.collapsedContainer ).children(
- data.collapsible + ':first' ) ).expandedWidth ) ) {
- //move the element from the dropdown to the tab
- $el.trigger( 'beforeTabExpand' );
- $.collapsibleTabs
- .moveToExpanded( data.collapsedContainer + ' ' + data.collapsible + ':first' );
- }
- });
- },
- moveToCollapsed: function ( ele ) {
- var $moving = $( ele ),
- data = $.collapsibleTabs.getSettings( $moving ),
- dataExp = $.collapsibleTabs.getSettings( data.expandedContainer );
- dataExp.shifting = true;
- $moving
- .detach()
- .prependTo( data.collapsedContainer )
- .data( 'collapsibleTabsSettings', data );
- dataExp.shifting = false;
- $.collapsibleTabs.handleResize();
- },
- moveToExpanded: function ( ele ) {
- var $moving = $( ele ),
- data = $.collapsibleTabs.getSettings( $moving ),
- dataExp = $.collapsibleTabs.getSettings( data.expandedContainer );
- dataExp.shifting = true;
- // remove this element from where it's at and put it in the dropdown menu
- $moving.detach().insertAfter( data.prevElement ).data( 'collapsibleTabsSettings', data );
- dataExp.shifting = false;
- $.collapsibleTabs.handleResize();
- }
- };
-
-}( jQuery ) );
/**
- * Simple Placeholder-based Localization
+ * @class jQuery.plugin.localize
+ */
+( function ( $, mw ) {
+
+/**
+ * Gets a localized message, using parameters from options if present.
+ * @ignore
+ *
+ * @param {Object} options
+ * @param {string} key
+ * @returns {string} Localized message
+ */
+function msg( options, key ) {
+ var args = options.params[key] || [];
+ // Format: mw.msg( key [, p1, p2, ...] )
+ args.unshift( options.prefix + ( options.keys[key] || key ) );
+ return mw.msg.apply( mw, args );
+}
+
+/**
+ * Localizes a DOM selection by replacing <html:msg /> elements with localized text and adding
+ * localized title and alt attributes to elements with title-msg and alt-msg attributes
+ * respectively.
*
- * Call on a selection of HTML which contains <html:msg key="message-key" /> elements or elements
+ * Call on a selection of HTML which contains `<html:msg key="message-key" />` elements or elements
* with title-msg="message-key", alt-msg="message-key" or placeholder-msg="message-key" attributes.
- * <html:msg /> elements will be replaced with localized text, *-msg attributes will be replaced
+ * `<html:msg />` elements will be replaced with localized text, *-msg attributes will be replaced
* with attributes that do not have the "-msg" suffix and contain a localized message.
*
* Example:
* Appends something like this to the body...
* <p>You may not get there all in one piece.</p>
*
- */
-( function ( $, mw ) {
-
-/**
- * Gets a localized message, using parameters from options if present.
- *
- * @function
- * @param {String} key Message key to get localized message for
- * @returns {String} Localized message
- */
-function msg( options, key ) {
- var args = options.params[key] || [];
- // Format: mw.msg( key [, p1, p2, ...] )
- args.unshift( options.prefix + ( options.keys[key] || key ) );
- return mw.msg.apply( mw, args );
-}
-
-/**
- * Localizes a DOM selection by replacing <html:msg /> elements with localized text and adding
- * localized title and alt attributes to elements with title-msg and alt-msg attributes
- * respectively.
- *
* @method
* @param {Object} options Map of options to be used while localizing
- * @param {String} options.prefix String to prepend to all message keys
+ * @param {string} options.prefix String to prepend to all message keys
* @param {Object} options.keys Message key aliases, used for remapping keys to a template
* @param {Object} options.params Lists of parameters to use with certain message keys
- * @returns {jQuery} This selection
+ * @return {jQuery}
*/
$.fn.localize = function ( options ) {
var $target = this,
// Let IE know about the msg tag before it's used...
document.createElement( 'msg' );
+/**
+ * @class jQuery
+ * @mixins jQuery.plugin.localize
+ */
+
}( jQuery, mediaWiki ) );
/**
- * QUnit v1.10.0 - A JavaScript Unit Testing Framework
+ * QUnit v1.11.0 - A JavaScript Unit Testing Framework
*
* http://qunitjs.com
*
/** Resets */
-#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0;
padding: 0;
}
color: #000;
}
-#qunit-tests ol {
+#qunit-tests li .runtime {
+ float: right;
+ font-size: smaller;
+}
+
+.qunit-assert-list {
margin-top: 0.5em;
padding: 0.5em;
-webkit-border-radius: 5px;
}
+.qunit-collapsed {
+ display: none;
+}
+
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
/**
- * QUnit v1.10.0 - A JavaScript Unit Testing Framework
+ * QUnit v1.11.0 - A JavaScript Unit Testing Framework
*
* http://qunitjs.com
*
(function( window ) {
var QUnit,
+ assert,
config,
onErrorFnPrev,
testId = 0,
// Keep a local reference to Date (GH-283)
Date = window.Date,
defined = {
- setTimeout: typeof window.setTimeout !== "undefined",
- sessionStorage: (function() {
- var x = "qunit-test-string";
- try {
- sessionStorage.setItem( x, x );
- sessionStorage.removeItem( x );
- return true;
- } catch( e ) {
- return false;
+ setTimeout: typeof window.setTimeout !== "undefined",
+ sessionStorage: (function() {
+ var x = "qunit-test-string";
+ try {
+ sessionStorage.setItem( x, x );
+ sessionStorage.removeItem( x );
+ return true;
+ } catch( e ) {
+ return false;
+ }
+ }())
+ },
+ /**
+ * Provides a normalized error string, correcting an issue
+ * with IE 7 (and prior) where Error.prototype.toString is
+ * not properly implemented
+ *
+ * Based on http://es5.github.com/#x15.11.4.4
+ *
+ * @param {String|Error} error
+ * @return {String} error message
+ */
+ errorString = function( error ) {
+ var name, message,
+ errorString = error.toString();
+ if ( errorString.substring( 0, 7 ) === "[object" ) {
+ name = error.name ? error.name.toString() : "Error";
+ message = error.message ? error.message.toString() : "";
+ if ( name && message ) {
+ return name + ": " + message;
+ } else if ( name ) {
+ return name;
+ } else if ( message ) {
+ return message;
+ } else {
+ return "Error";
+ }
+ } else {
+ return errorString;
}
- }())
-};
+ },
+ /**
+ * Makes a clone of an object using only Array or Object as base,
+ * and copies over the own enumerable properties.
+ *
+ * @param {Object} obj
+ * @return {Object} New object with only the own properties (recursively).
+ */
+ objectValues = function( obj ) {
+ // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
+ /*jshint newcap: false */
+ var key, val,
+ vals = QUnit.is( "array", obj ) ? [] : {};
+ for ( key in obj ) {
+ if ( hasOwn.call( obj, key ) ) {
+ val = obj[key];
+ vals[key] = val === Object(val) ? objectValues(val) : val;
+ }
+ }
+ return vals;
+ };
function Test( settings ) {
extend( this, settings );
Test.prototype = {
init: function() {
var a, b, li,
- tests = id( "qunit-tests" );
+ tests = id( "qunit-tests" );
if ( tests ) {
b = document.createElement( "strong" );
- b.innerHTML = this.name;
+ b.innerHTML = this.nameHtml;
// `a` initialized at top of scope
a = document.createElement( "a" );
teardown: function() {}
}, this.moduleTestEnvironment );
+ this.started = +new Date();
runLoggingCallbacks( "testStart", QUnit, {
name: this.testName,
module: this.module
try {
this.testEnvironment.setup.call( this.testEnvironment );
} catch( e ) {
- QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
+ QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
}
},
run: function() {
var running = id( "qunit-testresult" );
if ( running ) {
- running.innerHTML = "Running: <br/>" + this.name;
+ running.innerHTML = "Running: <br/>" + this.nameHtml;
}
if ( this.async ) {
QUnit.stop();
}
+ this.callbackStarted = +new Date();
+
if ( config.notrycatch ) {
this.callback.call( this.testEnvironment, QUnit.assert );
+ this.callbackRuntime = +new Date() - this.callbackStarted;
return;
}
try {
this.callback.call( this.testEnvironment, QUnit.assert );
+ this.callbackRuntime = +new Date() - this.callbackStarted;
} catch( e ) {
- QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + e.message, extractStacktrace( e, 0 ) );
+ this.callbackRuntime = +new Date() - this.callbackStarted;
+
+ QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
// else next test will carry the responsibility
saveGlobal();
teardown: function() {
config.current = this;
if ( config.notrycatch ) {
+ if ( typeof this.callbackRuntime === "undefined" ) {
+ this.callbackRuntime = +new Date() - this.callbackStarted;
+ }
this.testEnvironment.teardown.call( this.testEnvironment );
return;
} else {
try {
this.testEnvironment.teardown.call( this.testEnvironment );
} catch( e ) {
- QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) );
+ QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
}
}
checkPollution();
},
finish: function() {
config.current = this;
- if ( config.requireExpects && this.expected == null ) {
+ if ( config.requireExpects && this.expected === null ) {
QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
- } else if ( this.expected != null && this.expected != this.assertions.length ) {
+ } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
- } else if ( this.expected == null && !this.assertions.length ) {
+ } else if ( this.expected === null && !this.assertions.length ) {
QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
}
- var assertion, a, b, i, li, ol,
+ var i, assertion, a, b, time, li, ol,
test = this,
good = 0,
bad = 0,
tests = id( "qunit-tests" );
+ this.runtime = +new Date() - this.started;
config.stats.all += this.assertions.length;
config.moduleStats.all += this.assertions.length;
if ( tests ) {
ol = document.createElement( "ol" );
+ ol.className = "qunit-assert-list";
for ( i = 0; i < this.assertions.length; i++ ) {
assertion = this.assertions[i];
}
if ( bad === 0 ) {
- ol.style.display = "none";
+ addClass( ol, "qunit-collapsed" );
}
// `b` initialized at top of scope
b = document.createElement( "strong" );
- b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
+ b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
addEvent(b, "click", function() {
- var next = b.nextSibling.nextSibling,
- display = next.style.display;
- next.style.display = display === "none" ? "block" : "none";
+ var next = b.parentNode.lastChild,
+ collapsed = hasClass( next, "qunit-collapsed" );
+ ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
});
addEvent(b, "dblclick", function( e ) {
var target = e && e.target ? e.target : window.event.srcElement;
- if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
+ if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
target = target.parentNode;
}
if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
}
});
+ // `time` initialized at top of scope
+ time = document.createElement( "span" );
+ time.className = "runtime";
+ time.innerHTML = this.runtime + " ms";
+
// `li` initialized at top of scope
li = id( this.id );
li.className = bad ? "fail" : "pass";
li.removeChild( li.firstChild );
a = li.firstChild;
li.appendChild( b );
- li.appendChild ( a );
+ li.appendChild( a );
+ li.appendChild( time );
li.appendChild( ol );
} else {
module: this.module,
failed: bad,
passed: this.assertions.length - bad,
- total: this.assertions.length
+ total: this.assertions.length,
+ duration: this.runtime
});
QUnit.reset();
test: function( testName, expected, callback, async ) {
var test,
- name = "<span class='test-name'>" + escapeInnerText( testName ) + "</span>";
+ nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
if ( arguments.length === 2 ) {
callback = expected;
}
if ( config.currentModule ) {
- name = "<span class='module-name'>" + config.currentModule + "</span>: " + name;
+ nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
}
test = new Test({
- name: name,
+ nameHtml: nameHtml,
testName: testName,
expected: expected,
async: async,
},
start: function( count ) {
+ // QUnit hasn't been initialized yet.
+ // Note: RequireJS (et al) may delay onLoad
+ if ( config.semaphore === undefined ) {
+ QUnit.begin(function() {
+ // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
+ setTimeout(function() {
+ QUnit.start( count );
+ });
+ });
+ return;
+ }
+
config.semaphore -= count || 1;
// don't start until equal number of stop-calls
if ( config.semaphore > 0 ) {
// ignore if start is called more often then stop
if ( config.semaphore < 0 ) {
config.semaphore = 0;
+ QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
+ return;
}
// A slight delay, to avoid any current callbacks
if ( defined.setTimeout ) {
}
};
+// `assert` initialized at top of scope
// Asssert helpers
-// All of these must call either QUnit.push() or manually do:
+// All of these must either call QUnit.push() or manually do:
// - runLoggingCallbacks( "log", .. );
// - config.current.assertions.push({ .. });
-QUnit.assert = {
+// We attach it to the QUnit object *after* we expose the public API,
+// otherwise `assert` will become a global variable in browsers (#341).
+assert = {
/**
* Asserts rough true-ish result.
* @name ok
message: msg
};
- msg = escapeInnerText( msg || (result ? "okay" : "failed" ) );
+ msg = escapeText( msg || (result ? "okay" : "failed" ) );
msg = "<span class='test-message'>" + msg + "</span>";
if ( !result ) {
source = sourceFromStacktrace( 2 );
if ( source ) {
details.source = source;
- msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr></table>";
+ msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
}
}
runLoggingCallbacks( "log", QUnit, details );
* @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
*/
equal: function( actual, expected, message ) {
+ /*jshint eqeqeq:false */
QUnit.push( expected == actual, actual, expected, message );
},
* @function
*/
notEqual: function( actual, expected, message ) {
+ /*jshint eqeqeq:false */
QUnit.push( expected != actual, actual, expected, message );
},
+ /**
+ * @name propEqual
+ * @function
+ */
+ propEqual: function( actual, expected, message ) {
+ actual = objectValues(actual);
+ expected = objectValues(expected);
+ QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+ },
+
+ /**
+ * @name notPropEqual
+ * @function
+ */
+ notPropEqual: function( actual, expected, message ) {
+ actual = objectValues(actual);
+ expected = objectValues(expected);
+ QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+ },
+
/**
* @name deepEqual
* @function
QUnit.push( expected !== actual, actual, expected, message );
},
- throws: function( block, expected, message ) {
+ "throws": function( block, expected, message ) {
var actual,
+ expectedOutput = expected,
ok = false;
// 'expected' is optional
// we don't want to validate thrown error
if ( !expected ) {
ok = true;
+ expectedOutput = null;
// expected is a regexp
} else if ( QUnit.objectType( expected ) === "regexp" ) {
- ok = expected.test( actual );
+ ok = expected.test( errorString( actual ) );
// expected is a constructor
} else if ( actual instanceof expected ) {
ok = true;
// expected is a validation function which returns true is validation passed
} else if ( expected.call( {}, actual ) === true ) {
+ expectedOutput = null;
ok = true;
}
- QUnit.push( ok, actual, null, message );
+ QUnit.push( ok, actual, expectedOutput, message );
} else {
QUnit.pushFailure( message, null, 'No exception was thrown.' );
}
/**
* @deprecate since 1.8.0
- * Kept assertion helpers in root for backwards compatibility
+ * Kept assertion helpers in root for backwards compatibility.
*/
-extend( QUnit, QUnit.assert );
+extend( QUnit, assert );
/**
* @deprecated since 1.9.0
- * Kept global "raises()" for backwards compatibility
+ * Kept root "raises()" for backwards compatibility.
+ * (Note that we don't introduce assert.raises).
*/
-QUnit.raises = QUnit.assert.throws;
+QUnit.raises = assert[ "throws" ];
/**
* @deprecated since 1.0.0, replaced with error pushes since 1.3.0
moduleDone: []
};
+// Export global variables, unless an 'exports' object exists,
+// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
+if ( typeof exports === "undefined" ) {
+ extend( window, QUnit );
+
+ // Expose QUnit object
+ window.QUnit = QUnit;
+}
+
// Initialize more QUnit.config and QUnit.urlParams
(function() {
var i,
QUnit.isLocal = location.protocol === "file:";
}());
-// Export global variables, unless an 'exports' object exists,
-// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
-if ( typeof exports === "undefined" ) {
- extend( window, QUnit );
-
- // Expose QUnit object
- window.QUnit = QUnit;
-}
-
// Extend QUnit object,
// these after set here because they should not be exposed as global functions
extend( QUnit, {
+ assert: assert,
+
config: config,
// Initialize the configuration options
autorun: false,
filter: "",
queue: [],
- semaphore: 0
+ semaphore: 1
});
var tests, banner, result,
if ( qunit ) {
qunit.innerHTML =
- "<h1 id='qunit-header'>" + escapeInnerText( document.title ) + "</h1>" +
+ "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
"<h2 id='qunit-banner'></h2>" +
"<div id='qunit-testrunner-toolbar'></div>" +
"<h2 id='qunit-userAgent'></h2>" +
// Safe object type checking
is: function( type, obj ) {
- return QUnit.objectType( obj ) == type;
+ return QUnit.objectType( obj ) === type;
},
objectType: function( obj ) {
return "null";
}
- var type = toString.call( obj ).match(/^\[object\s(.*)\]$/)[1] || "";
+ var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
+ type = match && match[1] || "";
switch ( type ) {
case "Number":
expected: expected
};
- message = escapeInnerText( message ) || ( result ? "okay" : "failed" );
+ message = escapeText( message ) || ( result ? "okay" : "failed" );
message = "<span class='test-message'>" + message + "</span>";
output = message;
if ( !result ) {
- expected = escapeInnerText( QUnit.jsDump.parse(expected) );
- actual = escapeInnerText( QUnit.jsDump.parse(actual) );
+ expected = escapeText( QUnit.jsDump.parse(expected) );
+ actual = escapeText( QUnit.jsDump.parse(actual) );
output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
- if ( actual != expected ) {
+ if ( actual !== expected ) {
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
}
if ( source ) {
details.source = source;
- output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>";
+ output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
}
output += "</table>";
message: message
};
- message = escapeInnerText( message ) || "error";
+ message = escapeText( message ) || "error";
message = "<span class='test-message'>" + message + "</span>";
output = message;
output += "<table>";
if ( actual ) {
- output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeInnerText( actual ) + "</pre></td></tr>";
+ output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
}
if ( source ) {
details.source = source;
- output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>";
+ output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
}
output += "</table>";
querystring += encodeURIComponent( key ) + "=" +
encodeURIComponent( params[ key ] ) + "&";
}
- return window.location.pathname + querystring.slice( 0, -1 );
+ return window.location.protocol + "//" + window.location.host +
+ window.location.pathname + querystring.slice( 0, -1 );
},
extend: extend,
// testStart: { name }
testStart: registerLoggingCallback( "testStart" ),
- // testDone: { name, failed, passed, total }
+ // testDone: { name, failed, passed, total, duration }
testDone: registerLoggingCallback( "testDone" ),
// moduleStart: { name }
runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue
- var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter,
- numModules = 0,
- moduleFilterHtml = "",
+ var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
+ urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
+ numModules = 0,
+ moduleFilterHtml = "",
urlConfigHtml = "",
oldconfig = extend( {}, config );
};
}
config[ val.id ] = QUnit.urlParams[ val.id ];
- urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
+ urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
+ "' name='" + escapeText( val.id ) +
+ "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
+ " title='" + escapeText( val.tooltip ) +
+ "'><label for='qunit-urlconfig-" + escapeText( val.id ) +
+ "' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
}
- moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined ? "selected" : "" ) + ">< All Modules ></option>";
+ moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+ ( config.module === undefined ? "selected='selected'" : "" ) +
+ ">< All Modules ></option>";
+
for ( i in config.modules ) {
if ( config.modules.hasOwnProperty( i ) ) {
numModules += 1;
- moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>";
+ moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(i) ) + "' " +
+ ( config.module === i ? "selected='selected'" : "" ) +
+ ">" + escapeText(i) + "</option>";
}
}
moduleFilterHtml += "</select>";
label.innerHTML = "Hide passed tests";
toolbar.appendChild( label );
- urlConfigCheckboxes = document.createElement( 'span' );
- urlConfigCheckboxes.innerHTML = urlConfigHtml;
- addEvent( urlConfigCheckboxes, "change", function( event ) {
- var params = {};
- params[ event.target.name ] = event.target.checked ? true : undefined;
+ urlConfigCheckboxesContainer = document.createElement("span");
+ urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
+ urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
+ // For oldIE support:
+ // * Add handlers to the individual elements instead of the container
+ // * Use "click" instead of "change"
+ // * Fallback from event.target to event.srcElement
+ addEvents( urlConfigCheckboxes, "click", function( event ) {
+ var params = {},
+ target = event.target || event.srcElement;
+ params[ target.name ] = target.checked ? true : undefined;
window.location = QUnit.url( params );
});
- toolbar.appendChild( urlConfigCheckboxes );
+ toolbar.appendChild( urlConfigCheckboxesContainer );
if (numModules > 1) {
moduleFilter = document.createElement( 'span' );
moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
moduleFilter.innerHTML = moduleFilterHtml;
- addEvent( moduleFilter, "change", function() {
+ addEvent( moduleFilter.lastChild, "change", function() {
var selectBox = moduleFilter.getElementsByTagName("select")[0],
- selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+ selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
});
" milliseconds.<br/>",
"<span class='passed'>",
passed,
- "</span> tests of <span class='total'>",
+ "</span> assertions of <span class='total'>",
config.stats.all,
"</span> passed, <span class='failed'>",
config.stats.bad,
function extractStacktrace( e, offset ) {
offset = offset === undefined ? 3 : offset;
- var stack, include, i, regex;
+ var stack, include, i;
if ( e.stacktrace ) {
// Opera
if ( fileName ) {
include = [];
for ( i = offset; i < stack.length; i++ ) {
- if ( stack[ i ].indexOf( fileName ) != -1 ) {
+ if ( stack[ i ].indexOf( fileName ) !== -1 ) {
break;
}
include.push( stack[ i ] );
}
}
-function escapeInnerText( s ) {
+/**
+ * Escape text for attribute or text content.
+ */
+function escapeText( s ) {
if ( !s ) {
return "";
}
s = s + "";
- return s.replace( /[\&<>]/g, function( s ) {
+ // Both single quotes and double quotes (for attributes)
+ return s.replace( /['"<>&]/g, function( s ) {
switch( s ) {
- case "&": return "&";
- case "<": return "<";
- case ">": return ">";
- default: return s;
+ case '\'':
+ return ''';
+ case '"':
+ return '"';
+ case '<':
+ return '<';
+ case '>':
+ return '>';
+ case '&':
+ return '&';
}
});
}
}
}
-function checkPollution( name ) {
+function checkPollution() {
var newGlobals,
deletedGlobals,
old = config.pollution;
return a;
}
+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
function addEvent( elem, type, fn ) {
+ // Standards-based browsers
if ( elem.addEventListener ) {
elem.addEventListener( type, fn, false );
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, fn );
+ // IE
} else {
- fn();
+ elem.attachEvent( "on" + type, fn );
}
}
+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+ var i = elems.length;
+ while ( i-- ) {
+ addEvent( elems[i], type, fn );
+ }
+}
+
+function hasClass( elem, name ) {
+ return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
+}
+
+function addClass( elem, name ) {
+ if ( !hasClass( elem, name ) ) {
+ elem.className += (elem.className ? " " : "") + name;
+ }
+}
+
+function removeClass( elem, name ) {
+ var set = " " + elem.className + " ";
+ // Class name may appear multiple times
+ while ( set.indexOf(" " + name + " ") > -1 ) {
+ set = set.replace(" " + name + " " , " ");
+ }
+ // If possible, trim it for prettiness, but not neccecarily
+ elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set );
+}
+
function id( name ) {
return !!( typeof document !== "undefined" && document && document.getElementById ) &&
document.getElementById( name );
// Supports deprecated method of completely overwriting logging callbacks
function runLoggingCallbacks( key, scope, args ) {
- //debugger;
var i, callbacks;
if ( QUnit.hasOwnProperty( key ) ) {
QUnit[ key ].call(scope, args );
// for string, boolean, number and null
function useStrictEquality( b, a ) {
+ /*jshint eqeqeq:false */
if ( b instanceof a.constructor || a instanceof b.constructor ) {
// to catch short annotaion VS 'new' annotation of a
// declaration
var reName = /^function (\w+)/,
jsDump = {
- parse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance
+ // type is used mostly internally, you can fix a (custom)type in advance
+ parse: function( obj, type, stack ) {
stack = stack || [ ];
var inStack, res,
parser = this.parsers[ type || this.typeOf(obj) ];
type = typeof parser;
inStack = inArray( obj, stack );
- if ( inStack != -1 ) {
+ if ( inStack !== -1 ) {
return "recursion(" + (inStack - stack.length) + ")";
}
- //else
- if ( type == "function" ) {
+ if ( type === "function" ) {
stack.push( obj );
res = parser.call( this, obj, stack );
stack.pop();
return res;
}
- // else
- return ( type == "string" ) ? parser : this.parsers.error;
+ return ( type === "string" ) ? parser : this.parsers.error;
},
typeOf: function( obj ) {
var type;
( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
) {
type = "array";
+ } else if ( obj.constructor === Error.prototype.constructor ) {
+ type = "error";
} else {
type = typeof obj;
}
separator: function() {
return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? " " : " ";
},
- indent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
+ // extra can be a number, shortcut for increasing-calling-decreasing
+ indent: function( extra ) {
if ( !this.multiline ) {
return "";
}
parsers: {
window: "[Window]",
document: "[Document]",
- error: "[ERROR]", //when no parser is found, shouldn"t happen
+ error: function(error) {
+ return "Error(\"" + error.message + "\")";
+ },
unknown: "[Unknown]",
"null": "null",
"undefined": "undefined",
"function": function( fn ) {
var ret = "function",
- name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];//functions never have name in IE
+ // functions never have name in IE
+ name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
if ( name ) {
ret += " " + name;
object: function( map, stack ) {
var ret = [ ], keys, key, val, i;
QUnit.jsDump.up();
- if ( Object.keys ) {
- keys = Object.keys( map );
- } else {
- keys = [];
- for ( key in map ) {
- keys.push( key );
- }
+ keys = [];
+ for ( key in map ) {
+ keys.push( key );
}
keys.sort();
for ( i = 0; i < keys.length; i++ ) {
return join( "{", ret, "}" );
},
node: function( node ) {
- var a, val,
+ var len, i, val,
open = QUnit.jsDump.HTML ? "<" : "<",
close = QUnit.jsDump.HTML ? ">" : ">",
tag = node.nodeName.toLowerCase(),
- ret = open + tag;
-
- for ( a in QUnit.jsDump.DOMAttrs ) {
- val = node[ QUnit.jsDump.DOMAttrs[a] ];
- if ( val ) {
- ret += " " + a + "=" + QUnit.jsDump.parse( val, "attribute" );
+ ret = open + tag,
+ attrs = node.attributes;
+
+ if ( attrs ) {
+ for ( i = 0, len = attrs.length; i < len; i++ ) {
+ val = attrs[i].nodeValue;
+ // IE6 includes all attributes in .attributes, even ones not explicitly set.
+ // Those have values like undefined, null, 0, false, "" or "inherit".
+ if ( val && val !== "inherit" ) {
+ ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
+ }
}
}
- return ret + close + open + "/" + tag + close;
+ ret += close;
+
+ // Show content of TextNode or CDATASection
+ if ( node.nodeType === 3 || node.nodeType === 4 ) {
+ ret += node.nodeValue;
+ }
+
+ return ret + open + "/" + tag + close;
},
- functionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function
+ // function calls it internally, it's the arguments part of the function
+ functionArgs: function( fn ) {
var args,
l = fn.length;
args = new Array(l);
while ( l-- ) {
- args[l] = String.fromCharCode(97+l);//97 is 'a'
+ // 97 is 'a'
+ args[l] = String.fromCharCode(97+l);
}
return " " + args.join( ", " ) + " ";
},
- key: quote, //object calls it internally, the key part of an item in a map
- functionCode: "[code]", //function calls it internally, it's the content of the function
- attribute: quote, //node calls it internally, it's an html attribute value
+ // object calls it internally, the key part of an item in a map
+ key: quote,
+ // function calls it internally, it's the content of the function
+ functionCode: "[code]",
+ // node calls it internally, it's an html attribute value
+ attribute: quote,
string: quote,
date: quote,
- regexp: literal, //regex
+ regexp: literal,
number: literal,
"boolean": literal
},
- DOMAttrs: {
- //attributes to dump from nodes, name=>realName
- id: "id",
- name: "name",
- "class": "className"
- },
- HTML: false,//if true, entities are escaped ( <, >, \t, space and \n )
- indentChar: " ",//indentation unit
- multiline: true //if true, items in a collection, are separated by a \n, else just a space.
+ // if true, entities are escaped ( <, >, \t, space and \n )
+ HTML: false,
+ // indentation unit
+ indentChar: " ",
+ // if true, items in a collection, are separated by a \n, else just a space.
+ multiline: true
};
return jsDump;
}());
-// from Sizzle.js
-function getText( elems ) {
- var i, elem,
- ret = "";
-
- for ( i = 0; elems[i]; i++ ) {
- elem = elems[i];
-
- // Get the text from text nodes and CDATA nodes
- if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
- ret += elem.nodeValue;
-
- // Traverse everything else, except comment nodes
- } else if ( elem.nodeType !== 8 ) {
- ret += getText( elem.childNodes );
- }
- }
-
- return ret;
-}
-
// from jquery.js
function inArray( elem, array ) {
if ( array.indexOf ) {
* QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
*/
QUnit.diff = (function() {
+ /*jshint eqeqeq:false, eqnull:true */
function diff( o, n ) {
var i,
ns = {},
os = {};
for ( i = 0; i < n.length; i++ ) {
- if ( ns[ n[i] ] == null ) {
+ if ( !hasOwn.call( ns, n[i] ) ) {
ns[ n[i] ] = {
rows: [],
o: null
}
for ( i = 0; i < o.length; i++ ) {
- if ( os[ o[i] ] == null ) {
+ if ( !hasOwn.call( os, o[i] ) ) {
os[ o[i] ] = {
rows: [],
n: null
if ( !hasOwn.call( ns, i ) ) {
continue;
}
- if ( ns[i].rows.length == 1 && typeof os[i] != "undefined" && os[i].rows.length == 1 ) {
+ if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
n[ ns[i].rows[0] ] = {
text: n[ ns[i].rows[0] ],
row: os[i].rows[0]
// for CommonJS enviroments, export everything
if ( typeof exports !== "undefined" ) {
- extend(exports, QUnit);
+ extend( exports, QUnit );
}
// get at whatever the global object is, like window in browsers
var selected = context.data.$container.find( '.suggestions-result-current' );
if ( !result.get || selected.get( 0 ) !== result.get( 0 ) ) {
if ( result === 'prev' ) {
- if( selected.is( '.suggestions-special' ) ) {
+ if( selected.hasClass( 'suggestions-special' ) ) {
result = context.data.$container.find( '.suggestions-result:last' );
} else {
result = selected.prev();
- if ( !( result.length && result.hasClass( '.suggestions-result' ) ) ) {
+ if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
// there is something in the DOM between selected element and the wrapper, bypass it
result = selected.parents( '.suggestions-results > *' ).prev().find( '.suggestions-result' ).eq(0);
}
}
} else {
result = selected.next();
- if ( !( result.length && result.hasClass( '.suggestions-result' ) ) ) {
+ if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
// there is something in the DOM between selected element and the wrapper, bypass it
result = selected.parents( '.suggestions-results > *' ).next().find( '.suggestions-result' ).eq(0);
}
- if ( selected.is( '.suggestions-special' ) ) {
+ if ( selected.hasClass( 'suggestions-special' ) ) {
result = $( [] );
} else if (
result.length === 0 &&
/**
- * Additional mw.Api methods to assist with API calls related to categories.
+ * @class mw.Api.plugin.category
*/
( function ( mw, $ ) {
$.extend( mw.Api.prototype, {
/**
* Determine if a category exists.
- * @param title {mw.Title}
- * @param success {Function} callback to pass boolean of category's existence
- * @param err {Function} optional callback to run if api error
- * @return ajax call object
+ * @param {mw.Title} title
+ * @param {Function} [ok] Success callback (deprecated)
+ * @param {Function} [err] Error callback (deprecated)
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {boolean} return.done.isCategory Whether the category exists.
*/
- isCategory: function ( title, success, err ) {
- var params, ok;
- params = {
- prop: 'categoryinfo',
- titles: title.toString()
- };
- ok = function ( data ) {
- var exists = false;
- if ( data.query && data.query.pages ) {
- $.each( data.query.pages, function ( id, page ) {
- if ( page.categoryinfo ) {
- exists = true;
- }
- } );
- }
- success( exists );
- };
+ isCategory: function ( title, ok, err ) {
+ var d = $.Deferred();
+ // Backwards compatibility (< MW 1.20)
+ d.done( ok );
+ d.fail( err );
- return this.get( params, { ok: ok, err: err } );
+ this.get( {
+ prop: 'categoryinfo',
+ titles: title.toString()
+ } )
+ .done( function ( data ) {
+ var exists = false;
+ if ( data.query && data.query.pages ) {
+ $.each( data.query.pages, function ( id, page ) {
+ if ( page.categoryinfo ) {
+ exists = true;
+ }
+ } );
+ }
+ d.resolve( exists );
+ })
+ .fail( d.reject );
+
+ return d.promise();
},
/**
* Get a list of categories that match a certain prefix.
* e.g. given "Foo", return "Food", "Foolish people", "Foosball tables" ...
- * @param prefix {String} prefix to match
- * @param success {Function} callback to pass matched categories to
- * @param err {Function} optional callback to run if api error
- * @return {jqXHR}
+ * @param {string} prefix Prefix to match.
+ * @param {Function} [ok] Success callback (deprecated)
+ * @param {Function} [err] Error callback (deprecated)
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {String[]} return.done.categories Matched categories
*/
- getCategoriesByPrefix: function ( prefix, success, err ) {
+ getCategoriesByPrefix: function ( prefix, ok, err ) {
+ var d = $.Deferred();
+ // Backwards compatibility (< MW 1.20)
+ d.done( ok );
+ d.fail( err );
+
// Fetch with allpages to only get categories that have a corresponding description page.
- var params, ok;
- params = {
- 'list': 'allpages',
- 'apprefix': prefix,
- 'apnamespace': mw.config.get('wgNamespaceIds').category
- };
- ok = function ( data ) {
- var texts = [];
- if ( data.query && data.query.allpages ) {
- $.each( data.query.allpages, function ( i, category ) {
- texts.push( new mw.Title( category.title ).getNameText() );
- } );
- }
- success( texts );
- };
+ this.get( {
+ list: 'allpages',
+ apprefix: prefix,
+ apnamespace: mw.config.get('wgNamespaceIds').category
+ } )
+ .done( function ( data ) {
+ var texts = [];
+ if ( data.query && data.query.allpages ) {
+ $.each( data.query.allpages, function ( i, category ) {
+ texts.push( new mw.Title( category.title ).getNameText() );
+ } );
+ }
+ d.resolve( texts );
+ })
+ .fail( d.reject );
- return this.get( params, { ok: ok, err: err } );
+ return d.promise();
},
/**
* Get the categories that a particular page on the wiki belongs to
- * @param title {mw.Title}
- * @param success {Function} callback to pass categories to (or false, if title not found)
- * @param err {Function} optional callback to run if api error
- * @param async {Boolean} optional asynchronousness (default = true = async)
- * @return {jqXHR}
+ * @param {mw.Title} title
+ * @param {Function} [ok] Success callback (deprecated)
+ * @param {Function} [err] Error callback (deprecated)
+ * @param {boolean} [async=true] Asynchronousness
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {boolean|mw.Title[]} return.done.categories List of category titles or false
+ * if title was not found.
*/
- getCategories: function ( title, success, err, async ) {
- var params, ok;
- params = {
- prop: 'categories',
- titles: title.toString()
- };
- if ( async === undefined ) {
- async = true;
- }
- ok = function ( data ) {
- var ret = false;
- if ( data.query && data.query.pages ) {
- $.each( data.query.pages, function ( id, page ) {
- if ( page.categories ) {
- if ( typeof ret !== 'object' ) {
- ret = [];
+ getCategories: function ( title, ok, err, async ) {
+ var d = $.Deferred();
+ // Backwards compatibility (< MW 1.20)
+ d.done( ok );
+ d.fail( err );
+
+ this.get( {
+ prop: 'categories',
+ titles: title.toString()
+ }, {
+ async: async === undefined ? true : async
+ } )
+ .done( function ( data ) {
+ var ret = false;
+ if ( data.query && data.query.pages ) {
+ $.each( data.query.pages, function ( id, page ) {
+ if ( page.categories ) {
+ if ( typeof ret !== 'object' ) {
+ ret = [];
+ }
+ $.each( page.categories, function ( i, cat ) {
+ ret.push( new mw.Title( cat.title ) );
+ } );
}
- $.each( page.categories, function ( i, cat ) {
- ret.push( new mw.Title( cat.title ) );
- } );
- }
- } );
- }
- success( ret );
- };
+ } );
+ }
+ d.resolve( ret );
+ })
+ .fail( d.reject );
- return this.get( params, { ok: ok, err: err, async: async } );
+ return d.promise();
}
} );
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.category
+ */
+
}( mediaWiki, jQuery ) );
/**
- * Additional mw.Api methods to assist with API calls related to editing wiki pages.
+ * @class mw.Api.plugin.edit
*/
( function ( mw, $ ) {
* If we have a cached token try using that, and if it fails, blank out the
* cached token and start over.
*
- * @param params {Object} API parameters
- * @param ok {Function} callback for success
- * @param err {Function} [optional] error callback
- * @return {jqXHR}
+ * @param {Object} params API parameters
+ * @param {Function} [ok] Success callback (deprecated)
+ * @param {Function} [err] Error callback (deprecated)
+ * @return {jQuery.Promise} See #post
*/
postWithEditToken: function ( params, ok, err ) {
var useTokenToPost, getTokenIfBad,
},
/**
- * Api helper to grab an edit token
+ * Api helper to grab an edit token.
*
- * token callback has signature ( String token )
- * error callback has signature ( String code, Object results, XmlHttpRequest xhr, Exception exception )
- * Note that xhr and exception are only available for 'http_*' errors
- * code may be any http_* error code (see mw.Api), or 'token_missing'
- *
- * @param tokenCallback {Function} received token callback
- * @param err {Function} error callback
- * @return {jqXHR}
+ * @param {Function} [ok] Success callback
+ * @param {Function} [err] Error callback
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {string} return.done.token Received token.
*/
- getEditToken: function ( tokenCallback, err ) {
- var parameters = {
+ getEditToken: function ( ok, err ) {
+ var d = $.Deferred();
+ // Backwards compatibility (< MW 1.20)
+ d.done( ok );
+ d.fail( err );
+
+ this.get( {
action: 'tokens',
type: 'edit'
- },
- ok = function ( data ) {
+ }, {
+ // Due to the API assuming we're logged out if we pass the callback-parameter,
+ // we have to disable jQuery's callback system, and instead parse JSON string,
+ // by setting 'jsonp' to false.
+ // TODO: This concern seems genuine but no other module has it. Is it still
+ // needed and/or should we pass this by default?
+ jsonp: false
+ } )
+ .done( function ( data ) {
var token;
// If token type is not available for this user,
// key 'edittoken' is missing or can contain Boolean false
if ( data.tokens && data.tokens.edittoken ) {
token = data.tokens.edittoken;
cachedToken = token;
- tokenCallback( token );
+ d.resolve( token );
} else {
- err( 'token-missing', data );
+ d.reject( 'token-missing', data );
}
- },
- ajaxOptions = {
- ok: ok,
- err: err,
- // Due to the API assuming we're logged out if we pass the callback-parameter,
- // we have to disable jQuery's callback system, and instead parse JSON string,
- // by setting 'jsonp' to false.
- jsonp: false
- };
+ })
+ .fail( d.reject );
- return this.get( parameters, ajaxOptions );
+ return d.promise();
},
/**
* Create a new section of the page.
- * @param title {mw.Title|String} target page
- * @param header {String}
- * @param message {String} wikitext message
- * @param ok {Function} success handler
- * @param err {Function} error handler
- * @return {jqXHR}
+ * @see #postWithEditToken
+ * @param {mw.Title|String} title Target page
+ * @param {string} header
+ * @param {string} message wikitext message
+ * @param {Function} [ok] Success handler
+ * @param {Function} [err] Error handler
+ * @return {jQuery.Promise}
*/
newSection: function ( title, header, message, ok, err ) {
- var params = {
+ return this.postWithEditToken( {
action: 'edit',
section: 'new',
format: 'json',
title: title.toString(),
summary: header,
text: message
- };
- return this.postWithEditToken( params, ok, err );
+ }, ok, err );
}
} );
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.edit
+ */
+
}( mediaWiki, jQuery ) );
-/**
- * mw.Api objects represent the API of a particular MediaWiki server.
- */
( function ( mw, $ ) {
- /**
- * @var defaultOptions {Object}
- * We allow people to omit these default parameters from API requests
- * there is very customizable error handling here, on a per-call basis
- * wondering, would it be simpler to make it easy to clone the api object,
- * change error handling, and use that instead?
- */
+ // We allow people to omit these default parameters from API requests
+ // there is very customizable error handling here, on a per-call basis
+ // wondering, would it be simpler to make it easy to clone the api object,
+ // change error handling, and use that instead?
var defaultOptions = {
// Query parameters for API requests
/**
* Constructor to create an object to interact with the API of a particular MediaWiki server.
+ * mw.Api objects represent the API of a particular MediaWiki server.
+ *
+ * TODO: Share API objects with exact same config.
*
- * @todo Share API objects with exact same config.
- * @example
- * <code>
- * var api = new mw.Api();
- * api.get( {
- * action: 'query',
- * meta: 'userinfo'
- * }, {
- * ok: function () { console.log( arguments ); }
- * } );
- * </code>
+ * var api = new mw.Api();
+ * api.get( {
+ * action: 'query',
+ * meta: 'userinfo'
+ * } ).done ( function ( data ) {
+ * console.log( data );
+ * } );
+ *
+ * @class
*
* @constructor
- * @param options {Object} See defaultOptions documentation above. Ajax options can also be
- * overridden for each individual request to jQuery.ajax() later on.
+ * @param {Object} options See defaultOptions documentation above. Ajax options can also be
+ * overridden for each individual request to {@link jQuery#ajax} later on.
*/
mw.Api = function ( options ) {
/**
* Normalize the ajax options for compatibility and/or convenience methods.
*
- * @param {undefined|Object|Function} An object contaning one or more of options.ajax,
- * or just a success function (options.ajax.ok).
+ * @param {Object} [arg] An object contaning one or more of options.ajax.
* @return {Object} Normalized ajax options.
*/
normalizeAjaxOptions: function ( arg ) {
// Arg argument is usually empty
- // (before MW 1.20 it was often used to pass ok/err callbacks)
+ // (before MW 1.20 it was used to pass ok callbacks)
var opts = arg || {};
// Options can also be a success callback handler
if ( typeof arg === 'function' ) {
/**
* Perform API get request
*
- * @param {Object} request parameters
- * @param {Object|Function} [optional] ajax options
+ * @param {Object} parameters
+ * @param {Object|Function} [ajaxOptions]
* @return {jQuery.Promise}
*/
get: function ( parameters, ajaxOptions ) {
/**
* Perform API post request
- * @todo Post actions for nonlocal will need proxy
*
- * @param {Object} request parameters
- * @param {Object|Function} [optional] ajax options
+ * TODO: Post actions for non-local hostnames will need proxy.
+ *
+ * @param {Object} parameters
+ * @param {Object|Function} [ajaxOptions]
* @return {jQuery.Promise}
*/
post: function ( parameters, ajaxOptions ) {
/**
* Perform the API call.
*
- * @param {Object} request parameters
- * @param {Object} ajax options
- * @return {jQuery.Promise}
- * - done: API response data as first argument
- * - fail: errorcode as first arg, details (string or object) as second arg.
+ * @param {Object} parameters
+ * @param {Object} [ajaxOptions]
+ * @return {jQuery.Promise} Done: API response data. Fail: Error code
*/
ajax: function ( parameters, ajaxOptions ) {
var token,
};
/**
- * @var {Array} List of errors we might receive from the API.
+ * @static
+ * @property {Array}
+ * List of errors we might receive from the API.
* For now, this just documents our expectation that there should be similar messages
* available.
*/
];
/**
- * @var {Array} List of warnings we might receive from the API.
+ * @static
+ * @property {Array}
+ * List of warnings we might receive from the API.
* For now, this just documents our expectation that there should be similar messages
* available.
*/
/**
- * mw.Api methods for parsing wikitext.
+ * @class mw.Api.plugin.parse
*/
( function ( mw, $ ) {
$.extend( mw.Api.prototype, {
/**
- * Convinience method for 'action=parse'. Parses wikitext into HTML.
+ * Convinience method for 'action=parse'.
*
- * @param wikiText {String}
- * @param ok {Function} [optional] deprecated (success callback)
- * @param err {Function} [optional] deprecated (error callback)
+ * @param {string} wikitext
+ * @param {Function} [ok] Success callback (deprecated)
+ * @param {Function} [err] Error callback (deprecated)
* @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {string} return.done.data Parsed HTML of `wikitext`.
*/
- parse: function ( wikiText, ok, err ) {
- var apiDeferred = $.Deferred();
-
+ parse: function ( wikitext, ok, err ) {
+ var d = $.Deferred();
// Backwards compatibility (< MW 1.20)
- if ( ok ) {
- apiDeferred.done( ok );
- }
- if ( err ) {
- apiDeferred.fail( err );
- }
+ d.done( ok );
+ d.fail( err );
this.get( {
action: 'parse',
- text: wikiText
+ text: wikitext
} )
.done( function ( data ) {
if ( data.parse && data.parse.text && data.parse.text['*'] ) {
- apiDeferred.resolve( data.parse.text['*'] );
+ d.resolve( data.parse.text['*'] );
}
} )
- .fail( apiDeferred.reject );
+ .fail( d.reject );
- // Return the promise
- return apiDeferred.promise();
+ return d.promise();
}
} );
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.parse
+ */
+
}( mediaWiki, jQuery ) );
/**
- * Additional mw.Api methods to assist with API calls to the API module of the TitleBlacklist extension.
+ * @class mw.Api.plugin.titleblacklist
*/
-
( function ( mw, $ ) {
$.extend( mw.Api.prototype, {
/**
- * Convinience method for 'action=titleblacklist'.
+ * Convinience method for `action=titleblacklist`.
* Note: This action is not provided by MediaWiki core, but as part of the TitleBlacklist extension.
*
- * @param title {mw.Title}
- * @param success {Function} Called on successfull request. First argument is false if title wasn't blacklisted,
- * object with 'reason', 'line' and 'message' properties if title was blacklisted.
- * @param err {Function} optional callback to run if api error
- * @return {jqXHR}
+ * @param {mw.Title|string} title
+ * @param {Function} [ok] Success callback (deprecated)
+ * @param {Function} [err] Error callback (deprecated)
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {Object|boolean} return.done.result False if title wasn't blacklisted, an object with 'reason', 'line'
+ * and 'message' properties if title was blacklisted.
*/
- isBlacklisted: function ( title, success, err ) {
- var params = {
+ isBlacklisted: function ( title, ok, err ) {
+ var d = $.Deferred();
+ // Backwards compatibility (< MW 1.20)
+ d.done( ok );
+ d.fail( err );
+
+ this.get( {
action: 'titleblacklist',
tbaction: 'create',
tbtitle: title.toString()
- },
- ok = function ( data ) {
+ } )
+ .done( function ( data ) {
var result;
// this fails open (if nothing valid is returned by the api, allows the title)
// also fails open when the API is not present, which will be most of the time
// as this API module is part of the TitleBlacklist extension.
- if ( data.titleblacklist && data.titleblacklist.result && data.titleblacklist.result === 'blacklisted') {
+ if ( data.titleblacklist && data.titleblacklist.result && data.titleblacklist.result === 'blacklisted' ) {
if ( data.titleblacklist.reason ) {
result = {
reason: data.titleblacklist.reason,
message: data.titleblacklist.message
};
} else {
- mw.log('mw.Api.titleblacklist::isBlacklisted> no reason data for blacklisted title', 'debug');
- result = { reason: 'Blacklisted, but no reason supplied', line: 'Unknown', message: null };
+ mw.log( 'mw.Api.titleblacklist::isBlacklisted> no reason data for blacklisted title', 'debug' );
+ result = {
+ reason: 'Blacklisted, but no reason supplied',
+ line: 'Unknown',
+ message: null
+ };
}
- success( result );
+ d.resolve( result );
} else {
- success ( false );
+ d.resolve( false );
}
- };
+ } )
+ .fail( d.reject );
- return this.get( params, { ok: ok, err: err } );
+ return d.promise();
}
} );
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.titleblacklist
+ */
+
}( mediaWiki, jQuery ) );
/**
- * Additional mw.Api methods to assist with (un)watching wiki pages.
+ * @class mw.Api.plugin.watch
* @since 1.19
*/
( function ( mw, $ ) {
/**
- * @context {mw.Api}
+ * @private
+ * @context mw.Api
+ *
+ * @param {String|mw.Title} page Full page name or instance of mw.Title
+ * @param {Function} [ok] Success callback (deprecated)
+ * @param {Function} [err] Error callback (deprecated)
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {Object} return.done.watch
+ * @return {string} return.done.watch.title Full pagename
+ * @return {boolean} return.done.watch.watched
+ * @return {string} return.done.watch.message Parsed HTML of the confirmational interface message
*/
- function doWatchInternal( page, success, err, addParams ) {
- var params = {
+ function doWatchInternal( page, ok, err, addParams ) {
+ var params, d = $.Deferred();
+ // Backwards compatibility (< MW 1.20)
+ d.done( ok );
+ d.fail( err );
+
+ params = {
action: 'watch',
title: String( page ),
token: mw.user.tokens.get( 'watchToken' ),
uselang: mw.config.get( 'wgUserLanguage' )
};
- function ok( data ) {
- success( data.watch );
- }
+
if ( addParams ) {
$.extend( params, addParams );
}
- return this.post( params, { ok: ok, err: err } );
+
+ this.post( params )
+ .done( function ( data ) {
+ d.resolve( data.watch );
+ } )
+ .fail( d.reject );
+
+ return d.promise();
}
$.extend( mw.Api.prototype, {
/**
- * Convenience method for 'action=watch'.
+ * Convenience method for `action=watch`.
*
- * @param page {String|mw.Title} Full page name or instance of mw.Title
- * @param success {Function} Callback to which the watch object will be passed.
- * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and
- * 'message' (parsed HTML of the 'addedwatchtext' message).
- * @param err {Function} Error callback (optional)
- * @return {jqXHR}
+ * @inheritdoc #doWatchInternal
*/
- watch: function ( page, success, err ) {
- return doWatchInternal.call( this, page, success, err );
+ watch: function ( page, ok, err ) {
+ return doWatchInternal.call( this, page, ok, err );
},
/**
- * Convenience method for 'action=watch&unwatch=1'.
+ * Convenience method for `action=watch&unwatch=1`.
*
- * @param page {String|mw.Title} Full page name or instance of mw.Title
- * @param success {Function} Callback to which the watch object will be passed.
- * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and
- * 'message' (parsed HTML of the 'removedwatchtext' message).
- * @param err {Function} Error callback (optional)
- * @return {jqXHR}
+ * @inheritdoc #doWatchInternal
*/
- unwatch: function ( page, success, err ) {
- return doWatchInternal.call( this, page, success, err, { unwatch: 1 } );
+ unwatch: function ( page, ok, err ) {
+ return doWatchInternal.call( this, page, ok, err, { unwatch: 1 } );
}
} );
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.watch
+ */
+
}( mediaWiki, jQuery ) );
* Russian (Русский) language functions
*/
+// These tests were originally made for names of Wikimedia
+// websites, so they don't currently cover all the possible
+// cases.
+
mediaWiki.language.convertGrammar = function ( word, form ) {
- /*jshint noempty:false, onecase:true */
+ 'use strict';
+
var grammarForms = mediaWiki.language.getData( 'ru', 'grammarForms' );
if ( grammarForms && grammarForms[form] ) {
return grammarForms[form][word];
}
switch ( form ) {
case 'genitive': // родительный падеж
- if ( ( word.substr( word.length - 4 ) === 'вики' ) || ( word.substr( word.length - 4 ) === 'Вики' ) ) {
- } else if ( word.substr( word.length - 1 ) === 'ь' ) {
+ if ( word.substr( word.length - 1 ) === 'ь' ) {
word = word.substr(0, word.length - 1 ) + 'я';
} else if ( word.substr( word.length - 2 ) === 'ия' ) {
word = word.substr(0, word.length - 2 ) + 'ии';
word = word.substr(0, word.length - 2 ) + 'тей';
} else if ( word.substr( word.length - 2 ) === 'ды' ) {
word = word.substr(0, word.length - 2 ) + 'дов';
+ } else if ( word.substr( word.length - 3 ) === 'ные' ) {
+ word = word.substr(0, word.length - 3 ) + 'ных';
} else if ( word.substr( word.length - 3 ) === 'ник' ) {
word = word.substr(0, word.length - 3 ) + 'ника';
}
break;
+ case 'prepositional': // предложный падеж
+ if ( word.substr( word.length - 1 ) === 'ь' ) {
+ word = word.substr(0, word.length - 1 ) + 'е';
+ } else if ( word.substr( word.length - 2 ) === 'ия' ) {
+ word = word.substr(0, word.length - 2 ) + 'ии';
+ } else if ( word.substr( word.length - 2 ) === 'ка' ) {
+ word = word.substr(0, word.length - 2 ) + 'ке';
+ } else if ( word.substr( word.length - 2 ) === 'ти' ) {
+ word = word.substr(0, word.length - 2 ) + 'тях';
+ } else if ( word.substr( word.length - 2 ) === 'ды' ) {
+ word = word.substr(0, word.length - 2 ) + 'дах';
+ } else if ( word.substr( word.length - 3 ) === 'ные' ) {
+ word = word.substr(0, word.length - 3 ) + 'ных';
+ } else if ( word.substr( word.length - 3 ) === 'ник' ) {
+ word = word.substr(0, word.length - 3 ) + 'нике';
+ }
+ break;
}
return word;
};
return forms;
},
- /**
- * Converts a number using digitTransformTable.
- *
- * @param {Number} number Value to be converted
- * @param {boolean} integer Convert the return value to an integer
- * @return {Number|String} formatted number
- */
- convertNumber: function ( num, integer ) {
- var i, tmp, transformTable, numberString, convertedNumber;
-
- // Set the target Transform table:
- transformTable = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'digitTransformTable' );
-
- if ( !transformTable ) {
- return num;
- }
-
- // Check if the "restore" to Latin number flag is set:
- if ( integer ) {
- if ( parseInt( num, 10 ) === num ) {
- return num;
- }
- tmp = [];
- for ( i in transformTable ) {
- tmp[ transformTable[ i ] ] = i;
- }
- transformTable = tmp;
- }
- numberString = '' + num;
- convertedNumber = '';
- for ( i = 0; i < numberString.length; i++ ) {
- if ( transformTable[ numberString[i] ] ) {
- convertedNumber += transformTable[numberString[i]];
- } else {
- convertedNumber += numberString[i];
- }
- }
- return integer ? parseInt( convertedNumber, 10 ) : convertedNumber;
- },
-
/**
* Provides an alternative text depending on specified gender.
* Usage {{gender:[gender|user object]|masculine|feminine|neutral}}.
return grammarForms[form][word] || word;
}
return word;
- },
+ }
- // Digit Transform Table, populated by language classes where applicable
- digitTransformTable: mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'digitTransformTable' )
};
$.extend( mw.language, language );
--- /dev/null
+/*
+ * Number related utilities for mediawiki.language
+ */
+( function ( mw, $ ) {
+
+ /**
+ * Pad a string to guarantee that it is at least `size` length by
+ * filling with the character `ch` at either the start or end of the
+ * string. Pads at the start, by default.
+ * example:
+ * Fill the string to length 10 with '+' characters on the right. Yields 'blah++++++'.
+ * pad('blah', 10, '+', true);
+ *
+ * @param {string} text The string to pad
+ * @param {Number} size To provide padding
+ * @param {string} ch Character to pad, defaults to '0'
+ * @param {Boolean} end Adds padding at the end if true, otherwise pads at start
+ * @return {string}
+ */
+ function pad ( text, size, ch, end ) {
+ if ( !ch ) {
+ ch = '0';
+ }
+
+ var out = String( text ),
+ padStr = replicate( ch, Math.ceil( ( size - out.length ) / ch.length ) );
+
+ return end ? out + padStr : padStr + out;
+ }
+
+ /**
+ * Efficiently replicate a string n times.
+ *
+ * @param {string} str The string to replicate
+ * @param {Number} num Number of times to replicate the string
+ * @return {string}
+ */
+ function replicate ( str, num ) {
+ if ( num <= 0 || !str ) {
+ return '';
+ }
+
+ var buf = [];
+ while (num) {
+ buf.push( str );
+ str += str;
+ }
+ return buf.join( '' );
+ }
+
+ /**
+ * Apply numeric pattern to absolute value using options. Gives no
+ * consideration to local customs.
+ *
+ * Adapted from dojo/number library with thanks
+ * http://dojotoolkit.org/reference-guide/1.8/dojo/number.html
+ *
+ * @param {Number} value the number to be formatted, ignores sign
+ * @param {string} pattern the number portion of a pattern (e.g. `#,##0.00`)
+ * @param {string} options.decimalThe decimal separator
+ * @param {string} options.group The group separator
+ *
+ * @return {string}
+ */
+ function commafyNumber( value, pattern, options ) {
+ options = options || {
+ group: ',',
+ decimal: '.'
+ };
+
+ if ( isNaN( value) ) {
+ return value;
+ }
+
+ var padLength,
+ patternDigits,
+ index,
+ whole,
+ off,
+ remainder,
+ patternParts = pattern.split( '.' ),
+ maxPlaces = ( patternParts[1] || [] ).length,
+ valueParts = String( Math.abs( value ) ).split( '.' ),
+ fractional = valueParts[1] || '',
+ groupSize = 0,
+ groupSize2 = 0,
+ pieces = [];
+
+ if ( patternParts[1] ) {
+ // Pad fractional with trailing zeros
+ padLength = ( patternParts[1] && patternParts[1].lastIndexOf( '0' ) + 1 );
+
+ if ( padLength > fractional.length ) {
+ valueParts[1] = pad( fractional, padLength, '0', true );
+ }
+
+ // Truncate fractional
+ if ( maxPlaces < fractional.length ) {
+ valueParts[1] = fractional.substr( 0, maxPlaces );
+ }
+ } else {
+ if ( valueParts[1] ) {
+ valueParts.pop();
+ }
+ }
+
+ // Pad whole with leading zeros
+ patternDigits = patternParts[0].replace( ',', '' );
+
+ padLength = patternDigits.indexOf( '0' );
+
+ if ( padLength !== -1 ) {
+ padLength = patternDigits.length - padLength;
+
+ if ( padLength > valueParts[0].length ) {
+ valueParts[0] = pad( valueParts[0], padLength );
+ }
+
+ // Truncate whole
+ if ( patternDigits.indexOf( '#' ) === -1 ) {
+ valueParts[0] = valueParts[0].substr( valueParts[0].length - padLength );
+ }
+ }
+
+ // Add group separators
+ index = patternParts[0].lastIndexOf( ',' );
+
+ if ( index !== -1 ) {
+ groupSize = patternParts[0].length - index - 1;
+ remainder = patternParts[0].substr( 0, index );
+ index = remainder.lastIndexOf( ',' );
+ if ( index !== -1 ) {
+ groupSize2 = remainder.length - index - 1;
+ }
+ }
+
+ for ( whole = valueParts[0]; whole; ) {
+ off = whole.length - groupSize;
+
+ pieces.push( ( off > 0 ) ? whole.substr( off ) : whole );
+ whole = ( off > 0 ) ? whole.slice( 0, off ) : '';
+
+ if ( groupSize2 ) {
+ groupSize = groupSize2;
+ }
+ }
+ valueParts[0] = pieces.reverse().join( options.group );
+
+ return valueParts.join( options.decimal );
+ }
+
+ $.extend( mw.language, {
+
+ /**
+ * Converts a number using digitTransformTable.
+ *
+ * @param {Number} num Value to be converted
+ * @param {boolean} integer Convert the return value to an integer
+ * @return {Number|string} Formatted number
+ */
+ convertNumber: function ( num, integer ) {
+ var i, tmp, transformTable, numberString, convertedNumber, pattern;
+
+ pattern = mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+ 'digitGroupingPattern' ) || '#,##0.###';
+
+ // Set the target transform table:
+ transformTable = mw.language.getDigitTransformTable();
+
+ if ( !transformTable ) {
+ return num;
+ }
+
+ // Check if the 'restore' to Latin number flag is set:
+ if ( integer ) {
+ if ( parseInt( num, 10 ) === num ) {
+ return num;
+ }
+ tmp = [];
+ for ( i in transformTable ) {
+ tmp[ transformTable[ i ] ] = i;
+ }
+ transformTable = tmp;
+ numberString = num + '';
+ } else {
+ numberString = mw.language.commafy( num, pattern );
+ }
+
+ convertedNumber = '';
+ for ( i = 0; i < numberString.length; i++ ) {
+ if ( transformTable[ numberString[i] ] ) {
+ convertedNumber += transformTable[numberString[i]];
+ } else {
+ convertedNumber += numberString[i];
+ }
+ }
+ return integer ? parseInt( convertedNumber, 10 ) : convertedNumber;
+ },
+
+ getDigitTransformTable: function () {
+ return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+ 'digitTransformTable' ) || [];
+ },
+
+ getSeparatorTransformTable: function () {
+ return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+ 'separatorTransformTable' ) || [];
+ },
+
+ /**
+ * Apply pattern to format value as a string using as per
+ * unicode.org TR35 - http://www.unicode.org/reports/tr35/#Number_Format_Patterns.
+ *
+ * @param {Number} value
+ * @param {string} pattern Pattern string as described by Unicode TR35
+ * @throws Error
+ * @returns {String}
+ */
+ commafy: function ( value, pattern ) {
+ var numberPattern,
+ transformTable = mw.language.getSeparatorTransformTable(),
+ group = transformTable[','] || ',',
+ numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/, // not precise, but good enough
+ decimal = transformTable['.'] || '.',
+ patternList = pattern.split( ';' ),
+ positivePattern = patternList[0];
+
+ pattern = patternList[ ( value < 0 ) ? 1 : 0] || ( '-' + positivePattern );
+ numberPattern = positivePattern.match( numberPatternRE );
+
+ if ( !numberPattern ) {
+ throw new Error( 'unable to find a number expression in pattern: ' + pattern );
+ }
+
+ return pattern.replace( numberPatternRE, commafyNumber( value, numberPattern[0], {
+ decimal: decimal,
+ group: group
+ } ) );
+ }
+
+ } );
+
+}( mediaWiki, jQuery ) );
-/**
- * mediaWiki.Title
- *
+/*!
* @author Neil Kandalgaonkar, 2010
* @author Timo Tijhof, 2011
* @since 1.18
/* Local space */
/**
- * Title
- * @constructor
+ * @class mw.Title
*
- * @param title {String} Title of the page. If no second argument given,
+ * @constructor
+ * @param {string} title Title of the page. If no second argument given,
* this will be searched for a namespace.
- * @param namespace {Number} (optional) Namespace id. If given, title will be taken as-is.
- * @return {Title} this
+ * @param {number} [namespace] Namespace id. If given, title will be taken as-is.
*/
function Title( title, namespace ) {
this.ns = 0; // integer namespace id
}
var
- /**
- * Public methods (defined later)
- */
+ /* Public methods (defined later) */
fn,
/**
* Strip some illegal chars: control chars, colon, less than, greater than,
* brackets, braces, pipe, whitespace and normal spaces. This still leaves some insanity
* intact, like unicode bidi chars, but it's a good start..
- * @param s {String}
- * @return {String}
+ * @ignore
+ * @param {string} s
+ * @return {string}
*/
clean = function ( s ) {
if ( s !== undefined ) {
/**
* Convert db-key to readable text.
- * @param s {String}
- * @return {String}
+ * @ignore
+ * @param {string} s
+ * @return {string}
*/
text = function ( s ) {
if ( s !== null && s !== undefined ) {
/**
* Sanitize name.
+ * @ignore
*/
fixName = function ( s ) {
return clean( $.trim( s ) );
},
/**
- * Sanitize name.
+ * Sanitize extension.
+ * @ignore
*/
fixExt = function ( s ) {
return clean( s );
/**
* Sanitize namespace id.
+ * @ignore
* @param id {Number} Namespace id.
* @return {Number|Boolean} The id as-is or boolean false if invalid.
*/
/**
* Get namespace id from namespace name by any known namespace/id pair (localized, canonical or alias).
- *
- * @example On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or even 'Bild'.
+ * Example: On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or even 'Bild'.
+ * @ignore
* @param ns {String} Namespace name (case insensitive, leading/trailing space ignored).
* @return {Number|Boolean} Namespace id or boolean false if unrecognized.
*/
/**
* Helper to extract namespace, name and extension from a string.
*
- * @param title {mw.Title}
- * @param raw {String}
+ * @ignore
+ * @param {mw.Title} title
+ * @param {string} raw
* @return {mw.Title}
*/
setAll = function ( title, s ) {
/**
* Helper to extract name and extension from a string.
*
- * @param title {mw.Title}
- * @param raw {String}
+ * @ignore
+ * @param {mw.Title} title
+ * @param {string} raw
* @return {mw.Title}
*/
setNameAndExtension = function ( title, raw ) {
/**
* Whether this title exists on the wiki.
- * @param title {mixed} prefixed db-key name (string) or instance of Title
- * @return {mixed} Boolean true/false if the information is available. Otherwise null.
+ * @static
+ * @param {Mixed} title prefixed db-key name (string) or instance of Title
+ * @return {Mixed} Boolean true/false if the information is available. Otherwise null.
*/
Title.exists = function ( title ) {
var type = $.type( title ), obj = Title.exist.pages, match;
};
/**
- * @var Title.exist {Object}
+ * @static
+ * @property
*/
Title.exist = {
/**
- * @var Title.exist.pages {Object} Keyed by PrefixedDb title.
+ * @static
+ * @property {Object} exist.pages Keyed by PrefixedDb title.
* Boolean true value indicates page does exist.
*/
pages: {},
/**
- * @example Declare existing titles: Title.exist.set(['User:John_Doe', ...]);
- * @example Declare titles nonexistent: Title.exist.set(['File:Foo_bar.jpg', ...], false);
- * @param titles {String|Array} Title(s) in strict prefixedDb title form.
- * @param state {Boolean} (optional) State of the given titles. Defaults to true.
- * @return {Boolean}
+ * Example to declare existing titles:
+ * Title.exist.set(['User:John_Doe', ...]);
+ * Eample to declare titles nonexistent:
+ * Title.exist.set(['File:Foo_bar.jpg', ...], false);
+ *
+ * @static
+ * @property exist.set
+ * @param {string|Array} titles Title(s) in strict prefixedDb title form.
+ * @param {boolean} [state] State of the given titles. Defaults to true.
+ * @return {boolean}
*/
set: function ( titles, state ) {
titles = $.isArray( titles ) ? titles : [titles];
/**
* Get the namespace number.
- * @return {Number}
+ * @return {number}
*/
getNamespaceId: function (){
return this.ns;
/**
* Get the namespace prefix (in the content-language).
* In NS_MAIN this is '', otherwise namespace name plus ':'
- * @return {String}
+ * @return {string}
*/
getNamespacePrefix: function (){
return mw.config.get( 'wgFormattedNamespaces' )[this.ns].replace( / /g, '_' ) + (this.ns === 0 ? '' : ':');
/**
* The name, like "Foo_bar"
- * @return {String}
+ * @return {string}
*/
getName: function () {
if ( $.inArray( this.ns, mw.config.get( 'wgCaseSensitiveNamespaces' ) ) !== -1 ) {
/**
* The name, like "Foo bar"
- * @return {String}
+ * @return {string}
*/
getNameText: function () {
return text( this.getName() );
/**
* Get full name in prefixed DB form, like File:Foo_bar.jpg,
* most useful for API calls, anything that must identify the "title".
+ * @return {string}
*/
getPrefixedDb: function () {
return this.getNamespacePrefix() + this.getMain();
/**
* Get full name in text form, like "File:Foo bar.jpg".
- * @return {String}
+ * @return {string}
*/
getPrefixedText: function () {
return text( this.getPrefixedDb() );
/**
* The main title (without namespace), like "Foo_bar.jpg"
- * @return {String}
+ * @return {string}
*/
getMain: function () {
return this.getName() + this.getDotExtension();
/**
* The "text" form, like "Foo bar.jpg"
- * @return {String}
+ * @return {string}
*/
getMainText: function () {
return text( this.getMain() );
/**
* Get the extension (returns null if there was none)
- * @return {String|null} extension
+ * @return {string|null}
*/
getExtension: function () {
return this.ext;
/**
* Convenience method: return string like ".jpg", or "" if no extension
- * @return {String}
+ * @return {string}
*/
getDotExtension: function () {
return this.ext === null ? '' : '.' + this.ext;
/**
* Return the URL to this title
- * @return {String}
+ * @see mw.util#wikiGetlink
+ * @return {string}
*/
getUrl: function () {
return mw.util.wikiGetlink( this.toString() );
/**
* Whether this title exists on the wiki.
- * @return {mixed} Boolean true/false if the information is available. Otherwise null.
+ * @see #static-method-exists
+ * @return {boolean|null} If the information is available. Otherwise null.
*/
exists: function () {
return Title.exists( this );
$span.append( childNode );
} );
} else {
- // Let jQuery append nodes, arrays of nodes and jQuery objects
- // other things (strings, numbers, ..) are appended as text nodes (not as HTML strings)
- $span.append( $.type( node ) === 'object' ? node : document.createTextNode( node ) );
+ // strings, integers, anything else
+ // (will soon switch to createTextNode() for non-objects)
+ $span.append( node );
}
} );
return $span;
/* Object constructors */
/**
- * Map
- *
* Creates an object that can be read from or written to from prototype functions
* that allow both single and multiple variables at once.
+ * @class mw.Map
*
- * @param global boolean Whether to store the values in the global window
+ * @constructor
+ * @param {boolean} global Whether to store the values in the global window
* object or a exclusively in the object property 'values'.
- * @return Map
*/
function Map( global ) {
this.values = global === true ? window : {};
* If selection was an array, returns an object of key/values (value is null if not found),
* If selection was not passed or invalid, will return the 'values' object member (be careful as
* objects are always passed by reference in JavaScript!).
- * @return Values as a string or object, null if invalid/inexistant.
+ * @return {string|Object|null} Values as a string or object, null if invalid/inexistant.
*/
get: function ( selection, fallback ) {
var results, i;
* Checks if one or multiple keys exist.
*
* @param selection {mixed} String key or array of keys to check
- * @return {Boolean} Existence of key(s)
+ * @return {boolean} Existence of key(s)
*/
exists: function ( selection ) {
var s;
};
/**
- * Message
- *
* Object constructor for messages,
* similar to the Message class in MediaWiki PHP.
+ * @class mw.Message
*
- * @param map Map Instance of mw.Map
- * @param key String
- * @param parameters Array
- * @return Message
+ * @constructor
+ * @param {mw.Map} map Message storage
+ * @param {string} key
+ * @param {Array} [parameters]
*/
function Message( map, key, parameters ) {
this.format = 'text';
/**
* Appends (does not replace) parameters for replacement to the .parameters property.
*
- * @param parameters Array
- * @return Message
+ * @param {Array} parameters
+ * @chainable
*/
params: function ( parameters ) {
var i;
/**
* Converts message object to it's string form based on the state of format.
*
- * @return string Message as a string in the current form or <key> if key does not exist.
+ * @return {string} Message as a string in the current form or `<key>` if key does not exist.
*/
toString: function () {
var text;
/**
* Checks if message exists
*
- * @return {string} String form of parsed message
+ * @see mw.Map#exists
+ * @return {boolean}
*/
exists: function () {
return this.map.exists( this.key );
}
};
+ /**
+ * @class mw
+ * @alternateClassName mediaWiki
+ * @singleton
+ */
return {
/* Public Members */
*/
log: function () { },
- /**
- * @var constructor Make the Map constructor publicly available.
- */
+ // Make the Map constructor publicly available.
Map: Map,
- /**
- * @var constructor Make the Message constructor publicly available.
- */
+ // Make the Message constructor publicly available.
Message: Message,
/**
* List of configuration values
*
* Dummy placeholder. Initiated in startUp module as a new instance of mw.Map().
- * If $wgLegacyJavaScriptGlobals is true, this Map will have its values
+ * If `$wgLegacyJavaScriptGlobals` is true, this Map will have its values
* in the global window object.
+ * @property
*/
config: null,
/**
- * @var object
- *
* Empty object that plugins can be installed in.
+ * @property
*/
libs: {},
/* Extension points */
+ /**
+ * @property
+ */
legacy: {},
/**
* Localization system
+ * @property {mw.Map}
*/
messages: new Map(),
/* Public Methods */
/**
- * Gets a message object, similar to wfMessage()
+ * Gets a message object, similar to wfMessage().
*
- * @param key string Key of message to get
- * @param parameter1 mixed First argument in a list of variadic arguments,
- * each a parameter for $N replacement in messages.
- * @return Message
+ * @param {string} key Key of message to get
+ * @param {Mixed...} parameters Parameters for the $N replacements in messages.
+ * @return {mw.Message}
*/
- message: function ( key, parameter1 ) {
- var parameters;
- // Support variadic arguments
- if ( parameter1 !== undefined ) {
- parameters = slice.call( arguments );
- parameters.shift();
- } else {
- parameters = [];
- }
+ message: function ( key ) {
+ // Variadic arguments
+ var parameters = slice.call( arguments, 1 );
return new Message( mw.messages, key, parameters );
},
/**
* Gets a message string, similar to wfMessage()
*
- * @param key string Key of message to get
- * @param parameters mixed First argument in a list of variadic arguments,
- * each a parameter for $N replacement in messages.
- * @return String.
+ * @see mw.Message#toString
+ * @param {string} key Key of message to get
+ * @param {Mixed...} parameters Parameters for the $N replacements in messages.
+ * @return {string}
*/
- msg: function ( /* key, parameter_1, parameter_2, .. */ ) {
+ msg: function ( /* key, parameters... */ ) {
return mw.message.apply( mw.message, arguments ).toString();
},
/**
* Client-side module loader which integrates with the MediaWiki ResourceLoader
+ * @class mw.loader
+ * @singleton
*/
loader: ( function () {
* mw.loader.implement.
*
* Format:
- * {
- * 'moduleName': {
- * 'version': ############## (unix timestamp),
- * 'dependencies': ['required.foo', 'bar.also', ...], (or) function () {}
- * 'group': 'somegroup', (or) null,
- * 'source': 'local', 'someforeignwiki', (or) null
- * 'state': 'registered', 'loading', 'loaded', 'ready', 'error' or 'missing'
- * 'script': ...,
- * 'style': ...,
- * 'messages': { 'key': 'value' },
- * }
- * }
+ * {
+ * 'moduleName': {
+ * 'version': ############## (unix timestamp),
+ * 'dependencies': ['required.foo', 'bar.also', ...], (or) function () {}
+ * 'group': 'somegroup', (or) null,
+ * 'source': 'local', 'someforeignwiki', (or) null
+ * 'state': 'registered', 'loading', 'loaded', 'ready', 'error' or 'missing'
+ * 'script': ...,
+ * 'style': ...,
+ * 'messages': { 'key': 'value' },
+ * }
+ * }
+ *
+ * @property
+ * @private
*/
var registry = {},
- /**
- * Mapping of sources, keyed by source-id, values are objects.
- * Format:
- * {
- * 'sourceId': {
- * 'loadScript': 'http://foo.bar/w/load.php'
- * }
- * }
- */
+ //
+ // Mapping of sources, keyed by source-id, values are objects.
+ // Format:
+ // {
+ // 'sourceId': {
+ // 'loadScript': 'http://foo.bar/w/load.php'
+ // }
+ // }
+ //
sources = {},
// List of modules which will be loaded as when ready
batch = [],
/**
* Create a new style tag and add it to the DOM.
*
- * @param text String: CSS text
- * @param nextnode mixed: [optional] An Element or jQuery object for an element where
- * the style tag should be inserted before. Otherwise appended to the <head>.
- * @return HTMLStyleElement
+ * @private
+ * @param {string} text CSS text
+ * @param {Mixed} [nextnode] An Element or jQuery object for an element where
+ * the style tag should be inserted before. Otherwise appended to the `<head>`.
+ * @return {HTMLElement} Node reference to the created `<style>` tag.
*/
function addStyleTag( text, nextnode ) {
var s = document.createElement( 'style' );
* Checks if certain cssText is safe to append to
* a stylesheet.
*
- * Right now it only makes sure that cssText containing @import
+ * Right now it only makes sure that cssText containing `@import`
* rules will end up in a new stylesheet (as those only work when
* placed at the start of a stylesheet; bug 35562).
* This could later be extended to take care of other bugs, such as
* the IE cssRules limit - not the same as the IE styleSheets limit).
+ * @private
+ * @param {jQuery} $style
+ * @param {string} cssText
+ * @return {boolean}
*/
function canExpandStylesheetWith( $style, cssText ) {
return cssText.indexOf( '@import' ) === -1;
function addEmbeddedCSS( cssText ) {
var $style, styleEl;
$style = getMarker().prev();
- // Re-use <style> tags if possible, this to try to stay
+ // Re-use `<style>` tags if possible, this to try to stay
// under the IE stylesheet limit (bug 31676).
// Also verify that the the element before Marker actually is one
// that came from ResourceLoader, and not a style tag that some
// other script inserted before our marker, or, more importantly,
- // it may not be a style tag at all (could be <meta> or <script>).
+ // it may not be a style tag at all (could be `<meta>` or `<script>`).
if (
$style.data( 'ResourceLoaderDynamicStyleTag' ) === true &&
canExpandStylesheetWith( $style, cssText )
/**
* Generates an ISO8601 "basic" string from a UNIX timestamp
+ * @private
*/
function formatVersionNumber( timestamp ) {
var d = new Date();
/**
* Resolves dependencies and detects circular references.
*
- * @param module String Name of the top-level module whose dependencies shall be
+ * @private
+ * @param {string} module Name of the top-level module whose dependencies shall be
* resolved and sorted.
- * @param resolved Array Returns a topological sort of the given module and its
+ * @param {Array} resolved Returns a topological sort of the given module and its
* dependencies, such that later modules depend on earlier modules. The array
* contains the module names. If the array contains already some module names,
* this function appends its result to the pre-existing array.
- * @param unresolved Object [optional] Hash used to track the current dependency
+ * @param {Object} [unresolved] Hash used to track the current dependency
* chain; used to report loops in the dependency graph.
- * @throws Error if any unregistered module or a dependency loop is encountered
+ * @throws {Error} If any unregistered module or a dependency loop is encountered
*/
function sortDependencies( module, resolved, unresolved ) {
var n, deps, len;
* Gets a list of module names that a module depends on in their proper dependency
* order.
*
- * @param module string module name or array of string module names
- * @return list of dependencies, including 'module'.
- * @throws Error if circular reference is detected
+ * @private
+ * @param {string} module Module name or array of string module names
+ * @return {Array} list of dependencies, including 'module'.
+ * @throws {Error} If circular reference is detected
*/
function resolve( module ) {
var m, resolved;
* One can also filter for 'unregistered', which will return the
* modules names that don't have a registry entry.
*
- * @param states string or array of strings of module states to filter by
- * @param modules array list of module names to filter (optional, by default the entire
+ * @private
+ * @param {string|string[]} states Module states to filter by
+ * @param {Array} modules List of module names to filter (optional, by default the entire
* registry is used)
- * @return array list of filtered module names
+ * @return {Array} List of filtered module names
*/
function filter( states, modules ) {
var list, module, s, m;
* Determine whether all dependencies are in state 'ready', which means we may
* execute the module or job now.
*
- * @param dependencies Array dependencies (module names) to be checked.
- *
- * @return Boolean true if all dependencies are in state 'ready', false otherwise
+ * @private
+ * @param {Array} dependencies Dependencies (module names) to be checked.
+ * @return {boolean} True if all dependencies are in state 'ready', false otherwise
*/
function allReady( dependencies ) {
return filter( 'ready', dependencies ).length === dependencies.length;
* Gets console references in each invocation, so that delayed debugging tools work
* fine. No need for optimization here, which would only result in losing logs.
*
- * @param msg String text for the log entry.
- * @param e Error [optional] to also log.
+ * @private
+ * @param {string} msg text for the log entry.
+ * @param {Error} [e]
*/
function log( msg, e ) {
var console = window.console;
* state up the dependency tree; otherwise, execute all jobs/modules that now have all their
* dependencies satisfied. On jobs depending on a failed module, run the error callback, if any.
*
- * @param module String name of module that entered one of the states 'ready', 'error', or 'missing'.
+ * @private
+ * @param {string} module Name of module that entered one of the states 'ready', 'error', or 'missing'.
*/
function handlePending( module ) {
var j, job, hasErrors, m, stateChange;
* Adds a script tag to the DOM, either using document.write or low-level DOM manipulation,
* depending on whether document-ready has occurred yet and whether we are in async mode.
*
- * @param src String: URL to script, will be used as the src attribute in the script tag
- * @param callback Function: Optional callback which will be run when the script is done
+ * @private
+ * @param {string} src URL to script, will be used as the src attribute in the script tag
+ * @param {Function} [callback] Callback which will be run when the script is done
*/
function addScript( src, callback, async ) {
/*jshint evil:true */
/**
* Executes a loaded module, making it ready to use
*
- * @param module string module name to execute
+ * @private
+ * @param {string} module Module name to execute
*/
function execute( module ) {
var key, value, media, i, urls, script, markModuleReady, nestedAddScript;
/**
* Define loop-function here for efficiency
* and to avoid re-using badly scoped variables.
+ * @ignore
*/
function addLink( media, url ) {
var el = document.createElement( 'link' );
* Adds a dependencies to the queue with optional callbacks to be run
* when the dependencies are ready or fail
*
- * @param dependencies string module name or array of string module names
- * @param ready function callback to execute when all dependencies are ready
- * @param error function callback to execute when any dependency fails
- * @param async (optional) If true, load modules asynchronously even if
- * document ready has not yet occurred
+ * @private
+ * @param {string|string[]} dependencies Module name or array of string module names
+ * @param {Function} ready Callback to execute when all dependencies are ready
+ * @param {Function} error Callback to execute when any dependency fails
+ * @param {boolean} [async] If true, load modules asynchronously even if
+ * document ready has not yet occurred.
*/
function request( dependencies, ready, error, async ) {
var n;
/**
* Converts a module map of the form { foo: [ 'bar', 'baz' ], bar: [ 'baz, 'quux' ] }
* to a query string of the form foo.bar,baz|bar.baz,quux
+ * @private
*/
function buildModulesString( moduleMap ) {
var arr = [], p, prefix;
/**
* Asynchronously append a script tag to the end of the body
* that invokes load.php
- * @param moduleMap {Object}: Module map, see buildModulesString()
- * @param currReqBase {Object}: Object with other parameters (other than 'modules') to use in the request
- * @param sourceLoadScript {String}: URL of load.php
- * @param async {Boolean}: If true, use an asynchrounous request even if document ready has not yet occurred
+ * @private
+ * @param {Object} moduleMap Module map, see #buildModulesString
+ * @param {Object} currReqBase Object with other parameters (other than 'modules') to use in the request
+ * @param {string} sourceLoadScript URL of load.php
+ * @param {boolean} async If true, use an asynchrounous request even if document ready has not yet occurred
*/
function doRequest( moduleMap, currReqBase, sourceLoadScript, async ) {
var request = $.extend(
/**
* Register a source.
*
- * @param id {String}: Short lowercase a-Z string representing a source, only used internally.
- * @param props {Object}: Object containing only the loadScript property which is a url to
- * the load.php location of the source.
- * @return {Boolean}
+ * @param {string} id Short lowercase a-Z string representing a source, only used internally.
+ * @param {Object} props Object containing only the loadScript property which is a url to
+ * the load.php location of the source.
+ * @return {boolean}
*/
addSource: function ( id, props ) {
var source;
*
* All arguments are required.
*
- * @param {String} module Name of module
+ * @param {string} module Name of module
* @param {Function|Array} script Function with module code or Array of URLs to
- * be used as the src attribute of a new <script> tag.
+ * be used as the src attribute of a new `<script>` tag.
* @param {Object} style Should follow one of the following patterns:
- * { "css": [css, ..] }
- * { "url": { <media>: [url, ..] } }
- * And for backwards compatibility (needs to be supported forever due to caching):
- * { <media>: css }
- * { <media>: [url, ..] }
+ * { "css": [css, ..] }
+ * { "url": { <media>: [url, ..] } }
+ * And for backwards compatibility (needs to be supported forever due to caching):
+ * { <media>: css }
+ * { <media>: [url, ..] }
*
- * The reason css strings are not concatenated anymore is bug 31676. We now check
- * whether it's safe to extend the stylesheet (see canExpandStylesheetWith).
+ * The reason css strings are not concatenated anymore is bug 31676. We now check
+ * whether it's safe to extend the stylesheet (see #canExpandStylesheetWith).
*
- * @param {Object} msgs List of key/value pairs to be passed through mw.messages.set
+ * @param {Object} msgs List of key/value pairs to be added to {@link mw#messages}.
*/
implement: function ( module, script, style, msgs ) {
// Validate input
};
}() ),
- /** HTML construction helper functions */
+ /**
+ * HTML construction helper functions
+ * @class mw.html
+ * @singleton
+ */
html: ( function () {
function escapeCallback( s ) {
switch ( s ) {
return {
/**
* Escape a string for HTML. Converts special characters to HTML entities.
- * @param s The string to escape
+ * @param {string} s The string to escape
*/
escape: function ( s ) {
return s.replace( /['"<>&]/g, escapeCallback );
/**
* Wrapper object for raw HTML passed to mw.html.element().
- * @constructor
+ * @class mw.html.Raw
*/
Raw: function ( value ) {
this.value = value;
/**
* Wrapper object for CDATA element contents passed to mw.html.element()
- * @constructor
+ * @class mw.html.Cdata
*/
Cdata: function ( value ) {
this.value = value;
-/**
- * Implements mediaWiki.notification library
- */
( function ( mw, $ ) {
'use strict';
var notification,
isPageReady = false,
- isInitialized = false,
preReadyNotifQueue = [],
- /**
- * @var {jQuery}
- * The #mw-notification-area div that all notifications are contained inside.
- */
+ // The #mw-notification-area div that all notifications are contained inside.
$area = null;
/**
* Creates a Notification object for 1 message.
- * Does not insert anything into the document (see .start()).
+ * Does not insert anything into the document (see #start).
+ *
+ * The "_" in the name is to avoid a bug (http://github.com/senchalabs/jsduck/issues/304)
+ * It is not part of the actual class name.
+ *
+ * @class mw.Notification_
+ * @alternateClassName mw.Notification
+ * @private
*
* @constructor
- * @see mw.notification.notify
*/
function Notification( message, options ) {
var $notification, $notificationTitle, $notificationContent;
*
* @param {Object} options An object containing options for the closing of the notification.
* These are typically only used internally.
+ *
* - speed: Use a close speed different than the default 'slow'.
* - placeholder: Set to false to disable the placeholder transition.
*/
/**
* Helper function, take a list of notification divs and call
- * a function on the Notification instance attached to them
+ * a function on the Notification instance attached to them.
*
* @param {jQuery} $notifications A jQuery object containing notification divs
* @param {string} fn The name of the function to call on the Notification instance
}
/**
- * Initialisation
- * (don't call before document ready)
+ * Initialisation.
+ * Must only be called once, and not before the document is ready.
+ * @ignore
*/
function init() {
- if ( !isInitialized ) {
- isInitialized = true;
- $area = $( '<div id="mw-notification-area"></div>' )
- // Pause auto-hide timers when the mouse is in the notification area.
- .on( {
- mouseenter: notification.pause,
- mouseleave: notification.resume
- } )
- // When clicking on a notification close it.
- .on( 'click', '.mw-notification', function () {
- var notif = $( this ).data( 'mw.notification' );
- if ( notif ) {
- notif.close();
- }
- } )
- // Stop click events from <a> tags from propogating to prevent clicking.
- // on links from hiding a notification.
- .on( 'click', 'a', function ( e ) {
- e.stopPropagation();
- } );
-
- // Prepend the notification area to the content area and save it's object.
- mw.util.$content.prepend( $area );
- }
+ $area = $( '<div id="mw-notification-area"></div>' )
+ // Pause auto-hide timers when the mouse is in the notification area.
+ .on( {
+ mouseenter: notification.pause,
+ mouseleave: notification.resume
+ } )
+ // When clicking on a notification close it.
+ .on( 'click', '.mw-notification', function () {
+ var notif = $( this ).data( 'mw.notification' );
+ if ( notif ) {
+ notif.close();
+ }
+ } )
+ // Stop click events from <a> tags from propogating to prevent clicking.
+ // on links from hiding a notification.
+ .on( 'click', 'a', function ( e ) {
+ e.stopPropagation();
+ } );
+
+ // Prepend the notification area to the content area and save it's object.
+ mw.util.$content.prepend( $area );
}
+ /**
+ * @class mw.notification
+ * @singleton
+ */
notification = {
/**
* Pause auto-hide timers for all notifications.
* Notifications will not auto-hide until resume is called.
+ * @see mw.Notification#pause
*/
pause: function () {
callEachNotification(
/**
* Resume any paused auto-hide timers from the beginning.
- * Only the first {autoHideLimit} timers will be resumed.
+ * Only the first #autoHideLimit timers will be resumed.
*/
resume: function () {
callEachNotification(
- // Only call resume on the first {autoHideLimit} notifications.
- // Exclude noautohide notifications to avoid bugs where {autoHideLimit}
- // { autoHide: false } notifications are at the start preventing any
+ // Only call resume on the first #autoHideLimit notifications.
+ // Exclude noautohide notifications to avoid bugs where #autoHideLimit
+ // `{ autoHide: false }` notifications are at the start preventing any
// auto-hide notifications from being autohidden.
$area.children( '.mw-notification-autohide' ).slice( 0, notification.autoHideLimit ),
'resume'
/**
* Display a notification message to the user.
*
- * @param {mixed} message The DOM-element, jQuery object, mw.Message instance,
- * or plaintext string to be used as the message.
+ * @param {HTMLElement|jQuery|mw.Message|string} message
* @param {Object} options The options to use for the notification.
- * See mw.notification.defaults for details.
+ * See #defaults for details.
*/
notify: function ( message, options ) {
var notif;
},
/**
- * @var {Object}
- * The defaults for mw.notification.notify's options parameter
- * autoHide:
- * A boolean indicating whether the notifification should automatically
- * be hidden after shown. Or if it should persist.
+ * @property {Object}
+ * The defaults for #notify options parameter.
+ *
+ * - autoHide:
+ * A boolean indicating whether the notifification should automatically
+ * be hidden after shown. Or if it should persist.
*
- * tag:
- * An optional string. When a notification is tagged only one message
- * with that tag will be displayed. Trying to display a new notification
- * with the same tag as one already being displayed will cause the other
- * notification to be closed and this new notification to open up inside
- * the same place as the previous notification.
+ * - tag:
+ * An optional string. When a notification is tagged only one message
+ * with that tag will be displayed. Trying to display a new notification
+ * with the same tag as one already being displayed will cause the other
+ * notification to be closed and this new notification to open up inside
+ * the same place as the previous notification.
*
- * title:
- * An optional title for the notification. Will be displayed above the
- * content. Usually in bold.
+ * - title:
+ * An optional title for the notification. Will be displayed above the
+ * content. Usually in bold.
*/
defaults: {
autoHide: true,
},
/**
- * @var {number}
+ * @property {number}
* Number of seconds to wait before auto-hiding notifications.
*/
autoHideSeconds: 5,
/**
- * @var {number}
+ * @property {number}
* Maximum number of notifications to count down auto-hide timers for.
- * Only the first {autoHideLimit} notifications being displayed will
+ * Only the first #autoHideLimit notifications being displayed will
* auto-hide. Any notifications further down in the list will only start
* counting down to auto-hide after the first few messages have closed.
*
* This basically represents the number of notifications the user should
- * be able to process in {autoHideSeconds} time.
+ * be able to process in #autoHideSeconds time.
*/
autoHideLimit: 3
};
/**
- * Implements mediaWiki.notify function
+ * @class mw.plugin.notify
*/
( function ( mw ) {
'use strict';
/**
- * @see mw.notification.notify
+ * @see mw.notification#notify
+ * @param message
+ * @param options
*/
mw.notify = function ( message, options ) {
// Don't bother loading the whole notification system if we never use it.
} );
};
-}( mediaWiki ) );
\ No newline at end of file
+ /**
+ * @class mw
+ * @mixins mw.plugin.notify
+ */
+
+}( mediaWiki ) );
-/**
- * Implements mediaWiki.util library
- */
( function ( mw, $ ) {
'use strict';
- // Local cache and alias
+ /**
+ * Utility library
+ * @class mw.util
+ * @singleton
+ */
var util = {
/**
/**
* Encode the string like PHP's rawurlencode
*
- * @param str string String to be encoded
+ * @param {string} str String to be encoded.
*/
rawurlencode: function ( str ) {
str = String( str );
* We want / and : to be included as literal characters in our title URLs
* as they otherwise fatally break the title
*
- * @param str string String to be encoded
+ * @param {string} str String to be encoded.
*/
wikiUrlencode: function ( str ) {
return util.rawurlencode( str )
},
/**
- * Get the link to a page name (relative to wgServer)
+ * Get the link to a page name (relative to `wgServer`),
*
- * @param str String: Page name to get the link for.
- * @return String: Location for a page with name of 'str' or boolean false on error.
+ * @param {string} str Page name to get the link for.
+ * @return {string} Location for a page with name of `str` or boolean false on error.
*/
wikiGetlink: function ( str ) {
return mw.config.get( 'wgArticlePath' ).replace( '$1',
/**
* Get address to a script in the wiki root.
- * For index.php use mw.config.get( 'wgScript' )
+ * For index.php use `mw.config.get( 'wgScript' )`.
*
* @since 1.18
* @param str string Name of script (eg. 'api'), defaults to 'index'
/**
* Append a new style block to the head and return the CSSStyleSheet object.
- * Use .ownerNode to access the <style> element, or use mw.loader.addStyleTag.
+ * Use .ownerNode to access the `<style>` element, or use mw.loader#addStyleTag.
* This function returns the styleSheet object for convience (due to cross-browsers
* difference as to where it is located).
- * @example
- * <code>
- * var sheet = mw.util.addCSS('.foobar { display: none; }');
- * $(foo).click(function () {
- * // Toggle the sheet on and off
- * sheet.disabled = !sheet.disabled;
- * });
- * </code>
*
- * @param text string CSS to be appended
- * @return CSSStyleSheet (use .ownerNode to get to the <style> element)
+ * var sheet = mw.util.addCSS('.foobar { display: none; }');
+ * $(foo).click(function () {
+ * // Toggle the sheet on and off
+ * sheet.disabled = !sheet.disabled;
+ * });
+ *
+ * @param {string} text CSS to be appended
+ * @return {CSSStyleSheet} Use .ownerNode to get to the `<style>` element.
*/
addCSS: function ( text ) {
var s = mw.loader.addStyleTag( text );
/**
* Hide/show the table of contents element
*
- * @param $toggleLink jQuery A jQuery object of the toggle link.
- * @param callback function Function to be called after the toggle is
- * completed (including the animation) (optional)
- * @return mixed Boolean visibility of the toc (true if it's visible)
+ * @param {jQuery} $toggleLink A jQuery object of the toggle link.
+ * @param {Function} [callback] Function to be called after the toggle is
+ * completed (including the animation).
+ * @return {Mixed} Boolean visibility of the toc (true if it's visible)
* or Null if there was no table of contents.
*/
toggleToc: function ( $toggleLink, callback ) {
* Grab the URL parameter value for the given parameter.
* Returns null if not found.
*
- * @param param string The parameter name.
- * @param url string URL to search through (optional)
- * @return mixed Parameter value or null.
+ * @param {string} param The parameter name.
+ * @param {string} [url] URL to search through.
+ * @return {Mixed} Parameter value or null.
*/
getParamValue: function ( param, url ) {
if ( url === undefined ) {
},
/**
- * @var string
+ * @property {string}
* Access key prefix. Will be re-defined based on browser/operating system
- * detection in mw.util.init().
+ * detection in mw.util#init.
*/
tooltipAccessKeyPrefix: 'alt-',
/**
- * @var RegExp
+ * @property {RegExp}
* Regex to match accesskey tooltips.
*/
tooltipAccessKeyRegexp: /\[(ctrl-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
* otherwise, all the nodes that will probably have accesskeys by
* default are updated.
*
- * @param $nodes {Array|jQuery} [optional] A jQuery object, or array
- * of elements to update.
+ * @param {Array|jQuery} [$nodes] A jQuery object, or array of nodes to update.
*/
updateTooltipAccessKeys: function ( $nodes ) {
if ( !$nodes ) {
},
/*
- * @var jQuery
- * A jQuery object that refers to the content area element
- * Populated by init().
+ * @property {jQuery}
+ * A jQuery object that refers to the content area element.
+ * Populated by #init.
*/
$content: null,
*
* By default the new link will be added to the end of the list. To
* add the link before a given existing item, pass the DOM node
- * (document.getElementById( 'foobar' )) or the jQuery-selector
- * ( '#foobar' ) of that item.
+ * (e.g. `document.getElementById( 'foobar' )`) or a jQuery-selector
+ * (e.g. `'#foobar'`) for that item.
*
- * @example mw.util.addPortletLink(
- * 'p-tb', 'http://mediawiki.org/',
- * 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', '#t-print'
- * )
+ * mw.util.addPortletLink(
+ * 'p-tb', 'http://mediawiki.org/',
+ * 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', '#t-print'
+ * );
*
- * @param portlet string ID of the target portlet ( 'p-cactions' or 'p-personal' etc.)
- * @param href string Link URL
- * @param text string Link text
- * @param id string ID of the new item, should be unique and preferably have
- * the appropriate prefix ( 'ca-', 'pt-', 'n-' or 't-' )
- * @param tooltip string Text to show when hovering over the link, without accesskey suffix
- * @param accesskey string Access key to activate this link (one character, try
- * to avoid conflicts. Use $( '[accesskey=x]' ).get() in the console to
- * see if 'x' is already used.
- * @param nextnode mixed DOM Node or jQuery-selector string of the item that the new
- * item should be added before, should be another item in the same
- * list, it will be ignored otherwise
+ * @param {string} portlet ID of the target portlet ( 'p-cactions' or 'p-personal' etc.)
+ * @param {string} href Link URL
+ * @param {string} text Link text
+ * @param {string} [id] ID of the new item, should be unique and preferably have
+ * the appropriate prefix ( 'ca-', 'pt-', 'n-' or 't-' )
+ * @param {string} [tooltip] Text to show when hovering over the link, without accesskey suffix
+ * @param {string} [accesskey] Access key to activate this link (one character, try
+ * to avoid conflicts. Use `$( '[accesskey=x]' ).get()` in the console to
+ * see if 'x' is already used.
+ * @param {HTMLElement|jQuery|string} [nextnode] Element or jQuery-selector string to the item that
+ * the new item should be added before, should be another item in the same
+ * list, it will be ignored otherwise
*
- * @return mixed The DOM Node of the added item (a ListItem or Anchor element,
+ * @return {HTMLElement|null} The added element (a ListItem or Anchor element,
* depending on the skin) or null if no element was added to the document.
*/
addPortletLink: function ( portlet, href, text, id, tooltip, accesskey, nextnode ) {
* something, replacing any previous message.
* Calling with no arguments, with an empty string or null will hide the message
*
- * @param message {mixed} The DOM-element, jQuery object or HTML-string to be put inside the message box.
+ * @param {Mixed} message The DOM-element, jQuery object or HTML-string to be put inside the message box.
* to allow CSS/JS to hide different boxes. null = no class used.
- * @depreceated Use mw.notify
+ * @deprecated Use mw#notify
*/
jsMessage: function ( message ) {
if ( !arguments.length || message === '' || message === null ) {
* according to HTML5 specification. Please note the specification
* does not validate a domain with one character.
*
- * @todo FIXME: should be moved to or replaced by a JavaScript validation module.
+ * FIXME: should be moved to or replaced by a validation module.
*
- * @param mailtxt string E-mail address to be validated.
- * @return mixed Null if mailtxt was an empty string, otherwise true/false
- * is determined by validation.
+ * @param {string} mailtxt E-mail address to be validated.
+ * @return {boolean|null} Null if `mailtxt` was an empty string, otherwise true/false
+ * as determined by validation.
*/
validateEmail: function ( mailtxt ) {
var rfc5322Atext, rfc1034LdhStr, html5EmailRegexp;
return null;
}
- /**
- * HTML5 defines a string as valid e-mail address if it matches
- * the ABNF:
- * 1 * ( atext / "." ) "@" ldh-str 1*( "." ldh-str )
- * With:
- * - atext : defined in RFC 5322 section 3.2.3
- * - ldh-str : defined in RFC 1034 section 3.5
- *
- * (see STD 68 / RFC 5234 http://tools.ietf.org/html/std68):
- */
-
- /**
- * First, define the RFC 5322 'atext' which is pretty easy:
- * atext = ALPHA / DIGIT / ; Printable US-ASCII
- "!" / "#" / ; characters not including
- "$" / "%" / ; specials. Used for atoms.
- "&" / "'" /
- "*" / "+" /
- "-" / "/" /
- "=" / "?" /
- "^" / "_" /
- "`" / "{" /
- "|" / "}" /
- "~"
- */
+ // HTML5 defines a string as valid e-mail address if it matches
+ // the ABNF:
+ // 1 * ( atext / "." ) "@" ldh-str 1*( "." ldh-str )
+ // With:
+ // - atext : defined in RFC 5322 section 3.2.3
+ // - ldh-str : defined in RFC 1034 section 3.5
+ //
+ // (see STD 68 / RFC 5234 http://tools.ietf.org/html/std68)
+ // First, define the RFC 5322 'atext' which is pretty easy:
+ // atext = ALPHA / DIGIT / ; Printable US-ASCII
+ // "!" / "#" / ; characters not including
+ // "$" / "%" / ; specials. Used for atoms.
+ // "&" / "'" /
+ // "*" / "+" /
+ // "-" / "/" /
+ // "=" / "?" /
+ // "^" / "_" /
+ // "`" / "{" /
+ // "|" / "}" /
+ // "~"
rfc5322Atext = 'a-z0-9!#$%&\'*+\\-/=?^_`{|}~';
- /**
- * Next define the RFC 1034 'ldh-str'
- * <domain> ::= <subdomain> | " "
- * <subdomain> ::= <label> | <subdomain> "." <label>
- * <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
- * <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
- * <let-dig-hyp> ::= <let-dig> | "-"
- * <let-dig> ::= <letter> | <digit>
- */
+ // Next define the RFC 1034 'ldh-str'
+ // <domain> ::= <subdomain> | " "
+ // <subdomain> ::= <label> | <subdomain> "." <label>
+ // <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
+ // <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+ // <let-dig-hyp> ::= <let-dig> | "-"
+ // <let-dig> ::= <letter> | <digit>
rfc1034LdhStr = 'a-z0-9\\-';
html5EmailRegexp = new RegExp(
/**
* Note: borrows from IP::isIPv4
*
- * @param address string
- * @param allowBlock boolean
- * @return boolean
+ * @param {string} address
+ * @param {boolean} allowBlock
+ * @return {boolean}
*/
isIPv4Address: function ( address, allowBlock ) {
if ( typeof address !== 'string' ) {
/**
* Note: borrows from IP::isIPv6
*
- * @param address string
- * @param allowBlock boolean
- * @return boolean
+ * @param {string} address
+ * @param {boolean} allowBlock
+ * @return {boolean}
*/
isIPv6Address: function ( address, allowBlock ) {
if ( typeof address !== 'string' ) {
/**
* @file
* @ingroup Maintenance
- * @copyright Copyright © Wikimedia Deuschland, 2009
+ * @copyright Copyright © Wikimedia Deuschland, 2009
* @author Hallo Welt! Medienwerkstatt GmbH
* @author Markus Glaser, Dan Nessett, Priyanka Dhanda
* initial idea by Daniel Kinzler
require( __DIR__ . '/../maintenance/Maintenance.php' );
require_once( 'PHPUnit/Runner/Version.php' );
-if( version_compare( PHPUnit_Runner_Version::id(), '3.5.0', '>=' ) ) {
+if ( version_compare( PHPUnit_Runner_Version::id(), '3.5.0', '>=' ) ) {
# PHPUnit 3.5.0 introduced a nice autoloader based on class name
require_once( 'PHPUnit/Autoload.php' );
} else {
public function listBrowsers() {
$desc = "Available browsers:\n";
- foreach ($this->selenium->getAvailableBrowsers() as $k => $v) {
+ foreach ( $this->selenium->getAvailableBrowsers() as $k => $v ) {
$desc .= " $k => $v\n";
}
protected function startServer() {
if ( $this->seleniumServerExecPath == '' ) {
die ( "The selenium server exec path is not set in " .
- "selenium_settings.ini. Cannot start server \n" .
- "as requested - terminating RunSeleniumTests\n" );
+ "selenium_settings.ini. Cannot start server \n" .
+ "as requested - terminating RunSeleniumTests\n" );
}
$this->serverManager = new SeleniumServerManager( 'true',
$this->selenium->getPort(),
$configFile = $this->getOption( 'seleniumConfig', '' );
if ( strlen( $configFile ) > 0 ) {
- $this->output("Using Selenium Configuration file: " . $configFile . "\n");
+ $this->output( "Using Selenium Configuration file: " . $configFile . "\n" );
SeleniumConfig::getSeleniumSettings( $seleniumSettings,
$seleniumBrowsers,
$seleniumTestSuites,
$configFile );
} elseif ( !isset( $wgHooks['SeleniumSettings'] ) ) {
- $this->output("No command line, configuration file or configuration hook found.\n");
+ $this->output( "No command line, configuration file or configuration hook found.\n" );
SeleniumConfig::getSeleniumSettings( $seleniumSettings,
$seleniumBrowsers,
$seleniumTestSuites
- );
+ );
} else {
- $this->output("Using 'SeleniumSettings' hook for configuration.\n");
- wfRunHooks('SeleniumSettings', array( $seleniumSettings,
+ $this->output( "Using 'SeleniumSettings' hook for configuration.\n" );
+ wfRunHooks( 'SeleniumSettings', array( $seleniumSettings,
$seleniumBrowsers,
$seleniumTestSuites ) );
}
// State for starting/stopping the Selenium server has nothing to do with the Selenium
// class. Keep this state local to SeleniumTester class. Using getOption() is clumsy, but
// the Maintenance class does not have a setOption()
- if ( ! isset( $seleniumSettings['startserver'] ) ) $this->getOption( 'startserver', true );
- if ( ! isset( $seleniumSettings['stopserver'] ) ) $this->getOption( 'stopserver', true );
- if ( !isset( $seleniumSettings['seleniumserverexecpath'] ) ) $seleniumSettings['seleniumserverexecpath'] = '';
+ if ( !isset( $seleniumSettings['startserver'] ) ) {
+ $this->getOption( 'startserver', true );
+ }
+ if ( !isset( $seleniumSettings['stopserver'] ) ) {
+ $this->getOption( 'stopserver', true );
+ }
+ if ( !isset( $seleniumSettings['seleniumserverexecpath'] ) ) {
+ $seleniumSettings['seleniumserverexecpath'] = '';
+ }
$this->seleniumServerExecPath = $seleniumSettings['seleniumserverexecpath'];
//set reasonable defaults if we did not find the settings
- if ( !isset( $seleniumBrowsers ) ) $seleniumBrowsers = array ('firefox' => '*firefox');
- if ( !isset( $seleniumSettings['host'] ) ) $seleniumSettings['host'] = $wgServer . $wgScriptPath;
- if ( !isset( $seleniumSettings['port'] ) ) $seleniumSettings['port'] = '4444';
- if ( !isset( $seleniumSettings['wikiUrl'] ) ) $seleniumSettings['wikiUrl'] = 'http://localhost';
- if ( !isset( $seleniumSettings['username'] ) ) $seleniumSettings['username'] = '';
- if ( !isset( $seleniumSettings['userPassword'] ) ) $seleniumSettings['userPassword'] = '';
- if ( !isset( $seleniumSettings['testBrowser'] ) ) $seleniumSettings['testBrowser'] = 'firefox';
- if ( !isset( $seleniumSettings['jUnitLogFile'] ) ) $seleniumSettings['jUnitLogFile'] = false;
- if ( !isset( $seleniumSettings['runAgainstGrid'] ) ) $seleniumSettings['runAgainstGrid'] = false;
+ if ( !isset( $seleniumBrowsers ) ) {
+ $seleniumBrowsers = array( 'firefox' => '*firefox' );
+ }
+ if ( !isset( $seleniumSettings['host'] ) ) {
+ $seleniumSettings['host'] = $wgServer . $wgScriptPath;
+ }
+ if ( !isset( $seleniumSettings['port'] ) ) {
+ $seleniumSettings['port'] = '4444';
+ }
+ if ( !isset( $seleniumSettings['wikiUrl'] ) ) {
+ $seleniumSettings['wikiUrl'] = 'http://localhost';
+ }
+ if ( !isset( $seleniumSettings['username'] ) ) {
+ $seleniumSettings['username'] = '';
+ }
+ if ( !isset( $seleniumSettings['userPassword'] ) ) {
+ $seleniumSettings['userPassword'] = '';
+ }
+ if ( !isset( $seleniumSettings['testBrowser'] ) ) {
+ $seleniumSettings['testBrowser'] = 'firefox';
+ }
+ if ( !isset( $seleniumSettings['jUnitLogFile'] ) ) {
+ $seleniumSettings['jUnitLogFile'] = false;
+ }
+ if ( !isset( $seleniumSettings['runAgainstGrid'] ) ) {
+ $seleniumSettings['runAgainstGrid'] = false;
+ }
// Setup Selenium class
- $this->selenium = new Selenium( );
+ $this->selenium = new Selenium();
$this->selenium->setAvailableBrowsers( $seleniumBrowsers );
$this->selenium->setRunAgainstGrid( $this->getOption( 'runAgainstGrid', $seleniumSettings['runAgainstGrid'] ) );
$this->selenium->setUrl( $this->getOption( 'wikiUrl', $seleniumSettings['wikiUrl'] ) );
$this->selenium->setVerbose( $this->hasOption( 'verbose' ) );
$this->selenium->setJUnitLogFile( $this->getOption( 'jUnitLogFile', $seleniumSettings['jUnitLogFile'] ) );
- if( $this->hasOption( 'list-browsers' ) ) {
+ if ( $this->hasOption( 'list-browsers' ) ) {
$this->listBrowsers();
- exit(0);
+ exit( 0 );
}
if ( $this->hasOption( 'startserver' ) ) {
$this->startServer();
$this->runTests( $seleniumTestSuites );
- if ( $this->hasOption( 'stopserver' ) ) {
+ if ( $this->hasOption( 'stopserver' ) ) {
$this->stopServer();
}
}
public $regex = "";
private $savedGlobals = array();
+
/**
* Sets terminal colorization and diff/quick modes depending on OS and
* command-line options (--color and --quick).
$this->color = !wfIsWindows() && Maintenance::posix_isatty( 1 );
if ( isset( $options['color'] ) ) {
- switch( $options['color'] ) {
- case 'no':
- $this->color = false;
- break;
- case 'yes':
- default:
- $this->color = true;
- break;
+ switch ( $options['color'] ) {
+ case 'no':
+ $this->color = false;
+ break;
+ case 'yes':
+ default:
+ $this->color = true;
+ break;
}
}
$this->showProgress = !isset( $options['quiet'] );
$this->showFailure = !(
isset( $options['quiet'] )
- && ( isset( $options['record'] )
+ && ( isset( $options['record'] )
|| isset( $options['compare'] ) ) ); // redundant output
$this->showOutput = isset( $options['show-output'] );
$wgExtensionAssetsPath = '/extensions';
$wgThumbnailScriptPath = false;
$wgLockManagers = array( array(
- 'name' => 'fsLockManager',
- 'class' => 'FSLockManager',
+ 'name' => 'fsLockManager',
+ 'class' => 'FSLockManager',
'lockDirectory' => wfTempDir() . '/test-repo/lockdir',
), array(
- 'name' => 'nullLockManager',
- 'class' => 'NullLockManager',
+ 'name' => 'nullLockManager',
+ 'class' => 'NullLockManager',
) );
$wgLocalFileRepo = array(
- 'class' => 'LocalRepo',
- 'name' => 'local',
- 'url' => 'http://example.com/images',
- 'hashLevels' => 2,
+ 'class' => 'LocalRepo',
+ 'name' => 'local',
+ 'url' => 'http://example.com/images',
+ 'hashLevels' => 2,
'transformVia404' => false,
- 'backend' => new FSFileBackend( array(
- 'name' => 'local-backend',
+ 'backend' => new FSFileBackend( array(
+ 'name' => 'local-backend',
'lockManager' => 'fsLockManager',
'containerPaths' => array(
- 'local-public' => wfTempDir() . '/test-repo/public',
- 'local-thumb' => wfTempDir() . '/test-repo/thumb',
- 'local-temp' => wfTempDir() . '/test-repo/temp',
+ 'local-public' => wfTempDir() . '/test-repo/public',
+ 'local-thumb' => wfTempDir() . '/test-repo/thumb',
+ 'local-temp' => wfTempDir() . '/test-repo/temp',
'local-deleted' => wfTempDir() . '/test-repo/deleted',
)
) )
$wgRequest = $context->getRequest();
if ( $wgStyleDirectory === false ) {
- $wgStyleDirectory = "$IP/skins";
+ $wgStyleDirectory = "$IP/skins";
}
}
- public function setupRecorder ( $options ) {
+ public function setupRecorder( $options ) {
if ( isset( $options['record'] ) ) {
$this->recorder = new DbTestRecorder( $this );
$this->recorder->version = isset( $options['setversion'] ) ?
- $options['setversion'] : SpecialVersion::getVersion();
+ $options['setversion'] : SpecialVersion::getVersion();
} elseif ( isset( $options['compare'] ) ) {
$this->recorder = new DbTestPreviewer( $this );
} else {
* Remove last character if it is a newline
* @group utility
*/
- static public function chomp( $s ) {
+ public static function chomp( $s ) {
if ( substr( $s, -1 ) === "\n" ) {
return substr( $s, 0, -1 );
- }
- else {
+ } else {
return $s;
}
}
$this->teardownDatabase();
$this->recorder->report();
- } catch (DBError $e) {
+ } catch ( DBError $e ) {
echo $e->getMessage();
}
$this->recorder->end();
if ( isset( $opts['title'] ) ) {
$titleText = $opts['title'];
- }
- else {
+ } else {
$titleText = 'Parser test';
}
self::getOptionValue( 'wgLinkHolderBatchSize', $opts, 1000 );
$settings = array(
- 'wgServer' => 'http://Britney-Spears',
+ 'wgServer' => 'http://example.org',
'wgScript' => '/index.php',
'wgScriptPath' => '/',
'wgArticlePath' => '/wiki/$1',
'wgActionPaths' => array(),
'wgLockManagers' => array( array(
- 'name' => 'fsLockManager',
- 'class' => 'FSLockManager',
+ 'name' => 'fsLockManager',
+ 'class' => 'FSLockManager',
'lockDirectory' => $this->uploadDir . '/lockdir',
), array(
- 'name' => 'nullLockManager',
- 'class' => 'NullLockManager',
+ 'name' => 'nullLockManager',
+ 'class' => 'NullLockManager',
) ),
'wgLocalFileRepo' => array(
'class' => 'LocalRepo',
'url' => 'http://example.com/images',
'hashLevels' => 2,
'transformVia404' => false,
- 'backend' => new FSFileBackend( array(
- 'name' => 'local-backend',
+ 'backend' => new FSFileBackend( array(
+ 'name' => 'local-backend',
'lockManager' => 'fsLockManager',
'containerPaths' => array(
- 'local-public' => $this->uploadDir,
- 'local-thumb' => $this->uploadDir . '/thumb',
- 'local-temp' => $this->uploadDir . '/temp',
+ 'local-public' => $this->uploadDir,
+ 'local-thumb' => $this->uploadDir . '/thumb',
+ 'local-temp' => $this->uploadDir . '/temp',
'local-deleted' => $this->uploadDir . '/delete',
)
) )
'wgVariantArticlePath' => false,
'wgGroupPermissions' => array( '*' => array(
'createaccount' => true,
- 'read' => true,
- 'edit' => true,
- 'createpage' => true,
- 'createtalk' => true,
+ 'read' => true,
+ 'edit' => true,
+ 'createpage' => true,
+ 'createtalk' => true,
) ),
'wgNamespaceProtection' => array( NS_MEDIAWIKI => 'editinterface' ),
'wgDefaultExternalStore' => array(),
$tables = array( 'user', 'user_properties', 'user_former_groups', 'page', 'page_restrictions',
'protected_titles', 'revision', 'text', 'pagelinks', 'imagelinks',
'categorylinks', 'templatelinks', 'externallinks', 'langlinks', 'iwlinks',
- 'site_stats', 'hitcounter', 'ipblocks', 'image', 'oldimage',
+ 'site_stats', 'hitcounter', 'ipblocks', 'image', 'oldimage',
'recentchanges', 'watchlist', 'interwiki', 'logging',
'querycache', 'objectcache', 'job', 'l10n_cache', 'redirect', 'querycachetwo',
'archive', 'user_groups', 'page_props', 'category', 'msg_resource', 'msg_resource_links'
# Anonymous user
$this->db->insert( 'user', array(
- 'user_id' => 0,
- 'user_name' => 'Anonymous' ) );
+ 'user_id' => 0,
+ 'user_name' => 'Anonymous' ) );
}
# Hack: insert a few Wikipedia in-project interwiki prefixes,
# for testing inter-language links
$this->db->insert( 'interwiki', array(
array( 'iw_prefix' => 'wikipedia',
- 'iw_url' => 'http://en.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 0 ),
+ 'iw_url' => 'http://en.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 0 ),
array( 'iw_prefix' => 'meatball',
- 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 0 ),
+ 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 0 ),
array( 'iw_prefix' => 'zh',
- 'iw_url' => 'http://zh.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
+ 'iw_url' => 'http://zh.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
array( 'iw_prefix' => 'es',
- 'iw_url' => 'http://es.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
+ 'iw_url' => 'http://es.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
array( 'iw_prefix' => 'fr',
- 'iw_url' => 'http://fr.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
+ 'iw_url' => 'http://fr.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
array( 'iw_prefix' => 'ru',
- 'iw_url' => 'http://ru.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
- ) );
+ 'iw_url' => 'http://ru.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
+ ) );
# Update certain things in site_stats
$this->db->insert( 'site_stats', array( 'ss_row_id' => 1, 'ss_images' => 2, 'ss_good_articles' => 1 ) );
$user = User::createNew( 'WikiSysop' );
$image = wfLocalFile( Title::makeTitle( NS_FILE, 'Foobar.jpg' ) );
$image->recordUpload2( '', 'Upload of some lame file', 'Some lame file', array(
- 'size' => 12345,
- 'width' => 1941,
- 'height' => 220,
- 'bits' => 24,
- 'media_type' => MEDIATYPE_BITMAP,
- 'mime' => 'image/jpeg',
- 'metadata' => serialize( array() ),
- 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
- 'fileExists' => true
- ), $this->db->timestamp( '20010115123500' ), $user );
+ 'size' => 12345,
+ 'width' => 1941,
+ 'height' => 220,
+ 'bits' => 24,
+ 'media_type' => MEDIATYPE_BITMAP,
+ 'mime' => 'image/jpeg',
+ 'metadata' => serialize( array() ),
+ 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
+ 'fileExists' => true
+ ), $this->db->timestamp( '20010115123500' ), $user );
# This image will be blacklisted in [[MediaWiki:Bad image list]]
$image = wfLocalFile( Title::makeTitle( NS_FILE, 'Bad.jpg' ) );
$image->recordUpload2( '', 'zomgnotcensored', 'Borderline image', array(
- 'size' => 12345,
- 'width' => 320,
- 'height' => 240,
- 'bits' => 24,
- 'media_type' => MEDIATYPE_BITMAP,
- 'mime' => 'image/jpeg',
- 'metadata' => serialize( array() ),
- 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
- 'fileExists' => true
- ), $this->db->timestamp( '20010115123500' ), $user );
+ 'size' => 12345,
+ 'width' => 320,
+ 'height' => 240,
+ 'bits' => 24,
+ 'media_type' => MEDIATYPE_BITMAP,
+ 'mime' => 'image/jpeg',
+ 'metadata' => serialize( array() ),
+ 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
+ 'fileExists' => true
+ ), $this->db->timestamp( '20010115123500' ), $user );
}
public function teardownDatabase() {
$this->databaseSetupDone = false;
if ( $this->useTemporaryTables ) {
- if( $this->db->getType() == 'sqlite' ) {
+ if ( $this->db->getType() == 'sqlite' ) {
# Under SQLite the searchindex table is virtual and need
# to be explicitly destroyed. See bug 29912
# See also MediaWikiTestCase::destroyDB()
$this->db->query( $sql );
}
- if ( $this->db->getType() == 'oracle' )
+ if ( $this->db->getType() == 'oracle' ) {
$this->db->query( 'BEGIN FILL_WIKI_INFO; END;' );
+ }
$this->teardownGlobals();
}
// delete the files first, then the dirs.
self::deleteFiles(
- array (
+ array(
"$dir/3/3a/Foobar.jpg",
"$dir/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg",
"$dir/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg",
);
self::deleteDirs(
- array (
+ array(
"$dir/3/3a",
"$dir/3",
"$dir/thumb/6/65",
$outfile = "$prefix-$outFileTail";
$this->dumpToFile( $output, $outfile );
- $shellInfile = wfEscapeShellArg($infile);
- $shellOutfile = wfEscapeShellArg($outfile);
+ $shellInfile = wfEscapeShellArg( $infile );
+ $shellOutfile = wfEscapeShellArg( $outfile );
global $wgDiff3;
// we assume that people with diff3 also have usual diff
return preg_replace(
array( '/^(-.*)$/m', '/^(\+.*)$/m' ),
array( $this->term->color( 34 ) . '$1' . $this->term->reset(),
- $this->term->color( 31 ) . '$1' . $this->term->reset() ),
+ $this->term->color( 31 ) . '$1' . $this->term->reset() ),
$text );
}
* @param $line Integer: the input line number, for reporting errors
* @param $ignoreDuplicate Boolean: whether to silently ignore duplicate pages
*/
- static public function addArticle( $name, $text, $line = 'unknown', $ignoreDuplicate = '' ) {
+ public static function addArticle( $name, $text, $line = 'unknown', $ignoreDuplicate = '' ) {
global $wgCapitalLinks;
$oldCapitalLinks = $wgCapitalLinks;
public function requireHook( $name ) {
global $wgParser;
- $wgParser->firstCallInit( ); // make sure hooks are loaded.
+ $wgParser->firstCallInit(); // make sure hooks are loaded.
if ( isset( $wgParser->mTagHooks[$name] ) ) {
$this->hooks[$name] = $wgParser->mTagHooks[$name];
public function requireFunctionHook( $name ) {
global $wgParser;
- $wgParser->firstCallInit( ); // make sure hooks are loaded.
+ $wgParser->firstCallInit(); // make sure hooks are loaded.
if ( isset( $wgParser->mFunctionHooks[$name] ) ) {
$this->functionHooks[$name] = $wgParser->mFunctionHooks[$name];
private function wellFormed( $text ) {
$html =
Sanitizer::hackDocType() .
- '<html>' .
- $text .
- '</html>';
+ '<html>' .
+ $text .
+ '</html>';
$parser = xml_parser_create( "UTF-8" );
</p>
!! end
+!! test
+Parsing an URL
+!! input
+http://fr.wikipedia.org/wiki/🍺
+<!-- EasterEgg we love beer, better be able be able to link to it -->
+!! result
+<p><a rel="nofollow" class="external free" href="http://fr.wikipedia.org/wiki/🍺">http://fr.wikipedia.org/wiki/🍺</a>
+</p>
+!! end
+
!! test
Simple list
!! input
</p>
!! end
+!!test
+Text in square brackets that is not a link should parse as text
+!!input
+[foo]
+[{{echo|foo}}]
+[url={{echo|foo}}]
+[url=http://example.com]
+!!result
+<p>[foo]
+[foo]
+[url=foo]
+[url=<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>]
+</p>
+!!end
+
!! test
URL-encoding in URL functions (single parameter)
!! input
!! input
{{SERVER}}
!! result
-<p><a rel="nofollow" class="external free" href="http://Britney-Spears">http://Britney-Spears</a>
+<p><a rel="nofollow" class="external free" href="http://example.org">http://example.org</a>
</p>
!! end
!! input
{{SERVERNAME}}
!! result
-<p>Britney-Spears
+<p>example.org
</p>
!! end
</p>
!!end
+!!test
+Parsoid: Image caption containing leading space
+(The leading space should not trigger nowiki escaping in wt2wt mode)
+!! input
+[[Image:Foobar.jpg|thumb| bar]]
+!! result
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>bar</div></div></div>
+
+!!end
!! test
Bug 3090: External links other than http: in image captions
<meta http-equiv="refresh" content="5">
<meta itemprop="hello" content="5" />
</p>
- <link itemprop="hello" href="http://Britney-Spears" />
- <link rel="stylesheet" href="<a rel="nofollow" class="external free" href="http://Britney-Spears">http://Britney-Spears</a>">
- <link itemprop="hello" href="http://Britney-Spears" />
+ <link itemprop="hello" href="http://example.org" />
+ <link rel="stylesheet" href="<a rel="nofollow" class="external free" href="http://example.org">http://example.org</a>">
+ <link itemprop="hello" href="http://example.org" />
</div>
!! end
</p>
!! end
+!! test
+Check noCommafy in formatNum
+!! options
+language=be-tarask
+!! input
+{{formatnum:123456.78}}
+{{formatnum:123456.78|NOSEP}}
+!! result
+<p>123 456,78
+123456.78
+</p>
+!! end
+
!! test
Strip marker in grammar
!! options
static function dumpHook( $in, $argv ) {
return "<pre>\n" .
- var_export( $in, true ) . "\n" .
- var_export( $argv, true ) . "\n" .
- "</pre>";
+ var_export( $in, true ) . "\n" .
+ var_export( $argv, true ) . "\n" .
+ "</pre>";
}
static function staticTagHook( $in, $argv, $parser ) {
- if ( ! count( $argv ) ) {
+ if ( !count( $argv ) ) {
$parser->static_tag_buf = $in;
return '';
} elseif ( count( $argv ) === 1 && isset( $argv['action'] )
- && $argv['action'] === 'flush' && $in === null )
- {
+ && $argv['action'] === 'flush' && $in === null
+ ) {
// Clear the buffer, we probably don't need to
if ( isset( $parser->static_tag_buf ) ) {
$tmp = $parser->static_tag_buf;
}
$parser->static_tag_buf = null;
return $tmp;
- } else
- // wtf?
+ } else { // wtf?
return
"\nCall this extension as <statictag>string</statictag> or as" .
" <statictag action=flush/>, not in any other way.\n" .
"text: " . var_export( $in, true ) . "\n" .
"argv: " . var_export( $argv, true ) . "\n";
+ }
}
}
# refer to $wgTitle directly, but instead use the title
# passed to it.
$wgTitle = Title::newFromText( 'Parser test script do not use' );
-$tester = new ParserTest($options);
+$tester = new ParserTest( $options );
if ( isset( $options['file'] ) ) {
$files = array( $options['file'] );
parent::setUp();
if ( $wgLanguageCode != $wgContLang->getCode() ) {
- throw new MWException("Error in MediaWikiLangTestCase::setUp(): " .
+ throw new MWException( "Error in MediaWikiLangTestCase::setUp(): " .
"\$wgLanguageCode ('$wgLanguageCode') is different from " .
"\$wgContLang->getCode() (" . $wgContLang->getCode() . ")" );
}
'file=' => false,
'use-filebackend=' => false,
'use-bagostuff=' => false,
+ 'use-jobqueue=' => false,
'keep-uploads' => false,
'use-normal-tables' => false,
'reuse-db' => false,
);
public function __construct() {
- foreach( self::$additionalOptions as $option => $default ) {
+ foreach ( self::$additionalOptions as $option => $default ) {
$this->longOptions[$option] = $option . 'Handler';
}
public static function main( $exit = true ) {
$command = new self;
- if( wfIsWindows() ) {
+ if ( wfIsWindows() ) {
# Windows does not come anymore with ANSI.SYS loaded by default
# PHPUnit uses the suite.xml parameters to enable/disable colors
# which can be then forced to be enabled with --colors.
# See bug 32022
set_include_path(
__DIR__
- .PATH_SEPARATOR
- . get_include_path()
+ . PATH_SEPARATOR
+ . get_include_path()
);
- $command->run($_SERVER['argv'], $exit);
+ $command->run( $_SERVER['argv'], $exit );
}
public function __call( $func, $args ) {
- if( substr( $func, -7 ) == 'Handler' ) {
- if( is_null( $args[0] ) ) $args[0] = true; //Booleans
- self::$additionalOptions[substr( $func, 0, -7 ) ] = $args[0];
+ if ( substr( $func, -7 ) == 'Handler' ) {
+ if ( is_null( $args[0] ) ) {
+ $args[0] = true;
+ } //Booleans
+ self::$additionalOptions[substr( $func, 0, -7 )] = $args[0];
}
}
$needsResetDB = false;
$logName = get_class( $this ) . '::' . $this->getName( false );
- if( $this->needsDB() ) {
+ if ( $this->needsDB() ) {
// set up a DB connection for this test to use
self::$useTemporaryTables = !$this->getCliArg( 'use-normal-tables' );
- self::$reuseDB = $this->getCliArg('reuse-db');
+ self::$reuseDB = $this->getCliArg( 'reuse-db' );
$this->db = wfGetDB( DB_MASTER );
$this->checkDbIsSupported();
- if( !self::$dbSetup ) {
+ if ( !self::$dbSetup ) {
wfProfileIn( $logName . ' (clone-db)' );
// switch to a temporary clone of the database
parent::run( $result );
wfProfileOut( $logName );
- if( $needsResetDB ) {
+ if ( $needsResetDB ) {
wfProfileIn( $logName . ' (reset-db)' );
$this->resetDB();
wfProfileOut( $logName . ' (reset-db)' );
if ( $this->needsDB() && $this->db ) {
// Clean up open transactions
- while( $this->db->trxLevel() > 0 ) {
+ while ( $this->db->trxLevel() > 0 ) {
$this->db->rollback();
}
if ( $this->needsDB() && $this->db ) {
// Clean up open transactions
- while( $this->db->trxLevel() > 0 ) {
+ while ( $this->db->trxLevel() > 0 ) {
$this->db->rollback();
}
protected function setMwGlobals( $pairs, $value = null ) {
// Normalize (string, value) to an array
- if( is_string( $pairs ) ) {
+ if ( is_string( $pairs ) ) {
$pairs = array( $pairs => $value );
}
# Insert 0 user to prevent FK violations
# Anonymous user
$this->db->insert( 'user', array(
- 'user_id' => 0,
- 'user_name' => 'Anonymous' ), __METHOD__, array( 'IGNORE' ) );
+ 'user_id' => 0,
+ 'user_name' => 'Anonymous' ), __METHOD__, array( 'IGNORE' ) );
# Insert 0 page to prevent FK violations
# Blank page
* Empty all tables so they can be repopulated for tests
*/
private function resetDB() {
- if( $this->db ) {
- if ( $this->db->getType() == 'oracle' ) {
+ if ( $this->db ) {
+ if ( $this->db->getType() == 'oracle' ) {
if ( self::$useTemporaryTables ) {
wfGetLB()->closeAll();
$this->db = wfGetDB( DB_MASTER );
} else {
- foreach( $this->tablesUsed as $tbl ) {
- if( $tbl == 'interwiki') continue;
- $this->db->query( 'TRUNCATE TABLE '.$this->db->tableName($tbl), __METHOD__ );
+ foreach ( $this->tablesUsed as $tbl ) {
+ if ( $tbl == 'interwiki' ) {
+ continue;
+ }
+ $this->db->query( 'TRUNCATE TABLE ' . $this->db->tableName( $tbl ), __METHOD__ );
}
}
} else {
- foreach( $this->tablesUsed as $tbl ) {
- if( $tbl == 'interwiki' || $tbl == 'user' ) continue;
+ foreach ( $this->tablesUsed as $tbl ) {
+ if ( $tbl == 'interwiki' || $tbl == 'user' ) {
+ continue;
+ }
$this->db->delete( $tbl, '*', __METHOD__ );
}
}
);
if ( method_exists( $this->suite, $func ) ) {
- return call_user_func_array( array( $this->suite, $func ), $args);
+ return call_user_func_array( array( $this->suite, $func ), $args );
} elseif ( isset( $compatibility[$func] ) ) {
- return call_user_func_array( array( $this, $compatibility[$func] ), $args);
+ return call_user_func_array( array( $this, $compatibility[$func] ), $args );
} else {
throw new MWException( "Called non-existant $func method on "
. get_class( $this ) );
}
protected function checkDbIsSupported() {
- if( !in_array( $this->db->getType(), $this->supportedDBs ) ) {
+ if ( !in_array( $this->db->getType(), $this->supportedDBs ) ) {
throw new MWException( $this->db->getType() . " is not currently supported for unit testing." );
}
}
public function getCliArg( $offset ) {
- if( isset( MediaWikiPHPUnitCommand::$additionalOptions[$offset] ) ) {
+ if ( isset( MediaWikiPHPUnitCommand::$additionalOptions[$offset] ) ) {
return MediaWikiPHPUnitCommand::$additionalOptions[$offset];
}
protected function assertSelect( $table, $fields, $condition, array $expectedRows ) {
if ( !$this->needsDB() ) {
throw new MWException( 'When testing database state, the test cases\'s needDB()' .
- ' method should return true. Use @group Database or $this->tablesUsed.');
+ ' method should return true. Use @group Database or $this->tablesUsed.' );
}
$db = wfGetDB( DB_SLAVE );
*/
protected function arrayWrap( array $elements ) {
return array_map(
- function( $element ) {
+ function ( $element ) {
return array( $element );
},
$elements
* @param String $actual HTML on oneline
* @param String $msg Optional message
*/
- protected function assertHTMLEquals( $expected, $actual, $msg='' ) {
+ protected function assertHTMLEquals( $expected, $actual, $msg = '' ) {
$expected = str_replace( '>', ">\n", $expected );
- $actual = str_replace( '>', ">\n", $actual );
+ $actual = str_replace( '>', ">\n", $actual );
$this->assertEquals( $expected, $actual, $msg );
}
protected function objectAssociativeSort( array &$array ) {
uasort(
$array,
- function( $a, $b ) {
+ function ( $a, $b ) {
return serialize( $a ) > serialize( $b ) ? 1 : -1;
}
);
protected function assertTypeOrValue( $type, $actual, $value = false, $message = '' ) {
if ( $actual === $value ) {
$this->assertTrue( true, $message );
- }
- else {
+ } else {
$this->assertType( $type, $actual, $message );
}
}
protected function assertType( $type, $actual, $message = '' ) {
if ( class_exists( $type ) || interface_exists( $type ) ) {
$this->assertInstanceOf( $type, $actual, $message );
- }
- else {
+ } else {
$this->assertInternalType( $type, $actual, $message );
}
}
$namespaces = array_diff( $namespaces, array(
NS_FILE, NS_CATEGORY, NS_MEDIAWIKI, NS_USER // don't mess with magic namespaces
- ));
+ ) );
$talk = array_filter( $namespaces, function ( $ns ) {
return MWNamespace::isTalk( $ns );
// check default content model of each namespace
foreach ( $namespaces as $ns ) {
if ( !isset( $wgNamespaceContentModels[$ns] ) ||
- $wgNamespaceContentModels[$ns] === CONTENT_MODEL_WIKITEXT ) {
+ $wgNamespaceContentModels[$ns] === CONTENT_MODEL_WIKITEXT
+ ) {
$wikitextNS = $ns;
return $wikitextNS;
$haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
wfRestoreWarnings();
- if( !$haveDiff3 ) {
+ if ( !$haveDiff3 ) {
$this->markTestSkipped( "Skip test, since diff3 is not configured" );
}
}
protected function checkHasGzip() {
static $haveGzip;
- if( $haveGzip === null ) {
+ if ( $haveGzip === null ) {
$retval = null;
wfShellExec( 'gzip -V', $retval );
- $haveGzip = ($retval === 0);
+ $haveGzip = ( $retval === 0 );
}
- if( !$haveGzip ) {
+ if ( !$haveGzip ) {
$this->markTestSkipped( "Skip test, requires the gzip utility in PATH" );
}
*/
protected function checkPHPExtension( $extName ) {
$loaded = extension_loaded( $extName );
- if( ! $loaded ) {
+ if ( !$loaded ) {
$this->markTestSkipped( "PHP extension '$extName' is not loaded, skipping." );
}
return $loaded;
try {
call_user_func( $code );
- }
- catch ( Exception $pokemons ) {
+ } catch ( Exception $pokemons ) {
// Gotta Catch 'Em All!
}
$results = null;
$exitCode = null;
- exec($finder, $results, $exitCode);
+ exec( $finder, $results, $exitCode );
$this->assertEquals(
0,
array( $this, 'filterSuites' )
);
$strip = strlen( $rootPath ) - 1;
- foreach( $results as $k => $v) {
+ foreach ( $results as $k => $v ) {
$results[$k] = substr( $v, $strip );
}
$this->assertEquals(
// Output a notice when running with older versions of PHPUnit
if ( version_compare( PHPUnit_Runner_Version::id(), "3.6.7", "<" ) ) {
- echo <<<EOF
+ echo <<<EOF
********************************************************************************
These tests run best with version PHPUnit 3.6.7 or better. Earlier versions may
<?php
$result = array (
- 'xmp-exif' =>
- array (
- 'CameraOwnerName' => 'Me!',
- ),
- 'xmp-general' =>
- array (
- 'LicenseUrl' => 'http://creativecommons.com/cc-by-2.9',
- 'ImageDescription' =>
- array (
- 'x-default' => 'Test image for the cc: xmp: xmpRights: namespaces in xmp',
- '_type' => 'lang',
- ),
- 'ObjectName' =>
- array (
- 'x-default' => 'xmp core/xmp rights/cc ns test',
- '_type' => 'lang',
- ),
- 'DateTimeDigitized' => '2005:04:03',
- 'Software' => 'The one true editor: Vi (ok i used gimp)',
- 'Identifier' =>
- array (
- 0 => 'http://example.com/identifierurl',
- 1 => 'urn:sha1:342524abcdef',
- '_type' => 'ul',
- ),
- 'Label' => 'Test image',
- 'DateTimeMetadata' => '2011:05:12',
- 'DateTime' => '2007:03:04 06:34:10',
- 'Nickname' => 'My little xmp test image',
- 'Rating' => '5',
- 'RightsCertificate' => 'http://example.com/rights-certificate/',
- 'Copyrighted' => 'True',
- 'CopyrightOwner' =>
- array (
- 0 => 'Bawolff is copyright owner',
- '_type' => 'ul',
- ),
- 'UsageTerms' =>
- array (
- 'x-default' => 'do whatever you want',
- 'en-gb' => 'Do whatever you want in british english',
- '_type' => 'lang',
- ),
- 'WebStatement' => 'http://example.com/web_statement',
- ),
- 'xmp-deprecated' =>
- array (
- 'Identifier' => 'http://example.com/identifierurl/wrong',
- ),
+ 'xmp-exif' =>
+ array (
+ 'CameraOwnerName' => 'Me!',
+ ),
+ 'xmp-general' =>
+ array (
+ 'LicenseUrl' => 'http://creativecommons.com/cc-by-2.9',
+ 'ImageDescription' =>
+ array (
+ 'x-default' => 'Test image for the cc: xmp: xmpRights: namespaces in xmp',
+ '_type' => 'lang',
+ ),
+ 'ObjectName' =>
+ array (
+ 'x-default' => 'xmp core/xmp rights/cc ns test',
+ '_type' => 'lang',
+ ),
+ 'DateTimeDigitized' => '2005:04:03',
+ 'Software' => 'The one true editor: Vi (ok i used gimp)',
+ 'Identifier' =>
+ array (
+ 0 => 'http://example.com/identifierurl',
+ 1 => 'urn:sha1:342524abcdef',
+ '_type' => 'ul',
+ ),
+ 'Label' => 'Test image',
+ 'DateTimeMetadata' => '2011:05:12',
+ 'DateTime' => '2007:03:04 06:34:10',
+ 'Nickname' => 'My little xmp test image',
+ 'Rating' => '5',
+ 'RightsCertificate' => 'http://example.com/rights-certificate/',
+ 'Copyrighted' => 'True',
+ 'CopyrightOwner' =>
+ array (
+ 0 => 'Bawolff is copyright owner',
+ '_type' => 'ul',
+ ),
+ 'UsageTerms' =>
+ array (
+ 'x-default' => 'do whatever you want',
+ 'en-gb' => 'Do whatever you want in british english',
+ '_type' => 'lang',
+ ),
+ 'WebStatement' => 'http://example.com/web_statement',
+ ),
+ 'xmp-deprecated' =>
+ array (
+ 'Identifier' => 'http://example.com/identifierurl/wrong',
+ ),
);
try {
$this->assertTrue( $dom->schemaValidate( "../../docs/export-" . $version . ".xsd" ),
"schemaValidate has found an error" );
- } catch( Exception $e ) {
+ } catch ( Exception $e ) {
$this->fail( "xml not valid against xsd: " . $e->getMessage() );
}
}
$this->article->ext_someNewProperty = 12;
$this->assertEquals( 12, $this->article->ext_someNewProperty,
"Article get/set magic on new field" );
-
+
$this->article->ext_someNewProperty = -8;
$this->assertEquals( -8, $this->article->ext_someNewProperty,
"Article get/set magic on update to new field" );
$title = Title::makeTitle( NS_FILE, 'Someimage.png' );
$page = WikiPage::factory( $title );
$this->assertEquals( 'WikiFilePage', get_class( $page ) );
-
+
$title = Title::makeTitle( NS_CATEGORY, 'SomeCategory' );
$page = WikiPage::factory( $title );
$this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
-
+
$title = Title::makeTitle( NS_MAIN, 'SomePage' );
$page = WikiPage::factory( $title );
$this->assertEquals( 'WikiPage', get_class( $page ) );
function dumpBlocks() {
$v = $this->db->query( 'SELECT * FROM unittest_ipblocks' );
print "Got " . $v->numRows() . " rows. Full dump follow:\n";
- foreach( $v as $row ) {
+ foreach ( $v as $row ) {
print_r( $row );
}
}
function testInitializerFunctionsReturnCorrectBlock() {
// $this->dumpBlocks();
- $this->assertTrue( $this->block->equals( Block::newFromTarget('UTBlockee') ), "newFromTarget() returns the same block as the one that was made");
+ $this->assertTrue( $this->block->equals( Block::newFromTarget( 'UTBlockee' ) ), "newFromTarget() returns the same block as the one that was made" );
- $this->assertTrue( $this->block->equals( Block::newFromID( $this->blockId ) ), "newFromID() returns the same block as the one that was made");
+ $this->assertTrue( $this->block->equals( Block::newFromID( $this->blockId ) ), "newFromID() returns the same block as the one that was made" );
}
function testBug26425BlockTimestampDefaultsToTime() {
// delta to stop one-off errors when things happen to go over a second mark.
$delta = abs( $this->madeAt - $this->block->mTimestamp );
- $this->assertLessThan( 2, $delta, "If no timestamp is specified, the block is recorded as time()");
+ $this->assertLessThan( 2, $delta, "If no timestamp is specified, the block is recorded as time()" );
}
$this->hideDeprecated( 'Block::load' );
$uid = User::idFromName( 'UTBlockee' );
- $this->assertTrue( ($uid > 0), 'Must be able to look up the target user during tests' );
+ $this->assertTrue( ( $uid > 0 ), 'Must be able to look up the target user during tests' );
$block = new Block();
$ok = $block->load( $vagueTarget, $uid );
* @dataProvider provideBug29116Data
*/
function testBug29116NewFromTargetWithEmptyIp( $vagueTarget ) {
- $block = Block::newFromTarget('UTBlockee', $vagueTarget);
+ $block = Block::newFromTarget( 'UTBlockee', $vagueTarget );
$this->assertTrue( $this->block->equals( $block ), "newFromTarget() returns the same block as the one that was made when given empty vagueTarget param " . var_export( $vagueTarget, true ) );
}
* wrapper around assertEquals() which calls rrtrim() to normalize the
* expected and actual texts.
*/
- function assertEditedTextEquals( $expected, $actual, $msg='' ) {
- return $this->assertEquals( rtrim($expected), rtrim($actual), $msg );
+ function assertEditedTextEquals( $expected, $actual, $msg = '' ) {
+ return $this->assertEquals( rtrim( $expected ), rtrim( $actual ), $msg );
}
/**
}
public static function provideSectionEdit() {
- $text =
-'Intro
+ $text = 'Intro
== one ==
first section.
second section.
';
- $sectionOne =
-'== one ==
+ $sectionOne = '== one ==
hello
';
- $newSection =
-'== new section ==
+ $newSection = '== new section ==
hello
';
- $textWithNewSectionOne = preg_replace( '/== one ==.*== two ==/ms',
- "$sectionOne\n== two ==", $text );
+ $textWithNewSectionOne = preg_replace(
+ '/== one ==.*== two ==/ms',
+ "$sectionOne\n== two ==", $text
+ );
$textWithNewSectionAdded = "$text\n$newSection";
);
// see whether it makes a difference who did the base edit
- $testsWithAdam = array_map( function( $test ) {
+ $testsWithAdam = array_map( function ( $test ) {
$test[0] = 'Adam'; // change base edit user
return $test;
}, $tests );
- $testsWithBerta = array_map( function( $test ) {
+ $testsWithBerta = array_map( function ( $test ) {
$test[0] = 'Berta'; // change base edit user
return $test;
}, $tests );
* @dataProvider provideAutoMerge
*/
public function testAutoMerge( $baseUser, $text, $adamsEdit, $bertasEdit,
- $expectedCode, $expectedText, $message = null
+ $expectedCode, $expectedText, $message = null
) {
$this->checkHasDiff3();
);
$page = $this->assertEdit( 'EditPageTest_testAutoMerge', null,
- $baseUser, $baseEdit, null, null, __METHOD__ );
+ $baseUser, $baseEdit, null, null, __METHOD__ );
$this->forceRevisionDate( $page, '20120101000000' );
'wgAlwaysUseTidy' => false,
'wgCleanSignatures' => true,
) );
-
+
$this->options = ParserOptions::newFromUserAndLang( new User, $contLang );
$this->options->setTemplateCallback( array( __CLASS__, 'statelessFetchTemplate' ) );
$this->parser = new Parser;
MagicWord::clearCache();
}
- // Bug 8689 - Long numeric lines kill the parser
+ /**
+ * Bug 8689 - Long numeric lines kill the parser
+ *
+ * @group Database
+ */
function testBug8689() {
global $wgUser;
$longLine = '1.' . str_repeat( '1234567890', 100000 ) . "\n";
-
+
$t = Title::newFromText( 'Unit test' );
$options = ParserOptions::newFromUser( $wgUser );
$this->assertEquals( "<p>$longLine</p>",
$this->parser->parse( $longLine, $t, $options )->getText() );
}
-
- /* Test the parser entry points */
+
+ /**
+ * Test the parser entry points
+ *
+ * @group Database
+ */
function testParse() {
$title = Title::newFromText( __FUNCTION__ );
$parserOutput = $this->parser->parse( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options );
$this->assertEquals( "<p>Test\nContent of <i>Template:Foo</i>\nContent of <i>Template:Bar</i>\n</p>", $parserOutput->getText() );
}
-
+
+ /**
+ * @group Database
+ */
function testPreSaveTransform() {
global $wgUser;
$title = Title::newFromText( __FUNCTION__ );
$this->assertEquals( "Test\nContent of ''Template:Foo''\n{{Bar}}", $outputText );
}
-
+
+ /**
+ * @group Database
+ */
function testPreprocess() {
$title = Title::newFromText( __FUNCTION__ );
$outputText = $this->parser->preprocess( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options );
-
+
$this->assertEquals( "Test\nContent of ''Template:Foo''\nContent of ''Template:Bar''", $outputText );
}
-
+
/**
* cleanSig() makes all templates substs and removes tildes
*/
function testCleanSig() {
$title = Title::newFromText( __FUNCTION__ );
$outputText = $this->parser->cleanSig( "{{Foo}} ~~~~" );
-
+
$this->assertEquals( "{{SUBST:Foo}} ", $outputText );
}
$title = Title::newFromText( __FUNCTION__ );
$outputText = $this->parser->cleanSig( "{{Foo}} ~~~~" );
-
+
$this->assertEquals( "{{Foo}} ~~~~", $outputText );
}
-
+
/**
* cleanSigInSig() just removes tildes
* @dataProvider provideStringsForCleanSigInSig
*/
function testCleanSigInSig( $in, $out ) {
- $this->assertEquals( Parser::cleanSigInSig( $in), $out );
+ $this->assertEquals( Parser::cleanSigInSig( $in ), $out );
}
-
+
public static function provideStringsForCleanSigInSig() {
return array(
array( "{{Foo}} ~~~~", "{{Foo}} " ),
array( "~~~~~", "" ),
);
}
-
+
function testGetSection() {
$outputText2 = $this->parser->getSection( "Section 0\n== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2\n== Heading 3 ==\nSection 3\n", 2 );
$outputText1 = $this->parser->getSection( "Section 0\n== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2\n== Heading 3 ==\nSection 3\n", 1 );
-
+
$this->assertEquals( "=== Heading 2 ===\nSection 2", $outputText2 );
$this->assertEquals( "== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2", $outputText1 );
}
-
+
function testReplaceSection() {
$outputText = $this->parser->replaceSection( "Section 0\n== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2\n== Heading 3 ==\nSection 3\n", 1, "New section 1" );
-
+
$this->assertEquals( "Section 0\nNew section 1\n\n== Heading 3 ==\nSection 3", $outputText );
}
-
+
/**
* Templates and comments are not affected, but noinclude/onlyinclude is.
*/
function testGetPreloadText() {
$title = Title::newFromText( __FUNCTION__ );
$outputText = $this->parser->getPreloadText( "{{Foo}}<noinclude> censored</noinclude> information <!-- is very secret -->", $title, $this->options );
-
+
$this->assertEquals( "{{Foo}} information <!-- is very secret -->", $outputText );
}
-
- static function statelessFetchTemplate( $title, $parser=false ) {
+
+ static function statelessFetchTemplate( $title, $parser = false ) {
$text = "Content of ''" . $title->getFullText() . "''";
$deps = array();
-
+
return array(
'text' => $text,
'finalTitle' => $title,
*/
function testTrackingCategory() {
$title = Title::newFromText( __FUNCTION__ );
- $catName = wfMessage( 'broken-file-category' )->inContentLanguage()->text();
+ $catName = wfMessage( 'broken-file-category' )->inContentLanguage()->text();
$cat = Title::makeTitleSafe( NS_CATEGORY, $catName );
$expected = array( $cat->getDBkey() );
$parserOutput = $this->parser->parse( "[[file:nonexistent]]", $title, $this->options );
$result = $parserOutput->getCategoryLinks();
$this->assertEmpty( $result );
}
- }
+}
}
public function testAddStringOption() {
- $this->object->add( 'foo', 'string value' );
+ $this->object->add( 'foo', 'string value' );
$this->assertEquals(
array(
'foo' => array(
- 'default' => 'string value',
+ 'default' => 'string value',
'consumed' => false,
- 'type' => FormOptions::STRING,
- 'value' => null,
- )
+ 'type' => FormOptions::STRING,
+ 'value' => null,
+ )
),
$this->object->getOptions()
);
$this->assertEquals(
array(
'negone' => array(
- 'default' => -1,
- 'value' => null,
+ 'default' => -1,
+ 'value' => null,
'consumed' => false,
- 'type' => FormOptions::INT,
- ),
+ 'type' => FormOptions::INT,
+ ),
'one' => array(
- 'default' => 1,
- 'value' => null,
+ 'default' => 1,
+ 'value' => null,
'consumed' => false,
- 'type' => FormOptions::INT,
- )
+ 'type' => FormOptions::INT,
+ )
),
$this->object->getOptions()
);
* Reuse helpers above assertGuessBoolean assertGuessInt assertGuessString
*/
public function testGuessTypeDetection() {
- $this->assertGuessBoolean( true );
+ $this->assertGuessBoolean( true );
$this->assertGuessBoolean( false );
- $this->assertGuessInt( 0 );
- $this->assertGuessInt( -5 );
- $this->assertGuessInt( 5 );
+ $this->assertGuessInt( 0 );
+ $this->assertGuessInt( -5 );
+ $this->assertGuessInt( 5 );
$this->assertGuessInt( 0x0F );
- $this->assertGuessString( 'true' );
- $this->assertGuessString( 'false' );
- $this->assertGuessString( '5' );
- $this->assertGuessString( '0' );
+ $this->assertGuessString( 'true' );
+ $this->assertGuessString( 'false' );
+ $this->assertGuessString( '5' );
+ $this->assertGuessString( '0' );
}
/**
- * @expectedException MWException
+ * @expectedException MWException
*/
public function testGuessTypeOnArrayThrowException() {
- $this->object->guessType( array( 'foo' ) );
+ $this->object->guessType( array( 'foo' ) );
}
/**
- * @expectedException MWException
+ * @expectedException MWException
*/
public function testGuessTypeOnNullThrowException() {
- $this->object->guessType( null );
+ $this->object->guessType( null );
}
}
/** @dataProvider provideForWfArrayDiff2 */
public function testWfArrayDiff2( $a, $b, $expected ) {
$this->assertEquals(
- wfArrayDiff2( $a, $b), $expected
+ wfArrayDiff2( $a, $b ), $expected
);
}
// $a $b $expected
return array(
array(
- array( 'a', 'b'),
- array( 'a', 'b'),
+ array( 'a', 'b' ),
+ array( 'a', 'b' ),
array(),
),
array(
- array( array( 'a'), array( 'a', 'b', 'c' )),
- array( array( 'a'), array( 'a', 'b' )),
+ array( array( 'a' ), array( 'a', 'b', 'c' ) ),
+ array( array( 'a' ), array( 'a', 'b' ) ),
array( 1 => array( 'a', 'b', 'c' ) ),
),
);
'text/html',
mimeTypeMatch( 'text/html',
array( 'application/xhtml+xml' => 1.0,
- 'text/html' => 0.7,
- 'text/plain' => 0.3 ) ) );
+ 'text/html' => 0.7,
+ 'text/plain' => 0.3 ) ) );
$this->assertEquals(
'text/*',
mimeTypeMatch( 'text/html',
array( 'image/*' => 1.0,
- 'text/*' => 0.5 ) ) );
+ 'text/*' => 0.5 ) ) );
$this->assertEquals(
'*/*',
mimeTypeMatch( 'text/html',
array( '*/*' => 1.0 ) ) );
$this->assertNull(
mimeTypeMatch( 'text/html',
- array( 'image/png' => 1.0,
- 'image/svg+xml' => 0.5 ) ) );
+ array( 'image/png' => 1.0,
+ 'image/svg+xml' => 0.5 ) ) );
}
function testNegotiateType() {
'text/html',
wfNegotiateType(
array( 'application/xhtml+xml' => 1.0,
- 'text/html' => 0.7,
- 'text/plain' => 0.5,
- 'text/*' => 0.2 ),
- array( 'text/html' => 1.0 ) ) );
+ 'text/html' => 0.7,
+ 'text/plain' => 0.5,
+ 'text/*' => 0.2 ),
+ array( 'text/html' => 1.0 ) ) );
$this->assertEquals(
'application/xhtml+xml',
wfNegotiateType(
array( 'application/xhtml+xml' => 1.0,
- 'text/html' => 0.7,
- 'text/plain' => 0.5,
- 'text/*' => 0.2 ),
+ 'text/html' => 0.7,
+ 'text/plain' => 0.5,
+ 'text/*' => 0.2 ),
array( 'application/xhtml+xml' => 1.0,
- 'text/html' => 0.5 ) ) );
+ 'text/html' => 0.5 ) ) );
$this->assertEquals(
'text/html',
wfNegotiateType(
- array( 'text/html' => 1.0,
- 'text/plain' => 0.5,
- 'text/*' => 0.5,
- 'application/xhtml+xml' => 0.2 ),
+ array( 'text/html' => 1.0,
+ 'text/plain' => 0.5,
+ 'text/*' => 0.5,
+ 'application/xhtml+xml' => 0.2 ),
array( 'application/xhtml+xml' => 1.0,
- 'text/html' => 0.5 ) ) );
+ 'text/html' => 0.5 ) ) );
$this->assertEquals(
'text/html',
wfNegotiateType(
- array( 'text/*' => 1.0,
- 'image/*' => 0.7,
- '*/*' => 0.3 ),
+ array( 'text/*' => 1.0,
+ 'image/*' => 0.7,
+ '*/*' => 0.3 ),
array( 'application/xhtml+xml' => 1.0,
- 'text/html' => 0.5 ) ) );
+ 'text/html' => 0.5 ) ) );
$this->assertNull(
wfNegotiateType(
- array( 'text/*' => 1.0 ),
+ array( 'text/*' => 1.0 ),
array( 'application/xhtml+xml' => 1.0 ) ) );
}
-
+
function testFallbackMbstringFunctions() {
-
- if( !extension_loaded( 'mbstring' ) ) {
+
+ if ( !extension_loaded( 'mbstring' ) ) {
$this->markTestSkipped( "The mb_string functions must be installed to test the fallback functions" );
}
-
+
$sampleUTF = "Östergötland_coat_of_arms.png";
-
-
+
+
//mb_substr
$substr_params = array(
array( 0, 0 ),
array( 1, 1 ),
array( 2, -1 )
);
-
- foreach( $substr_params as $param_set ) {
+
+ foreach ( $substr_params as $param_set ) {
$old_param_set = $param_set;
array_unshift( $param_set, $sampleUTF );
-
+
$this->assertEquals(
MWFunction::callArray( 'mb_substr', $param_set ),
MWFunction::callArray( 'Fallback::mb_substr', $param_set ),
'Fallback mb_substr with params ' . implode( ', ', $old_param_set )
- );
+ );
}
-
-
+
+
//mb_strlen
$this->assertEquals(
mb_strlen( $sampleUTF ),
Fallback::mb_strlen( $sampleUTF ),
'Fallback mb_strlen'
- );
-
-
+ );
+
+
//mb_str(r?)pos
$strpos_params = array(
//array( 'ter' ),
//array( 'c', -10 ),
//Broken for now
);
-
- foreach( $strpos_params as $param_set ) {
+
+ foreach ( $strpos_params as $param_set ) {
$old_param_set = $param_set;
array_unshift( $param_set, $sampleUTF );
-
+
$this->assertEquals(
MWFunction::callArray( 'mb_strpos', $param_set ),
MWFunction::callArray( 'Fallback::mb_strpos', $param_set ),
'Fallback mb_strpos with params ' . implode( ', ', $old_param_set )
- );
-
+ );
+
$this->assertEquals(
MWFunction::callArray( 'mb_strrpos', $param_set ),
MWFunction::callArray( 'Fallback::mb_strrpos', $param_set ),
'Fallback mb_strrpos with params ' . implode( ', ', $old_param_set )
- );
+ );
}
-
+
}
$this->assertGreaterThan( 5000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
unlink( $wgDebugLogFile );
- wfDebugMem(true);
+ wfDebugMem( true );
$this->assertGreaterThan( 5000000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
unlink( $wgDebugLogFile );
}
function testClientAcceptsGzipTest() {
-
+
$settings = array(
'gzip' => true,
'bzip' => false,
'gzip;q=12345678.9' => true,
' gzip' => true,
);
-
- if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) $old_server_setting = $_SERVER['HTTP_ACCEPT_ENCODING'];
-
+
+ if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
+ $old_server_setting = $_SERVER['HTTP_ACCEPT_ENCODING'];
+ }
+
foreach ( $settings as $encoding => $expect ) {
$_SERVER['HTTP_ACCEPT_ENCODING'] = $encoding;
-
+
$this->assertEquals( $expect, wfClientAcceptsGzip( true ),
"'$encoding' => " . wfBoolToStr( $expect ) );
}
-
- if( isset( $old_server_setting ) ) $_SERVER['HTTP_ACCEPT_ENCODING'] = $old_server_setting;
+ if ( isset( $old_server_setting ) ) {
+ $_SERVER['HTTP_ACCEPT_ENCODING'] = $old_server_setting;
+ }
}
-
-
-
- function testSwapVarsTest() {
-
+ function testSwapVarsTest() {
$var1 = 1;
$var2 = 2;
}
-
function testWfPercentTest() {
$pcts = array(
- array( 6/7, '0.86%', 2, false ),
- array( 3/3, '1%' ),
- array( 22/7, '3.14286%', 5 ),
- array( 3/6, '0.5%' ),
- array( 1/3, '0%', 0 ),
- array( 10/3, '0%', -1 ),
- array( 3/4/5, '0.1%', 1 ),
- array( 6/7*8, '6.8571428571%', 10 ),
+ array( 6 / 7, '0.86%', 2, false ),
+ array( 3 / 3, '1%' ),
+ array( 22 / 7, '3.14286%', 5 ),
+ array( 3 / 6, '0.5%' ),
+ array( 1 / 3, '0%', 0 ),
+ array( 10 / 3, '0%', -1 ),
+ array( 3 / 4 / 5, '0.1%', 1 ),
+ array( 6 / 7 * 8, '6.8571428571%', 10 ),
);
-
- foreach( $pcts as $pct ) {
- if( !isset( $pct[2] ) ) $pct[2] = 2;
- if( !isset( $pct[3] ) ) $pct[3] = true;
-
+
+ foreach ( $pcts as $pct ) {
+ if ( !isset( $pct[2] ) ) {
+ $pct[2] = 2;
+ }
+ if ( !isset( $pct[3] ) ) {
+ $pct[3] = true;
+ }
+
$this->assertEquals( wfPercent( $pct[0], $pct[2], $pct[3] ), $pct[1], $pct[1] );
}
-
}
/**
public function testWfShorthandToInteger( $shorthand, $expected ) {
$this->assertEquals( $expected,
wfShorthandToInteger( $shorthand )
- );
+ );
}
/** array( shorthand, expected integer ) */
public static function provideShorthand() {
return array(
# Null, empty ...
- array( '', -1),
- array( ' ', -1),
- array( null, -1),
+ array( '', -1 ),
+ array( ' ', -1 ),
+ array( null, -1 ),
# Failures returns 0 :(
array( 'ABCDEFG', 0 ),
- array( 'Ak', 0 ),
+ array( 'Ak', 0 ),
# Int, strings with spaces
- array( 1, 1 ),
- array( ' 1 ', 1 ),
- array( 1023, 1023 ),
+ array( 1, 1 ),
+ array( ' 1 ', 1 ),
+ array( 1023, 1023 ),
array( ' 1023 ', 1023 ),
# kilo, Mega, Giga
- array( '1k', 1024 ),
- array( '1K', 1024 ),
- array( '1m', 1024 * 1024 ),
- array( '1M', 1024 * 1024 ),
- array( '1g', 1024 * 1024 * 1024 ),
- array( '1G', 1024 * 1024 * 1024 ),
+ array( '1k', 1024 ),
+ array( '1K', 1024 ),
+ array( '1m', 1024 * 1024 ),
+ array( '1M', 1024 * 1024 ),
+ array( '1g', 1024 * 1024 * 1024 ),
+ array( '1G', 1024 * 1024 * 1024 ),
# Negatives
- array( -1, -1 ),
- array( -500, -500 ),
- array( '-500', -500 ),
- array( '-1k', -1024 ),
+ array( -1, -1 ),
+ array( -500, -500 ),
+ array( '-500', -500 ),
+ array( '-1k', -1024 ),
# Zeroes
- array( '0', 0 ),
- array( '0k', 0 ),
- array( '0M', 0 ),
- array( '0G', 0 ),
- array( '-0', 0 ),
+ array( '0', 0 ),
+ array( '0k', 0 ),
+ array( '0M', 0 ),
+ array( '0G', 0 ),
+ array( '-0', 0 ),
array( '-0k', 0 ),
array( '-0M', 0 ),
array( '-0G', 0 ),
$msg .= $expectedMergeResult ? 'success' : 'failure';
$this->assertEquals( $expectedMergeResult, $isMerged, $msg );
- if( $isMerged ) {
+ if ( $isMerged ) {
// Verify the merged text
$this->assertEquals( $expectedText, $mergedText,
'is merged text as expected?' );
$EXPECT_MERGE_FAILURE = false;
return array(
-
// #0: clean merge
array(
// old:
"one one one\n" . // trimmed
- "\n" .
- "two two two",
+ "\n" .
+ "two two two",
// mine:
"one one one ONE ONE\n" .
- "\n" .
- "two two two\n", // with tailing whitespace
+ "\n" .
+ "two two two\n", // with tailing whitespace
// yours:
"one one one\n" .
- "\n" .
- "two two TWO TWO", // trimmed
+ "\n" .
+ "two two TWO TWO", // trimmed
// ok:
$EXPECT_MERGE_SUCCESS,
// result:
"one one one ONE ONE\n" .
- "\n" .
- "two two TWO TWO\n", // note: will always end in a newline
+ "\n" .
+ "two two TWO TWO\n", // note: will always end in a newline
),
// #1: conflict, fail
// mine:
"one one one ONE ONE\n" .
- "\n" .
- "bla bla\n" .
- "\n", // with tailing whitespace
+ "\n" .
+ "bla bla\n" .
+ "\n", // with tailing whitespace
// yours:
"one one one\n" .
- "\n" .
- "two two", // trimmed
+ "\n" .
+ "two two", // trimmed
$EXPECT_MERGE_FAILURE,
),
);
}
-
+
/**
* @dataProvider provideWfMatchesDomainList
*/
$actual = wfMatchesDomainList( $url, $domains );
$this->assertEquals( $expected, $actual, $description );
}
-
+
function provideWfMatchesDomainList() {
$a = array();
$protocols = array( 'HTTP' => 'http:', 'HTTPS' => 'https:', 'protocol-relative' => '' );
array( "$p//www.example2.com", array( 'www.example.com', 'www.example2.com', 'www.example3.com' ), true, "Exact match with other domains in array, $pDesc URL" ),
array( "$p//www.example2.com", array( 'example.com', 'example2.com', 'example3,com' ), true, "Match without subdomain with other domains in array, $pDesc URL" ),
array( "$p//www.example4.com", array( 'example.com', 'example2.com', 'example3,com' ), false, "Domain not in array, $pDesc URL" ),
-
+
// FIXME: This is a bug in wfMatchesDomainList(). If and when this is fixed, update this test case
array( "$p//nds-nl.wikipedia.org", array( 'nl.wikipedia.org' ), true, "Substrings of domains match while they shouldn't, $pDesc URL" ),
) );
* @dataProvider provideWfShellMaintenanceCmdList
*/
function testWfShellMaintenanceCmd( $script, $parameters, $options, $expected, $description ) {
- if( wfIsWindows() ) {
+ if ( wfIsWindows() ) {
// Approximation that's good enough for our purposes just now
$expected = str_replace( "'", '"', $expected );
}
array( 'eval.php', array( '--help', '--test' ), array(),
"'$wgPhpCli' 'eval.php' '--help' '--test'",
"Called eval.php --help --test" ),
- array( 'eval.php', array( '--help', '--test space' ), array('php' => 'php5'),
+ array( 'eval.php', array( '--help', '--test space' ), array( 'php' => 'php5' ),
"'php5' 'eval.php' '--help' '--test space'",
"Called eval.php --help --test with php option" ),
- array( 'eval.php', array( '--help', '--test', 'X' ), array('wrapper' => 'MWScript.php'),
+ array( 'eval.php', array( '--help', '--test', 'X' ), array( 'wrapper' => 'MWScript.php' ),
"'$wgPhpCli' 'MWScript.php' 'eval.php' '--help' '--test' 'X'",
"Called eval.php --help --test with wrapper option" ),
- array( 'eval.php', array( '--help', '--test', 'y' ), array('php' => 'php5', 'wrapper' => 'MWScript.php'),
+ array( 'eval.php', array( '--help', '--test', 'y' ), array( 'php' => 'php5', 'wrapper' => 'MWScript.php' ),
"'php5' 'MWScript.php' 'eval.php' '--help' '--test' 'y'",
"Called eval.php --help --test with wrapper and php option" ),
);
<?php
/**
- * Unit tests for wfAssembleUrl()
+ * Tests for wfAssembleUrl()
*/
-
-class wfAssembleUrl extends MediaWikiTestCase {
+class WfAssembleUrlTest extends MediaWikiTestCase {
/** @dataProvider provideURLParts */
public function testWfAssembleUrl( $parts, $output ) {
$partsDump = print_r( $parts, true );
$parts['query'] = $query;
$url .= '?' . $query;
}
- if( $fragment ) {
+ if ( $fragment ) {
$parts['fragment'] = $fragment;
$url .= '#' . $fragment;
}
<?php
/**
- * Unit tests for wfBCP47()
+ * Tests for wfBCP47()
*/
-class wfBCP47 extends MediaWikiTestCase {
+class WfBCP47Test extends MediaWikiTestCase {
/**
* test @see wfBCP47().
* Please note the BCP explicitly state that language codes are case
*/
function testBCP47( $code, $expected ) {
$code = strtolower( $code );
- $this->assertEquals( $expected, wfBCP47($code),
+ $this->assertEquals( $expected, wfBCP47( $code ),
"Applying BCP47 standard to lower case '$code'"
);
$code = strtoupper( $code );
- $this->assertEquals( $expected, wfBCP47($code),
+ $this->assertEquals( $expected, wfBCP47( $code ),
"Applying BCP47 standard to upper case '$code'"
);
}
return array(
// Extracted from BCP47 (list not exhaustive)
# 2.1.1
- array( 'en-ca-x-ca' , 'en-CA-x-ca' ),
- array( 'sgn-be-fr' , 'sgn-BE-FR' ),
+ array( 'en-ca-x-ca', 'en-CA-x-ca' ),
+ array( 'sgn-be-fr', 'sgn-BE-FR' ),
array( 'az-latn-x-latn', 'az-Latn-x-latn' ),
# 2.2
array( 'sr-Latn-RS', 'sr-Latn-RS' ),
array( 'az-arab-ir', 'az-Arab-IR' ),
# 2.2.5
- array( 'sl-nedis' , 'sl-nedis' ),
+ array( 'sl-nedis', 'sl-nedis' ),
array( 'de-ch-1996', 'de-CH-1996' ),
# 2.2.6
array( 'ja', 'ja' ),
# Language subtag plus script subtag:
- array( 'zh-hans', 'zh-Hans'),
- array( 'sr-cyrl', 'sr-Cyrl'),
- array( 'sr-latn', 'sr-Latn'),
+ array( 'zh-hans', 'zh-Hans' ),
+ array( 'sr-cyrl', 'sr-Cyrl' ),
+ array( 'sr-latn', 'sr-Latn' ),
# Extended language subtags and their primary language subtag
# counterparts:
array( 'zh-cmn-hans-cn', 'zh-cmn-Hans-CN' ),
- array( 'cmn-hans-cn' , 'cmn-Hans-CN' ),
- array( 'zh-yue-hk' , 'zh-yue-HK' ),
- array( 'yue-hk' , 'yue-HK' ),
+ array( 'cmn-hans-cn', 'cmn-Hans-CN' ),
+ array( 'zh-yue-hk', 'zh-yue-HK' ),
+ array( 'yue-hk', 'yue-HK' ),
# Language-Script-Region:
array( 'zh-hans-cn', 'zh-Hans-CN' ),
array( 'sr-latn-RS', 'sr-Latn-RS' ),
# Language-Variant:
- array( 'sl-rozaj' , 'sl-rozaj' ),
+ array( 'sl-rozaj', 'sl-rozaj' ),
array( 'sl-rozaj-biske', 'sl-rozaj-biske' ),
- array( 'sl-nedis' , 'sl-nedis' ),
+ array( 'sl-nedis', 'sl-nedis' ),
# Language-Region-Variant:
- array( 'de-ch-1901' , 'de-CH-1901' ),
- array( 'sl-it-nedis' , 'sl-IT-nedis' ),
+ array( 'de-ch-1901', 'de-CH-1901' ),
+ array( 'sl-it-nedis', 'sl-IT-nedis' ),
# Language-Script-Region-Variant:
array( 'hy-latn-it-arevela', 'hy-Latn-IT-arevela' ),
# Language-Region:
- array( 'de-de' , 'de-DE' ),
- array( 'en-us' , 'en-US' ),
- array( 'es-419', 'es-419'),
+ array( 'de-de', 'de-DE' ),
+ array( 'en-us', 'en-US' ),
+ array( 'es-419', 'es-419' ),
# Private use subtags:
- array( 'de-ch-x-phonebk' , 'de-CH-x-phonebk' ),
+ array( 'de-ch-x-phonebk', 'de-CH-x-phonebk' ),
array( 'az-arab-x-aze-derbend', 'az-Arab-x-aze-derbend' ),
/**
* Previous test does not reflect the BCP which states:
# Private use registry values:
array( 'x-whatever', 'x-whatever' ),
array( 'qaa-qaaa-qm-x-southern', 'qaa-Qaaa-QM-x-southern' ),
- array( 'de-qaaa' , 'de-Qaaa' ),
+ array( 'de-qaaa', 'de-Qaaa' ),
array( 'sr-latn-qm', 'sr-Latn-QM' ),
array( 'sr-qaaa-rs', 'sr-Qaaa-RS' ),
// de-419-DE
// a-DE
// ar-a-aaa-b-bbb-a-ccc
-
- /*
+
+ /*
// ISO 15924 :
array( 'sr-Cyrl', 'sr-Cyrl' ),
# @todo FIXME: Fix our function?
array( 'uS', 'us' ), # USA
array( 'Fr', 'fr' ), # France
array( 'va', 'va' ), # Holy See (Vatican City State)
- */);
+ */
+ );
}
}
<?php
-
/**
* Tests for wfBaseConvert()
*/
-class wfBaseConvertTest extends MediaWikiTestCase {
+class WfBaseConvertTest extends MediaWikiTestCase {
public static function provideSingleDigitConversions() {
return array(
// 2 3 5 8 10 16 36
public static function provideNumbers() {
$x = array();
$chars = '0123456789abcdefghijklmnopqrstuvwxyz';
- for( $i = 0; $i < 50; $i++ ) {
+ for ( $i = 0; $i < 50; $i++ ) {
$base = mt_rand( 2, 36 );
$len = mt_rand( 10, 100 );
$str = '';
- for( $j = 0; $j < $len; $j++ ) {
- $str .= $chars[mt_rand(0, $base - 1)];
+ for ( $j = 0; $j < $len; $j++ ) {
+ $str .= $chars[mt_rand( 0, $base - 1 )];
}
$x[] = array( $base, $str );
/**
* Tests for wfBaseName()
*/
-class wfBaseName extends MediaWikiTestCase {
+class WfBaseNameTest extends MediaWikiTestCase {
/**
* @dataProvider providePaths
*/
function testBaseName( $fullpath, $basename ) {
$this->assertEquals( $basename, wfBaseName( $fullpath ),
- "wfBaseName('$fullpath') => '$basename'" );
+ "wfBaseName('$fullpath') => '$basename'" );
}
-
+
function providePaths() {
return array(
array( '', '' ),
<?php
/**
- * Unit tests for wfExpandUrl()
+ * Tests for wfExpandUrl()
*/
-
-class wfExpandUrl extends MediaWikiTestCase {
+class WfExpandUrlTest extends MediaWikiTestCase {
/** @dataProvider provideExpandableUrls */
public function testWfExpandUrl( $fullUrl, $shortUrl, $defaultProto, $server, $canServer, $httpsMode, $message ) {
// Fake $wgServer and $wgCanonicalServer
foreach ( $modes as $mode ) {
$httpsMode = $mode == 'https';
foreach ( $servers as $serverDesc => $server ) {
- foreach ( $modes as $canServerMode ) {
+ foreach ( $modes as $canServerMode ) {
$canServer = "$canServerMode://example2.com";
foreach ( $defaultProtos as $protoDesc => $defaultProto ) {
$retval[] = array(
<?php
-class wfGetCaller extends MediaWikiTestCase {
+class WfGetCallerTest extends MediaWikiTestCase {
function testZero() {
$this->assertEquals( __METHOD__, wfGetCaller( 1 ) );
}
function testOne() {
- $this->assertEquals( "wfGetCaller::testOne", self::callerOne() );
+ $this->assertEquals( 'WfGetCallerTest::testOne', self::callerOne() );
}
function intermediateFunction( $level = 2, $n = 0 ) {
- if ( $n > 0 )
+ if ( $n > 0 ) {
return self::intermediateFunction( $level, $n - 1 );
+ }
return wfGetCaller( $level );
}
function testTwo() {
- $this->assertEquals( "wfGetCaller::testTwo", self::intermediateFunction() );
+ $this->assertEquals( 'WfGetCallerTest::testTwo', self::intermediateFunction() );
}
function testN() {
- $this->assertEquals( "wfGetCaller::testN", self::intermediateFunction( 2, 0 ) );
- $this->assertEquals( "wfGetCaller::intermediateFunction", self::intermediateFunction( 1, 0 ) );
+ $this->assertEquals( 'WfGetCallerTest::testN', self::intermediateFunction( 2, 0 ) );
+ $this->assertEquals( 'WfGetCallerTest::intermediateFunction', self::intermediateFunction( 1, 0 ) );
- for ($i=0; $i < 10; $i++)
- $this->assertEquals( "wfGetCaller::intermediateFunction", self::intermediateFunction( $i + 1, $i ) );
+ for ( $i = 0; $i < 10; $i++ )
+ $this->assertEquals( 'WfGetCallerTest::intermediateFunction', self::intermediateFunction( $i + 1, $i ) );
}
}
--- /dev/null
+<?php
+/**
+ * Tests for wfParseUrl()
+ *
+ * Copyright © 2013 Alexandre Emsenhuber
+ *
+ * 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
+ */
+
+class WfParseUrlTest extends MediaWikiTestCase {
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( 'wgUrlProtocols', array(
+ '//', 'http://', 'file://', 'mailto:',
+ ) );
+ }
+
+ /** @dataProvider provideURLs */
+ public function testWfParseUrl( $url, $parts ) {
+ $partsDump = var_export( $parts, true );
+ $this->assertEquals(
+ $parts,
+ wfParseUrl( $url ),
+ "Testing $url parses to $partsDump"
+ );
+ }
+
+ /**
+ * Provider of URLs for testing wfParseUrl()
+ *
+ * @return array
+ */
+ public static function provideURLs() {
+ return array(
+ array(
+ '//example.org',
+ array(
+ 'scheme' => '',
+ 'delimiter' => '//',
+ 'host' => 'example.org',
+ )
+ ),
+ array(
+ 'http://example.org',
+ array(
+ 'scheme' => 'http',
+ 'delimiter' => '://',
+ 'host' => 'example.org',
+ )
+ ),
+ array(
+ 'http://id:key@example.org:123/path?foo=bar#baz',
+ array(
+ 'scheme' => 'http',
+ 'delimiter' => '://',
+ 'user' => 'id',
+ 'pass' => 'key',
+ 'host' => 'example.org',
+ 'port' => 123,
+ 'path' => '/path',
+ 'query' => 'foo=bar',
+ 'fragment' => 'baz',
+ )
+ ),
+ array(
+ 'file://example.org/etc/php.ini',
+ array(
+ 'scheme' => 'file',
+ 'delimiter' => '://',
+ 'host' => 'example.org',
+ 'path' => '/etc/php.ini',
+ )
+ ),
+ array(
+ 'file:///etc/php.ini',
+ array(
+ 'scheme' => 'file',
+ 'delimiter' => '://',
+ 'host' => '',
+ 'path' => '/etc/php.ini',
+ )
+ ),
+ array(
+ 'file:///c:/',
+ array(
+ 'scheme' => 'file',
+ 'delimiter' => '://',
+ 'host' => '',
+ 'path' => '/c:/',
+ )
+ ),
+ array(
+ 'mailto:id@example.org',
+ array(
+ 'scheme' => 'mailto',
+ 'delimiter' => ':',
+ 'host' => 'id@example.org',
+ 'path' => '',
+ )
+ ),
+ array(
+ 'mailto:id@example.org?subject=Foo',
+ array(
+ 'scheme' => 'mailto',
+ 'delimiter' => ':',
+ 'host' => 'id@example.org',
+ 'path' => '',
+ 'query' => 'subject=Foo',
+ )
+ ),
+ array(
+ 'mailto:?subject=Foo',
+ array(
+ 'scheme' => 'mailto',
+ 'delimiter' => ':',
+ 'host' => '',
+ 'path' => '',
+ 'query' => 'subject=Foo',
+ )
+ ),
+ array(
+ 'invalid://test/',
+ false
+ ),
+ );
+ }
+}
<?php
/**
- * Unit tests for wfRemoveDotSegments()
+ * Tests for wfRemoveDotSegments()
*/
-
-class wfRemoveDotSegments extends MediaWikiTestCase {
+class WfRemoveDotSegmentsTest extends MediaWikiTestCase {
/** @dataProvider providePaths */
public function testWfRemoveDotSegments( $inputPath, $outputPath ) {
$this->assertEquals(
<?php
-class wfShorthandToIntegerTest extends MediaWikiTestCase {
+class WfShorthandToIntegerTest extends MediaWikiTestCase {
/**
* @dataProvider provideABunchOfShorthands
*/
array( '1k', 1024, 'One kb lowercased' ),
);
}
-
+
}
<?php
-
/*
* Tests for wfTimestamp()
*/
-class wfTimestamp extends MediaWikiTestCase {
+class WfTimestampTest extends MediaWikiTestCase {
/**
* @dataProvider provideNormalTimestamps
*/
function provideNormalTimestamps() {
$t = gmmktime( 12, 34, 56, 1, 15, 2001 );
- return array (
+ return array(
// TS_UNIX
array( $t, TS_MW, '20010115123456', 'TS_UNIX to TS_MW' ),
array( -30281104, TS_MW, '19690115123456', 'Negative TS_UNIX to TS_MW' ),
array( $t, TS_DB, '2001-01-15 12:34:56', 'TS_UNIX to TS_DB' ),
array( $t, TS_ISO_8601_BASIC, '20010115T123456Z', 'TS_ISO_8601_BASIC to TS_DB' ),
-
+
// TS_MW
array( '20010115123456', TS_MW, '20010115123456', 'TS_MW to TS_MW' ),
array( '20010115123456', TS_UNIX, 979562096, 'TS_MW to TS_UNIX' ),
array( '20010115123456', TS_DB, '2001-01-15 12:34:56', 'TS_MW to TS_DB' ),
array( '20010115123456', TS_ISO_8601_BASIC, '20010115T123456Z', 'TS_MW to TS_ISO_8601_BASIC' ),
-
+
// TS_DB
array( '2001-01-15 12:34:56', TS_MW, '20010115123456', 'TS_DB to TS_MW' ),
array( '2001-01-15 12:34:56', TS_UNIX, 979562096, 'TS_DB to TS_UNIX' ),
}
function provideOldTimestamps() {
- return array (
+ return array(
array( '19011213204554', TS_RFC2822, 'Fri, 13 Dec 1901 20:45:54 GMT', 'Earliest time according to php documentation' ),
array( '20380119031407', TS_RFC2822, 'Tue, 19 Jan 2038 03:14:07 GMT', 'Latest 32 bit time' ),
array( '19011213204552', TS_UNIX, '-2147483648', 'Earliest 32 bit unix time' ),
<?php
/**
- * Tests for includes/GlobalFunctions.php -> wfUrlencode()
+ * Tests for wfUrlencode()
*
* The function only need a string parameter and might react to IIS7.0
*/
-
-class wfUrlencodeTest extends MediaWikiTestCase {
-
+class WfUrlencodeTest extends MediaWikiTestCase {
#### TESTS ##############################################################
-
+
/** @dataProvider provideURLS */
public function testEncodingUrlWith( $input, $expected ) {
$this->verifyEncodingFor( 'Apache', $input, $expected );
}
#### HELPERS #############################################################
-
+
/**
* Internal helper that actually run the test.
* Called by the public methods testEncodingUrlWith...()
$expected = $this->extractExpect( $server, $expectations );
// save up global
- $old = isset($_SERVER['SERVER_SOFTWARE'])
+ $old = isset( $_SERVER['SERVER_SOFTWARE'] )
? $_SERVER['SERVER_SOFTWARE']
- : null
- ;
+ : null;
$_SERVER['SERVER_SOFTWARE'] = $server;
wfUrlencode( null );
);
// restore global
- if( $old === null ) {
+ if ( $old === null ) {
unset( $_SERVER['SERVER_SOFTWARE'] );
} else {
$_SERVER['SERVER_SOFTWARE'] = $old;
* the HTTP server name.
*/
private function extractExpect( $server, $expectations ) {
- if( is_string( $expectations ) ) {
+ if ( is_string( $expectations ) ) {
return $expectations;
- } elseif( is_array( $expectations ) ) {
- if( !array_key_exists( $server, $expectations ) ) {
+ } elseif ( is_array( $expectations ) ) {
+ if ( !array_key_exists( $server, $expectations ) ) {
throw new MWException( __METHOD__ . " expectation does not have any value for server name $server. Check the provider array.\n" );
} else {
return $expectations[$server];
}
- } else {
+ } else {
throw new MWException( __METHOD__ . " given invalid expectation for '$server'. Should be a string or an array( <http server name> => <string> ).\n" );
- }
- }
-
+ }
+ }
#### PROVIDERS ###########################################################
* array( 'Microsoft-IIS/7', 'expected' ),
* ),
* If you want to add other HTTP server name, you will have to add a new
- * testing method much like the testEncodingUrlWith() method above.
+ * testing method much like the testEncodingUrlWith() method above.
*/
public static function provideURLS() {
return array(
- ### RFC 1738 chars
+ ### RFC 1738 chars
// + is not safe
array( '+', '%2B' ),
// & and = not safe in queries
array( '=', '%3D' ),
array( ':', array(
- 'Apache' => ':',
+ 'Apache' => ':',
'Microsoft-IIS/7' => '%3A',
) ),
';@$-_.!*',
),
- ### Other tests
+ ### Other tests
// slash remain unchanged. %2F seems to break things
array( '/', '/' ),
-
+
// Other 'funnies' chars
array( '[]', '%5B%5D' ),
array( '<>', '%3C%3E' ),
$langObj->setNamespaces( array(
-2 => 'Media',
-1 => 'Special',
- 0 => '',
- 1 => 'Talk',
- 2 => 'User',
- 3 => 'User_talk',
- 4 => 'MyWiki',
- 5 => 'MyWiki_Talk',
- 6 => 'File',
- 7 => 'File_talk',
- 8 => 'MediaWiki',
- 9 => 'MediaWiki_talk',
- 10 => 'Template',
- 11 => 'Template_talk',
- 14 => 'Category',
- 15 => 'Category_talk',
- 100 => 'Custom',
- 101 => 'Custom_talk',
+ 0 => '',
+ 1 => 'Talk',
+ 2 => 'User',
+ 3 => 'User_talk',
+ 4 => 'MyWiki',
+ 5 => 'MyWiki_Talk',
+ 6 => 'File',
+ 7 => 'File_talk',
+ 8 => 'MediaWiki',
+ 9 => 'MediaWiki_talk',
+ 10 => 'Template',
+ 11 => 'Template_talk',
+ 14 => 'Category',
+ 15 => 'Category_talk',
+ 100 => 'Custom',
+ 101 => 'Custom_talk',
) );
$this->setMwGlobals( array(
'one' => 1,
# Method use isset() internally, make sure we do discard
- # attributes values which have been assigned well known values
+ # attributes values which have been assigned well known values
'emptystring' => '',
'boolfalse' => false,
'zero' => 0,
'null' => null,
- )))
+ ) ) )
);
}
'GREEN',
'GREEN' => false,
'GREEN',
- )))
+ ) ) )
);
}
function testNamespaceSelector() {
$this->assertEquals(
'<select id=namespace name=namespace>' . "\n" .
-'<option value=0>(Main)</option>' . "\n" .
-'<option value=1>Talk</option>' . "\n" .
-'<option value=2>User</option>' . "\n" .
-'<option value=3>User talk</option>' . "\n" .
-'<option value=4>MyWiki</option>' . "\n" .
-'<option value=5>MyWiki Talk</option>' . "\n" .
-'<option value=6>File</option>' . "\n" .
-'<option value=7>File talk</option>' . "\n" .
-'<option value=8>MediaWiki</option>' . "\n" .
-'<option value=9>MediaWiki talk</option>' . "\n" .
-'<option value=10>Template</option>' . "\n" .
-'<option value=11>Template talk</option>' . "\n" .
-'<option value=14>Category</option>' . "\n" .
-'<option value=15>Category talk</option>' . "\n" .
-'<option value=100>Custom</option>' . "\n" .
-'<option value=101>Custom talk</option>' . "\n" .
-'</select>',
+ '<option value=0>(Main)</option>' . "\n" .
+ '<option value=1>Talk</option>' . "\n" .
+ '<option value=2>User</option>' . "\n" .
+ '<option value=3>User talk</option>' . "\n" .
+ '<option value=4>MyWiki</option>' . "\n" .
+ '<option value=5>MyWiki Talk</option>' . "\n" .
+ '<option value=6>File</option>' . "\n" .
+ '<option value=7>File talk</option>' . "\n" .
+ '<option value=8>MediaWiki</option>' . "\n" .
+ '<option value=9>MediaWiki talk</option>' . "\n" .
+ '<option value=10>Template</option>' . "\n" .
+ '<option value=11>Template talk</option>' . "\n" .
+ '<option value=14>Category</option>' . "\n" .
+ '<option value=15>Category talk</option>' . "\n" .
+ '<option value=100>Custom</option>' . "\n" .
+ '<option value=101>Custom talk</option>' . "\n" .
+ '</select>',
Html::namespaceSelector(),
'Basic namespace selector without custom options'
);
$this->assertEquals(
'<label for=mw-test-namespace>Select a namespace:</label> ' .
-'<select id=mw-test-namespace name=wpNamespace>' . "\n" .
-'<option value=all>all</option>' . "\n" .
-'<option value=0>(Main)</option>' . "\n" .
-'<option value=1>Talk</option>' . "\n" .
-'<option value=2 selected>User</option>' . "\n" .
-'<option value=3>User talk</option>' . "\n" .
-'<option value=4>MyWiki</option>' . "\n" .
-'<option value=5>MyWiki Talk</option>' . "\n" .
-'<option value=6>File</option>' . "\n" .
-'<option value=7>File talk</option>' . "\n" .
-'<option value=8>MediaWiki</option>' . "\n" .
-'<option value=9>MediaWiki talk</option>' . "\n" .
-'<option value=10>Template</option>' . "\n" .
-'<option value=11>Template talk</option>' . "\n" .
-'<option value=14>Category</option>' . "\n" .
-'<option value=15>Category talk</option>' . "\n" .
-'<option value=100>Custom</option>' . "\n" .
-'<option value=101>Custom talk</option>' . "\n" .
-'</select>',
+ '<select id=mw-test-namespace name=wpNamespace>' . "\n" .
+ '<option value=all>all</option>' . "\n" .
+ '<option value=0>(Main)</option>' . "\n" .
+ '<option value=1>Talk</option>' . "\n" .
+ '<option value=2 selected>User</option>' . "\n" .
+ '<option value=3>User talk</option>' . "\n" .
+ '<option value=4>MyWiki</option>' . "\n" .
+ '<option value=5>MyWiki Talk</option>' . "\n" .
+ '<option value=6>File</option>' . "\n" .
+ '<option value=7>File talk</option>' . "\n" .
+ '<option value=8>MediaWiki</option>' . "\n" .
+ '<option value=9>MediaWiki talk</option>' . "\n" .
+ '<option value=10>Template</option>' . "\n" .
+ '<option value=11>Template talk</option>' . "\n" .
+ '<option value=14>Category</option>' . "\n" .
+ '<option value=15>Category talk</option>' . "\n" .
+ '<option value=100>Custom</option>' . "\n" .
+ '<option value=101>Custom talk</option>' . "\n" .
+ '</select>',
Html::namespaceSelector(
array( 'selected' => '2', 'all' => 'all', 'label' => 'Select a namespace:' ),
array( 'name' => 'wpNamespace', 'id' => 'mw-test-namespace' )
$this->assertEquals(
'<label for=namespace>Select a namespace:</label> ' .
-'<select id=namespace name=namespace>' . "\n" .
-'<option value=0>(Main)</option>' . "\n" .
-'<option value=1>Talk</option>' . "\n" .
-'<option value=2>User</option>' . "\n" .
-'<option value=3>User talk</option>' . "\n" .
-'<option value=4>MyWiki</option>' . "\n" .
-'<option value=5>MyWiki Talk</option>' . "\n" .
-'<option value=6>File</option>' . "\n" .
-'<option value=7>File talk</option>' . "\n" .
-'<option value=8>MediaWiki</option>' . "\n" .
-'<option value=9>MediaWiki talk</option>' . "\n" .
-'<option value=10>Template</option>' . "\n" .
-'<option value=11>Template talk</option>' . "\n" .
-'<option value=14>Category</option>' . "\n" .
-'<option value=15>Category talk</option>' . "\n" .
-'<option value=100>Custom</option>' . "\n" .
-'<option value=101>Custom talk</option>' . "\n" .
-'</select>',
+ '<select id=namespace name=namespace>' . "\n" .
+ '<option value=0>(Main)</option>' . "\n" .
+ '<option value=1>Talk</option>' . "\n" .
+ '<option value=2>User</option>' . "\n" .
+ '<option value=3>User talk</option>' . "\n" .
+ '<option value=4>MyWiki</option>' . "\n" .
+ '<option value=5>MyWiki Talk</option>' . "\n" .
+ '<option value=6>File</option>' . "\n" .
+ '<option value=7>File talk</option>' . "\n" .
+ '<option value=8>MediaWiki</option>' . "\n" .
+ '<option value=9>MediaWiki talk</option>' . "\n" .
+ '<option value=10>Template</option>' . "\n" .
+ '<option value=11>Template talk</option>' . "\n" .
+ '<option value=14>Category</option>' . "\n" .
+ '<option value=15>Category talk</option>' . "\n" .
+ '<option value=100>Custom</option>' . "\n" .
+ '<option value=101>Custom talk</option>' . "\n" .
+ '</select>',
Html::namespaceSelector(
array( 'label' => 'Select a namespace:' )
),
function testCanFilterOutNamespaces() {
$this->assertEquals(
-'<select id=namespace name=namespace>' . "\n" .
-'<option value=2>User</option>' . "\n" .
-'<option value=4>MyWiki</option>' . "\n" .
-'<option value=5>MyWiki Talk</option>' . "\n" .
-'<option value=6>File</option>' . "\n" .
-'<option value=7>File talk</option>' . "\n" .
-'<option value=8>MediaWiki</option>' . "\n" .
-'<option value=9>MediaWiki talk</option>' . "\n" .
-'<option value=10>Template</option>' . "\n" .
-'<option value=11>Template talk</option>' . "\n" .
-'<option value=14>Category</option>' . "\n" .
-'<option value=15>Category talk</option>' . "\n" .
-'</select>',
+ '<select id=namespace name=namespace>' . "\n" .
+ '<option value=2>User</option>' . "\n" .
+ '<option value=4>MyWiki</option>' . "\n" .
+ '<option value=5>MyWiki Talk</option>' . "\n" .
+ '<option value=6>File</option>' . "\n" .
+ '<option value=7>File talk</option>' . "\n" .
+ '<option value=8>MediaWiki</option>' . "\n" .
+ '<option value=9>MediaWiki talk</option>' . "\n" .
+ '<option value=10>Template</option>' . "\n" .
+ '<option value=11>Template talk</option>' . "\n" .
+ '<option value=14>Category</option>' . "\n" .
+ '<option value=15>Category talk</option>' . "\n" .
+ '</select>',
Html::namespaceSelector(
array( 'exclude' => array( 0, 1, 3, 100, 101 ) )
),
function testCanDisableANamespaces() {
$this->assertEquals(
-'<select id=namespace name=namespace>' . "\n" .
-'<option disabled value=0>(Main)</option>' . "\n" .
-'<option disabled value=1>Talk</option>' . "\n" .
-'<option disabled value=2>User</option>' . "\n" .
-'<option disabled value=3>User talk</option>' . "\n" .
-'<option disabled value=4>MyWiki</option>' . "\n" .
-'<option value=5>MyWiki Talk</option>' . "\n" .
-'<option value=6>File</option>' . "\n" .
-'<option value=7>File talk</option>' . "\n" .
-'<option value=8>MediaWiki</option>' . "\n" .
-'<option value=9>MediaWiki talk</option>' . "\n" .
-'<option value=10>Template</option>' . "\n" .
-'<option value=11>Template talk</option>' . "\n" .
-'<option value=14>Category</option>' . "\n" .
-'<option value=15>Category talk</option>' . "\n" .
-'<option value=100>Custom</option>' . "\n" .
-'<option value=101>Custom talk</option>' . "\n" .
-'</select>',
+ '<select id=namespace name=namespace>' . "\n" .
+ '<option disabled value=0>(Main)</option>' . "\n" .
+ '<option disabled value=1>Talk</option>' . "\n" .
+ '<option disabled value=2>User</option>' . "\n" .
+ '<option disabled value=3>User talk</option>' . "\n" .
+ '<option disabled value=4>MyWiki</option>' . "\n" .
+ '<option value=5>MyWiki Talk</option>' . "\n" .
+ '<option value=6>File</option>' . "\n" .
+ '<option value=7>File talk</option>' . "\n" .
+ '<option value=8>MediaWiki</option>' . "\n" .
+ '<option value=9>MediaWiki talk</option>' . "\n" .
+ '<option value=10>Template</option>' . "\n" .
+ '<option value=11>Template talk</option>' . "\n" .
+ '<option value=14>Category</option>' . "\n" .
+ '<option value=15>Category talk</option>' . "\n" .
+ '<option value=100>Custom</option>' . "\n" .
+ '<option value=101>Custom talk</option>' . "\n" .
+ '</select>',
Html::namespaceSelector( array(
'disable' => array( 0, 1, 2, 3, 4 )
) ),
'color',
);
$cases = array();
- foreach( $types as $type ) {
+ foreach ( $types as $type ) {
$cases[] = array( $type );
}
return $cases;
# Craft the Html elements
$ret = array();
- foreach( $cases as $case ) {
+ foreach ( $cases as $case ) {
$ret[] = array(
$case[0],
$case[1], $case[2],
public static function cookieDomains() {
return array(
- array( false, "org"),
- array( false, ".org"),
- array( true, "wikipedia.org"),
- array( true, ".wikipedia.org"),
+ array( false, "org" ),
+ array( false, ".org" ),
+ array( true, "wikipedia.org" ),
+ array( true, ".wikipedia.org" ),
array( false, "co.uk" ),
array( false, ".co.uk" ),
array( false, "gov.uk" ),
array( false, '¿non sens before!! http://a', 'Allow anything before URI' ),
# (http|https) - only two schemes allowed
- array( true, 'http://www.example.org/' ),
- array( true, 'https://www.example.org/' ),
- array( true, 'http://www.example.org', 'URI without directory' ),
- array( true, 'http://a', 'Short name' ),
- array( true, 'http://étoile', 'Allow UTF-8 in hostname' ), # 'étoile' is french for 'star'
+ array( true, 'http://www.example.org/' ),
+ array( true, 'https://www.example.org/' ),
+ array( true, 'http://www.example.org', 'URI without directory' ),
+ array( true, 'http://a', 'Short name' ),
+ array( true, 'http://étoile', 'Allow UTF-8 in hostname' ), # 'étoile' is french for 'star'
array( false, '\\host\directory', 'CIFS share' ),
array( false, 'gopher://host/dir', 'Reject gopher scheme' ),
array( false, 'telnet://host', 'Reject telnet scheme' ),
# :\/\/ - double slashes
- array( false, 'http//example.org', 'Reject missing colon in protocol' ),
- array( false, 'http:/example.org', 'Reject missing slash in protocol' ),
- array( false, 'http:example.org', 'Must have two slashes' ),
+ array( false, 'http//example.org', 'Reject missing colon in protocol' ),
+ array( false, 'http:/example.org', 'Reject missing slash in protocol' ),
+ array( false, 'http:example.org', 'Must have two slashes' ),
# Following fail since hostname can be made of anything
- array( false, 'http:///example.org', 'Must have exactly two slashes, not three' ),
+ array( false, 'http:///example.org', 'Must have exactly two slashes, not three' ),
# (\w+:{0,1}\w*@)? - optional user:pass
- array( true, 'http://user@host', 'Username provided' ),
- array( true, 'http://user:@host', 'Username provided, no password' ),
- array( true, 'http://user:pass@host', 'Username and password provided' ),
+ array( true, 'http://user@host', 'Username provided' ),
+ array( true, 'http://user:@host', 'Username provided, no password' ),
+ array( true, 'http://user:pass@host', 'Username and password provided' ),
# (\S+) - host part is made of anything not whitespaces
array( false, 'http://!"èèè¿¿¿~~\'', 'hostname is made of any non whitespace' ),
array( true, 'http://example/&' ),
# Fragment
- array( true, 'http://exam#ple.org', ), # This one is valid, really!
+ array( true, 'http://exam#ple.org', ), # This one is valid, really!
array( true, 'http://example.org:80#anchor' ),
array( true, 'http://example.org/?id#anchor' ),
array( true, 'http://example.org/?#anchor' ),
/**
* Warning:
- *
+ *
* These tests are for code that makes use of an artifact of how CURL
* handles header reporting on redirect pages, and will need to be
* rewritten when bug 29232 is taken care of (high-level handling of
# Forge a Location header
$h->setRespHeaders( 'location', array(
- 'http://newsite/file.ext',
- '/newfile.ext',
+ 'http://newsite/file.ext',
+ '/newfile.ext',
)
);
# Verify we correctly fix the Location
);
$h->setRespHeaders( 'location', array(
- 'https://oldsite/file.ext'
+ 'https://oldsite/file.ext'
)
);
$this->assertEquals(
);
$h->setRespHeaders( 'location', array(
- '/anotherfile.ext',
- 'http://anotherfile/hoster.ext',
- 'https://anotherfile/hoster.ext'
+ '/anotherfile.ext',
+ 'http://anotherfile/hoster.ext',
+ 'https://anotherfile/hoster.ext'
)
);
$this->assertEquals(
'https://anotherfile/hoster.ext',
- $h->getFinalUrl( "Relative file path Location: should keep the latest host and scheme!")
+ $h->getFinalUrl( "Relative file path Location: should keep the latest host and scheme!" )
);
}
}
Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php';
} elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
throw new MWException( __METHOD__ . ': curl (http://php.net/curl) is not installed, but' .
- 'Http::$httpEngine is set to "curl"' );
+ 'Http::$httpEngine is set to "curl"' );
}
- switch( Http::$httpEngine ) {
+ switch ( Http::$httpEngine ) {
case 'curl':
return new CurlHttpRequestTester( $url, $options );
case 'php':
*/
public function testisIPAddress() {
$this->assertFalse( IP::isIPAddress( false ), 'Boolean false is not an IP' );
- $this->assertFalse( IP::isIPAddress( true ), 'Boolean true is not an IP' );
+ $this->assertFalse( IP::isIPAddress( true ), 'Boolean true is not an IP' );
$this->assertFalse( IP::isIPAddress( "" ), 'Empty string is not an IP' );
$this->assertFalse( IP::isIPAddress( 'abc' ), 'Garbage IP string' );
$this->assertFalse( IP::isIPAddress( ':' ), 'Single ":" is not an IP' );
- $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::1'), 'IPv6 with a double :: occurrence' );
- $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::'), 'IPv6 with a double :: occurrence, last at end' );
- $this->assertFalse( IP::isIPAddress( '::2001:0DB8::5:1'), 'IPv6 with a double :: occurrence, firt at beginning' );
+ $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::1' ), 'IPv6 with a double :: occurrence' );
+ $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::' ), 'IPv6 with a double :: occurrence, last at end' );
+ $this->assertFalse( IP::isIPAddress( '::2001:0DB8::5:1' ), 'IPv6 with a double :: occurrence, firt at beginning' );
$this->assertFalse( IP::isIPAddress( '124.24.52' ), 'IPv4 not enough quads' );
$this->assertFalse( IP::isIPAddress( '24.324.52.13' ), 'IPv4 out of range' );
$this->assertFalse( IP::isIPAddress( '.24.52.13' ), 'IPv4 starts with period' );
$this->assertTrue( IP::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
$this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' );
$this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
- $this->assertTrue( IP::isIPv6( '2001::df'), 'IPv6 with "::" and 2 words' );
- $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df'), 'IPv6 with "::" and 5 words' );
- $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df:2'), 'IPv6 with "::" and 6 words' );
+ $this->assertTrue( IP::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' );
+ $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
+ $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
$this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
$this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
*/
public function testisIPv4() {
$this->assertFalse( IP::isIPv4( false ), 'Boolean false is not an IP' );
- $this->assertFalse( IP::isIPv4( true ), 'Boolean true is not an IP' );
+ $this->assertFalse( IP::isIPv4( true ), 'Boolean true is not an IP' );
$this->assertFalse( IP::isIPv4( "" ), 'Empty string is not an IP' );
$this->assertFalse( IP::isIPv4( 'abc' ) );
$this->assertFalse( IP::isIPv4( ':' ) );
$this->assertTrue( IP::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' );
$this->assertTrue( IP::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
- $this->assertTrue( IP::isValid( '2001::df'), 'IPv6 with "::" and 2 words' );
- $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df'), 'IPv6 with "::" and 5 words' );
- $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df:2'), 'IPv6 with "::" and 6 words' );
+ $this->assertTrue( IP::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' );
+ $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
+ $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
$this->assertTrue( IP::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
$this->assertTrue( IP::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
* @todo Most probably incomplete
*/
public function testSanitizeIP() {
- $this->assertNull( IP::sanitizeIP('') );
- $this->assertNull( IP::sanitizeIP(' ') );
+ $this->assertNull( IP::sanitizeIP( '' ) );
+ $this->assertNull( IP::sanitizeIP( ' ' ) );
}
/**
*/
public function testip2longWrapper() {
// @todo FIXME: Add more tests ?
- $this->assertEquals( pow(2,32) - 1, IP::toUnsigned( '255.255.255.255' ) );
+ $this->assertEquals( pow( 2, 32 ) - 1, IP::toUnsigned( '255.255.255.255' ) );
$i = 'IN.VA.LI.D';
$this->assertFalse( IP::toUnSigned( $i ) );
}
}
// Private wrapper used to test CIDR Parsing.
- private function assertFalseCIDR( $CIDR, $msg='' ) {
+ private function assertFalseCIDR( $CIDR, $msg = '' ) {
$ff = array( false, false );
$this->assertEquals( $ff, IP::parseCIDR( $CIDR ), $msg );
}
* @covers IP::hexToQuad
*/
public function testHexToQuad() {
- $this->assertEquals( '0.0.0.1' , IP::hexToQuad( '00000001' ) );
- $this->assertEquals( '255.0.0.0' , IP::hexToQuad( 'FF000000' ) );
+ $this->assertEquals( '0.0.0.1', IP::hexToQuad( '00000001' ) );
+ $this->assertEquals( '255.0.0.0', IP::hexToQuad( 'FF000000' ) );
$this->assertEquals( '255.255.255.255', IP::hexToQuad( 'FFFFFFFF' ) );
- $this->assertEquals( '10.188.222.255' , IP::hexToQuad( '0ABCDEFF' ) );
+ $this->assertEquals( '10.188.222.255', IP::hexToQuad( '0ABCDEFF' ) );
// hex not left-padded...
- $this->assertEquals( '0.0.0.0' , IP::hexToQuad( '0' ) );
- $this->assertEquals( '0.0.0.1' , IP::hexToQuad( '1' ) );
- $this->assertEquals( '0.0.0.255' , IP::hexToQuad( 'FF' ) );
- $this->assertEquals( '0.0.255.0' , IP::hexToQuad( 'FF00' ) );
+ $this->assertEquals( '0.0.0.0', IP::hexToQuad( '0' ) );
+ $this->assertEquals( '0.0.0.1', IP::hexToQuad( '1' ) );
+ $this->assertEquals( '0.0.0.255', IP::hexToQuad( 'FF' ) );
+ $this->assertEquals( '0.0.255.0', IP::hexToQuad( 'FF00' ) );
}
/**
$this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
IP::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) );
// hex not left-padded...
- $this->assertEquals( '0:0:0:0:0:0:0:0' , IP::hexToOctet( '0' ) );
- $this->assertEquals( '0:0:0:0:0:0:0:1' , IP::hexToOctet( '1' ) );
- $this->assertEquals( '0:0:0:0:0:0:0:FF' , IP::hexToOctet( 'FF' ) );
- $this->assertEquals( '0:0:0:0:0:0:0:FFD0' , IP::hexToOctet( 'FFD0' ) );
- $this->assertEquals( '0:0:0:0:0:0:FA00:0' , IP::hexToOctet( 'FA000000' ) );
+ $this->assertEquals( '0:0:0:0:0:0:0:0', IP::hexToOctet( '0' ) );
+ $this->assertEquals( '0:0:0:0:0:0:0:1', IP::hexToOctet( '1' ) );
+ $this->assertEquals( '0:0:0:0:0:0:0:FF', IP::hexToOctet( 'FF' ) );
+ $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP::hexToOctet( 'FFD0' ) );
+ $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP::hexToOctet( 'FA000000' ) );
$this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP::hexToOctet( 'FCCFFAFF' ) );
}
* @covers IP::parseCIDR
*/
function testCIDRParsing() {
- $this->assertFalseCIDR( '192.0.2.0' , "missing mask" );
+ $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
$this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
// Verify if statement
- $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
+ $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
$this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" );
- $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
- $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
+ $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
+ $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
// Check internal logic
# 0 mask always result in array(0,0)
- $this->assertEquals( array( 0, 0 ), IP::parseCIDR('192.0.0.2/0') );
- $this->assertEquals( array( 0, 0 ), IP::parseCIDR('0.0.0.0/0') );
- $this->assertEquals( array( 0, 0 ), IP::parseCIDR('255.255.255.255/0') );
+ $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '192.0.0.2/0' ) );
+ $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '0.0.0.0/0' ) );
+ $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '255.255.255.255/0' ) );
// @todo FIXME: Add more tests.
# This part test network shifting
- $this->assertNet( '192.0.0.0' , '192.0.0.2/24' );
- $this->assertNet( '192.168.5.0', '192.168.5.13/24');
- $this->assertNet( '10.0.0.160' , '10.0.0.161/28' );
- $this->assertNet( '10.0.0.0' , '10.0.0.3/28' );
- $this->assertNet( '10.0.0.0' , '10.0.0.3/30' );
- $this->assertNet( '10.0.0.4' , '10.0.0.4/30' );
+ $this->assertNet( '192.0.0.0', '192.0.0.2/24' );
+ $this->assertNet( '192.168.5.0', '192.168.5.13/24' );
+ $this->assertNet( '10.0.0.160', '10.0.0.161/28' );
+ $this->assertNet( '10.0.0.0', '10.0.0.3/28' );
+ $this->assertNet( '10.0.0.0', '10.0.0.3/30' );
+ $this->assertNet( '10.0.0.4', '10.0.0.4/30' );
$this->assertNet( '172.17.32.0', '172.17.35.48/21' );
- $this->assertNet( '10.128.0.0' , '10.135.0.0/9' );
- $this->assertNet( '134.0.0.0' , '134.0.5.1/8' );
+ $this->assertNet( '10.128.0.0', '10.135.0.0/9' );
+ $this->assertNet( '134.0.0.0', '134.0.5.1/8' );
}
-
/**
* @covers IP::canonicalize
*/
public function testIPCanonicalizeOnValidIp() {
$this->assertEquals( '192.0.2.152', IP::canonicalize( '192.0.2.152' ),
- 'Canonicalization of a valid IP returns it unchanged' );
+ 'Canonicalization of a valid IP returns it unchanged' );
}
/**
/** Provider for testIPIsInRange() */
public static function provideIPsAndRanges() {
- # Format: (expected boolean, address, range, optional message)
+ # Format: (expected boolean, address, range, optional message)
return array(
# IPv4
- array( true , '192.0.2.0' , '192.0.2.0/24', 'Network address' ),
- array( true , '192.0.2.77' , '192.0.2.0/24', 'Simple address' ),
- array( true , '192.0.2.255' , '192.0.2.0/24', 'Broadcast address' ),
+ array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ),
+ array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ),
+ array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ),
- array( false, '0.0.0.0' , '192.0.2.0/24' ),
- array( false, '255.255.255' , '192.0.2.0/24' ),
+ array( false, '0.0.0.0', '192.0.2.0/24' ),
+ array( false, '255.255.255', '192.0.2.0/24' ),
# IPv6
- array( false, '::1' , '2001:DB8::/32' ),
- array( false, '::' , '2001:DB8::/32' ),
+ array( false, '::1', '2001:DB8::/32' ),
+ array( false, '::', '2001:DB8::/32' ),
array( false, 'FE80::1', '2001:DB8::/32' ),
- array( true , '2001:DB8::' , '2001:DB8::/32' ),
- array( true , '2001:0DB8::' , '2001:DB8::/32' ),
- array( true , '2001:DB8::1' , '2001:DB8::/32' ),
- array( true , '2001:0DB8::1', '2001:DB8::/32' ),
- array( true , '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
+ array( true, '2001:DB8::', '2001:DB8::/32' ),
+ array( true, '2001:0DB8::', '2001:DB8::/32' ),
+ array( true, '2001:DB8::1', '2001:DB8::/32' ),
+ array( true, '2001:0DB8::1', '2001:DB8::/32' ),
+ array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
'2001:DB8::/32' ),
array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
<?php
class JsonTest extends MediaWikiTestCase {
-
+
function testPhpBug46944Test() {
- $this->assertNotEquals(
- '\ud840\udc00',
+ $this->assertNotEquals(
+ '\ud840\udc00',
strtolower( FormatJson::encode( "\xf0\xa0\x80\x80" ) ),
'Test encoding an broken json_encode character (U+20000)'
);
}
-
+
function testDecodeVarTypes() {
- $this->assertInternalType(
- 'object',
+ $this->assertInternalType(
+ 'object',
FormatJson::decode( '{"Name": "Cheeso", "Rank": 7}' ),
'Default to object'
);
- $this->assertInternalType(
- 'array',
+ $this->assertInternalType(
+ 'array',
FormatJson::decode( '{"Name": "Cheeso", "Rank": 7}', true ),
'Optional array'
);
$wgUser->setId( 1 );
$wgUser->mFrom = 'defaults';
$wgUser->mOptionsLoaded = true;
- $wgUser->setOption( 'variant', 'tg-latn' ); // The user's data is ignored
- // because the variant is set in the URL.
+ // The user's data is ignored because the variant is set in the URL.
+ $wgUser->setOption( 'variant', 'tg-latn' );
$this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
}
function loadDefaultTables() {
$this->mTables = array(
'tg-latn' => new ReplacementArray( $this->table ),
- 'tg' => new ReplacementArray()
+ 'tg' => new ReplacementArray()
);
}
'section' => 'description',
'id' => 'wpLicense',
'label' => 'A label text', # Note can't test label-message because $wgOut is not defined
- 'name' => 'AnotherName',
- 'licenses' => $str,
+ 'name' => 'AnotherName',
+ 'licenses' => $str,
) );
$this->assertThat( $lc, $this->isInstanceOf( 'Licenses' ) );
}
* @dataProvider provideCasesForUserLink
* @cover Linker::userLink
*/
- function testUserLink( $expected, $userId, $userName, $altUserName = false, $msg='' ) {
+ function testUserLink( $expected, $userId, $userName, $altUserName = false, $msg = '' ) {
$this->setMwGlobals( array(
'wgArticlePath' => '/wiki/$1',
'wgWellFormedXml' => true,
- ) );
+ ) );
$this->assertEquals( $expected,
Linker::userLink( $userId, $userName, $altUserName, $msg )
$this->setMwGlobals( 'wgCapitalLinks', true );
$info = array(
- 'name' => 'test',
- 'directory' => '/testdir',
- 'url' => '/testurl',
- 'hashLevels' => 2,
+ 'name' => 'test',
+ 'directory' => '/testdir',
+ 'url' => '/testurl',
+ 'hashLevels' => 2,
'transformVia404' => false,
- 'backend' => new FSFileBackend( array(
- 'name' => 'local-backend',
+ 'backend' => new FSFileBackend( array(
+ 'name' => 'local-backend',
'lockManager' => 'fsLockManager',
'containerPaths' => array(
'cont1' => "/testdir/local-backend/tempimages/cont1",
<?php
class MWFunctionTest extends MediaWikiTestCase {
-
function testCallUserFuncWorkarounds() {
- $this->assertEquals(
+ $this->assertEquals(
call_user_func( array( 'MWFunctionTest', 'someMethod' ) ),
MWFunction::call( 'MWFunctionTest::someMethod' )
);
- $this->assertEquals(
+ $this->assertEquals(
call_user_func( array( 'MWFunctionTest', 'someMethod' ), 'foo', 'bar', 'baz' ),
MWFunction::call( 'MWFunctionTest::someMethod', 'foo', 'bar', 'baz' )
);
- $this->assertEquals(
+ $this->assertEquals(
call_user_func_array( array( 'MWFunctionTest', 'someMethod' ), array() ),
MWFunction::callArray( 'MWFunctionTest::someMethod', array() )
);
- $this->assertEquals(
+ $this->assertEquals(
call_user_func_array( array( 'MWFunctionTest', 'someMethod' ), array( 'foo', 'bar', 'baz' ) ),
MWFunction::callArray( 'MWFunctionTest::someMethod', array( 'foo', 'bar', 'baz' ) )
);
}
-
+
function testNewObjFunction() {
$arg1 = 'Foo';
$arg2 = 'Bar';
$args = array( $arg1, $arg2, $arg3, $arg4 );
$newObject = new MWBlankClass( $arg1, $arg2, $arg3, $arg4 );
- $this->assertEquals(
- MWFunction::newObj( 'MWBlankClass', $args )->args,
+ $this->assertEquals(
+ MWFunction::newObj( 'MWBlankClass', $args )->args,
$newObject->args
);
- $this->assertEquals(
- MWFunction::newObj( 'MWBlankClass', $args, true )->args,
+ $this->assertEquals(
+ MWFunction::newObj( 'MWBlankClass', $args, true )->args,
$newObject->args,
'Works even with PHP version < 5.1.3'
);
}
-
+
/**
* @expectedException MWException
*/
function testCallingParentFails() {
MWFunction::call( 'parent::foo' );
}
-
+
/**
* @expectedException MWException
*/
function testCallingSelfFails() {
MWFunction::call( 'self::foo' );
}
-
+
public static function someMethod() {
return func_get_args();
}
-
+
}
class MWBlankClass {
$this->setMwGlobals( array(
'wgContentNamespaces' => array( NS_MAIN ),
'wgNamespacesWithSubpages' => array(
- NS_TALK => true,
- NS_USER => true,
- NS_USER_TALK => true,
+ NS_TALK => true,
+ NS_USER => true,
+ NS_USER_TALK => true,
),
'wgCapitalLinks' => true,
'wgCapitalLinkOverrides' => array(),
*/
public function testIsSubject() {
// Special namespaces
- $this->assertIsSubject( NS_MEDIA );
+ $this->assertIsSubject( NS_MEDIA );
$this->assertIsSubject( NS_SPECIAL );
// Subject pages
$this->assertIsSubject( NS_MAIN );
$this->assertIsSubject( NS_USER );
- $this->assertIsSubject( 100 ); # user defined
+ $this->assertIsSubject( 100 ); # user defined
// Talk pages
- $this->assertIsNotSubject( NS_TALK );
+ $this->assertIsNotSubject( NS_TALK );
$this->assertIsNotSubject( NS_USER_TALK );
- $this->assertIsNotSubject( 101 ); # user defined
+ $this->assertIsNotSubject( 101 ); # user defined
}
/**
*/
public function testIsTalk() {
// Special namespaces
- $this->assertIsNotTalk( NS_MEDIA );
+ $this->assertIsNotTalk( NS_MEDIA );
$this->assertIsNotTalk( NS_SPECIAL );
// Subject pages
- $this->assertIsNotTalk( NS_MAIN );
- $this->assertIsNotTalk( NS_USER );
- $this->assertIsNotTalk( 100 ); # user defined
+ $this->assertIsNotTalk( NS_MAIN );
+ $this->assertIsNotTalk( NS_USER );
+ $this->assertIsNotTalk( 100 ); # user defined
// Talk pages
- $this->assertIsTalk( NS_TALK );
+ $this->assertIsTalk( NS_TALK );
$this->assertIsTalk( NS_USER_TALK );
- $this->assertIsTalk( 101 ); # user defined
+ $this->assertIsTalk( 101 ); # user defined
}
/**
* @expectedException MWException
*/
public function testGetAssociatedExceptionsForNsMedia() {
- $this->assertNull( MWNamespace::getAssociated( NS_MEDIA ) );
+ $this->assertNull( MWNamespace::getAssociated( NS_MEDIA ) );
}
/**
/**
* @todo Implement testExists().
*/
-/*
+ /*
public function testExists() {
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet. Rely on $wgCanonicalNamespaces.'
);
}
-*/
+ */
/**
* Test MWNamespace::equals
$this->assertSameSubject( NS_USER, NS_USER_TALK );
$this->assertDifferentSubject( NS_PROJECT, NS_TEMPLATE );
- $this->assertDifferentSubject( NS_SPECIAL, NS_MAIN );
+ $this->assertDifferentSubject( NS_SPECIAL, NS_MAIN );
}
public function testSpecialAndMediaAreDifferentSubjects() {
/**
* @todo Implement testGetCanonicalNamespaces().
*/
-/*
+ /*
public function testGetCanonicalNamespaces() {
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet. Rely on $wgCanonicalNamespaces.'
);
}
-*/
+ */
/**
* @todo Implement testGetCanonicalName().
*/
-/*
- public function testGetCanonicalName() {
- // Remove the following lines when you implement this test.
- $this->markTestIncomplete(
- 'This test has not been implemented yet. Rely on $wgCanonicalNamespaces.'
- );
- }
-*/
+ /*
+ public function testGetCanonicalName() {
+ // Remove the following lines when you implement this test.
+ $this->markTestIncomplete(
+ 'This test has not been implemented yet. Rely on $wgCanonicalNamespaces.'
+ );
+ }
+ */
/**
* @todo Implement testGetCanonicalIndex().
*/
-/*
+ /*
public function testGetCanonicalIndex() {
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet. Rely on $wgCanonicalNamespaces.'
);
}
-*/
+ */
+
/**
* @todo Implement testGetValidNamespaces().
*/
-/*
+ /*
public function testGetValidNamespaces() {
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet. Rely on $wgCanonicalNamespaces.'
);
}
-*/
+ */
+
/**
*/
public function testCanTalk() {
- $this->assertCanNotTalk( NS_MEDIA );
+ $this->assertCanNotTalk( NS_MEDIA );
$this->assertCanNotTalk( NS_SPECIAL );
- $this->assertCanTalk( NS_MAIN );
- $this->assertCanTalk( NS_TALK );
- $this->assertCanTalk( NS_USER );
+ $this->assertCanTalk( NS_MAIN );
+ $this->assertCanTalk( NS_TALK );
+ $this->assertCanTalk( NS_USER );
$this->assertCanTalk( NS_USER_TALK );
// User defined namespaces
public function testIsWatchable() {
// Specials namespaces are not watchable
- $this->assertIsNotWatchable( NS_MEDIA );
+ $this->assertIsNotWatchable( NS_MEDIA );
$this->assertIsNotWatchable( NS_SPECIAL );
// Core defined namespaces are watchables
global $wgNamespacesWithSubpages;
// Special namespaces:
- $this->assertHasNotSubpages( NS_MEDIA );
+ $this->assertHasNotSubpages( NS_MEDIA );
$this->assertHasNotSubpages( NS_SPECIAL );
// Namespaces without subpages
$this->assertHasNotSubpages( NS_MAIN );
// Some namespaces with subpages
- $this->assertHasSubpages( NS_TALK );
- $this->assertHasSubpages( NS_USER );
+ $this->assertHasSubpages( NS_TALK );
+ $this->assertHasSubpages( NS_USER );
$this->assertHasSubpages( NS_USER_TALK );
}
*/
public function testGetSubjectNamespaces() {
$subjectsNS = MWNamespace::getSubjectNamespaces();
- $this->assertContains( NS_MAIN, $subjectsNS,
+ $this->assertContains( NS_MAIN, $subjectsNS,
"Talk namespaces should have NS_MAIN" );
$this->assertNotContains( NS_TALK, $subjectsNS,
"Talk namespaces should have NS_TALK" );
*/
public function testGetTalkNamespaces() {
$talkNS = MWNamespace::getTalkNamespaces();
- $this->assertContains( NS_TALK, $talkNS,
+ $this->assertContains( NS_TALK, $talkNS,
"Subject namespaces should have NS_TALK" );
$this->assertNotContains( NS_MAIN, $talkNS,
"Subject namespaces should not have NS_MAIN" );
// NS_MEDIA and NS_FILE are treated the same
$this->assertEquals(
MWNamespace::isCapitalized( NS_MEDIA ),
- MWNamespace::isCapitalized( NS_FILE ),
+ MWNamespace::isCapitalized( NS_FILE ),
'NS_MEDIA and NS_FILE have same capitalization rendering'
);
// Boths are capitalized by default
$this->assertIsCapitalized( NS_MEDIA );
- $this->assertIsCapitalized( NS_FILE );
+ $this->assertIsCapitalized( NS_FILE );
// Always capitalized namespaces
// @see MWNamespace::$alwaysCapitalizedNamespaces
- $this->assertIsCapitalized( NS_SPECIAL );
- $this->assertIsCapitalized( NS_USER );
+ $this->assertIsCapitalized( NS_SPECIAL );
+ $this->assertIsCapitalized( NS_USER );
$this->assertIsCapitalized( NS_MEDIAWIKI );
}
public function testIsCapitalizedWithWgCapitalLinks() {
global $wgCapitalLinks;
- $this->assertIsCapitalized( NS_PROJECT );
+ $this->assertIsCapitalized( NS_PROJECT );
$this->assertIsCapitalized( NS_PROJECT_TALK );
$wgCapitalLinks = false;
// hardcoded namespaces (see above function) are still capitalized:
- $this->assertIsCapitalized( NS_SPECIAL );
- $this->assertIsCapitalized( NS_USER );
+ $this->assertIsCapitalized( NS_SPECIAL );
+ $this->assertIsCapitalized( NS_USER );
$this->assertIsCapitalized( NS_MEDIAWIKI );
// setting is correctly applied
- $this->assertIsNotCapitalized( NS_PROJECT );
+ $this->assertIsNotCapitalized( NS_PROJECT );
$this->assertIsNotCapitalized( NS_PROJECT_TALK );
}
global $wgCapitalLinkOverrides;
// Test default settings
- $this->assertIsCapitalized( NS_PROJECT );
+ $this->assertIsCapitalized( NS_PROJECT );
$this->assertIsCapitalized( NS_PROJECT_TALK );
// hardcoded namespaces (see above function) are capitalized:
- $this->assertIsCapitalized( NS_SPECIAL );
- $this->assertIsCapitalized( NS_USER );
+ $this->assertIsCapitalized( NS_SPECIAL );
+ $this->assertIsCapitalized( NS_USER );
$this->assertIsCapitalized( NS_MEDIAWIKI );
// Hardcoded namespaces remains capitalized
- $wgCapitalLinkOverrides[NS_SPECIAL] = false;
- $wgCapitalLinkOverrides[NS_USER] = false;
+ $wgCapitalLinkOverrides[NS_SPECIAL] = false;
+ $wgCapitalLinkOverrides[NS_USER] = false;
$wgCapitalLinkOverrides[NS_MEDIAWIKI] = false;
- $this->assertIsCapitalized( NS_SPECIAL );
- $this->assertIsCapitalized( NS_USER );
+ $this->assertIsCapitalized( NS_SPECIAL );
+ $this->assertIsCapitalized( NS_USER );
$this->assertIsCapitalized( NS_MEDIAWIKI );
$wgCapitalLinkOverrides[NS_PROJECT] = false;
$this->assertIsNotCapitalized( NS_PROJECT );
- $wgCapitalLinkOverrides[NS_PROJECT] = true ;
+ $wgCapitalLinkOverrides[NS_PROJECT] = true;
$this->assertIsCapitalized( NS_PROJECT );
unset( $wgCapitalLinkOverrides[NS_PROJECT] );
public function testHasGenderDistinction() {
// Namespaces with gender distinctions
- $this->assertTrue( MWNamespace::hasGenderDistinction( NS_USER ) );
+ $this->assertTrue( MWNamespace::hasGenderDistinction( NS_USER ) );
$this->assertTrue( MWNamespace::hasGenderDistinction( NS_USER_TALK ) );
// Other ones, "genderless"
- $this->assertFalse( MWNamespace::hasGenderDistinction( NS_MEDIA ) );
+ $this->assertFalse( MWNamespace::hasGenderDistinction( NS_MEDIA ) );
$this->assertFalse( MWNamespace::hasGenderDistinction( NS_SPECIAL ) );
- $this->assertFalse( MWNamespace::hasGenderDistinction( NS_MAIN ) );
- $this->assertFalse( MWNamespace::hasGenderDistinction( NS_TALK ) );
-
+ $this->assertFalse( MWNamespace::hasGenderDistinction( NS_MAIN ) );
+ $this->assertFalse( MWNamespace::hasGenderDistinction( NS_TALK ) );
}
public function testIsNonincludable() {
####### HELPERS ###########################################################
function __call( $method, $args ) {
// Call the real method if it exists
- if( method_exists($this, $method ) ) {
+ if ( method_exists( $this, $method ) ) {
return $this->$method( $args );
}
- if( preg_match( '/^assert(Has|Is|Can)(Not|)(Subject|Talk|Watchable|Content|Subpages|Capitalized)$/', $method, $m ) ) {
+ if ( preg_match( '/^assert(Has|Is|Can)(Not|)(Subject|Talk|Watchable|Content|Subpages|Capitalized)$/', $method, $m ) ) {
# Interprets arguments:
- $ns = $args[0];
- $msg = isset($args[1]) ? $args[1] : " dummy message";
+ $ns = $args[0];
+ $msg = isset( $args[1] ) ? $args[1] : " dummy message";
# Forge the namespace constant name:
- if( $ns === 0 ) {
+ if ( $ns === 0 ) {
$ns_name = "NS_MAIN";
} else {
- $ns_name = "NS_" . strtoupper( MWNamespace::getCanonicalName( $ns ) );
+ $ns_name = "NS_" . strtoupper( MWNamespace::getCanonicalName( $ns ) );
}
# ... and the MWNamespace method name
$nsMethod = strtolower( $m[1] ) . $m[3];
- $expect = ($m[2] === '');
+ $expect = ( $m[2] === '' );
$expect_name = $expect ? 'TRUE' : 'FALSE';
return $this->assertEquals( $expect,
function assertSameSubject( $ns1, $ns2, $msg = '' ) {
$this->assertTrue( MWNamespace::subjectEquals( $ns1, $ns2, $msg ) );
}
+
function assertDifferentSubject( $ns1, $ns2, $msg = '' ) {
$this->assertFalse( MWNamespace::subjectEquals( $ns1, $ns2, $msg ) );
}
*
* @param array $args key-value array of arguments as shown above
*/
- protected function assertTransformCssMediaCase($args) {
+ protected function assertTransformCssMediaCase( $args ) {
$queryData = array();
if ( isset( $args['printableQuery'] ) ) {
$queryData['printable'] = $args['printableQuery'];
$fauxRequest = new FauxRequest( $queryData, false );
$this->setMWGlobals( array(
- 'wgRequest' => $fauxRequest,
- 'wgHandheldForIPhone' => $args['handheldForIPhone']
+ 'wgRequest' => $fauxRequest,
+ 'wgHandheldForIPhone' => $args['handheldForIPhone']
) );
$actualReturn = OutputPage::transformCssMedia( $args['media'] );
- $this->assertSame( $args['expectedReturn'], $actualReturn, $args['message']);
+ $this->assertSame( $args['expectedReturn'], $actualReturn, $args['message'] );
}
/**
* @param array $args key-value array of arguments as shown in assertTransformCssMediaCase.
* Will be mutated.
*/
- protected function assertTransformCssMediaCaseWithBothHandheldForIPhone($args) {
+ protected function assertTransformCssMediaCaseWithBothHandheldForIPhone( $args ) {
$message = $args['message'];
- foreach( array( true, false ) as $handheldForIPhone ) {
+ foreach ( array( true, false ) as $handheldForIPhone ) {
$args['handheldForIPhone'] = $handheldForIPhone;
- $stringHandheldForIPhone = var_export($handheldForIPhone, true);
+ $stringHandheldForIPhone = var_export( $handheldForIPhone, true );
$args['message'] = "$message. \$wgHandheldForIPhone was $stringHandheldForIPhone";
$this->assertTransformCssMediaCase( $args );
}
* Tests handheld and wgHandheldForIPhone behavior
*/
public function testHandheld() {
- $this->assertTransformCssMediaCaseWithBothHandheldForIPhone(array(
+ $this->assertTransformCssMediaCaseWithBothHandheldForIPhone( array(
'handheldQuery' => '1',
'media' => 'handheld',
'expectedReturn' => '',
'message' => 'On request with handheld querystring and media is handheld, returns empty string'
) );
- $this->assertTransformCssMediaCaseWithBothHandheldForIPhone(array(
+ $this->assertTransformCssMediaCaseWithBothHandheldForIPhone( array(
'handheldQuery' => '1',
'media' => 'screen',
'expectedReturn' => null,
) );
// A bit counter-intuitively, $wgHandheldForIPhone should only matter if the query handheld is false or omitted
- $this->assertTransformCssMediaCase(array(
+ $this->assertTransformCssMediaCase( array(
'handheldQuery' => '0',
'media' => 'screen',
'handheldForIPhone' => true,
'message' => 'With $wgHandheldForIPhone true, screen media type is transformed'
) );
- $this->assertTransformCssMediaCase(array(
+ $this->assertTransformCssMediaCase( array(
'media' => 'handheld',
'handheldForIPhone' => true,
'expectedReturn' => 'handheld, only screen and (max-device-width: 480px)',
protected function setUp() {
parent::setUp();
$router = new PathRouter;
- $router->add("/wiki/$1");
+ $router->add( "/wiki/$1" );
$this->basicRouter = $router;
}
*/
public function testLoose() {
$router = new PathRouter;
- $router->add("/"); # Should be the same as "/$1"
+ $router->add( "/" ); # Should be the same as "/$1"
$matches = $router->parse( "/Foo" );
$this->assertEquals( $matches, array( 'title' => "Foo" ) );
$router = new PathRouter;
- $router->add("/wiki"); # Should be the same as /wiki/$1
+ $router->add( "/wiki" ); # Should be the same as /wiki/$1
$matches = $router->parse( "/wiki/Foo" );
$this->assertEquals( $matches, array( 'title' => "Foo" ) );
$router = new PathRouter;
- $router->add("/wiki/"); # Should be the same as /wiki/$1
+ $router->add( "/wiki/" ); # Should be the same as /wiki/$1
$matches = $router->parse( "/wiki/Foo" );
$this->assertEquals( $matches, array( 'title' => "Foo" ) );
}
*/
public function testOrder() {
$router = new PathRouter;
- $router->add("/$1");
- $router->add("/a/$1");
- $router->add("/b/$1");
+ $router->add( "/$1" );
+ $router->add( "/a/$1" );
+ $router->add( "/b/$1" );
$matches = $router->parse( "/a/Foo" );
$this->assertEquals( $matches, array( 'title' => "Foo" ) );
$router = new PathRouter;
- $router->add("/b/$1");
- $router->add("/a/$1");
- $router->add("/$1");
+ $router->add( "/b/$1" );
+ $router->add( "/a/$1" );
+ $router->add( "/$1" );
$matches = $router->parse( "/a/Foo" );
$this->assertEquals( $matches, array( 'title' => "Foo" ) );
}
$router->add( array( 'qwerty' => "/qwerty/$1" ), array( 'qwerty' => '$key' ) );
$router->add( "/$2/$1", array( 'restricted-to-y' => '$2' ), array( '$2' => 'y' ) );
- foreach( array(
- "/Foo" => array( 'title' => "Foo" ),
- "/Bar" => array( 'ping' => 'pong' ),
- "/Baz" => array( 'marco' => 'polo' ),
- "/asdf-foo" => array( 'title' => "qwerty-foo" ),
- "/qwerty-bar" => array( 'title' => "asdf-bar" ),
- "/a/Foo" => array( 'title' => "Foo" ),
- "/asdf/Foo" => array( 'title' => "Foo" ),
- "/qwerty/Foo" => array( 'title' => "Foo", 'qwerty' => 'qwerty' ),
- "/baz/Foo" => array( 'title' => "Foo", 'unrestricted' => 'baz' ),
- "/y/Foo" => array( 'title' => "Foo", 'restricted-to-y' => 'y' ),
- ) as $path => $result ) {
+ foreach ( array(
+ '/Foo' => array( 'title' => 'Foo' ),
+ '/Bar' => array( 'ping' => 'pong' ),
+ '/Baz' => array( 'marco' => 'polo' ),
+ '/asdf-foo' => array( 'title' => 'qwerty-foo' ),
+ '/qwerty-bar' => array( 'title' => 'asdf-bar' ),
+ '/a/Foo' => array( 'title' => 'Foo' ),
+ '/asdf/Foo' => array( 'title' => 'Foo' ),
+ '/qwerty/Foo' => array( 'title' => 'Foo', 'qwerty' => 'qwerty' ),
+ '/baz/Foo' => array( 'title' => 'Foo', 'unrestricted' => 'baz' ),
+ '/y/Foo' => array( 'title' => 'Foo', 'restricted-to-y' => 'y' ),
+ ) as $path => $result ) {
$this->assertEquals( $router->parse( $path ), $result );
}
}
$this->prefUsers['notauth']
->setEmail( 'noauth@example.org' );
- $this->prefUsers['auth'] = new User;
+ $this->prefUsers['auth'] = new User;
$this->prefUsers['auth']
->setEmail( 'noauth@example.org' );
$this->prefUsers['auth']
->setEmailAuthenticationTimestamp( 1330946623 );
$this->context = new RequestContext;
- $this->context->setTitle( Title::newFromText('PreferencesTest') );
+ $this->context->setTitle( Title::newFromText( 'PreferencesTest' ) );
}
protected function setUp() {
);
$this->assertEquals( 'mw-email-none', $prefs['emailaddress']['cssclass'] );
}
+
/**
* Placeholder to verify bug 34302
* @covers Preferences::profilePreferences
);
$this->assertEquals( 'mw-email-not-authenticated', $prefs['emailaddress']['cssclass'] );
}
+
/**
* Placeholder to verify bug 34302
* @covers Preferences::profilePreferences
/* provide an array of numbers from 1 up to @param $num */
private static function createProviderUpTo( $num ) {
$ret = array();
- for( $i=1; $i<=$num;$i++ ) {
+ for ( $i = 1; $i <= $num; $i++ ) {
$ret[] = array( $i );
}
return $ret;
$ret = array();
$months = self::Months();
- $days = self::Days();
- foreach( $months as $month) {
- foreach( $days as $day ) {
+ $days = self::Days();
+ foreach ( $months as $month ) {
+ foreach ( $days as $day ) {
$ret[] = array( $day[0], $month[0] );
}
}
function __construct() {
parent::__construct();
- $this->title = Title::newFromText( 'SomeTitle' );
+ $this->title = Title::newFromText( 'SomeTitle' );
$this->target = Title::newFromText( 'TestTarget' );
- $this->user = User::newFromName( 'UserName' );
+ $this->user = User::newFromName( 'UserName' );
$this->user_comment = '<User comment about action>';
$this->context = RequestContext::newExtraneousContext( $this->title );
# block/block
$this->assertIRCComment(
- $this->context->msg( 'blocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'blocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
'block', 'block',
array(),
$this->user_comment
);
# block/unblock
$this->assertIRCComment(
- $this->context->msg( 'unblocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'unblocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
'block', 'unblock',
array(),
$this->user_comment
# delete/delete
$this->assertIRCComment(
- $this->context->msg( 'deletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'deletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
'delete', 'delete',
array(),
$this->user_comment
# delete/restore
$this->assertIRCComment(
- $this->context->msg( 'undeletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'undeletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
'delete', 'restore',
array(),
$this->user_comment
*/
function testIrcMsgForLogTypeMove() {
$move_params = array(
- '4::target' => $this->target->getPrefixedText(),
+ '4::target' => $this->target->getPrefixedText(),
'5::noredir' => 0,
);
$sep = $this->context->msg( 'colon-separator' )->text();
# move/move
$this->assertIRCComment(
- $this->context->msg( '1movedto2', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( '1movedto2', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
'move', 'move',
$move_params,
$this->user_comment
# move/move_redir
$this->assertIRCComment(
- $this->context->msg( '1movedto2_redir', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( '1movedto2_redir', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
'move', 'move_redir',
$move_params,
$this->user_comment
$this->context->msg( 'patrol-log-line', 'revision 777', '[[SomeTitle]]', '' )->plain(),
'patrol', 'patrol',
array(
- '4::curid' => '777',
+ '4::curid' => '777',
'5::previd' => '666',
- '6::auto' => 0,
+ '6::auto' => 0,
)
);
}
# protect/protect
$this->assertIRCComment(
- $this->context->msg( 'protectedarticle', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'protectedarticle', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
'protect', 'protect',
$protectParams,
$this->user_comment
# protect/unprotect
$this->assertIRCComment(
- $this->context->msg( 'unprotectedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'unprotectedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
'protect', 'unprotect',
array(),
$this->user_comment
# protect/modify
$this->assertIRCComment(
- $this->context->msg( 'modifiedarticleprotection', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'modifiedarticleprotection', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
'protect', 'modify',
$protectParams,
$this->user_comment
# upload/upload
$this->assertIRCComment(
- $this->context->msg( 'uploadedimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'uploadedimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
'upload', 'upload',
array(),
$this->user_comment
# upload/overwrite
$this->assertIRCComment(
- $this->context->msg( 'overwroteimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'overwroteimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
'upload', 'overwrite',
array(),
$this->user_comment
* raw edit summary from RecentChange object
* --
*/
-/*
+ /*
function testIrcMsgForBlankingAES() {
// $this->context->msg( 'autosumm-blank', .. );
}
function testIrcMsgForUndoAES() {
// $this->context->msg( 'undo-summary', .. );
}
-
-*/
+ */
/**
* @param $expected String Expected IRC text without colors codes
/* Stubs */
-class ResourceLoaderTestModule extends ResourceLoaderModule { }
+class ResourceLoaderTestModule extends ResourceLoaderModule {}
/* Hooks */
global $wgHooks;
parent::__construct( $name, $data, $dataName );
$this->tablesUsed = array_merge( $this->tablesUsed,
- array( 'page',
- 'revision',
- 'text',
-
- 'recentchanges',
- 'logging',
-
- 'page_props',
- 'pagelinks',
- 'categorylinks',
- 'langlinks',
- 'externallinks',
- 'imagelinks',
- 'templatelinks',
- 'iwlinks' ) );
+ array( 'page',
+ 'revision',
+ 'text',
+
+ 'recentchanges',
+ 'logging',
+
+ 'page_props',
+ 'pagelinks',
+ 'categorylinks',
+ 'langlinks',
+ 'externallinks',
+ 'imagelinks',
+ 'templatelinks',
+ 'iwlinks' ) );
}
public function setUp() {
parent::setUp();
- $wgExtraNamespaces[ 12312 ] = 'Dummy';
- $wgExtraNamespaces[ 12313 ] = 'Dummy_talk';
+ $wgExtraNamespaces[12312] = 'Dummy';
+ $wgExtraNamespaces[12313] = 'Dummy_talk';
- $wgNamespaceContentModels[ 12312 ] = 'DUMMY';
- $wgContentHandlers[ 'DUMMY' ] = 'DummyContentHandlerForTesting';
+ $wgNamespaceContentModels[12312] = 'DUMMY';
+ $wgContentHandlers['DUMMY'] = 'DummyContentHandlerForTesting';
MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
$wgContLang->resetNamespaces(); # reset namespace cache
parent::tearDown();
- unset( $wgExtraNamespaces[ 12312 ] );
- unset( $wgExtraNamespaces[ 12313 ] );
+ unset( $wgExtraNamespaces[12312] );
+ unset( $wgExtraNamespaces[12313] );
- unset( $wgNamespaceContentModels[ 12312 ] );
- unset( $wgContentHandlers[ 'DUMMY' ] );
+ unset( $wgNamespaceContentModels[12312] );
+ unset( $wgContentHandlers['DUMMY'] );
MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
$wgContLang->resetNamespaces(); # reset namespace cache
}
protected function makeRevision( $props = null ) {
- if ( $props === null ) $props = array();
+ if ( $props === null ) {
+ $props = array();
+ }
- if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) $props['text'] = 'Lorem Ipsum';
- if ( !isset( $props['comment'] ) ) $props['comment'] = 'just a test';
- if ( !isset( $props['page'] ) ) $props['page'] = $this->the_page->getId();
+ if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) {
+ $props['text'] = 'Lorem Ipsum';
+ }
+
+ if ( !isset( $props['comment'] ) ) {
+ $props['comment'] = 'just a test';
+ }
+
+ if ( !isset( $props['page'] ) ) {
+ $props['page'] = $this->the_page->getId();
+ }
$rev = new Revision( $props );
protected function createPage( $page, $text, $model = null ) {
if ( is_string( $page ) ) {
if ( !preg_match( '/:/', $page ) &&
- ( $model === null || $model === CONTENT_MODEL_WIKITEXT ) ) {
-
+ ( $model === null || $model === CONTENT_MODEL_WIKITEXT )
+ ) {
$ns = $this->getDefaultWikitextNS();
$page = MWNamespace::getCanonicalName( $ns ) . ':' . $page;
}
#note: order is unspecified
$rows = array();
while ( ( $row = $res->fetchObject() ) ) {
- $rows[ $row->rev_id ]= $row;
+ $rows[$row->rev_id] = $row;
}
$row = $res->fetchObject();
- $this->assertEquals( 1, count($rows), 'expected exactly one revision' );
+ $this->assertEquals( 1, count( $rows ), 'expected exactly one revision' );
$this->assertArrayHasKey( $id2, $rows, 'missing revision with id ' . $id2 );
}
$fields = Revision::selectFields();
- $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields');
- $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields');
- $this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields');
- $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields');
+ $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields' );
+ $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields' );
+ $this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields' );
+ $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields' );
if ( $wgContentHandlerUseDB ) {
$this->assertTrue( in_array( 'rev_content_model', $fields ),
- 'missing rev_content_model in list of fields');
+ 'missing rev_content_model in list of fields' );
$this->assertTrue( in_array( 'rev_content_format', $fields ),
- 'missing rev_content_format in list of fields');
+ 'missing rev_content_format in list of fields' );
}
}
*/
public function testGetContent_failure() {
$rev = new Revision( array(
- 'page' => $this->the_page->getId(),
+ 'page' => $this->the_page->getId(),
'content_model' => $this->the_page->getContentModel(),
'text_id' => 123456789, // not in the test DB
) );
}
$orig = $this->makeRevision( array( 'text' => 'hello hello.',
- 'content_model' => CONTENT_MODEL_JAVASCRIPT ) );
+ 'content_model' => CONTENT_MODEL_JAVASCRIPT ) );
$rev = Revision::newFromId( $orig->getId() );
$this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() );
$this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
}
- $orig = $this->makeRevision( array( 'text' => 'hello hello.',
- 'content_model' => CONTENT_MODEL_JAVASCRIPT,
- 'content_format' => CONTENT_FORMAT_JAVASCRIPT ) );
+ $orig = $this->makeRevision( array(
+ 'text' => 'hello hello.',
+ 'content_model' => CONTENT_MODEL_JAVASCRIPT,
+ 'content_format' => CONTENT_FORMAT_JAVASCRIPT
+ ) );
$rev = Revision::newFromId( $orig->getId() );
$this->assertEquals( CONTENT_FORMAT_JAVASCRIPT, $rev->getContentFormat() );
$this->assertNull( $rev1->getPrevious() );
$page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
- 'second rev testGetPrevious' );
+ 'second rev testGetPrevious' );
$rev2 = $page->getRevision();
$this->assertNotNull( $rev2->getPrevious() );
$this->assertNull( $rev1->getNext() );
$page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
- 'second rev testGetNext' );
+ 'second rev testGetNext' );
$rev2 = $page->getRevision();
$this->assertNotNull( $rev1->getNext() );
$rev = Revision::newNullRevision( $dbw, $page->getId(), 'a null revision', false );
$this->assertNotEquals( $orig->getId(), $rev->getId(),
- 'new null revision shold have a different id from the original revision' );
+ 'new null revision shold have a different id from the original revision' );
$this->assertEquals( $orig->getTextId(), $rev->getTextId(),
- 'new null revision shold have the same text id as the original revision' );
+ 'new null revision shold have the same text id as the original revision' );
$this->assertEquals( 'some testing text', $rev->getContent()->getNativeData() );
}
$revisions[4]->insertOn( $dbw );
// test it ---------------------------------
- $since = $revisions[ $sinceIdx ]->getTimestamp();
+ $since = $revisions[$sinceIdx]->getTimestamp();
$wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
public function testSelectFields() {
$fields = Revision::selectFields();
- $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields');
- $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields');
- $this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields');
- $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields');
+ $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields' );
+ $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields' );
+ $this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields' );
+ $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields' );
- $this->assertFalse( in_array( 'rev_content_model', $fields ), 'missing rev_content_model in list of fields');
- $this->assertFalse( in_array( 'rev_content_format', $fields ), 'missing rev_content_format in list of fields');
+ $this->assertFalse( in_array( 'rev_content_model', $fields ), 'missing rev_content_model in list of fields' );
+ $this->assertFalse( in_array( 'rev_content_format', $fields ), 'missing rev_content_format in list of fields' );
}
/**
public function testGetContentModel() {
try {
$this->makeRevision( array( 'text' => 'hello hello.',
- 'content_model' => CONTENT_MODEL_JAVASCRIPT ) );
+ 'content_model' => CONTENT_MODEL_JAVASCRIPT ) );
$this->fail( "Creating JavaScript content on a wikitext page should fail with "
. "\$wgContentHandlerUseDB disabled" );
// used for this though.
$this->makeRevision( array( 'text' => 'hello hello.',
- 'content_model' => CONTENT_MODEL_JAVASCRIPT,
- 'content_format' => 'text/javascript' ) );
+ 'content_model' => CONTENT_MODEL_JAVASCRIPT,
+ 'content_format' => 'text/javascript' ) );
$this->fail( "Creating JavaScript content on a wikitext page should fail with "
. "\$wgContentHandlerUseDB disabled" );
$rev = new Revision(
array(
- 'id' => 42,
- 'page' => 23,
- 'title' => $title,
+ 'id' => 42,
+ 'page' => 23,
+ 'title' => $title,
- 'content' => $content,
- 'length' => $content->getSize(),
- 'comment' => "testing",
+ 'content' => $content,
+ 'length' => $content->getSize(),
+ 'comment' => "testing",
'minor_edit' => false,
'content_format' => $format,
return array(
array( 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT ),
array( 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS ),
- array( serialize('hello world'), 'Dummy:Hello', null, null, "testing" ),
+ array( serialize( 'hello world' ), 'Dummy:Hello', null, null, "testing" ),
);
}
array( 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT ),
array( 'hello world', 'Help:Hello', CONTENT_MODEL_CSS, null, CONTENT_FORMAT_CSS ),
array( 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS ),
- array( serialize('hello world'), 'Dummy:Hello', null, null, "testing" ),
+ array( serialize( 'hello world' ), 'Dummy:Hello', null, null, "testing" ),
);
}
return array(
array( 'hello world', 'Help:Hello', null, null, 'WikitextContentHandler' ),
array( 'hello world', 'User:hello/there.css', null, null, 'CssContentHandler' ),
- array( serialize('hello world'), 'Dummy:Hello', null, null, 'DummyContentHandlerForTesting' ),
+ array( serialize( 'hello world' ), 'Dummy:Hello', null, null, 'DummyContentHandlerForTesting' ),
);
}
//NOTE: we expect the help namespace to always contain wikitext
return array(
array( 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ),
- array( serialize('hello world'), 'Hello', "testing", null, Revision::FOR_PUBLIC, serialize('hello world') ),
- array( serialize('hello world'), 'Dummy:Hello', null, null, Revision::FOR_PUBLIC, serialize('hello world') ),
+ array( serialize( 'hello world' ), 'Hello', "testing", null, Revision::FOR_PUBLIC, serialize( 'hello world' ) ),
+ array( serialize( 'hello world' ), 'Dummy:Hello', null, null, Revision::FOR_PUBLIC, serialize( 'hello world' ) ),
);
}
//NOTE: we expect the help namespace to always contain wikitext
return array(
array( 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ),
- array( serialize('hello world'), 'Hello', "testing", null, Revision::FOR_PUBLIC, null ),
- array( serialize('hello world'), 'Dummy:Hello', null, null, Revision::FOR_PUBLIC, null ),
+ array( serialize( 'hello world' ), 'Hello', "testing", null, Revision::FOR_PUBLIC, null ),
+ array( serialize( 'hello world' ), 'Dummy:Hello', null, null, Revision::FOR_PUBLIC, null ),
);
}
}
- public function dataGetSize( ) {
+ public function dataGetSize() {
return array(
array( "hello world.", CONTENT_MODEL_WIKITEXT, 12 ),
array( serialize( "hello world." ), "testing", 12 ),
$this->assertEquals( $expected_size, $rev->getSize() );
}
- public function dataGetSha1( ) {
+ public function dataGetSha1() {
return array(
array( "hello world.", CONTENT_MODEL_WIKITEXT, Revision::base36Sha1( "hello world." ) ),
array( serialize( "hello world." ), "testing", Revision::base36Sha1( serialize( "hello world." ) ) ),
$this->hideDeprecated( "Revision::getText" );
$rev = new Revision( array(
- 'text' => 'hello world.',
- 'content_model' => CONTENT_MODEL_JAVASCRIPT
- ));
+ 'text' => 'hello world.',
+ 'content_model' => CONTENT_MODEL_JAVASCRIPT
+ ) );
$this->assertNotNull( $rev->getText(), 'no content text' );
$this->assertNotNull( $rev->getContent(), 'no content object available' );
$title = Title::newFromText( 'RevisionTest_testConstructWithContent' );
$rev = new Revision( array(
- 'content' => ContentHandler::makeContent( 'hello world.', $title, CONTENT_MODEL_JAVASCRIPT ),
- ));
+ 'content' => ContentHandler::makeContent( 'hello world.', $title, CONTENT_MODEL_JAVASCRIPT ),
+ ) );
$this->assertNotNull( $rev->getText(), 'no content text' );
$this->assertNotNull( $rev->getContent(), 'no content object available' );
*
* @group Database
*/
- function testGetContentClone( ) {
+ function testGetContentClone() {
$content = new RevisionTestModifyableContent( "foo" );
$rev = new Revision(
array(
- 'id' => 42,
- 'page' => 23,
- 'title' => Title::newFromText( "testGetContentClone_dummy" ),
+ 'id' => 42,
+ 'page' => 23,
+ 'title' => Title::newFromText( "testGetContentClone_dummy" ),
- 'content' => $content,
- 'length' => $content->getSize(),
- 'comment' => "testing",
+ 'content' => $content,
+ 'length' => $content->getSize(),
+ 'comment' => "testing",
'minor_edit' => false,
)
);
parent::__construct( $text, "RevisionTestModifyableContent" );
}
- public function copy( ) {
+ public function copy() {
return new RevisionTestModifyableContent( $this->mText );
}
class RevisionTestModifyableContentHandler extends TextContentHandler {
- public function __construct( ) {
+ public function __construct() {
parent::__construct( "RevisionTestModifyableContent", array( CONTENT_FORMAT_TEXT ) );
}
* http://www.phpunit.de/manual/3.4/en/other-uses-for-tests.html
*/
function testTitleObjectStringConversion() {
- $title = Title::newFromText("text");
- $this->assertInstanceOf('Title', $title, "Title creation");
- $this->assertEquals("Text", $title, "Automatic string conversion");
+ $title = Title::newFromText( "text" );
+ $this->assertInstanceOf( 'Title', $title, "Title creation" );
+ $this->assertEquals( "Text", $title, "Automatic string conversion" );
- $title = Title::newFromText("text", NS_MEDIA);
- $this->assertEquals("Media:Text", $title, "Title creation with namespace");
+ $title = Title::newFromText( "text", NS_MEDIA );
+ $this->assertEquals( "Media:Text", $title, "Title creation with namespace" );
}
/**
* @dataProvider provideTitles
* See http://www.phpunit.de/manual/3.4/en/appendixes.annotations.html#appendixes.annotations.dataProvider
*/
- public function testCreateBasicListOfTitles($titleName, $ns, $text) {
- $title = Title::newFromText($titleName, $ns);
- $this->assertEquals($text, "$title", "see if '$titleName' matches '$text'");
+ public function testCreateBasicListOfTitles( $titleName, $ns, $text ) {
+ $title = Title::newFromText( $titleName, $ns );
+ $this->assertEquals( $text, "$title", "see if '$titleName' matches '$text'" );
}
public function testSetUpMainPageTitleForNextTest() {
$title = Title::newMainPage();
- $this->assertEquals("Main Page", "$title", "Test initial creation of a title");
+ $this->assertEquals( "Main Page", "$title", "Test initial creation of a title" );
return $title;
}
# Enable HTML5 mode
'wgHtml5' => true,
'wgUseTidy' => false
- ));
+ ) );
- if( $escaped ) {
+ if ( $escaped ) {
$this->assertEquals( "<$tag>",
Sanitizer::removeHTMLtags( "<$tag>" )
);
* Provide HTML5 tags
*/
function provideHtml5Tags() {
- $ESCAPED = true; # We want tag to be escaped
- $VERBATIM = false; # We want to keep the tag
+ $ESCAPED = true; # We want tag to be escaped
+ $VERBATIM = false; # We want to keep the tag
return array(
array( 'data', $VERBATIM ),
array( 'mark', $VERBATIM ),
function testSelfClosingTag() {
$this->setMwGlobals( array(
'wgUseTidy' => false
- ));
+ ) );
$this->assertEquals(
'<div>Hello world</div>',
array( ' ', "\\2f\\2a foo \\2a\\2f",
'Backslash-escaped comments must be stripped (bug 28450)' ),
array( '', '/* unfinished comment structure',
- 'Remove anything after a comment-start token' ),
+ 'Remove anything after a comment-start token' ),
array( '', "\\2f\\2a unifinished comment'",
- 'Remove anything after a backslash-escaped comment-start token' ),
- array( '/* insecure input */', 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'asdf.png\',sizingMethod=\'scale\');'),
- array( '/* insecure input */', '-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'asdf.png\',sizingMethod=\'scale\')";'),
- array( '/* insecure input */', 'width: expression(1+1);'),
- array( '/* insecure input */', 'background-image: image(asdf.png);'),
- array( '/* insecure input */', 'background-image: -webkit-image(asdf.png);'),
- array( '/* insecure input */', 'background-image: -moz-image(asdf.png);'),
- array( '/* insecure input */', 'background-image: image-set("asdf.png" 1x, "asdf.png" 2x);'),
- array( '/* insecure input */', 'background-image: -webkit-image-set("asdf.png" 1x, "asdf.png" 2x);'),
- array( '/* insecure input */', 'background-image: -moz-image-set("asdf.png" 1x, "asdf.png" 2x);'),
+ 'Remove anything after a backslash-escaped comment-start token' ),
+ array( '/* insecure input */', 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'asdf.png\',sizingMethod=\'scale\');' ),
+ array( '/* insecure input */', '-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'asdf.png\',sizingMethod=\'scale\')";' ),
+ array( '/* insecure input */', 'width: expression(1+1);' ),
+ array( '/* insecure input */', 'background-image: image(asdf.png);' ),
+ array( '/* insecure input */', 'background-image: -webkit-image(asdf.png);' ),
+ array( '/* insecure input */', 'background-image: -moz-image(asdf.png);' ),
+ array( '/* insecure input */', 'background-image: image-set("asdf.png" 1x, "asdf.png" 2x);' ),
+ array( '/* insecure input */', 'background-image: -webkit-image-set("asdf.png" 1x, "asdf.png" 2x);' ),
+ array( '/* insecure input */', 'background-image: -moz-image-set("asdf.png" 1x, "asdf.png" 2x);' ),
);
}
+
+ /**
+ * Test for support or lack of support for specific attributes in the attribute whitelist.
+ */
+ function provideAttributeSupport() {
+ /** array( <attributes>, <expected>, <message> ) */
+ return array(
+ array( 'div', ' role="presentation"', ' role="presentation"', 'Support for WAI-ARIA\'s role="presentation".' ),
+ array( 'div', ' role="main"', '', "Other WAI-ARIA roles are currently not supported." ),
+ );
+ }
+
+ /**
+ * @dataProvider provideAttributeSupport
+ */
+ function testAttributeSupport( $tag, $attributes, $expected, $message ) {
+ $this->assertEquals( $expected,
+ Sanitizer::fixTagAttributes( $attributes, $tag ),
+ $message
+ );
+ }
+
}
class SanitizerValidateEmailTest extends MediaWikiTestCase {
- private function checkEmail( $addr, $expected = true, $msg = '') {
- if( $msg == '' ) { $msg = "Testing $addr"; }
+ private function checkEmail( $addr, $expected = true, $msg = '' ) {
+ if ( $msg == '' ) {
+ $msg = "Testing $addr";
+ }
+
$this->assertEquals(
$expected,
Sanitizer::validateEmail( $addr ),
$msg
);
}
+
private function valid( $addr, $msg = '' ) {
$this->checkEmail( $addr, true, $msg );
}
+
private function invalid( $addr, $msg = '' ) {
$this->checkEmail( $addr, false, $msg );
}
$this->valid( 'user@example.com' );
$this->valid( 'user@example.museum' );
}
+
function testEmailWithUpperCaseCharactersAreValid() {
$this->valid( 'USER@example.com' );
$this->valid( 'user@EXAMPLE.COM' );
$this->valid( 'user@Example.com' );
$this->valid( 'USER@eXAMPLE.com' );
}
+
function testEmailWithAPlusInUserName() {
$this->valid( 'user+sub@example.com' );
$this->valid( 'user+@example.com' );
}
+
function testEmailDoesNotNeedATopLevelDomain() {
$this->valid( "user@localhost" );
$this->valid( "FooBar@localdomain" );
$this->valid( "nobody@mycompany" );
}
+
function testEmailWithWhiteSpacesBeforeOrAfterAreInvalids() {
$this->invalid( " user@host.com" );
$this->invalid( "user@host.com " );
$this->invalid( "\tuser@host.com" );
$this->invalid( "user@host.com\t" );
}
+
function testEmailWithWhiteSpacesAreInvalids() {
$this->invalid( "User user@host" );
$this->invalid( "first last@mycompany" );
$this->invalid( "firstlast@my company" );
}
+
// bug 26948 : comma were matched by an incorrect regexp range
function testEmailWithCommasAreInvalids() {
$this->invalid( "user,foo@example.org" );
$this->invalid( "userfoo@ex,ample.org" );
}
+
function testEmailWithHyphens() {
$this->valid( "user-foo@example.org" );
$this->valid( "userfoo@ex-ample.org" );
}
+
function testEmailDomainCanNotBeginWithDot() {
$this->invalid( "user@." );
$this->invalid( "user@.localdomain" );
$this->valid( ".@localdomain" );
$this->invalid( ".@a............" );
}
+
function testEmailWithFunnyCharacters() {
$this->valid( "\$user!ex{this}@123.com" );
}
+
function testEmailTopLevelDomainCanBeNumerical() {
$this->valid( "user@example.1234" );
}
+
function testEmailWithoutAtSignIsInvalid() {
$this->invalid( 'useràexample.com' );
}
+
function testEmailWithOneCharacterDomainIsValid() {
$this->valid( 'user@a' );
}
/**
* String containing the a sample selenium settings
*/
- private $testConfig0 =
-'
+ private $testConfig0 = '
[SeleniumSettings]
browsers[firefox] = "*firefox"
browsers[iexplorer] = "*iexploreproxy"
/**
* Array of expected browsers from $testConfig0
*/
- private $testBrowsers0 = array( 'firefox' => '*firefox',
- 'iexplorer' => '*iexploreproxy',
- 'chrome' => '*chrome'
+ private $testBrowsers0 = array( 'firefox' => '*firefox',
+ 'iexplorer' => '*iexploreproxy',
+ 'chrome' => '*chrome'
);
/**
* Array of expected selenium settings from $testConfig0
*/
private $testSettings0 = array(
- 'host' => 'localhost',
- 'port' => 'foobarr',
- 'wikiUrl' => 'http://localhost/deployment',
- 'username' => 'xxxxxxx',
- 'userPassword' => '',
- 'testBrowser' => 'chrome',
+ 'host' => 'localhost',
+ 'port' => 'foobarr',
+ 'wikiUrl' => 'http://localhost/deployment',
+ 'username' => 'xxxxxxx',
+ 'userPassword' => '',
+ 'testBrowser' => 'chrome',
'startserver' => null,
'stopserver' => null,
'seleniumserverexecpath' => null,
* Array of expected testSuites from $testConfig0
*/
private $testSuites0 = array(
- 'SimpleSeleniumTestSuite' => 'tests/selenium/SimpleSeleniumTestSuite.php',
- 'TestSuiteName' => 'testSuitePath'
+ 'SimpleSeleniumTestSuite' => 'tests/selenium/SimpleSeleniumTestSuite.php',
+ 'TestSuiteName' => 'testSuitePath'
);
-
/**
* Another sample selenium settings file contents
*/
private $testConfig1 =
-'
+ '
[SeleniumSettings]
host = "localhost"
testBrowser = "firefox"
* Expected selenium settings from $testConfig1
*/
private $testSettings1 = array(
- 'host' => 'localhost',
- 'port' => null,
- 'wikiUrl' => null,
- 'username' => null,
- 'userPassword' => null,
- 'testBrowser' => 'firefox',
+ 'host' => 'localhost',
+ 'port' => null,
+ 'wikiUrl' => null,
+ 'username' => null,
+ 'userPassword' => null,
+ 'testBrowser' => 'firefox',
'startserver' => null,
'stopserver' => null,
'seleniumserverexecpath' => null,
$seleniumBrowsers = array();
$seleniumTestSuites = array();
- SeleniumConfig::getSeleniumSettings($seleniumSettings,
+ SeleniumConfig::getSeleniumSettings( $seleniumSettings,
$seleniumBrowsers,
$seleniumTestSuites,
"Some_fake_settings_file.ini" );
-
}
/**
$seleniumTestSuites = array();
global $wgSeleniumConfigFile;
$wgSeleniumConfigFile = '';
- SeleniumConfig::getSeleniumSettings($seleniumSettings,
+ SeleniumConfig::getSeleniumSettings( $seleniumSettings,
$seleniumBrowsers,
- $seleniumTestSuites);
+ $seleniumTestSuites );
}
/**
global $wgSeleniumConfigFile;
$this->writeToTempFile( $this->testConfig0 );
$wgSeleniumConfigFile = $this->tempFileName;
- SeleniumConfig::getSeleniumSettings($seleniumSettings,
+ SeleniumConfig::getSeleniumSettings( $seleniumSettings,
$seleniumBrowsers,
- $seleniumTestSuites);
- $this->assertEquals($seleniumSettings, $this->testSettings0,
- 'The selenium settings should have been read from the file defined in $wgSeleniumConfigFile'
+ $seleniumTestSuites );
+ $this->assertEquals( $seleniumSettings, $this->testSettings0,
+ 'The selenium settings should have been read from the file defined in $wgSeleniumConfigFile'
);
- $this->assertEquals($seleniumBrowsers, $this->testBrowsers0,
- 'The available browsers should have been read from the file defined in $wgSeleniumConfigFile'
+ $this->assertEquals( $seleniumBrowsers, $this->testBrowsers0,
+ 'The available browsers should have been read from the file defined in $wgSeleniumConfigFile'
);
- $this->assertEquals($seleniumTestSuites, $this->testSuites0,
- 'The test suites should have been read from the file defined in $wgSeleniumConfigFile'
+ $this->assertEquals( $seleniumTestSuites, $this->testSuites0,
+ 'The test suites should have been read from the file defined in $wgSeleniumConfigFile'
);
}
* @group SeleniumFramework
* @dataProvider sampleConfigs
*/
- public function testgetSeleniumSettings($sampleConfig, $expectedSettings, $expectedBrowsers, $expectedSuites ) {
+ public function testgetSeleniumSettings( $sampleConfig, $expectedSettings, $expectedBrowsers, $expectedSuites ) {
$this->writeToTempFile( $sampleConfig );
$seleniumSettings = array();
$seleniumBrowsers = array();
$seleniumTestSuites = null;
- SeleniumConfig::getSeleniumSettings($seleniumSettings,
+ SeleniumConfig::getSeleniumSettings( $seleniumSettings,
$seleniumBrowsers,
$seleniumTestSuites,
$this->tempFileName );
- $this->assertEquals($seleniumSettings, $expectedSettings,
- "The selenium settings for the following test configuration was not retrieved correctly" . $sampleConfig
+ $this->assertEquals( $seleniumSettings, $expectedSettings,
+ "The selenium settings for the following test configuration was not retrieved correctly" . $sampleConfig
);
- $this->assertEquals($seleniumBrowsers, $expectedBrowsers,
- "The available browsers for the following test configuration was not retrieved correctly" . $sampleConfig
+ $this->assertEquals( $seleniumBrowsers, $expectedBrowsers,
+ "The available browsers for the following test configuration was not retrieved correctly" . $sampleConfig
);
- $this->assertEquals($seleniumTestSuites, $expectedSuites,
- "The test suites for the following test configuration was not retrieved correctly" . $sampleConfig
+ $this->assertEquals( $seleniumTestSuites, $expectedSuites,
+ "The test suites for the following test configuration was not retrieved correctly" . $sampleConfig
);
-
-
}
/**
* create a temp file and write text to it.
* @param $testToWrite the text to write to the temp file
*/
- private function writeToTempFile($textToWrite) {
- $this->tempFileName = tempnam(sys_get_temp_dir(), 'test_settings.');
- $tempFile = fopen( $this->tempFileName, "w" );
- fwrite($tempFile, $textToWrite);
- fclose($tempFile);
+ private function writeToTempFile( $textToWrite ) {
+ $this->tempFileName = tempnam( sys_get_temp_dir(), 'test_settings.' );
+ $tempFile = fopen( $this->tempFileName, "w" );
+ fwrite( $tempFile, $textToWrite );
+ fclose( $tempFile );
}
/**
* Returns an array containing:
- * The contents of the selenium cingiguration ini file
+ * The contents of the selenium cingiguration ini file
* The expected selenium configuration array that getSeleniumSettings should return
* The expected available browsers array that getSeleniumSettings should return
* The expected test suites arrya that getSeleniumSettings should return
*/
public function sampleConfigs() {
return array(
- array($this->testConfig0, $this->testSettings0, $this->testBrowsers0, $this->testSuites0 ),
- array($this->testConfig1, $this->testSettings1, $this->testBrowsers1, $this->testSuites1 )
+ array( $this->testConfig0, $this->testSettings0, $this->testBrowsers0, $this->testSuites0 ),
+ array( $this->testConfig1, $this->testSettings1, $this->testBrowsers1, $this->testSuites1 )
);
}
-
-
}
* @cover StringUtils::isUtf8
* @dataProvider provideStringsForIsUtf8Check
*/
- function testIsUtf8WithMbstring($expected, $string ) {
- if( !function_exists( 'mb_check_encoding' ) ) {
+ function testIsUtf8WithMbstring( $expected, $string ) {
+ if ( !function_exists( 'mb_check_encoding' ) ) {
$this->markTestSkipped( 'Test requires the mbstring PHP extension' );
}
$this->assertEquals( $expected,
* @cover StringUtils::isUtf8
* @dataProvider provideStringsForIsUtf8Check
*/
- function testIsUtf8WithPhpFallbackImplementation($expected, $string ) {
+ function testIsUtf8WithPhpFallbackImplementation( $expected, $string ) {
$this->assertEquals( $expected,
StringUtils::isUtf8( $string, /** disable mbstring: */ true ),
'Testing string "' . $this->escaped( $string ) . '" with pure PHP implementation'
*/
function escaped( $string ) {
$escaped = '';
- for($i=0; $i<strlen($string);$i++) {
+ $length = strlen( $string );
+ for ( $i = 0; $i < $length; $i++ ) {
$char = $string[$i];
- $val = ord($char);
- if( $val > 127 ) {
- $escaped .='\x' . dechex($val);
+ $val = ord( $char );
+ if ( $val > 127 ) {
+ $escaped .= '\x' . dechex( $val );
} else {
$escaped .= $char;
}
# Collection of parameters for Language_t_Offset.
# Format: date to be formatted, localTZoffset value, expected date
$userAdjust_tests = array(
- array( 20061231235959, 0, 20061231235959 ),
- array( 20061231235959, 5, 20070101000459 ),
- array( 20061231235959, 15, 20070101001459 ),
- array( 20061231235959, 60, 20070101005959 ),
- array( 20061231235959, 90, 20070101012959 ),
+ array( 20061231235959, 0, 20061231235959 ),
+ array( 20061231235959, 5, 20070101000459 ),
+ array( 20061231235959, 15, 20070101001459 ),
+ array( 20061231235959, 60, 20070101005959 ),
+ array( 20061231235959, 90, 20070101012959 ),
array( 20061231235959, 120, 20070101015959 ),
array( 20061231235959, 540, 20070101085959 ),
- array( 20061231235959, -5, 20061231235459 ),
+ array( 20061231235959, -5, 20061231235459 ),
array( 20061231235959, -30, 20061231232959 ),
array( 20061231235959, -60, 20061231225959 ),
);
'wgLang' => Language::factory( 'en' ),
) );
}
+
/**
* Test parsing of valid timestamps and outputing to MW format.
* @dataProvider provideValidTimestamps
$this->setTitle( NS_MAIN );
$this->setUserPerm( "createpage" );
$res = $this->title->getUserPermissionsErrors( 'create', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setTitle( NS_MAIN );
$this->setUserPerm( "createtalk" );
$this->setTitle( NS_TALK );
$this->setUserPerm( "createtalk" );
$res = $this->title->getUserPermissionsErrors( 'create', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setTitle( NS_TALK );
$this->setUserPerm( "createpage" );
$this->setTitle( NS_MAIN );
$this->setUserPerm( "createpage" );
$res = $this->title->getUserPermissionsErrors( 'create', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setTitle( NS_MAIN );
$this->setUserPerm( "createtalk" );
$this->setTitle( NS_MAIN );
$this->setUser( 'anon' );
$this->setUserPerm( "move" );
- $this->runGroupPermissions( 'move', array( ) );
+ $this->runGroupPermissions( 'move', array() );
$this->setUserPerm( "" );
$this->runGroupPermissions( 'move', array( array( 'movenotallowed' ) ),
$this->runGroupPermissions( 'move', array( array( 'movenotallowed' ) ) );
$this->setUserPerm( "move" );
- $this->runGroupPermissions( 'move', array( ) );
+ $this->runGroupPermissions( 'move', array() );
$this->setUser( 'anon' );
$this->setUserPerm( 'move' );
$res = $this->title->getUserPermissionsErrors( 'move-target', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setUserPerm( '' );
$res = $this->title->getUserPermissionsErrors( 'move-target', $this->user );
$this->setUser( $this->userName );
$this->setUserPerm( array( "move", "move-rootuserpages" ) );
$res = $this->title->getUserPermissionsErrors( 'move-target', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setUserPerm( "move" );
$res = $this->title->getUserPermissionsErrors( 'move-target', $this->user );
$this->setUser( 'anon' );
$this->setUserPerm( array( "move", "move-rootuserpages" ) );
$res = $this->title->getUserPermissionsErrors( 'move-target', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setTitle( NS_USER, "User/subpage" );
$this->setUserPerm( array( "move", "move-rootuserpages" ) );
$res = $this->title->getUserPermissionsErrors( 'move-target', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setUserPerm( "move" );
$res = $this->title->getUserPermissionsErrors( 'move-target', $this->user );
- $this->assertEquals( array( ), $res );
+ $this->assertEquals( array(), $res );
$this->setUser( 'anon' );
$check = array( 'edit' => array( array( array( 'badaccess-groups', "*, [[$prefix:Users|Users]]", 2 ) ),
- array( array( 'badaccess-group0' ) ),
- array( ), true ),
- 'protect' => array( array( array( 'badaccess-groups', "[[$prefix:Administrators|Administrators]]", 1 ), array( 'protect-cantedit' ) ),
- array( array( 'badaccess-group0' ), array( 'protect-cantedit' ) ),
- array( array( 'protect-cantedit' ) ), false ),
- '' => array( array( ), array( ), array( ), true ) );
+ array( array( 'badaccess-group0' ) ),
+ array(), true ),
+ 'protect' => array( array( array( 'badaccess-groups', "[[$prefix:Administrators|Administrators]]", 1 ), array( 'protect-cantedit' ) ),
+ array( array( 'badaccess-group0' ), array( 'protect-cantedit' ) ),
+ array( array( 'protect-cantedit' ) ), false ),
+ '' => array( array(), array(), array(), true ) );
foreach ( array( "edit", "protect", "" ) as $action ) {
$this->setUserPerm( null );
function runGroupPermissions( $action, $result, $result2 = null ) {
global $wgGroupPermissions;
- if ( $result2 === null ) $result2 = $result;
+ if ( $result2 === null ) {
+ $result2 = $result;
+ }
$wgGroupPermissions['autoconfirmed']['move'] = false;
$wgGroupPermissions['user']['move'] = false;
$this->setTitle( NS_SPECIAL );
$this->assertEquals( array( array( 'badaccess-group0' ), array( 'ns-specialprotected' ) ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->setTitle( NS_MAIN );
$this->setUserPerm( 'bogus' );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->setTitle( NS_MAIN );
$this->setUserPerm( '' );
$this->assertEquals( array( array( 'badaccess-group0' ) ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$wgNamespaceProtection[NS_USER] = array( 'bogus' );
$this->setTitle( NS_USER );
$this->setUserPerm( '' );
$this->assertEquals( array( array( 'badaccess-group0' ), array( 'namespaceprotected', 'User' ) ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->setTitle( NS_MEDIAWIKI );
$this->setUserPerm( 'bogus' );
$this->assertEquals( array( array( 'protectedinterface' ) ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->setTitle( NS_MEDIAWIKI );
$this->setUserPerm( 'bogus' );
$this->assertEquals( array( array( 'protectedinterface' ) ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$wgNamespaceProtection = null;
$this->setUserPerm( 'bogus' );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->assertEquals( true,
- $this->title->userCan( 'bogus', $this->user ) );
+ $this->title->userCan( 'bogus', $this->user ) );
$this->setUserPerm( '' );
$this->assertEquals( array( array( 'badaccess-group0' ) ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->assertEquals( false,
- $this->title->userCan( 'bogus', $this->user ) );
+ $this->title->userCan( 'bogus', $this->user ) );
}
function testCssAndJavascriptPermissions() {
$this->runCSSandJSPermissions(
array( array( 'badaccess-group0' ), array( 'customcssprotected' ) ),
array( array( 'badaccess-group0' ) ),
- array( array( 'badaccess-group0' ), array( 'customcssprotected' ) ) );
+ array( array( 'badaccess-group0' ), array( 'customcssprotected' ) ) );
$this->setTitle( NS_USER, $this->altUserName . '/tempo' );
$this->runCSSandJSPermissions(
function runCSSandJSPermissions( $result0, $result1, $result2 ) {
$this->setUserPerm( '' );
$this->assertEquals( $result0,
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
$this->setUserPerm( 'editusercss' );
$this->assertEquals( $result1,
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
$this->setUserPerm( 'edituserjs' );
$this->assertEquals( $result2,
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
$this->setUserPerm( 'editusercssjs' );
$this->assertEquals( array( array( 'badaccess-group0' ) ),
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
$this->setUserPerm( array( 'edituserjs', 'editusercss' ) );
$this->assertEquals( array( array( 'badaccess-group0' ) ),
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
}
function testPageRestrictions() {
$this->setUserPerm( "edit" );
$this->title->mRestrictions = array( "bogus" => array( 'bogus', "sysop", "protect", "" ) );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'edit',
- $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'edit',
+ $this->user ) );
$this->assertEquals( true,
- $this->title->quickUserCan( 'edit', $this->user ) );
+ $this->title->quickUserCan( 'edit', $this->user ) );
$this->title->mRestrictions = array( "edit" => array( 'bogus', "sysop", "protect", "" ),
- "bogus" => array( 'bogus', "sysop", "protect", "" ) );
+ "bogus" => array( 'bogus', "sysop", "protect", "" ) );
$this->assertEquals( array( array( 'badaccess-group0' ),
- array( 'protectedpagetext', 'bogus' ),
- array( 'protectedpagetext', 'protect' ),
- array( 'protectedpagetext', 'protect' ) ),
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ array( 'protectedpagetext', 'bogus' ),
+ array( 'protectedpagetext', 'protect' ),
+ array( 'protectedpagetext', 'protect' ) ),
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
$this->assertEquals( array( array( 'protectedpagetext', 'bogus' ),
- array( 'protectedpagetext', 'protect' ),
- array( 'protectedpagetext', 'protect' ) ),
- $this->title->getUserPermissionsErrors( 'edit',
- $this->user ) );
+ array( 'protectedpagetext', 'protect' ),
+ array( 'protectedpagetext', 'protect' ) ),
+ $this->title->getUserPermissionsErrors( 'edit',
+ $this->user ) );
$this->setUserPerm( "" );
$this->assertEquals( array( array( 'badaccess-group0' ),
- array( 'protectedpagetext', 'bogus' ),
- array( 'protectedpagetext', 'protect' ),
- array( 'protectedpagetext', 'protect' ) ),
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ array( 'protectedpagetext', 'bogus' ),
+ array( 'protectedpagetext', 'protect' ),
+ array( 'protectedpagetext', 'protect' ) ),
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
$this->assertEquals( array( array( 'badaccess-groups', "*, [[$prefix:Users|Users]]", 2 ),
- array( 'protectedpagetext', 'bogus' ),
- array( 'protectedpagetext', 'protect' ),
- array( 'protectedpagetext', 'protect' ) ),
- $this->title->getUserPermissionsErrors( 'edit',
- $this->user ) );
+ array( 'protectedpagetext', 'bogus' ),
+ array( 'protectedpagetext', 'protect' ),
+ array( 'protectedpagetext', 'protect' ) ),
+ $this->title->getUserPermissionsErrors( 'edit',
+ $this->user ) );
$this->setUserPerm( array( "edit", "editprotected" ) );
$this->assertEquals( array( array( 'badaccess-group0' ),
- array( 'protectedpagetext', 'bogus' ),
- array( 'protectedpagetext', 'protect' ),
- array( 'protectedpagetext', 'protect' ) ),
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'edit',
- $this->user ) );
+ array( 'protectedpagetext', 'bogus' ),
+ array( 'protectedpagetext', 'protect' ),
+ array( 'protectedpagetext', 'protect' ) ),
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'edit',
+ $this->user ) );
$this->title->mCascadeRestriction = true;
$this->assertEquals( false,
- $this->title->quickUserCan( 'bogus', $this->user ) );
+ $this->title->quickUserCan( 'bogus', $this->user ) );
$this->assertEquals( false,
- $this->title->quickUserCan( 'edit', $this->user ) );
+ $this->title->quickUserCan( 'edit', $this->user ) );
$this->assertEquals( array( array( 'badaccess-group0' ),
- array( 'protectedpagetext', 'bogus' ),
- array( 'protectedpagetext', 'protect' ),
- array( 'protectedpagetext', 'protect' ) ),
- $this->title->getUserPermissionsErrors( 'bogus',
- $this->user ) );
+ array( 'protectedpagetext', 'bogus' ),
+ array( 'protectedpagetext', 'protect' ),
+ array( 'protectedpagetext', 'protect' ) ),
+ $this->title->getUserPermissionsErrors( 'bogus',
+ $this->user ) );
$this->assertEquals( array( array( 'protectedpagetext', 'bogus' ),
- array( 'protectedpagetext', 'protect' ),
- array( 'protectedpagetext', 'protect' ) ),
- $this->title->getUserPermissionsErrors( 'edit',
- $this->user ) );
+ array( 'protectedpagetext', 'protect' ),
+ array( 'protectedpagetext', 'protect' ) ),
+ $this->title->getUserPermissionsErrors( 'edit',
+ $this->user ) );
}
function testCascadingSourcesRestrictions() {
$this->title->mCascadingRestrictions = array( "bogus" => array( 'bogus', "sysop", "protect", "" ) );
$this->assertEquals( false,
- $this->title->userCan( 'bogus', $this->user ) );
+ $this->title->userCan( 'bogus', $this->user ) );
$this->assertEquals( array( array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n" ),
- array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n" ) ),
- $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
+ array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n" ) ),
+ $this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->assertEquals( true,
- $this->title->userCan( 'edit', $this->user ) );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'edit', $this->user ) );
+ $this->title->userCan( 'edit', $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'edit', $this->user ) );
}
$this->title->mCascadeRestriction = false;
$this->assertEquals( array( array( 'titleprotected', 'Useruser', 'test' ) ),
- $this->title->getUserPermissionsErrors( 'create', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'create', $this->user ) );
$this->assertEquals( false,
- $this->title->userCan( 'create', $this->user ) );
+ $this->title->userCan( 'create', $this->user ) );
$this->title->mTitleProtection['pt_create_perm'] = 'sysop';
$this->setUserPerm( array( 'createpage', 'protect' ) );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'create', $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'create', $this->user ) );
$this->assertEquals( true,
- $this->title->userCan( 'create', $this->user ) );
+ $this->title->userCan( 'create', $this->user ) );
$this->setUserPerm( array( 'createpage' ) );
$this->assertEquals( array( array( 'titleprotected', 'Useruser', 'test' ) ),
- $this->title->getUserPermissionsErrors( 'create', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'create', $this->user ) );
$this->assertEquals( false,
- $this->title->userCan( 'create', $this->user ) );
+ $this->title->userCan( 'create', $this->user ) );
$this->setTitle( NS_MEDIA, "test page" );
$this->setUserPerm( array( "move" ) );
$this->assertEquals( false,
- $this->title->userCan( 'move', $this->user ) );
+ $this->title->userCan( 'move', $this->user ) );
$this->assertEquals( array( array( 'immobile-source-namespace', 'Media' ) ),
- $this->title->getUserPermissionsErrors( 'move', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'move', $this->user ) );
$this->setTitle( NS_HELP, "test page" );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'move', $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'move', $this->user ) );
$this->assertEquals( true,
- $this->title->userCan( 'move', $this->user ) );
+ $this->title->userCan( 'move', $this->user ) );
$this->title->mInterwiki = "no";
$this->assertEquals( array( array( 'immobile-source-page' ) ),
- $this->title->getUserPermissionsErrors( 'move', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'move', $this->user ) );
$this->assertEquals( false,
- $this->title->userCan( 'move', $this->user ) );
+ $this->title->userCan( 'move', $this->user ) );
$this->setTitle( NS_MEDIA, "test page" );
$this->assertEquals( false,
- $this->title->userCan( 'move-target', $this->user ) );
+ $this->title->userCan( 'move-target', $this->user ) );
$this->assertEquals( array( array( 'immobile-target-namespace', 'Media' ) ),
- $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
$this->setTitle( NS_HELP, "test page" );
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
$this->assertEquals( true,
- $this->title->userCan( 'move-target', $this->user ) );
+ $this->title->userCan( 'move-target', $this->user ) );
$this->title->mInterwiki = "no";
$this->assertEquals( array( array( 'immobile-target-page' ) ),
- $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
$this->assertEquals( false,
- $this->title->userCan( 'move-target', $this->user ) );
+ $this->title->userCan( 'move-target', $this->user ) );
}
# $short
$this->assertEquals( array( array( 'confirmedittext' ) ),
- $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
+ $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
$wgEmailConfirmToEdit = false;
$this->assertEquals( true, $this->title->userCan( 'move-target', $this->user ) );
# $wgEmailConfirmToEdit && !$user->isEmailConfirmed() && $action != 'createaccount'
- $this->assertEquals( array( ),
- $this->title->getUserPermissionsErrors( 'move-target',
- $this->user ) );
+ $this->assertEquals( array(),
+ $this->title->getUserPermissionsErrors( 'move-target',
+ $this->user ) );
global $wgLang;
$prev = time();
$now = time() + 120;
$this->user->mBlockedby = $this->user->getId();
$this->user->mBlock = new Block( '127.0.8.1', 0, $this->user->getId(),
- 'no reason given', $prev + 3600, 1, 0 );
+ 'no reason given', $prev + 3600, 1, 0 );
$this->user->mBlock->mTimestamp = 0;
$this->assertEquals( array( array( 'autoblockedtext',
- '[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
- 'Useruser', null, 'infinite', '127.0.8.1',
- $wgLang->timeanddate( wfTimestamp( TS_MW, $prev ), true ) ) ),
+ '[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
+ 'Useruser', null, 'infinite', '127.0.8.1',
+ $wgLang->timeanddate( wfTimestamp( TS_MW, $prev ), true ) ) ),
$this->title->getUserPermissionsErrors( 'move-target',
- $this->user ) );
+ $this->user ) );
$this->assertEquals( false, $this->title->userCan( 'move-target', $this->user ) );
// quickUserCan should ignore user blocks
$this->user->mBlockedby = $this->user->getName();
$this->user->mBlock = new Block( '127.0.8.1', 0, 1, 'no reason given', $now, 0, 10 );
$this->assertEquals( array( array( 'blockedtext',
- '[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
- 'Useruser', null, '23:00, 31 December 1969', '127.0.8.1',
- $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ) ),
+ '[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
+ 'Useruser', null, '23:00, 31 December 1969', '127.0.8.1',
+ $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ) ),
$this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
# $action != 'read' && $action != 'createaccount' && $user->isBlockedFrom( $this )
* ^--- needed for language cache stuff
*/
class TitleTest extends MediaWikiTestCase {
-
protected function setUp() {
parent::setUp();
array( 'Special:Version/param', 'param' ),
);
}
-
+
/**
* Auth-less test of Title::isValidMoveOperation
- *
+ *
* @group Database
* @param string $source
* @param string $target
}
}
}
-
+
/**
* Provides test parameter values for testIsValidMoveOperation()
*/
* @covers Title::checkReadPermission
* @dataProvider dataWgWhitelistReadRegexp
*/
- function testWgWhitelistReadRegexp($whitelistRegexp, $source, $action, $expected) {
-
+ function testWgWhitelistReadRegexp( $whitelistRegexp, $source, $action, $expected ) {
// $wgWhitelistReadRegexp must be an array. Since the provided test cases
// usually have only one regex, it is more concise to write the lonely regex
// as a string. Thus we cast to an array() to honor $wgWhitelistReadRegexp
// type requisite.
- if( is_string( $whitelistRegexp ) ) {
+ if ( is_string( $whitelistRegexp ) ) {
$whitelistRegexp = array( $whitelistRegexp );
}
$wgWhitelistRead = array( 'some random non sense title' );
global $wgWhitelistReadRegexp;
- $oldWhitelistRegexp = $wgWhitelistReadRegexp;
- $wgWhitelistReadRegexp = $whitelistRegexp ;
+ $oldWhitelistRegexp = $wgWhitelistReadRegexp;
+ $wgWhitelistReadRegexp = $whitelistRegexp;
// Just use $wgUser which in test is a user object for '127.0.0.1'
global $wgUser;
$wgWhitelistRead = $oldWhitelist;
$wgWhitelistReadRegexp = $oldWhitelistRegexp;
- if( is_bool( $expected ) ) {
+ if ( is_bool( $expected ) ) {
# Forge the assertion message depending on the assertion expectation
$allowableness = $expected
? " should be allowed"
- : " should NOT be allowed"
- ;
+ : " should NOT be allowed";
$this->assertEquals( $expected, $errors, "User action '$action' on [[$source]] $allowableness." );
} else {
$errors = $this->flattenErrorsArray( $errors );
* Provides test parameter values for testWgWhitelistReadRegexp()
*/
function dataWgWhitelistReadRegexp() {
- $ALLOWED = true;
+ $ALLOWED = true;
$DISALLOWED = false;
return array(
}
return $result;
}
-
+
public static function provideTestIsValidMoveOperation() {
- return array(
+ return array(
array( 'Test', 'Test', 'selfmove' ),
array( 'File:Test.jpg', 'Page', 'imagenocrossnamespace' )
);
array( 'es', 'Help:I_need_somebody', 'es', 'zh-tw', false ),
array( 'zh', 'Help:I_need_somebody', 'zh', 'zh-tw', false ),
- array( 'es', 'Help:I_need_somebody', 'es', 'zh-tw', 'zh-cn' ),
- array( 'es', 'MediaWiki:About', 'es', 'zh-tw', 'zh-cn' ),
- array( 'es', 'MediaWiki:About/', 'es', 'zh-tw', 'zh-cn' ),
- array( 'de', 'MediaWiki:About/de', 'es', 'zh-tw', 'zh-cn' ),
- array( 'en', 'MediaWiki:Common.js', 'es', 'zh-tw', 'zh-cn' ),
- array( 'en', 'MediaWiki:Common.css', 'es', 'zh-tw', 'zh-cn' ),
- array( 'en', 'User:JohnDoe/Common.js', 'es', 'zh-tw', 'zh-cn' ),
- array( 'en', 'User:JohnDoe/Monobook.css', 'es', 'zh-tw', 'zh-cn' ),
-
- array( 'zh-cn', 'Help:I_need_somebody', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'zh', 'MediaWiki:About', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'zh', 'MediaWiki:About/', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'de', 'MediaWiki:About/de', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'zh-cn', 'MediaWiki:About/zh-cn', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'zh-tw', 'MediaWiki:About/zh-tw', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'en', 'MediaWiki:Common.js', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'en', 'MediaWiki:Common.css', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'en', 'User:JohnDoe/Common.js', 'zh', 'zh-tw', 'zh-cn' ),
- array( 'en', 'User:JohnDoe/Monobook.css', 'zh', 'zh-tw', 'zh-cn' ),
-
- array( 'zh-tw', 'Special:NewPages', 'es', 'zh-tw', 'zh-cn' ),
- array( 'zh-tw', 'Special:NewPages', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'es', 'Help:I_need_somebody', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'es', 'MediaWiki:About', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'es', 'MediaWiki:About/', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'de', 'MediaWiki:About/de', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.js', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.css', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Common.js', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Monobook.css', 'es', 'zh-tw', 'zh-cn' ),
+
+ array( 'zh-cn', 'Help:I_need_somebody', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh', 'MediaWiki:About', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh', 'MediaWiki:About/', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'de', 'MediaWiki:About/de', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh-cn', 'MediaWiki:About/zh-cn', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'zh-tw', 'MediaWiki:About/zh-tw', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.js', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'MediaWiki:Common.css', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Common.js', 'zh', 'zh-tw', 'zh-cn' ),
+ array( 'en', 'User:JohnDoe/Monobook.css', 'zh', 'zh-tw', 'zh-cn' ),
+
+ array( 'zh-tw', 'Special:NewPages', 'es', 'zh-tw', 'zh-cn' ),
+ array( 'zh-tw', 'Special:NewPages', 'zh', 'zh-tw', 'zh-cn' ),
);
}
/**
* @dataProvider provideBaseTitleCases
*/
- function testExtractingBaseTextFromTitle( $title, $expected, $msg='' ) {
+ function testExtractingBaseTextFromTitle( $title, $expected, $msg = '' ) {
$title = Title::newFromText( $title );
$this->assertEquals( $expected,
$title->getBaseText(),
function provideBaseTitleCases() {
return array(
# Title, expected base, optional message
- array('User:John_Doe/subOne/subTwo', 'John Doe/subOne' ),
- array('User:Foo/Bar/Baz', 'Foo/Bar' ),
+ array( 'User:John_Doe/subOne/subTwo', 'John Doe/subOne' ),
+ array( 'User:Foo/Bar/Baz', 'Foo/Bar' ),
);
}
/**
* @dataProvider provideRootTitleCases
*/
- function testExtractingRootTextFromTitle( $title, $expected, $msg='' ) {
+ function testExtractingRootTextFromTitle( $title, $expected, $msg = '' ) {
$title = Title::newFromText( $title );
$this->assertEquals( $expected,
$title->getRootText(),
public static function provideRootTitleCases() {
return array(
# Title, expected base, optional message
- array('User:John_Doe/subOne/subTwo', 'John Doe' ),
- array('User:Foo/Bar/Baz', 'Foo' ),
+ array( 'User:John_Doe/subOne/subTwo', 'John Doe' ),
+ array( 'User:Foo/Bar/Baz', 'Foo' ),
);
}
* @todo Handle $wgNamespacesWithSubpages cases
* @dataProvider provideSubpageTitleCases
*/
- function testExtractingSubpageTextFromTitle( $title, $expected, $msg='' ) {
+ function testExtractingSubpageTextFromTitle( $title, $expected, $msg = '' ) {
$title = Title::newFromText( $title );
$this->assertEquals( $expected,
$title->getSubpageText(),
function provideSubpageTitleCases() {
return array(
# Title, expected base, optional message
- array('User:John_Doe/subOne/subTwo', 'subTwo' ),
- array('User:John_Doe/subOne', 'subOne' ),
+ array( 'User:John_Doe/subOne/subTwo', 'subTwo' ),
+ array( 'User:John_Doe/subOne', 'subOne' ),
);
}
-
}
* @group Database
*/
class UserTest extends MediaWikiTestCase {
-
/**
* @var User
*/
$this->assertContains( 'modifytest', $rights );
$this->assertNotContains( 'nukeworld', $rights );
}
+
public function testRevokePermissions() {
$rights = User::getGroupPermissions( array( 'unittesters', 'formertesters' ) );
$this->assertNotContains( 'runtest', $rights );
array( '', false, 'Empty string' ),
array( ' ', false, 'Blank space' ),
array( 'abcd', false, 'Starts with small letter' ),
- array( 'Ab/cd', false, 'Contains slash' ),
- array( 'Ab cd' , true, 'Whitespace' ),
- array( '192.168.1.1', false, 'IP' ),
+ array( 'Ab/cd', false, 'Contains slash' ),
+ array( 'Ab cd', true, 'Whitespace' ),
+ array( '192.168.1.1', false, 'IP' ),
array( 'User:Abcd', false, 'Reserved Namespace' ),
- array( '12abcd232' , true , 'Starts with Numbers' ),
- array( '?abcd' , true, 'Start with ? mark' ),
+ array( '12abcd232', true, 'Starts with Numbers' ),
+ array( '?abcd', true, 'Start with ? mark' ),
array( '#abcd', false, 'Start with #' ),
- array( 'Abcdകഖഗഘ', true, ' Mixed scripts' ),
- array( 'ജോസ്തോമസ്', false, 'ZWNJ- Format control character' ),
+ array( 'Abcdകഖഗഘ', true, ' Mixed scripts' ),
+ array( 'ജോസ്തോമസ്', false, 'ZWNJ- Format control character' ),
array( 'Ab cd', false, ' Ideographic space' ),
);
}
// let the user have a few (3) edits
$page = WikiPage::factory( Title::newFromText( 'Help:UserTest_EditCount' ) );
- for( $i = 0; $i < 3; $i++ ) {
+ for ( $i = 0; $i < 3; $i++ ) {
$page->doEdit( (string)$i, 'test', 0, false, $user );
}
/**
* @dataProvider provideLanguageData
*/
- function testAcceptLang($acceptLanguageHeader, $expectedLanguages, $description) {
+ function testAcceptLang( $acceptLanguageHeader, $expectedLanguages, $description ) {
$_SERVER = array( 'HTTP_ACCEPT_LANGUAGE' => $acceptLanguageHeader );
$request = new WebRequest();
- $this->assertSame( $request->getAcceptLang(), $expectedLanguages, $description);
+ $this->assertSame( $request->getAcceptLang(), $expectedLanguages, $description );
}
}
<?php
/**
-* @group ContentHandler
-* @group Database
-* ^--- important, causes temporary tables to be used instead of the real database
-* @group medium
-**/
+ * @group ContentHandler
+ * @group Database
+ * ^--- important, causes temporary tables to be used instead of the real database
+ * @group medium
+ **/
class WikiPageTest extends MediaWikiLangTestCase {
function __construct( $name = null, array $data = array(), $dataName = '' ) {
parent::__construct( $name, $data, $dataName );
- $this->tablesUsed = array_merge (
+ $this->tablesUsed = array_merge(
$this->tablesUsed,
array( 'page',
- 'revision',
- 'text',
+ 'revision',
+ 'text',
- 'recentchanges',
- 'logging',
+ 'recentchanges',
+ 'logging',
- 'page_props',
- 'pagelinks',
- 'categorylinks',
- 'langlinks',
- 'externallinks',
- 'imagelinks',
- 'templatelinks',
- 'iwlinks' ) );
+ 'page_props',
+ 'pagelinks',
+ 'categorylinks',
+ 'langlinks',
+ 'externallinks',
+ 'imagelinks',
+ 'templatelinks',
+ 'iwlinks' ) );
}
protected function setUp() {
return $p;
}
-
/**
* @param String|Title|WikiPage $page
* @param String $text
$title = $page->getTitle();
$content = ContentHandler::makeContent( "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
- . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
- $title, CONTENT_MODEL_WIKITEXT );
+ . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
+ $title, CONTENT_MODEL_WIKITEXT );
$page->doEditContent( $content, "[[testing]] 1" );
# ------------------------
$content = ContentHandler::makeContent( "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
- . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.",
- $title, CONTENT_MODEL_WIKITEXT );
+ . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.",
+ $title, CONTENT_MODEL_WIKITEXT );
$page->doEditContent( $content, "testing 2" );
$page = $this->newPage( $title );
$text = "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
- . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.";
+ . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.";
$page->doEdit( $text, "[[testing]] 1" );
# ------------------------
$text = "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
- . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.";
+ . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.";
$page->doEdit( $text, "testing 2" );
// any
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- '',
- 'any',
- true
+ CONTENT_MODEL_WIKITEXT,
+ '',
+ 'any',
+ true
),
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo',
- 'any',
- true
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo',
+ 'any',
+ true
),
// comma
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo',
- 'comma',
- false
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo',
+ 'comma',
+ false
),
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo, bar',
- 'comma',
- true
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo, bar',
+ 'comma',
+ true
),
// link
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo',
- 'link',
- false
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo',
+ 'link',
+ false
),
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo [[bar]]',
- 'link',
- true
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo [[bar]]',
+ 'link',
+ true
),
// redirects
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- '#REDIRECT [[bar]]',
- 'any',
- false
+ CONTENT_MODEL_WIKITEXT,
+ '#REDIRECT [[bar]]',
+ 'any',
+ false
),
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- '#REDIRECT [[bar]]',
- 'comma',
- false
+ CONTENT_MODEL_WIKITEXT,
+ '#REDIRECT [[bar]]',
+ 'comma',
+ false
),
array( 'WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- '#REDIRECT [[bar]]',
- 'link',
- false
+ CONTENT_MODEL_WIKITEXT,
+ '#REDIRECT [[bar]]',
+ 'link',
+ false
),
// not a content namespace
array( 'Talk:WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo',
- 'any',
- false
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo',
+ 'any',
+ false
),
array( 'Talk:WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo, bar',
- 'comma',
- false
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo, bar',
+ 'comma',
+ false
),
array( 'Talk:WikiPageTest_testIsCountable',
- CONTENT_MODEL_WIKITEXT,
- 'Foo [[bar]]',
- 'link',
- false
+ CONTENT_MODEL_WIKITEXT,
+ 'Foo [[bar]]',
+ 'link',
+ false
),
// not a content namespace, different model
array( 'MediaWiki:WikiPageTest_testIsCountable.js',
- null,
- 'Foo',
- 'any',
- false
+ null,
+ 'Foo',
+ 'any',
+ false
),
array( 'MediaWiki:WikiPageTest_testIsCountable.js',
- null,
- 'Foo, bar',
- 'comma',
- false
+ null,
+ 'Foo, bar',
+ 'comma',
+ false
),
array( 'MediaWiki:WikiPageTest_testIsCountable.js',
- null,
- 'Foo [[bar]]',
- 'link',
- false
+ null,
+ 'Foo [[bar]]',
+ 'link',
+ false
),
);
}
$page = $this->createPage( $title, $text, $model );
$hasLinks = wfGetDB( DB_SLAVE )->selectField( 'pagelinks', 1,
- array( 'pl_from' => $page->getId() ), __METHOD__ );
+ array( 'pl_from' => $page->getId() ), __METHOD__ );
$editInfo = $page->prepareContentForEdit( $page->getContent() );
$w = $page->isCountable( $editInfo );
$this->assertEquals( $expected, $v, "isCountable( null ) returned unexpected value " . var_export( $v, true )
- . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
+ . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
$this->assertEquals( $expected, $w, "isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
- . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
+ . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
}
public static function provideGetParserOutput() {
return array(
- array( CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i></p>"),
+ array( CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i></p>" ),
// @todo: more...?
);
}
return $po;
}
- public function testGetParserOutput_nonexisting( ) {
+ public function testGetParserOutput_nonexisting() {
static $count = 0;
- $count ++;
+ $count++;
$page = new WikiPage( new Title( "WikiPageTest_testGetParserOutput_nonexisting_$count" ) );
$this->assertFalse( $po, "getParserOutput() shall return false for non-existing pages." );
}
- public function testGetParserOutput_badrev( ) {
+ public function testGetParserOutput_badrev() {
$page = $this->createPage( 'WikiPageTest_testGetParserOutput', "dummy", CONTENT_MODEL_WIKITEXT );
$opt = new ParserOptions();
//NOTE: assume the Help namespace to contain wikitext
return array(
array( 'Help:WikiPageTest_testReplaceSection',
- CONTENT_MODEL_WIKITEXT,
- WikiPageTest::$sections,
- "0",
- "No more",
- null,
- trim( preg_replace( '/^Intro/sm', 'No more', WikiPageTest::$sections ) )
+ CONTENT_MODEL_WIKITEXT,
+ WikiPageTest::$sections,
+ "0",
+ "No more",
+ null,
+ trim( preg_replace( '/^Intro/sm', 'No more', WikiPageTest::$sections ) )
),
array( 'Help:WikiPageTest_testReplaceSection',
- CONTENT_MODEL_WIKITEXT,
- WikiPageTest::$sections,
- "",
- "No more",
- null,
- "No more"
+ CONTENT_MODEL_WIKITEXT,
+ WikiPageTest::$sections,
+ "",
+ "No more",
+ null,
+ "No more"
),
array( 'Help:WikiPageTest_testReplaceSection',
- CONTENT_MODEL_WIKITEXT,
- WikiPageTest::$sections,
- "2",
- "== TEST ==\nmore fun",
- null,
- trim( preg_replace( '/^== test ==.*== foo ==/sm',
- "== TEST ==\nmore fun\n\n== foo ==",
- WikiPageTest::$sections ) )
+ CONTENT_MODEL_WIKITEXT,
+ WikiPageTest::$sections,
+ "2",
+ "== TEST ==\nmore fun",
+ null,
+ trim( preg_replace( '/^== test ==.*== foo ==/sm',
+ "== TEST ==\nmore fun\n\n== foo ==",
+ WikiPageTest::$sections ) )
),
array( 'Help:WikiPageTest_testReplaceSection',
- CONTENT_MODEL_WIKITEXT,
- WikiPageTest::$sections,
- "8",
- "No more",
- null,
- trim( WikiPageTest::$sections )
+ CONTENT_MODEL_WIKITEXT,
+ WikiPageTest::$sections,
+ "8",
+ "No more",
+ null,
+ trim( WikiPageTest::$sections )
),
array( 'Help:WikiPageTest_testReplaceSection',
- CONTENT_MODEL_WIKITEXT,
- WikiPageTest::$sections,
- "new",
- "No more",
- "New",
- trim( WikiPageTest::$sections ) . "\n\n== New ==\n\nNo more"
+ CONTENT_MODEL_WIKITEXT,
+ WikiPageTest::$sections,
+ "new",
+ "No more",
+ "New",
+ trim( WikiPageTest::$sections ) . "\n\n== New ==\n\nNo more"
),
);
}
/* @todo FIXME: fix this!
public function testGetUndoText() {
- $this->checkHasDiff3();
+ $this->checkHasDiff3();
- $text = "one";
- $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
- $rev1 = $page->getRevision();
+ $text = "one";
+ $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
+ $rev1 = $page->getRevision();
- $text .= "\n\ntwo";
- $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section two");
- $rev2 = $page->getRevision();
+ $text .= "\n\ntwo";
+ $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section two");
+ $rev2 = $page->getRevision();
- $text .= "\n\nthree";
- $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section three");
- $rev3 = $page->getRevision();
+ $text .= "\n\nthree";
+ $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section three");
+ $rev3 = $page->getRevision();
- $text .= "\n\nfour";
- $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section four");
- $rev4 = $page->getRevision();
+ $text .= "\n\nfour";
+ $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section four");
+ $rev4 = $page->getRevision();
- $text .= "\n\nfive";
- $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section five");
- $rev5 = $page->getRevision();
+ $text .= "\n\nfive";
+ $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section five");
+ $rev5 = $page->getRevision();
- $text .= "\n\nsix";
- $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section six");
- $rev6 = $page->getRevision();
+ $text .= "\n\nsix";
+ $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), "adding section six");
+ $rev6 = $page->getRevision();
- $undo6 = $page->getUndoText( $rev6 );
- if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
- $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
+ $undo6 = $page->getUndoText( $rev6 );
+ if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
+ $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
- $undo3 = $page->getUndoText( $rev4, $rev2 );
- if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
- $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
+ $undo3 = $page->getUndoText( $rev4, $rev2 );
+ if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
+ $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
- $undo2 = $page->getUndoText( $rev2 );
- if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
- $this->assertEquals( "one\n\nfive", $undo2 );
+ $undo2 = $page->getUndoText( $rev2 );
+ if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
+ $this->assertEquals( "one\n\nfive", $undo2 );
}
- */
+ */
/**
* @todo FIXME: this is a better rollback test than the one below, but it keeps failing in jenkins for some reason.
*/
public function broken_testDoRollback() {
$admin = new User();
- $admin->setName("Admin");
+ $admin->setName( "Admin" );
$text = "one";
$page = $this->newPage( "WikiPageTest_testDoRollback" );
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
- "section one", EDIT_NEW, false, $admin );
+ "section one", EDIT_NEW, false, $admin );
$user1 = new User();
$user1->setName( "127.0.1.11" );
$text .= "\n\ntwo";
$page = new WikiPage( $page->getTitle() );
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
- "adding section two", 0, false, $user1 );
+ "adding section two", 0, false, $user1 );
$user2 = new User();
$user2->setName( "127.0.2.13" );
$text .= "\n\nthree";
$page = new WikiPage( $page->getTitle() );
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
- "adding section three", 0, false, $user2 );
+ "adding section three", 0, false, $user2 );
# we are having issues with doRollback spuriously failing. apparently the last revision somehow goes missing
# or not committed under some circumstances. so, make sure the last revision has the right user name.
$page = new WikiPage( $page->getTitle() );
$this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(),
- "rollback did not revert to the correct revision" );
+ "rollback did not revert to the correct revision" );
$this->assertEquals( "one\n\ntwo", $page->getContent()->getNativeData() );
}
*/
public function testDoRollback() {
$admin = new User();
- $admin->setName("Admin");
+ $admin->setName( "Admin" );
$text = "one";
$page = $this->newPage( "WikiPageTest_testDoRollback" );
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
- "section one", EDIT_NEW, false, $admin );
+ "section one", EDIT_NEW, false, $admin );
$rev1 = $page->getRevision();
$user1 = new User();
$text .= "\n\ntwo";
$page = new WikiPage( $page->getTitle() );
$page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
- "adding section two", 0, false, $user1 );
+ "adding section two", 0, false, $user1 );
# now, try the rollback
$admin->addGroup( "sysop" ); #XXX: make the test user a sysop...
$page = new WikiPage( $page->getTitle() );
$this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
- "rollback did not revert to the correct revision" );
+ "rollback did not revert to the correct revision" );
$this->assertEquals( "one", $page->getContent()->getNativeData() );
}
- public static function provideGetAutosummary( ) {
+ public static function provideGetAutosummary() {
return array(
array(
'Hello there, world!',
$summary = $page->getAutosummary( $old, $new, $flags );
$this->assertTrue( (bool)preg_match( $expected, $summary ),
- "Autosummary didn't match expected pattern $expected: $summary" );
+ "Autosummary didn't match expected pattern $expected: $summary" );
}
- public static function provideGetAutoDeleteReason( ) {
+ public static function provideGetAutoDeleteReason() {
return array(
array(
array(),
array(
array(
array( "first edit: "
- . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
- . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. "
- . "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea "
- . "takimata sanctus est Lorem ipsum dolor sit amet.'", null ),
+ . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
+ . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. "
+ . "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea "
+ . "takimata sanctus est Lorem ipsum dolor sit amet.'", null ),
),
'/first edit:.*\.\.\."/',
false
foreach ( $edits as $edit ) {
$user = new User();
- if ( !empty( $edit[1] ) ) $user->setName( $edit[1] );
- else $user = $wgUser;
+ if ( !empty( $edit[1] ) ) {
+ $user->setName( $edit[1] );
+ } else {
+ $user = $wgUser;
+ }
$content = ContentHandler::makeContent( $edit[0], $page->getTitle(), $page->getContentModel() );
$reason = $page->getAutoDeleteReason( $hasHistory );
- if ( is_bool( $expectedResult ) || is_null( $expectedResult ) ) $this->assertEquals( $expectedResult, $reason );
- else $this->assertTrue( (bool)preg_match( $expectedResult, $reason ),
- "Autosummary didn't match expected pattern $expectedResult: $reason" );
+ if ( is_bool( $expectedResult ) || is_null( $expectedResult ) ) {
+ $this->assertEquals( $expectedResult, $reason );
+ } else {
+ $this->assertTrue( (bool)preg_match( $expectedResult, $reason ),
+ "Autosummary didn't match expected pattern $expectedResult: $reason" );
+ }
$this->assertEquals( $expectedHistory, $hasHistory,
- "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
+ "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
$page->doDeleteArticle( "done" );
}
public static function providePreSaveTransform() {
return array(
array( 'hello this is ~~~',
- "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
+ "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
),
array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
- 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
),
);
}
public function testPreSaveTransform( $text, $expected ) {
$this->hideDeprecated( 'WikiPage::preSaveTransform' );
$user = new User();
- $user->setName("127.0.0.1");
+ $user->setName( "127.0.0.1" );
//NOTE: assume Help namespace to contain wikitext
$page = $this->newPage( "Help:WikiPageTest_testPreloadTransform" );
$this->setMwGlobals( array(
'wgHtml5' => true,
'wgWellFormedXml' => true,
- ));
+ ) );
$this->select = new XmlSelect();
}
+
protected function tearDown() {
parent::tearDown();
$this->select = null;
* See http://en.wikipedia.org/wiki/Gray_code
*/
# $name $id $default
- array( false , false, false, '<select></select>' ),
- array( false , false, 'foo', '<select></select>' ),
- array( false , 'id' , 'foo', '<select id="id"></select>' ),
- array( false , 'id' , false, '<select id="id"></select>' ),
- array( 'name', 'id' , false, '<select name="name" id="id"></select>' ),
- array( 'name', 'id' , 'foo', '<select name="name" id="id"></select>' ),
- array( 'name', false, 'foo', '<select name="name"></select>' ),
- array( 'name', false, false, '<select name="name"></select>' ),
+ array( false, false, false, '<select></select>' ),
+ array( false, false, 'foo', '<select></select>' ),
+ array( false, 'id', 'foo', '<select id="id"></select>' ),
+ array( false, 'id', false, '<select id="id"></select>' ),
+ array( 'name', 'id', false, '<select name="name" id="id"></select>' ),
+ array( 'name', 'id', 'foo', '<select name="name" id="id"></select>' ),
+ array( 'name', false, 'foo', '<select name="name"></select>' ),
+ array( 'name', false, false, '<select name="name"></select>' ),
);
}
$this->select->addOption( 'foo' );
$this->assertEquals( '<select><option value="foo">foo</option></select>', $this->select->getHTML() );
}
+
public function testAddOptionWithDefault() {
$this->select->addOption( 'foo', true );
$this->assertEquals( '<select><option value="1">foo</option></select>', $this->select->getHTML() );
}
+
public function testAddOptionWithFalse() {
$this->select->addOption( 'foo', false );
$this->assertEquals( '<select><option value="foo">foo</option></select>', $this->select->getHTML() );
}
+
public function testAddOptionWithValueZero() {
$this->select->addOption( 'foo', 0 );
$this->assertEquals( '<select><option value="0">foo</option></select>', $this->select->getHTML() );
}
+
# End XmlSelect::addOption() similar to Xml::option
public function testSetDefault() {
$this->select->addOption( 'bar1' );
$this->select->addOption( 'foo2' );
$this->assertEquals(
-'<select><option value="foo1">foo1</option>' . "\n" .
-'<option value="bar1" selected="">bar1</option>' . "\n" .
-'<option value="foo2">foo2</option></select>', $this->select->getHTML() );
+ '<select><option value="foo1">foo1</option>' . "\n" .
+ '<option value="bar1" selected="">bar1</option>' . "\n" .
+ '<option value="foo2">foo2</option></select>', $this->select->getHTML() );
}
/**
$this->select->addOption( 'foo2' );
$this->select->setDefault( 'bar1' ); # setting default after adding options
$this->assertEquals(
-'<select><option value="foo1">foo1</option>' . "\n" .
-'<option value="bar1" selected="">bar1</option>' . "\n" .
-'<option value="foo2">foo2</option></select>', $this->select->getHTML() );
+ '<select><option value="foo1">foo1</option>' . "\n" .
+ '<option value="bar1" selected="">bar1</option>' . "\n" .
+ '<option value="foo2">foo2</option></select>', $this->select->getHTML() );
}
public function testGetAttributes() {
# verify string / integer
$this->assertEquals(
$this->select->getAttribute( '1911' ),
- 'razor'
+ 'razor'
);
$this->assertEquals(
$this->select->getAttribute( 'dummy' ),
$langObj->setNamespaces( array(
-2 => 'Media',
-1 => 'Special',
- 0 => '',
- 1 => 'Talk',
- 2 => 'User',
- 3 => 'User_talk',
- 4 => 'MyWiki',
- 5 => 'MyWiki_Talk',
- 6 => 'File',
- 7 => 'File_talk',
- 8 => 'MediaWiki',
- 9 => 'MediaWiki_talk',
- 10 => 'Template',
- 11 => 'Template_talk',
- 100 => 'Custom',
- 101 => 'Custom_talk',
+ 0 => '',
+ 1 => 'Talk',
+ 2 => 'User',
+ 3 => 'User_talk',
+ 4 => 'MyWiki',
+ 5 => 'MyWiki_Talk',
+ 6 => 'File',
+ 7 => 'File_talk',
+ 8 => 'MediaWiki',
+ 9 => 'MediaWiki_talk',
+ 10 => 'Template',
+ 11 => 'Template_talk',
+ 100 => 'Custom',
+ 101 => 'Custom_talk',
) );
$this->setMwGlobals( array(
}
public function testExpandAttributes() {
- $this->assertNull( Xml::expandAttributes(null),
+ $this->assertNull( Xml::expandAttributes( null ),
'Converting a null list of attributes'
);
$this->assertEquals( '', Xml::expandAttributes( array() ),
}
public function testExpandAttributesException() {
- $this->setExpectedException('MWException');
- Xml::expandAttributes('string');
+ $this->setExpectedException( 'MWException' );
+ Xml::expandAttributes( 'string' );
}
function testElementOpen() {
'Input with a value of 0 (bug 23797)'
);
}
+
function testElementEscaping() {
$this->assertEquals(
'<element>hello <there> you & you</element>',
$this->assertEquals( '</element>', Xml::closeElement( 'element' ), 'closeElement() shortcut' );
}
- public function testDateMenu( ) {
- $curYear = intval(gmdate('Y'));
- $prevYear = $curYear - 1;
+ public function testDateMenu() {
+ $curYear = intval( gmdate( 'Y' ) );
+ $prevYear = $curYear - 1;
- $curMonth = intval(gmdate('n'));
+ $curMonth = intval( gmdate( 'n' ) );
$prevMonth = $curMonth - 1;
- if( $prevMonth == 0 ) { $prevMonth = 12; }
+ if ( $prevMonth == 0 ) {
+ $prevMonth = 12;
+ }
$nextMonth = $curMonth + 1;
- if( $nextMonth == 13 ) { $nextMonth = 1; }
+ if ( $nextMonth == 13 ) {
+ $nextMonth = 1;
+ }
$this->assertEquals(
'<label for="year">From year (and earlier):</label> <input id="year" maxlength="4" size="7" type="number" value="2011" name="year" /> <label for="month">From month (and earlier):</label> <select id="month" name="month" class="mw-month-selector"><option value="-1">all</option>' . "\n" .
-'<option value="1">January</option>' . "\n" .
-'<option value="2" selected="">February</option>' . "\n" .
-'<option value="3">March</option>' . "\n" .
-'<option value="4">April</option>' . "\n" .
-'<option value="5">May</option>' . "\n" .
-'<option value="6">June</option>' . "\n" .
-'<option value="7">July</option>' . "\n" .
-'<option value="8">August</option>' . "\n" .
-'<option value="9">September</option>' . "\n" .
-'<option value="10">October</option>' . "\n" .
-'<option value="11">November</option>' . "\n" .
-'<option value="12">December</option></select>',
+ '<option value="1">January</option>' . "\n" .
+ '<option value="2" selected="">February</option>' . "\n" .
+ '<option value="3">March</option>' . "\n" .
+ '<option value="4">April</option>' . "\n" .
+ '<option value="5">May</option>' . "\n" .
+ '<option value="6">June</option>' . "\n" .
+ '<option value="7">July</option>' . "\n" .
+ '<option value="8">August</option>' . "\n" .
+ '<option value="9">September</option>' . "\n" .
+ '<option value="10">October</option>' . "\n" .
+ '<option value="11">November</option>' . "\n" .
+ '<option value="12">December</option></select>',
Xml::dateMenu( 2011, 02 ),
"Date menu for february 2011"
);
$this->assertEquals(
'<label for="year">From year (and earlier):</label> <input id="year" maxlength="4" size="7" type="number" value="2011" name="year" /> <label for="month">From month (and earlier):</label> <select id="month" name="month" class="mw-month-selector"><option value="-1">all</option>' . "\n" .
-'<option value="1">January</option>' . "\n" .
-'<option value="2">February</option>' . "\n" .
-'<option value="3">March</option>' . "\n" .
-'<option value="4">April</option>' . "\n" .
-'<option value="5">May</option>' . "\n" .
-'<option value="6">June</option>' . "\n" .
-'<option value="7">July</option>' . "\n" .
-'<option value="8">August</option>' . "\n" .
-'<option value="9">September</option>' . "\n" .
-'<option value="10">October</option>' . "\n" .
-'<option value="11">November</option>' . "\n" .
-'<option value="12">December</option></select>',
- Xml::dateMenu( 2011, -1),
+ '<option value="1">January</option>' . "\n" .
+ '<option value="2">February</option>' . "\n" .
+ '<option value="3">March</option>' . "\n" .
+ '<option value="4">April</option>' . "\n" .
+ '<option value="5">May</option>' . "\n" .
+ '<option value="6">June</option>' . "\n" .
+ '<option value="7">July</option>' . "\n" .
+ '<option value="8">August</option>' . "\n" .
+ '<option value="9">September</option>' . "\n" .
+ '<option value="10">October</option>' . "\n" .
+ '<option value="11">November</option>' . "\n" .
+ '<option value="12">December</option></select>',
+ Xml::dateMenu( 2011, -1 ),
"Date menu with negative month for 'All'"
);
$this->assertEquals(
Xml::dateMenu( $curYear, $curMonth ),
- Xml::dateMenu( '' , $curMonth ),
+ Xml::dateMenu( '', $curMonth ),
"Date menu year is the current one when not specified"
);
$this->assertEquals(
'<label for="year">From year (and earlier):</label> <input id="year" maxlength="4" size="7" type="number" name="year" /> <label for="month">From month (and earlier):</label> <select id="month" name="month" class="mw-month-selector"><option value="-1">all</option>' . "\n" .
-'<option value="1">January</option>' . "\n" .
-'<option value="2">February</option>' . "\n" .
-'<option value="3">March</option>' . "\n" .
-'<option value="4">April</option>' . "\n" .
-'<option value="5">May</option>' . "\n" .
-'<option value="6">June</option>' . "\n" .
-'<option value="7">July</option>' . "\n" .
-'<option value="8">August</option>' . "\n" .
-'<option value="9">September</option>' . "\n" .
-'<option value="10">October</option>' . "\n" .
-'<option value="11">November</option>' . "\n" .
-'<option value="12">December</option></select>',
+ '<option value="1">January</option>' . "\n" .
+ '<option value="2">February</option>' . "\n" .
+ '<option value="3">March</option>' . "\n" .
+ '<option value="4">April</option>' . "\n" .
+ '<option value="5">May</option>' . "\n" .
+ '<option value="6">June</option>' . "\n" .
+ '<option value="7">July</option>' . "\n" .
+ '<option value="8">August</option>' . "\n" .
+ '<option value="9">September</option>' . "\n" .
+ '<option value="10">October</option>' . "\n" .
+ '<option value="11">November</option>' . "\n" .
+ '<option value="12">December</option></select>',
Xml::dateMenu( '', '' ),
"Date menu with neither year or month"
);
'label() with no attribs'
);
}
+
function testLabelAttributeCanOnlyBeClassOrTitle() {
$this->assertEquals(
'<label for="id">name</label>',
$this->assertEquals(
'<label for="id" class="nice" title="nice tooltip">name</label>',
Xml::label( 'name', 'id', array(
- 'generated' => true,
- 'class' => 'nice',
- 'title' => 'nice tooltip',
- 'anotherattr' => 'value',
+ 'generated' => true,
+ 'class' => 'nice',
+ 'title' => 'nice tooltip',
+ 'anotherattr' => 'value',
)
),
'label() skip all attributes but "class" and "title"'
}
function testMultiDisk0() {
- $this->readZipAssertError( 'split.zip', 'zip-unsupported',
+ $this->readZipAssertError( 'split.zip', 'zip-unsupported',
'Split zip error' );
}
function testNoSignature() {
- $this->readZipAssertError( 'nosig.zip', 'zip-wrong-format',
+ $this->readZipAssertError( 'nosig.zip', 'zip-wrong-format',
'No signature should give "wrong format" error' );
}
}
function testWrongCDStart() {
- $this->readZipAssertError( 'wrong-cd-start-disk.zip', 'zip-unsupported',
+ $this->readZipAssertError( 'wrong-cd-start-disk.zip', 'zip-unsupported',
'Wrong CD start disk error' );
}
*/
class ApiCreateAccountTest extends ApiTestCase {
function setUp() {
+ global $wgHooks;
parent::setUp();
LoginForm::setCreateaccountToken();
+
+ $hooks = $wgHooks;
+ Hooks::clear( 'AlternateUserMailer' );
+ $hooks['AlternateUserMailer'] = array( function () { return false; } );
+ $this->setMwGlobals( array( 'wgHooks' => $hooks ) );
}
/**
*/
function testInvalidEmail() {
global $wgEnableEmail;
- if( !$wgEnableEmail ) {
+ if ( !$wgEnableEmail ) {
$this->markTestSkipped( 'email is not enabled, so createaccount does not check it' );
}
$this->doApiRequest( array(
$this->markTestIncomplete( "The user UTApiBlockee does not exist" );
}
- if( !isset( $data[0]['query']['pages'] ) ) {
+ if ( !isset( $data[0]['query']['pages'] ) ) {
$this->markTestIncomplete( "No block token found" );
}
'reason' => 'Some reason',
'token' => $pageinfo['blocktoken'] ), null, false, self::$users['sysop']->user );
- $block = Block::newFromTarget('UTApiBlockee');
+ $block = Block::newFromTarget( 'UTApiBlockee' );
$this->assertTrue( !is_null( $block ), 'Block is valid' );
'action' => $action,
'user' => 'UTApiBlockee',
'reason' => 'Some reason',
- ),
+ ),
null,
false,
self::$users['sysop']->user
*/
function provideBlockUnblockAction() {
return array(
- array( 'block' ),
+ array( 'block' ),
array( 'unblock' ),
);
}
parent::teardown();
}
- function testEdit( ) {
+ function testEdit() {
$name = 'Help:ApiEditPageTest_testEdit'; // assume Help namespace to default to wikitext
// -- test new page --------------------------------------------
$apiResult = $this->doApiRequestWithToken( array(
- 'action' => 'edit',
- 'title' => $name,
- 'text' => 'some text', ) );
+ 'action' => 'edit',
+ 'title' => $name,
+ 'text' => 'some text',
+ ) );
$apiResult = $apiResult[0];
// Validate API result data
// -- test existing page, no change ----------------------------
$data = $this->doApiRequestWithToken( array(
- 'action' => 'edit',
- 'title' => $name,
- 'text' => 'some text', ) );
+ 'action' => 'edit',
+ 'title' => $name,
+ 'text' => 'some text',
+ ) );
$this->assertEquals( 'Success', $data[0]['edit']['result'] );
// -- test existing page, with change --------------------------
$data = $this->doApiRequestWithToken( array(
- 'action' => 'edit',
- 'title' => $name,
- 'text' => 'different text' ) );
+ 'action' => 'edit',
+ 'title' => $name,
+ 'text' => 'different text'
+ ) );
$this->assertEquals( 'Success', $data[0]['edit']['result'] );
);
}
- function testNonTextEdit( ) {
+ function testNonTextEdit() {
$name = 'Dummy:ApiEditPageTest_testNonTextEdit';
$data = serialize( 'some bla bla text' );
if ( $text !== null ) {
if ( $text === '' ) {
// can't create an empty page, so create it with some content
- list( $re,, ) = $this->doApiRequestWithToken( array(
+ list( $re, , ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
'text' => '(dummy)', ) );
}
- list( $re,, ) = $this->doApiRequestWithToken( array(
+ list( $re, , ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
'text' => $text, ) );
}
// -- try append/prepend --------------------------------------------
- list( $re,, ) = $this->doApiRequestWithToken( array(
+ list( $re, , ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
$op . 'text' => $append, ) );
// try to save edit, expect conflict
try {
- list( $re,, ) = $this->doApiRequestWithToken( array(
+ list( $re, , ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
'text' => 'nix bar!',
'basetimestamp' => $baseTime,
- ), null, self::$users['sysop']->user );
+ ), null, self::$users['sysop']->user );
$this->fail( 'edit conflict expected' );
} catch ( UsageException $ex ) {
$this->forceRevisionDate( $rpage, '20120101020202' );
// try to save edit; should work, because we follow the redirect
- list( $re,, ) = $this->doApiRequestWithToken( array(
+ list( $re, , ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $rname,
'text' => 'nix bar!',
// try again, without following the redirect. Should fail.
try {
- list( $re,, ) = $this->doApiRequestWithToken( array(
+ list( $re, , ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $rname,
'text' => 'nix bar!',
$this->forceRevisionDate( $rpage, '20120101020202' );
// try to save edit; should work, following the redirect.
- list( $re,, ) = $this->doApiRequestWithToken( array(
+ list( $re, , ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $rname,
'text' => 'nix bar!',
+++ /dev/null
-<?php
-
-/**
- * @group API
- */
-class ApiGeneratorTest extends MediaWikiTestCase {
-
- /**
- * Helper to easily get an ApiQuery object instance
- */
- function getApiQuery() {
- // Initialize an ApiQuery object to play with
- $main = new ApiMain( new FauxRequest() );
- return new ApiQuery( $main, 'foo', 'bar' );
- }
-
- /**
- * Test whether all registered query modules which are subclasses of
- * ApiQueryGeneratorBase are listed as being a generator. Registration is
- * done:
- * - for core: add it to ApiQuery::$mQueryGenerators
- * - for extension: by adding to $wgAPIGeneratorModules
- *
- * @dataProvider provideApiquerygeneratorbaseChilds
- */
- public function testApiquerygeneatorbaseModulesListedAsGenerators(
- $moduleName, $moduleClass
- ) {
- $generators = $this->getApiQuery()->getGenerators();
- $this->assertArrayHasKey( $moduleName, $generators,
- "API module '$moduleName' of class '$moduleClass' (an ApiQueryGeneratorBase subclass) must be listed in ApiQuery::\$mQueryGenerators or added to \$wgAPIGeneratorModules."
- );
- }
-
- /**
- * Returns API modules which are subclassing ApiQueryGeneratorBase.
- * Case format is:
- * (moduleName, moduleClass)
- */
- public function provideApiquerygeneratorbaseChilds() {
- $cases = array();
- $modules = $this->getApiQuery()->getModuleManager()->getNamesWithClasses();
- foreach( $modules as $moduleName => $moduleClass ) {
- if( !is_subclass_of( $moduleClass, 'ApiQueryGeneratorBase' ) ) {
- continue;
- }
- $cases[] = array( $moduleName, $moduleClass );
- }
- return $cases;
- }
-
- /**
- * @dataProvider provideListedApiqueryGenerators
- */
- public function testGeneratorsAreApiquerygeneratorbaseSubclasses(
- $generatorName, $generatorClass
- ) {
- $modules = $this->getApiQuery()->getModuleManager()->getNamesWithClasses();
- $this->assertArrayHasKey( $generatorName, $modules,
- "Class '$generatorClass' of generator '$generatorName' must be a subclass of 'ApiQueryGeneratorBase'. Listed either in ApiQuery::\$mQueryGenerators or in \$wgAPIGeneratorModules."
- );
-
- }
-
- /**
- * Return ApiQuery generators, either listed in ApiQuery or registered
- * via wgAPIGeneratorModules.
- * Case format is:
- * (moduleName, $moduleClass).
- */
- public function provideListedApiqueryGenerators() {
- $cases = array();
- $generators = $this->getApiQuery()->getGenerators();
- foreach( $generators as $generatorName => $generatorClass ) {
- $cases[] = array( $generatorName, $generatorClass );
- }
- return $cases;
- }
-
-}
'page' => $somePage ) );
$this->fail( "API did not return an error when parsing a nonexistent page" );
- } catch(UsageException $ex){
+ } catch ( UsageException $ex ) {
$this->assertEquals( 'missingtitle', $ex->getCodeString(),
"Parse request for nonexistent page must give 'missingtitle' error: " . var_export( $ex->getMessageArray(), true ) );
}
"Purge request for three articles should give back three results received: " . var_export( $data[0]['purge'], true ) );
$pages = array( 'UTPage' => 'purged', $somePage => 'missing', '%5D' => 'invalid' );
- foreach( $data[0]['purge'] as $v ) {
+ foreach ( $data[0]['purge'] as $v ) {
$this->assertArrayHasKey( $pages[$v['title']], $v );
}
}
$this->assertEquals(
null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
- "enablechunks" => false ), "filename", "enablechunks" ) );
+ "enablechunks" => false ), "filename", "enablechunks" ) );
}
/**
$this->assertEquals(
null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
- "enablechunks" => 0 ), "filename", "enablechunks" ) );
+ "enablechunks" => 0 ), "filename", "enablechunks" ) );
}
/**
$this->assertEquals(
null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
- "enablechunks" => true ), "filename", "enablechunks" ) );
+ "enablechunks" => true ), "filename", "enablechunks" ) );
}
/**
$token = $result["login"]["token"];
- $ret = $this->doApiRequest( array(
- "action" => "login",
- "lgtoken" => $token,
- "lgname" => $user->username,
- "lgpassword" => "badnowayinhell",
- ), $ret[2]
+ $ret = $this->doApiRequest(
+ array(
+ "action" => "login",
+ "lgtoken" => $token,
+ "lgname" => $user->username,
+ "lgpassword" => "badnowayinhell",
+ ),
+ $ret[2]
);
$result = $ret[0];
$user->user->logOut();
$ret = $this->doApiRequest( array(
- "action" => "login",
- "lgname" => $user->username,
- "lgpassword" => $user->password,
+ "action" => "login",
+ "lgname" => $user->username,
+ "lgpassword" => $user->password,
)
);
$this->assertEquals( "NeedToken", $a );
$token = $result["login"]["token"];
- $ret = $this->doApiRequest( array(
- "action" => "login",
- "lgtoken" => $token,
- "lgname" => $user->username,
- "lgpassword" => $user->password,
- ), $ret[2]
+ $ret = $this->doApiRequest(
+ array(
+ "action" => "login",
+ "lgtoken" => $token,
+ "lgname" => $user->username,
+ "lgpassword" => $user->password,
+ ),
+ $ret[2]
);
$result = $ret[0];
* @group Broken
*/
function testApiGotCookie() {
- $this->markTestIncomplete( "The server can't do external HTTP requests, and the internal one won't give cookies" );
+ $this->markTestIncomplete( "The server can't do external HTTP requests, and the internal one won't give cookies" );
global $wgServer, $wgScriptPath;
$req = MWHttpRequest::factory( self::$apiUrl . "?action=login&format=xml",
array( "method" => "POST",
"postData" => array(
- "lgname" => $user->username,
- "lgpassword" => $user->password ) ) );
+ "lgname" => $user->username,
+ "lgpassword" => $user->password
+ )
+ )
+ );
$req->execute();
libxml_use_internal_errors( true );
-<?php
+<?php
abstract class ApiTestCase extends MediaWikiLangTestCase {
protected static $apiUrl;
$token = $data[0]['login']['token'];
- $data = $this->doApiRequest( array(
- 'action' => 'login',
- 'lgtoken' => $token,
- 'lgname' => self::$users['sysop']->username,
- 'lgpassword' => self::$users['sysop']->password
- ), $data[2] );
+ $data = $this->doApiRequest(
+ array(
+ 'action' => 'login',
+ 'lgtoken' => $token,
+ 'lgname' => self::$users['sysop']->username,
+ 'lgpassword' => self::$users['sysop']->password,
+ ),
+ $data[2]
+ );
return $data;
}
}
class MockApi extends ApiBase {
- public function execute() { }
- public function getVersion() { }
+ public function execute() {}
+
+ public function getVersion() {}
- public function __construct() { }
+ public function __construct() {}
public function getAllowedParams() {
return array(
// see if it now doesn't exist; reload
$title = Title::newFromText( $title->getText(), NS_FILE );
}
- return ! ( $title && $title instanceof Title && $title->exists() );
+ return !( $title && $title instanceof Title && $title->exists() );
}
/**
$tmpName = tempnam( wfTempDir(), "" );
if ( !file_exists( $filePath ) ) {
throw new Exception( "$filePath doesn't exist!" );
- };
+ }
if ( !copy( $filePath, $tmpName ) ) {
throw new Exception( "couldn't copy $filePath to $tmpName" );
throw new Exception( "couldn't stat $tmpName" );
}
- $_FILES[ $fieldName ] = array(
- 'name' => $fileName,
- 'type' => $type,
- 'tmp_name' => $tmpName,
- 'size' => $size,
- 'error' => null
+ $_FILES[$fieldName] = array(
+ 'name' => $fileName,
+ 'type' => $type,
+ 'tmp_name' => $tmpName,
+ 'size' => $size,
+ 'error' => null
);
return true;
}
- function fakeUploadChunk( $fieldName, $fileName, $type, & $chunkData ) {
+ function fakeUploadChunk( $fieldName, $fileName, $type, & $chunkData ) {
$tmpName = tempnam( wfTempDir(), "" );
// copy the chunk data to temp location:
if ( !file_put_contents( $tmpName, $chunkData ) ) {
throw new Exception( "couldn't stat $tmpName" );
}
- $_FILES[ $fieldName ] = array(
- 'name' => $fileName,
- 'type' => $type,
- 'tmp_name' => $tmpName,
- 'size' => $size,
- 'error' => null
+ $_FILES[$fieldName] = array(
+ 'name' => $fileName,
+ 'type' => $type,
+ 'tmp_name' => $tmpName,
+ 'size' => $size,
+ 'error' => null
);
}
function clearTempUpload() {
- if( isset( $_FILES['file']['tmp_name'] ) ) {
+ if ( isset( $_FILES['file']['tmp_name'] ) ) {
$tmp = $_FILES['file']['tmp_name'];
- if( file_exists( $tmp ) ) {
+ if ( file_exists( $tmp ) ) {
unlink( $tmp );
}
}
try {
$randomImageGenerator = new RandomImageGenerator();
$filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
- }
- catch ( Exception $e ) {
+ } catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
$this->deleteFileByContent( $filePath );
- if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
+ if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
'filename' => $fileName,
'file' => 'dummy content',
'comment' => 'dummy comment',
- 'text' => "This is the page text for $fileName",
+ 'text' => "This is the page text for $fileName",
);
$exception = false;
$this->deleteFileByFileName( $fileName );
- if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
+ if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
'filename' => $fileName,
'file' => 'dummy content',
'comment' => 'dummy comment',
- 'text' => "This is the page text for $fileName",
+ 'text' => "This is the page text for $fileName",
);
$exception = false;
try {
$randomImageGenerator = new RandomImageGenerator();
$filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() );
- }
- catch ( Exception $e ) {
+ } catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
'filename' => $fileName,
'file' => 'dummy content',
'comment' => 'dummy comment',
- 'text' => "This is the page text for $fileName",
+ 'text' => "This is the page text for $fileName",
);
// first upload .... should succeed
- if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[0] ) ) {
+ if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[0] ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
// second upload with the same name (but different content)
- if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[1] ) ) {
+ if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePaths[1] ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
try {
$randomImageGenerator = new RandomImageGenerator();
$filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
- }
- catch ( Exception $e ) {
+ } catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
'filename' => $fileNames[0],
'file' => 'dummy content',
'comment' => 'dummy comment',
- 'text' => "This is the page text for " . $fileNames[0],
+ 'text' => "This is the page text for " . $fileNames[0],
);
- if (! $this->fakeUploadFile( 'file', $fileNames[0], $mimeType, $filePaths[0] ) ) {
+ if ( !$this->fakeUploadFile( 'file', $fileNames[0], $mimeType, $filePaths[0] ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
// second upload with the same content (but different name)
- if (! $this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePaths[0] ) ) {
+ if ( !$this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePaths[0] ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
'filename' => $fileNames[1],
'file' => 'dummy content',
'comment' => 'dummy comment',
- 'text' => "This is the page text for " . $fileNames[1],
+ 'text' => "This is the page text for " . $fileNames[1],
);
$exception = false;
try {
$randomImageGenerator = new RandomImageGenerator();
$filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
- }
- catch ( Exception $e ) {
+ } catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
$this->deleteFileByFileName( $fileName );
$this->deleteFileByContent( $filePath );
- if (! $this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
+ if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
$params = array(
'action' => 'upload',
- 'stash' => 1,
+ 'stash' => 1,
'filename' => $fileName,
'file' => 'dummy content',
'comment' => 'dummy comment',
- 'text' => "This is the page text for $fileName",
+ 'text' => "This is the page text for $fileName",
);
$exception = false;
'filekey' => $filekey,
'filename' => $fileName,
'comment' => 'dummy comment',
- 'text' => "This is the page text for $fileName, altered",
+ 'text' => "This is the page text for $fileName, altered",
);
$this->clearFakeUploads();
$this->deleteFileByFilename( $fileName );
unlink( $filePath );
}
-
-
+
/**
* @depends testLogin
*/
$filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg';
try {
// Only download if the file is not avaliable in the temp location:
- if( !is_file( $filePath ) ){
- copy($url, $filePath);
+ if ( !is_file( $filePath ) ) {
+ copy( $url, $filePath );
}
- }
- catch ( Exception $e ) {
+ } catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
// Base upload params:
$params = array(
'action' => 'upload',
- 'stash' => 1,
+ 'stash' => 1,
'filename' => $fileName,
'filesize' => $fileSize,
'offset' => 0,
);
-
+
// Upload chunks
$chunkSessionKey = false;
$resultOffset = 0;
// Open the file:
- $handle = @fopen ($filePath, "r");
- if( $handle === false ){
+ $handle = @fopen( $filePath, "r" );
+ if ( $handle === false ) {
$this->markTestIncomplete( "could not open file: $filePath" );
}
- while (!feof ($handle)) {
+ while ( !feof( $handle ) ) {
// Get the current chunk
$chunkData = @fread( $handle, $chunkSize );
// Upload the current chunk into the $_FILE object:
$this->fakeUploadChunk( 'chunk', 'blob', $mimeType, $chunkData );
-
+
// Check for chunkSessionKey
- if( !$chunkSessionKey ){
+ if ( !$chunkSessionKey ) {
// Upload fist chunk ( and get the session key )
try {
list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
$this->assertTrue( isset( $result['upload'] ) );
$this->assertTrue( isset( $result['upload']['filekey'] ) );
// If we don't get a session key mark test incomplete.
- if( ! isset( $result['upload']['filekey'] ) ){
+ if ( !isset( $result['upload']['filekey'] ) ) {
$this->markTestIncomplete( "no filekey provided" );
}
$chunkSessionKey = $result['upload']['filekey'];
// Make sure we got a valid chunk continue:
$this->assertTrue( isset( $result['upload'] ) );
$this->assertTrue( isset( $result['upload']['filekey'] ) );
-
+
// Check if we were on the last chunk:
- if( $params['offset'] + $chunkSize >= $fileSize ){
+ if ( $params['offset'] + $chunkSize >= $fileSize ) {
$this->assertEquals( 'Success', $result['upload']['result'] );
break;
} else {
// update $resultOffset
$resultOffset = $result['upload']['offset'];
}
- }
- fclose ($handle);
-
+ }
+ fclose( $handle );
+
// Check that we got a valid file result:
- wfDebug( __METHOD__ . " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n");
+ wfDebug( __METHOD__ . " hohoh filesize {$fileSize} info {$result['upload']['imageinfo']['size']}\n\n" );
$this->assertEquals( $fileSize, $result['upload']['imageinfo']['size'] );
$this->assertEquals( $mimeType, $result['upload']['imageinfo']['mime'] );
$this->assertTrue( isset( $result['upload']['filekey'] ) );
'filekey' => $filekey,
'filename' => $fileName,
'comment' => 'dummy comment',
- 'text' => "This is the page text for $fileName, altered",
+ 'text' => "This is the page text for $fileName, altered",
);
$this->clearFakeUploads();
$exception = false;
$this->assertArrayHasKey( 'rollback', $data[0] );
$this->assertArrayHasKey( 'title', $data[0]['rollback'] );
- } catch( UsageException $ue ) {
- if( $ue->getCodeString() == 'onlyauthor' ) {
+ } catch ( UsageException $ue ) {
+ if ( $ue->getCodeString() == 'onlyauthor' ) {
$this->markTestIncomplete( "Only one author to 'Help:UTPage', cannot test rollback" );
} else {
$this->fail( "Received error '" . $ue->getCodeString() . "'" );
class RandomImageGenerator {
private $dictionaryFile;
- private $minWidth = 400 ;
- private $maxWidth = 800 ;
- private $minHeight = 400 ;
- private $maxHeight = 800 ;
- private $shapesToDraw = 5 ;
+ private $minWidth = 400;
+ private $maxWidth = 800;
+ private $minHeight = 400;
+ private $maxHeight = 800;
+ private $shapesToDraw = 5;
/**
* Orientations: 0th row, 0th column, EXIF orientation code, rotation 2x2 matrix that is opposite of orientation
// find the dictionary file, to generate random names
if ( !isset( $this->dictionaryFile ) ) {
- foreach ( array(
+ foreach (
+ array(
'/usr/share/dict/words',
'/usr/dict/words',
- __DIR__ . '/words.txt' )
- as $dictionaryFile ) {
+ __DIR__ . '/words.txt'
+ ) as $dictionaryFile
+ ) {
if ( is_file( $dictionaryFile ) and is_readable( $dictionaryFile ) ) {
$this->dictionaryFile = $dictionaryFile;
break;
function writeImages( $number, $format = 'jpg', $dir = null ) {
$filenames = $this->getRandomFilenames( $number, $format, $dir );
$imageWriteMethod = $this->getImageWriteMethod( $format );
- foreach( $filenames as $filename ) {
+ foreach ( $filenames as $filename ) {
$this->{$imageWriteMethod}( $this->getImageSpec(), $format, $filename );
}
return $filenames;
$dir = getcwd();
}
$filenames = array();
- foreach( $this->getRandomWordPairs( $number ) as $pair ) {
+ foreach ( $this->getRandomWordPairs( $number ) as $pair ) {
$basename = $pair[0] . '_' . $pair[1];
if ( !is_null( $extension ) ) {
$basename .= '.' . $extension;
}
$originX = mt_rand( -1 * $radius, $spec['width'] + $radius );
$originY = mt_rand( -1 * $radius, $spec['height'] + $radius );
- $angle = mt_rand( 0, ( 3.141592/2 ) * $radius ) / $radius;
+ $angle = mt_rand( 0, ( 3.141592 / 2 ) * $radius ) / $radius;
$legDeltaX = round( $radius * sin( $angle ) );
$legDeltaY = round( $radius * cos( $angle ) );
$draw = array();
$draw['fill'] = $this->getRandomColor();
$draw['shape'] = array(
- array( 'x' => $originX, 'y' => $originY - $radius ),
- array( 'x' => $originX + $legDeltaX, 'y' => $originY + $legDeltaY ),
- array( 'x' => $originX - $legDeltaX, 'y' => $originY + $legDeltaY ),
- array( 'x' => $originX, 'y' => $originY - $radius )
+ array( 'x' => $originX, 'y' => $originY - $radius ),
+ array( 'x' => $originX + $legDeltaX, 'y' => $originY + $legDeltaY ),
+ array( 'x' => $originX - $legDeltaX, 'y' => $originY + $legDeltaY ),
+ array( 'x' => $originX, 'y' => $originY - $radius )
);
$draws[] = $draw;
$shape = $g->addChild( 'polygon' );
$shape->addAttribute( 'fill', $drawSpec['fill'] );
$shape->addAttribute( 'points', self::shapePointsToString( $drawSpec['shape'] ) );
- };
- if ( ! $fh = fopen( $filename, 'w' ) ) {
+ }
+
+ if ( !$fh = fopen( $filename, 'w' ) ) {
throw new Exception( "couldn't open $filename for writing" );
}
fwrite( $fh, $svg->asXML() );
- if ( !fclose($fh) ) {
+ if ( !fclose( $fh ) ) {
throw new Exception( "couldn't close $filename" );
}
}
*/
$orientation = self::$orientations[0]; // default is normal orientation
if ( $format == 'jpg' ) {
- $orientation = self::$orientations[ array_rand( self::$orientations ) ];
+ $orientation = self::$orientations[array_rand( self::$orientations )];
$spec = self::rotateImageSpec( $spec, $orientation['counterRotation'] );
}
$tSpec['height'] = abs( $dims['y'] );
$tSpec['fill'] = $spec['fill'];
$tSpec['draws'] = array();
- foreach( $spec['draws'] as $draw ) {
+ foreach ( $spec['draws'] as $draw ) {
$tDraw = array(
'fill' => $draw['fill'],
'shape' => array()
);
- foreach( $draw['shape'] as $point ) {
+ foreach ( $draw['shape'] as $point ) {
$tPoint = self::matrixMultiply2x2( $matrix, $point['x'], $point['y'] );
$tPoint['x'] += $correctionX;
$tPoint['y'] += $correctionY;
*
* Sample command line:
* $ convert -size 100x60 xc:rgb(90,87,45) \
- * -draw 'fill rgb(12,34,56) polygon 41,39 44,57 50,57 41,39' \
+ * -draw 'fill rgb(12,34,56) polygon 41,39 44,57 50,57 41,39' \
* -draw 'fill rgb(99,123,231) circle 59,39 56,57' \
* -draw 'fill rgb(240,12,32) circle 50,21 50,3' filename.png
*
$args = array();
$args[] = "-size " . wfEscapeShellArg( $spec['width'] . 'x' . $spec['height'] );
$args[] = wfEscapeShellArg( "xc:" . $spec['fill'] );
- foreach( $spec['draws'] as $draw ) {
+ foreach ( $spec['draws'] as $draw ) {
$fill = $draw['fill'];
$polygon = self::shapePointsToString( $draw['shape'] );
$drawCommand = "fill $fill polygon $polygon";
*/
public function getRandomColor() {
$components = array();
- for ($i = 0; $i <= 2; $i++ ) {
+ for ( $i = 0; $i <= 2; $i++ ) {
$components[] = mt_rand( 0, 255 );
}
- return 'rgb(' . join(', ', $components) . ')';
+ return 'rgb(' . join( ', ', $components ) . ')';
}
/**
// construct pairs of words
$pairs = array();
$count = count( $lines );
- for( $i = 0; $i < $count; $i += 2 ) {
- $pairs[] = array( $lines[$i], $lines[$i+1] );
+ for ( $i = 0; $i < $count; $i += 2 ) {
+ $pairs[] = array( $lines[$i], $lines[$i + 1] );
}
return $pairs;
}
-
/**
* Return N random lines from a file
*
*/
$fh = fopen( $filepath, "r" );
if ( !$fh ) {
- throw new Exception( "couldn't open $filepath" );
+ throw new Exception( "couldn't open $filepath" );
}
$line_number = 0;
$max_index = $number_desired - 1;
- while( !feof( $fh ) ) {
+ while ( !feof( $fh ) ) {
$line = fgets( $fh );
if ( $line !== false ) {
$line_number++;
$line = trim( $line );
if ( mt_rand( 0, $line_number ) <= $max_index ) {
- $lines[ mt_rand( 0, $max_index ) ] = $line;
+ $lines[mt_rand( 0, $max_index )] = $line;
}
}
}
$data = parent::doApiRequest( $params, $data, true );
$module = $data[3];
-
+
$printer = $module->createPrinterByName( $format );
$printer->setUnescapeAmps( false );
ob_start();
$printer->execute();
$out = ob_get_clean();
-
+
$printer->closePrinter();
return $out;
// Start up MediaWiki in command-line mode
require_once( "$IP/maintenance/Maintenance.php" );
-require( __DIR__ . "/RandomImageGenerator.php" );
+require( __DIR__ . "/RandomImageGenerator.php" );
class GenerateRandomImages extends Maintenance {
* @group medium
*/
class ApiQueryBasicTest extends ApiTestCase {
-
/**
* Create a set of pages. These must not change, otherwise the tests might give wrong results.
* @see MediaWikiTestCase::addDBData()
private function merge( /*...*/ ) {
$request = array();
$expected = array();
- foreach ( func_get_args() as $v ) {
+ foreach ( func_get_args() as $v ) {
$request = array_merge_recursive( $request, $v[0] );
$this->mergeExpected( $expected, $v[1] );
}
private function mergeExpected( &$all, $item ) {
foreach ( $item as $k => $v ) {
if ( array_key_exists( $k, $all ) ) {
- if ( is_array ( $all[$k] ) ) {
+ if ( is_array( $all[$k] ) ) {
$this->mergeExpected( $all[$k], $v );
} else {
$this->assertEquals( $all[$k], $v );
$expected = array( 'query' => $expected );
try {
$this->assertQueryResults( $expected, $result );
- } catch (Exception $e) {
- print("\nRequest:\n");
+ } catch ( Exception $e ) {
+ print( "\nRequest:\n" );
print_r( $request );
- print("\nExpected:\n");
+ print( "\nExpected:\n" );
print_r( $expected );
- print("\nResult:\n");
+ print( "\nResult:\n" );
print_r( $result );
throw $e; // rethrow it
}
* @group medium
*/
function testContentComesWithContentModelAndFormat() {
-
- $pageName = 'Help:' . __METHOD__ ;
+ $pageName = 'Help:' . __METHOD__;
$title = Title::newFromText( $pageName );
$page = WikiPage::factory( $title );
$page->doEdit( 'Some text', 'inserting content' );
) );
$this->assertArrayHasKey( 'query', $apiResult[0] );
$this->assertArrayHasKey( 'pages', $apiResult[0]['query'] );
- foreach( $apiResult[0]['query']['pages'] as $page ) {
+ foreach ( $apiResult[0]['query']['pages'] as $page ) {
$this->assertArrayHasKey( 'revisions', $page );
- foreach( $page['revisions'] as $revision ) {
+ foreach ( $page['revisions'] as $revision ) {
$this->assertArrayHasKey( 'contentformat', $revision,
'contentformat should be included when asking content so client knows how to interpret it'
);
$this->assertArrayHasKey( 'normalized', $data[0]['query'] );
// Forge a normalized title
- $to = Title::newFromText( $wgMetaNamespace.':ArticleA' );
+ $to = Title::newFromText( $wgMetaNamespace . ':ArticleA' );
$this->assertEquals(
array(
function testTitlesAreRejectedIfInvalid() {
$title = false;
- while( !$title || Title::newFromText( $title )->exists() ) {
+ while ( !$title || Title::newFromText( $title )->exists() ) {
$title = md5( mt_rand( 0, 10000 ) + rand( 0, 999000 ) );
}
function addDBData() {
$user = User::newFromName( 'UTMale' );
- if( $user->getID() == 0 ) {
+ if ( $user->getID() == 0 ) {
$user->addToDatabase();
$user->setPassword( 'UTMalePassword' );
}
$user->saveSettings();
$user = User::newFromName( 'UTFemale' );
- if( $user->getID() == 0 ) {
+ if ( $user->getID() == 0 ) {
$user->addToDatabase();
$user->setPassword( 'UTFemalePassword' );
}
$user->saveSettings();
$user = User::newFromName( 'UTDefaultGender' );
- if( $user->getID() == 0 ) {
+ if ( $user->getID() == 0 ) {
$user->addToDatabase();
$user->setPassword( 'UTDefaultGenderPassword' );
}
*/
function fillCache( &$cache, $numEntries ) {
// Fill cache with three values
- for( $i=1; $i<=$numEntries; $i++) {
+ for ( $i = 1; $i <= $numEntries; $i++ ) {
$cache->set( "cache-key-$i", "prop-$i", "value-$i" );
}
}
function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
$expected = array();
- if( $entryToFill === 0 ) {
+ if ( $entryToFill === 0 ) {
# The cache is empty!
return array();
- } elseif( $entryToFill <= $cacheMaxEntries ) {
+ } elseif ( $entryToFill <= $cacheMaxEntries ) {
# Cache is not fully filled
$firstKey = 1;
} else {
$firstKey = 1 + $entryToFill - $cacheMaxEntries;
}
- $lastKey = $entryToFill;
+ $lastKey = $entryToFill;
- for( $i=$firstKey; $i<=$lastKey; $i++ ) {
+ for ( $i = $firstKey; $i <= $lastKey; $i++ ) {
$expected["cache-key-$i"] = array( "prop-$i" => "value-$i" );
}
return $expected;
function testPhpUnitArrayEquality() {
$one = array( 'A' => 1, 'B' => 2 );
$two = array( 'B' => 2, 'A' => 1 );
- $this->assertEquals( $one, $two ); // ==
+ $this->assertEquals( $one, $two ); // ==
$this->assertNotSame( $one, $two ); // ===
}
*/
function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) {
$cache = new ProcessCacheLRUTestable( $cacheMaxEntries );
- $this->fillCache( $cache, $entryToFill);
+ $this->fillCache( $cache, $entryToFill );
$this->assertSame(
$this->getExpectedCache( $cacheMaxEntries, $entryToFill ),
public static function provideCacheFilling() {
// ($cacheMaxEntries, $entryToFill, $msg='')
return array(
- array( 1, 0 ),
- array( 1, 1 ),
- array( 1, 2 ), # overflow
+ array( 1, 0 ),
+ array( 1, 1 ),
+ array( 1, 2 ), # overflow
array( 5, 33 ), # overflow
);
-
}
/**
function testRecentlyAccessedKeyStickIn() {
$cache = new ProcessCacheLRUTestable( 2 );
- $cache->set( 'first' , 'prop1', 'value1' );
+ $cache->set( 'first', 'prop1', 'value1' );
$cache->set( 'second', 'prop2', 'value2' );
// Get first
public function getCache() {
return $this->cache;
}
+
public function getEntriesCount() {
return count( $this->cache );
}
$this->assertEquals( $expected->getCode(), $lang->getCode() );
}
- public function testGetContentText_Null( ) {
+ public function testGetContentText_Null() {
global $wgContentHandlerTextFallback;
$content = null;
$this->assertEquals( '', $text );
}
- public function testGetContentText_TextContent( ) {
+ public function testGetContentText_TextContent() {
global $wgContentHandlerTextFallback;
$content = new WikitextContent( "hello world" );
$this->assertEquals( $content->getNativeData(), $text );
}
- public function testGetContentText_NonTextContent( ) {
+ public function testGetContentText_NonTextContent() {
global $wgContentHandlerTextFallback;
$content = new DummyContentForTesting( "hello world" );
return array(
array( 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, 'hallo', false ),
array( 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ),
- array( serialize('hallo'), 'Dummy:Test', null, null, "testing", 'hallo', false ),
+ array( serialize( 'hallo' ), 'Dummy:Test', null, null, "testing", 'hallo', false ),
array( 'hallo', 'Help:Test', null, CONTENT_FORMAT_WIKITEXT, CONTENT_MODEL_WIKITEXT, 'hallo', false ),
array( 'hallo', 'MediaWiki:Test.js', null, CONTENT_FORMAT_JAVASCRIPT, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ),
- array( serialize('hallo'), 'Dummy:Test', null, "testing", "testing", 'hallo', false ),
+ array( serialize( 'hallo' ), 'Dummy:Test', null, "testing", "testing", 'hallo', false ),
array( 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ),
array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ),
- array( serialize('hallo'), 'Dummy:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, serialize('hallo'), false ),
+ array( serialize( 'hallo' ), 'Dummy:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, serialize( 'hallo' ), false ),
array( 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, null, true ),
array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, null, true ),
$this->assertEquals( $expectedModelId, $content->getModel(), 'bad model id' );
$this->assertEquals( $expectedNativeData, $content->getNativeData(), 'bads native data' );
} catch ( MWException $ex ) {
- if ( !$shouldFail ) $this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() );
- else $this->assertTrue( true ); // dummy, so we don't get the "test did not perform any assertions" message.
+ if ( !$shouldFail ) {
+ $this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() );
+ }
+ else {
+ // dummy, so we don't get the "test did not perform any assertions" message.
+ $this->assertTrue( true );
+ }
}
-
}
/*
* @return String serialized form of the content
*/
public function serializeContent( Content $content, $format = null ) {
- return $content->serialize();
+ return $content->serialize();
}
/**
$this->assertEquals( CONTENT_MODEL_CSS, $content->getContentHandler()->getModelID() );
}
- public static function dataEquals( ) {
+ public static function dataEquals() {
return array(
array( new CssContent( 'hallo' ), null, false ),
array( new CssContent( 'hallo' ), new CssContent( 'hallo' ), true ),
public static function dataGetSection() {
return array(
array( WikitextContentTest::$sections,
- '0',
- null
+ '0',
+ null
),
array( WikitextContentTest::$sections,
- '2',
- null
+ '2',
+ null
),
array( WikitextContentTest::$sections,
- '8',
- null
+ '8',
+ null
),
);
}
public static function dataReplaceSection() {
return array(
array( WikitextContentTest::$sections,
- '0',
- 'No more',
- null,
- null
+ '0',
+ 'No more',
+ null,
+ null
),
array( WikitextContentTest::$sections,
- '',
- 'No more',
- null,
- null
+ '',
+ 'No more',
+ null,
+ null
),
array( WikitextContentTest::$sections,
- '2',
- "== TEST ==\nmore fun",
- null,
- null
+ '2',
+ "== TEST ==\nmore fun",
+ null,
+ null
),
array( WikitextContentTest::$sections,
- '8',
- 'No more',
- null,
- null
+ '8',
+ 'No more',
+ null,
+ null
),
array( WikitextContentTest::$sections,
- 'new',
- 'No more',
- 'New',
- null
+ 'new',
+ 'No more',
+ 'New',
+ null
),
);
}
- public function testAddSectionHeader( ) {
+ public function testAddSectionHeader() {
$content = $this->newContent( 'hello world' );
$c = $content->addSectionHeader( 'test' );
public static function dataPreloadTransform() {
return array(
array( 'hello this is ~~~',
- 'hello this is ~~~',
+ 'hello this is ~~~',
),
array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
- 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
+ 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
),
);
}
public static function dataGetRedirectTarget() {
return array(
array( '#REDIRECT [[Test]]',
- null,
+ null,
),
array( '#REDIRECT Test',
- null,
+ null,
),
array( '* #REDIRECT [[Test]]',
- null,
+ null,
),
);
}
public static function dataIsCountable() {
return array(
array( '',
- null,
- 'any',
- true
+ null,
+ 'any',
+ true
),
array( 'Foo',
- null,
- 'any',
- true
+ null,
+ 'any',
+ true
),
array( 'Foo',
- null,
- 'comma',
- false
+ null,
+ 'comma',
+ false
),
array( 'Foo, bar',
- null,
- 'comma',
- false
+ null,
+ 'comma',
+ false
),
array( 'Foo',
- null,
- 'link',
- false
+ null,
+ 'link',
+ false
),
array( 'Foo [[bar]]',
- null,
- 'link',
- false
+ null,
+ 'link',
+ false
),
array( 'Foo',
- true,
- 'link',
- false
+ true,
+ 'link',
+ false
),
array( 'Foo [[bar]]',
- false,
- 'link',
- false
+ false,
+ 'link',
+ false
),
array( '#REDIRECT [[bar]]',
- true,
- 'any',
- true
+ true,
+ 'any',
+ true
),
array( '#REDIRECT [[bar]]',
- true,
- 'comma',
- false
+ true,
+ 'comma',
+ false
),
array( '#REDIRECT [[bar]]',
- true,
- 'link',
- false
+ true,
+ 'link',
+ false
),
);
}
public static function dataGetTextForSummary() {
return array(
array( "hello\nworld.",
- 16,
- 'hello world.',
+ 16,
+ 'hello world.',
),
array( 'hello world.',
- 8,
- 'hello...',
+ 8,
+ 'hello...',
),
array( '[[hello world]].',
- 8,
- '[[hel...',
+ 8,
+ '[[hel...',
),
);
}
- public function testMatchMagicWord( ) {
+ public function testMatchMagicWord() {
$mw = MagicWord::get( "staticredirect" );
$content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
$this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" );
}
- public function testUpdateRedirect( ) {
+ public function testUpdateRedirect() {
$target = Title::newFromText( "testUpdateRedirect_target" );
$content = $this->newContent( "#REDIRECT [[Someplace]]" );
$this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() );
}
- public static function dataEquals( ) {
+ public static function dataEquals() {
return array(
array( new JavaScriptContent( "hallo" ), null, false ),
array( new JavaScriptContent( "hallo" ), new JavaScriptContent( "hallo" ), true ),
*/
public function testGetRedirectTarget( $text, $expected ) {
$content = $this->newContent( $text );
- $t = $content->getRedirectTarget( );
+ $t = $content->getRedirectTarget();
if ( is_null( $expected ) ) {
$this->assertNull( $t, "text should not have generated a redirect target: $text" );
public function testIsRedirect( $text, $expected ) {
$content = $this->newContent( $text );
- $this->assertEquals( !is_null($expected), $content->isRedirect() );
+ $this->assertEquals( !is_null( $expected ), $content->isRedirect() );
}
/**
public static function dataIsCountable() {
return array(
array( '',
- null,
- 'any',
- true
+ null,
+ 'any',
+ true
),
array( 'Foo',
- null,
- 'any',
- true
+ null,
+ 'any',
+ true
),
array( 'Foo',
- null,
- 'comma',
- false
+ null,
+ 'comma',
+ false
),
array( 'Foo, bar',
- null,
- 'comma',
- false
+ null,
+ 'comma',
+ false
),
);
}
-
/**
* @dataProvider dataIsCountable
* @group Database
$wgArticleCountMethod = $old;
$this->assertEquals( $expected, $v, 'isCountable() returned unexpected value ' . var_export( $v, true )
- . ' instead of ' . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
+ . ' instead of ' . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
}
public static function dataGetTextForSummary() {
return array(
array( "hello\nworld.",
- 16,
- 'hello world.',
+ 16,
+ 'hello world.',
),
array( 'hello world.',
- 8,
- 'hello...',
+ 8,
+ 'hello...',
),
array( '[[hello world]].',
- 8,
- '[[hel...',
+ 8,
+ '[[hel...',
),
);
}
$this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
}
-
- public function testGetTextForSearchIndex( ) {
+ public function testGetTextForSearchIndex() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 'hello world.', $content->getTextForSearchIndex() );
$this->assertEquals( 'hello world.', $copy->getNativeData() );
}
- public function testGetSize( ) {
+ public function testGetSize() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 12, $content->getSize() );
}
- public function testGetNativeData( ) {
+ public function testGetNativeData() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 'hello world.', $content->getNativeData() );
}
- public function testGetWikitextForTransclusion( ) {
+ public function testGetWikitextForTransclusion() {
$content = $this->newContent( 'hello world.' );
$this->assertEquals( 'hello world.', $content->getWikitextForTransclusion() );
$this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() );
}
- public static function dataIsEmpty( ) {
+ public static function dataIsEmpty() {
return array(
array( '', true ),
array( ' ', false ),
$this->assertEquals( $empty, $content->isEmpty() );
}
- public static function dataEquals( ) {
+ public static function dataEquals() {
return array(
array( new TextContent( "hallo" ), null, false ),
array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ),
public static function dataGetDeletionUpdates() {
return array(
- array("TextContentTest_testGetSecondaryDataUpdates_1",
+ array( "TextContentTest_testGetSecondaryDataUpdates_1",
CONTENT_MODEL_TEXT, "hello ''world''\n",
- array( )
+ array()
),
- array("TextContentTest_testGetSecondaryDataUpdates_2",
+ array( "TextContentTest_testGetSecondaryDataUpdates_2",
CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n",
- array( )
+ array()
),
// TODO: more...?
);
// make updates accessible by class name
foreach ( $updates as $update ) {
$class = get_class( $update );
- $updates[ $class ] = $update;
+ $updates[$class] = $update;
}
if ( !$expectedStuff ) {
foreach ( $expectedStuff as $class => $fieldValues ) {
$this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
- $update = $updates[ $class ];
+ $update = $updates[$class];
foreach ( $fieldValues as $field => $value ) {
$v = $update->$field; #if the field doesn't exist, just crash and burn
$this->handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT );
}
- public function testSerializeContent( ) {
+ public function testSerializeContent() {
$content = new WikitextContent( 'hello world' );
$this->assertEquals( 'hello world', $this->handler->serializeContent( $content ) );
}
}
- public function testUnserializeContent( ) {
+ public function testUnserializeContent() {
$content = $this->handler->unserializeContent( 'hello world' );
$this->assertEquals( 'hello world', $content->getNativeData() );
$this->assertEquals( '', $content->getNativeData() );
}
- public static function dataIsSupportedFormat( ) {
+ public static function dataIsSupportedFormat() {
return array(
array( null, true ),
array( CONTENT_FORMAT_WIKITEXT, true ),
$this->assertEquals( $supported, $this->handler->isSupportedFormat( $format ) );
}
- public static function dataMerge3( ) {
+ public static function dataMerge3() {
return array(
- array( "first paragraph
+ array(
+ "first paragraph
second paragraph\n",
- "FIRST paragraph
+ "FIRST paragraph
second paragraph\n",
- "first paragraph
+ "first paragraph
SECOND paragraph\n",
- "FIRST paragraph
+ "FIRST paragraph
SECOND paragraph\n",
),
array( "first paragraph
second paragraph\n",
- "Bla bla\n",
+ "Bla bla\n",
- "Blubberdibla\n",
+ "Blubberdibla\n",
- false,
+ false,
),
-
);
}
$this->assertEquals( $expected, $merged ? $merged->getNativeData() : $merged );
}
- public static function dataGetAutosummary( ) {
+ public static function dataGetAutosummary() {
return array(
array(
'Hello there, world!',
* ^--- needed, because we do need the database to test link updates
*/
class WikitextContentTest extends TextContentTest {
-
- static $sections =
-
-"Intro
+ static $sections = "Intro
== stuff ==
hello world
public static function dataGetSection() {
return array(
array( WikitextContentTest::$sections,
- "0",
- "Intro"
+ "0",
+ "Intro"
),
array( WikitextContentTest::$sections,
- "2",
-"== test ==
+ "2",
+ "== test ==
just a test"
),
array( WikitextContentTest::$sections,
- "8",
- false
+ "8",
+ false
),
);
}
public static function dataReplaceSection() {
return array(
array( WikitextContentTest::$sections,
- "0",
- "No more",
- null,
- trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) )
+ "0",
+ "No more",
+ null,
+ trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) )
),
array( WikitextContentTest::$sections,
- "",
- "No more",
- null,
- "No more"
+ "",
+ "No more",
+ null,
+ "No more"
),
array( WikitextContentTest::$sections,
- "2",
- "== TEST ==\nmore fun",
- null,
- trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikitextContentTest::$sections ) )
+ "2",
+ "== TEST ==\nmore fun",
+ null,
+ trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikitextContentTest::$sections ) )
),
array( WikitextContentTest::$sections,
- "8",
- "No more",
- null,
- WikitextContentTest::$sections
+ "8",
+ "No more",
+ null,
+ WikitextContentTest::$sections
),
array( WikitextContentTest::$sections,
- "new",
- "No more",
- "New",
- trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more"
+ "new",
+ "No more",
+ "New",
+ trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more"
),
);
}
$this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
}
- public function testAddSectionHeader( ) {
+ public function testAddSectionHeader() {
$content = $this->newContent( 'hello world' );
$content = $content->addSectionHeader( 'test' );
public static function dataPreSaveTransform() {
return array(
array( 'hello this is ~~~',
- "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
+ "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
),
array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
- 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
),
array( // rtrim
" Foo \n ",
public static function dataPreloadTransform() {
return array(
array( 'hello this is ~~~',
- "hello this is ~~~",
+ "hello this is ~~~",
),
array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
- 'hello \'\'this\'\' is bar',
+ 'hello \'\'this\'\' is bar',
),
);
}
public static function dataGetRedirectTarget() {
return array(
array( '#REDIRECT [[Test]]',
- 'Test',
+ 'Test',
),
array( '#REDIRECT Test',
- null,
+ null,
),
array( '* #REDIRECT [[Test]]',
- null,
+ null,
),
);
}
public static function dataIsCountable() {
return array(
array( '',
- null,
- 'any',
- true
+ null,
+ 'any',
+ true
),
array( 'Foo',
- null,
- 'any',
- true
+ null,
+ 'any',
+ true
),
array( 'Foo',
- null,
- 'comma',
- false
+ null,
+ 'comma',
+ false
),
array( 'Foo, bar',
- null,
- 'comma',
- true
+ null,
+ 'comma',
+ true
),
array( 'Foo',
- null,
- 'link',
- false
+ null,
+ 'link',
+ false
),
array( 'Foo [[bar]]',
- null,
- 'link',
- true
+ null,
+ 'link',
+ true
),
array( 'Foo',
- true,
- 'link',
- true
+ true,
+ 'link',
+ true
),
array( 'Foo [[bar]]',
- false,
- 'link',
- false
+ false,
+ 'link',
+ false
),
array( '#REDIRECT [[bar]]',
- true,
- 'any',
- false
+ true,
+ 'any',
+ false
),
array( '#REDIRECT [[bar]]',
- true,
- 'comma',
- false
+ true,
+ 'comma',
+ false
),
array( '#REDIRECT [[bar]]',
- true,
- 'link',
- false
+ true,
+ 'link',
+ false
),
);
}
- public function testMatchMagicWord( ) {
+ public function testMatchMagicWord() {
$mw = MagicWord::get( "staticredirect" );
$content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
$this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" );
}
- public function testUpdateRedirect( ) {
+ public function testUpdateRedirect() {
$target = Title::newFromText( "testUpdateRedirect_target" );
// test with non-redirect page
$this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
}
- public static function dataEquals( ) {
+ public static function dataEquals() {
return array(
array( new WikitextContent( "hallo" ), null, false ),
array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ),
public static function dataGetDeletionUpdates() {
return array(
- array("WikitextContentTest_testGetSecondaryDataUpdates_1",
+ array( "WikitextContentTest_testGetSecondaryDataUpdates_1",
CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
- array( 'LinksDeletionUpdate' => array( ) )
+ array( 'LinksDeletionUpdate' => array() )
),
- array("WikitextContentTest_testGetSecondaryDataUpdates_2",
+ array( "WikitextContentTest_testGetSecondaryDataUpdates_2",
CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
- array( 'LinksDeletionUpdate' => array( ) )
+ array( 'LinksDeletionUpdate' => array() )
),
// @todo: more...?
);
}
-
}
'conds' => array( 'alias' => 'text' ),
),
"SELECT field,field2 AS alias " .
- "FROM `unittest_table` " .
- "WHERE alias = 'text'"
+ "FROM `unittest_table` " .
+ "WHERE alias = 'text'"
),
array(
array(
'options' => array( 'LIMIT' => 1, 'ORDER BY' => 'field' ),
),
"SELECT field,field2 AS alias " .
- "FROM `unittest_table` " .
- "WHERE alias = 'text' " .
- "ORDER BY field " .
- "LIMIT 1"
+ "FROM `unittest_table` " .
+ "WHERE alias = 'text' " .
+ "ORDER BY field " .
+ "LIMIT 1"
),
array(
array(
'options' => array( 'LIMIT' => 1, 'ORDER BY' => 'field' ),
'join_conds' => array( 't2' => array(
'LEFT JOIN', 'tid = t2.id'
- )),
+ ) ),
),
"SELECT tid,field,field2 AS alias,t2.id " .
- "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
- "WHERE alias = 'text' " .
- "ORDER BY field " .
- "LIMIT 1"
+ "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
+ "WHERE alias = 'text' " .
+ "ORDER BY field " .
+ "LIMIT 1"
),
array(
array(
'options' => array( 'LIMIT' => 1, 'GROUP BY' => 'field', 'HAVING' => 'COUNT(*) > 1' ),
'join_conds' => array( 't2' => array(
'LEFT JOIN', 'tid = t2.id'
- )),
+ ) ),
),
"SELECT tid,field,field2 AS alias,t2.id " .
- "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
- "WHERE alias = 'text' " .
- "GROUP BY field HAVING COUNT(*) > 1 " .
- "LIMIT 1"
+ "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
+ "WHERE alias = 'text' " .
+ "GROUP BY field HAVING COUNT(*) > 1 " .
+ "LIMIT 1"
),
array(
array(
'options' => array( 'LIMIT' => 1, 'GROUP BY' => array( 'field', 'field2' ), 'HAVING' => array( 'COUNT(*) > 1', 'field' => 1 ) ),
'join_conds' => array( 't2' => array(
'LEFT JOIN', 'tid = t2.id'
- )),
+ ) ),
),
"SELECT tid,field,field2 AS alias,t2.id " .
- "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
- "WHERE alias = 'text' " .
- "GROUP BY field,field2 HAVING (COUNT(*) > 1) AND field = '1' " .
- "LIMIT 1"
+ "FROM `unittest_table` LEFT JOIN `unittest_table2` `t2` ON ((tid = t2.id)) " .
+ "WHERE alias = 'text' " .
+ "GROUP BY field,field2 HAVING (COUNT(*) > 1) AND field = '1' " .
+ "LIMIT 1"
),
);
}
class MockDatabaseSqlite extends DatabaseSqliteStandalone {
var $lastQuery;
- function __construct( ) {
+ function __construct() {
parent::__construct( ':memory:' );
}
private function assertResultIs( $expected, $res ) {
$this->assertNotNull( $res );
$i = 0;
- foreach( $res as $row ) {
- foreach( $expected[$i] as $key => $value ) {
+ foreach ( $res as $row ) {
+ foreach ( $expected[$i] as $key => $value ) {
$this->assertTrue( isset( $row->$key ) );
$this->assertEquals( $value, $row->$key );
}
$this->assertEquals( 'foo', $this->replaceVars( 'foo' ), "Don't break anything accidentally" );
$this->assertEquals( "CREATE TABLE /**/foo (foo_key INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
- . "foo_bar TEXT, foo_name TEXT NOT NULL DEFAULT '', foo_int INTEGER, foo_int2 INTEGER );",
+ . "foo_bar TEXT, foo_name TEXT NOT NULL DEFAULT '', foo_int INTEGER, foo_int2 INTEGER );",
$this->replaceVars( "CREATE TABLE /**/foo (foo_key int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
foo_bar char(13), foo_name varchar(255) binary NOT NULL DEFAULT '', foo_int tinyint ( 8 ), foo_int2 int(16) ) ENGINE=MyISAM;" )
- );
+ );
$this->assertEquals( "CREATE TABLE foo ( foo1 REAL, foo2 REAL, foo3 REAL );",
$this->replaceVars( "CREATE TABLE foo ( foo1 FLOAT, foo2 DOUBLE( 1,10), foo3 DOUBLE PRECISION );" )
- );
+ );
$this->assertEquals( "CREATE TABLE foo ( foo_binary1 BLOB, foo_binary2 BLOB );",
$this->replaceVars( "CREATE TABLE foo ( foo_binary1 binary(16), foo_binary2 varbinary(32) );" )
- );
+ );
$this->assertEquals( "CREATE TABLE text ( text_foo TEXT );",
$this->replaceVars( "CREATE TABLE text ( text_foo tinytext );" ),
'Table name changed'
- );
+ );
$this->assertEquals( "CREATE TABLE foo ( foobar INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL );",
- $this->replaceVars("CREATE TABLE foo ( foobar INT PRIMARY KEY NOT NULL AUTO_INCREMENT );" )
- );
+ $this->replaceVars( "CREATE TABLE foo ( foobar INT PRIMARY KEY NOT NULL AUTO_INCREMENT );" )
+ );
$this->assertEquals( "CREATE TABLE foo ( foobar INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL );",
- $this->replaceVars("CREATE TABLE foo ( foobar INT PRIMARY KEY AUTO_INCREMENT NOT NULL );" )
- );
+ $this->replaceVars( "CREATE TABLE foo ( foobar INT PRIMARY KEY AUTO_INCREMENT NOT NULL );" )
+ );
$this->assertEquals( "CREATE TABLE enums( enum1 TEXT, myenum TEXT)",
$this->replaceVars( "CREATE TABLE enums( enum1 ENUM('A', 'B'), myenum ENUM ('X', 'Y'))" )
- );
+ );
$this->assertEquals( "ALTER TABLE foo ADD COLUMN foo_bar INTEGER DEFAULT 42",
$this->replaceVars( "ALTER TABLE foo\nADD COLUMN foo_bar int(10) unsigned DEFAULT 42" )
- );
+ );
}
public function testTableName() {
function testCaseInsensitiveLike() {
// TODO: Test this for all databases
- $db = new DatabaseSqliteStandalone( ':memory:' );\r
- $res = $db->query( 'SELECT "a" LIKE "A" AS a' );\r
- $row = $res->fetchRow();\r
- $this->assertFalse( (bool)$row['a'] );\r
+ $db = new DatabaseSqliteStandalone( ':memory:' );
+ $res = $db->query( 'SELECT "a" LIKE "A" AS a' );
+ $row = $res->fetchRow();
+ $this->assertFalse( (bool)$row['a'] );
}
}
private function dropFunctions() {
$this->db->query( 'DROP FUNCTION IF EXISTS mw_test_function'
- . ( $this->db->getType() == 'postgres' ? '()' : '' )
+ . ( $this->db->getType() == 'postgres' ? '()' : '' )
);
}
}
parent::setUp();
// Make sure MWDebug class is enabled
static $MWDebugEnabled = false;
- if( !$MWDebugEnabled ) {
+ if ( !$MWDebugEnabled ) {
MWDebug::init();
$MWDebugEnabled = true;
}
function testAddLog() {
MWDebug::log( 'logging a string' );
- $this->assertEquals( array( array(
- 'msg' => 'logging a string',
- 'type' => 'log',
- 'caller' => __METHOD__ ,
+ $this->assertEquals(
+ array( array(
+ 'msg' => 'logging a string',
+ 'type' => 'log',
+ 'caller' => __METHOD__,
) ),
MWDebug::getLog()
);
function testAddWarning() {
MWDebug::warning( 'Warning message' );
- $this->assertEquals( array( array(
- 'msg' => 'Warning message',
- 'type' => 'warn',
- 'caller' => 'MWDebugTest::testAddWarning',
+ $this->assertEquals(
+ array( array(
+ 'msg' => 'Warning message',
+ 'type' => 'warn',
+ 'caller' => 'MWDebugTest::testAddWarning',
) ),
MWDebug::getLog()
);
array( 'mwstore://backend/container/path', 'mwstore://backend/container/path' ),
array( 'mwstore://backend/container//path', 'mwstore://backend/container/path' ),
array( 'mwstore://backend/container///path', 'mwstore://backend/container/path' ),
- array( 'mwstore://backend/container///path//to///obj', 'mwstore://backend/container/path/to/obj',
+ array( 'mwstore://backend/container///path//to///obj', 'mwstore://backend/container/path/to/obj' ),
array( 'mwstore://', null ),
array( 'mwstore://backend', null ),
array( 'mwstore://backend//container/path', null ),
array( 'mwstore://backend//container//path', null ),
array( 'mwstore:///', null ),
array( 'mwstore:/', null ),
- array( 'mwstore:', null ), )
+ array( 'mwstore:', null ),
);
}
$cases[] = array( "$base/unittest-cont1/e/b/some-other_file.txt", "more file contents" );
$cases[] = array(
array( "$base/unittest-cont1/e/a/x.txt", "$base/unittest-cont1/e/a/y.txt",
- "$base/unittest-cont1/e/a/z.txt" ),
+ "$base/unittest-cont1/e/a/z.txt" ),
array( "contents xx", "contents xy", "contents xz" )
);
$cases[] = array( "$base/unittest-cont1/e/a/\$odd&.txt", "test file contents" );
$cases[] = array(
array( "$base/unittest-cont1/e/a/x.txt", "$base/unittest-cont1/e/a/y.txt",
- "$base/unittest-cont1/e/a/z.txt" ),
+ "$base/unittest-cont1/e/a/z.txt" ),
array( "contents xx", "contents xy", "contents xz" )
);
$cases[] = array( "$base/unittest-cont1/e/a/\$odd&.txt", "test file contents" );
$cases[] = array(
array( "$base/unittest-cont1/e/a/x.txt", "$base/unittest-cont1/e/a/y.txt",
- "$base/unittest-cont1/e/a/z.txt" ),
+ "$base/unittest-cont1/e/a/z.txt" ),
array( "contents xx", "contents xy", "contents xz" )
);
function testFileRepoConstructionOptionCanNotBeNull() {
$f = new FileRepo();
}
+
/**
* @expectedException MWException
*/
function testFileRepoConstructionOptionCanNotBeAnEmptyArray() {
$f = new FileRepo( array() );
}
+
/**
* @expectedException MWException
*/
'backend' => 'foobar'
) );
}
+
/**
* @expectedException MWException
*/
function testFileRepoConstructionWithRequiredOptions() {
$f = new FileRepo( array(
- 'name' => 'FileRepoTestRepository',
+ 'name' => 'FileRepoTestRepository',
'backend' => new FSFileBackend( array(
- 'name' => 'local-testing',
- 'lockManager' => 'nullLockManager',
+ 'name' => 'local-testing',
+ 'lockManager' => 'nullLockManager',
'containerPaths' => array()
) )
) );
$backend = new $class( $useConfig );
} else {
$backend = new FSFileBackend( array(
- 'name' => 'local-testing',
+ 'name' => 'local-testing',
'lockManager' => 'nullLockManager',
'containerPaths' => array(
- 'unittests-public' => "{$tmpPrefix}-public",
- 'unittests-thumb' => "{$tmpPrefix}-thumb",
- 'unittests-temp' => "{$tmpPrefix}-temp",
+ 'unittests-public' => "{$tmpPrefix}-public",
+ 'unittests-thumb' => "{$tmpPrefix}-thumb",
+ 'unittests-temp' => "{$tmpPrefix}-temp",
'unittests-deleted' => "{$tmpPrefix}-deleted",
)
) );
}
$this->repo = new FileRepo( array(
- 'name' => 'unittests',
+ 'name' => 'unittests',
'backend' => $backend
) );
* @param $srcPath string The filepath or virtual URL
* @param $flags integer Flags to pass into repo::store().
*/
- private function storeit($originalName, $srcPath, $flags) {
+ private function storeit( $originalName, $srcPath, $flags ) {
$hashPath = $this->repo->getHashPath( $originalName );
$dstRel = "$hashPath{$this->date}!$originalName";
$dstUrlRel = $hashPath . $this->date . '!' . rawurlencode( $originalName );
* @param $otherfn string The name of the different file (in the filesystem)
* @param $fromrepo logical 'true' if we want to copy from a virtual URL out of the Repo.
*/
- private function storecohort($fn, $infn, $otherfn, $fromrepo) {
+ private function storecohort( $fn, $infn, $otherfn, $fromrepo ) {
$f = $this->storeit( $fn, $infn, 0 );
$this->assertTrue( $f->isOK(), 'failed to store a new file' );
$this->assertEquals( $f->failCount, 0, "counts wrong {$f->successCount} {$f->failCount}" );
$this->assertEquals( $f->successCount, 1, "counts wrong {$f->successCount} {$f->failCount}" );
if ( $fromrepo ) {
- $f = $this->storeit( "Other-$fn", $infn, FileRepo::OVERWRITE);
+ $f = $this->storeit( "Other-$fn", $infn, FileRepo::OVERWRITE );
$infn = $f->value;
}
// This should work because we're allowed to overwrite
$this->assertEquals( $f->successCount, 1, "counts wrong {$f->successCount} {$f->failCount}" );
// This should fail because we're overwriting different content.
if ( $fromrepo ) {
- $f = $this->storeit( "Other-$fn", $otherfn, FileRepo::OVERWRITE);
+ $f = $this->storeit( "Other-$fn", $otherfn, FileRepo::OVERWRITE );
$otherfn = $f->value;
}
$f = $this->storeit( $fn, $otherfn, FileRepo::OVERWRITE_SAME );
# Format: (expected string, unformattedText string, optional message)
return array(
# Escape some wikitext
- array( 'Install <tag>' , 'Install <tag>', 'Escaping <' ),
- array( 'Install {{template}}' , 'Install {{template}}', 'Escaping [[' ),
- array( 'Install [[page]]' , 'Install [[page]]', 'Escaping {{' ),
- array( 'Install ' , "Install \r", 'Removing \r' ),
+ array( 'Install <tag>', 'Install <tag>', 'Escaping <' ),
+ array( 'Install {{template}}', 'Install {{template}}', 'Escaping [[' ),
+ array( 'Install [[page]]', 'Install [[page]]', 'Escaping {{' ),
+ array( 'Install ', "Install \r", 'Removing \r' ),
# Transform \t{1,2} into :{1,2}
array( ':One indentation', "\tOne indentation", 'Replacing a single \t' ),
array( '::Two indentations', "\t\tTwo indentations", 'Replacing 2 x \t' ),
# Transform 'bug 123' links
- array(
+ array(
'<span class="config-plainlink">[https://bugzilla.wikimedia.org/123 bug 123]</span>',
'bug 123', 'Testing bug 123 links' ),
array(
array(
'<span class="config-plainlink">[http://www.mediawiki.org/wiki/Manual:$wgFoo_Bar $wgFoo_Bar]</span>',
'$wgFoo_Bar', 'Testing $wgFoo_Bar (with underscore)' ),
-
+
# Icky variables that shouldn't link
array( '$myAwesomeVariable', '$myAwesomeVariable', 'Testing $myAwesomeVariable (not starting with $wg)' ),
array( '$()not!a&Var', '$()not!a&Var', 'Testing $()not!a&Var (obviously not a variable)' ),
* @group Database
*/
class JobQueueTest extends MediaWikiTestCase {
+ protected $key;
+ protected $queueRand, $queueRandTTL, $queueFifo, $queueFifoTTL;
protected $old = array();
function __construct( $name = null, array $data = array(), $dataName = '' ) {
}
protected function setUp() {
- global $wgMemc;
+ global $wgMemc, $wgJobTypeConf;
parent::setUp();
$this->old['wgMemc'] = $wgMemc;
$wgMemc = new HashBagOStuff();
- $this->queueRand = JobQueue::factory( array( 'class' => 'JobQueueDB',
- 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'random' ) );
- $this->queueRandTTL = JobQueue::factory( array( 'class' => 'JobQueueDB',
- 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'random', 'claimTTL' => 10 ) );
- $this->queueFifo = JobQueue::factory( array( 'class' => 'JobQueueDB',
- 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'fifo' ) );
- $this->queueFifoTTL = JobQueue::factory( array( 'class' => 'JobQueueDB',
- 'wiki' => wfWikiID(), 'type' => 'null', 'order' => 'fifo', 'claimTTL' => 10 ) );
+ if ( $this->getCliArg( 'use-jobqueue=' ) ) {
+ $name = $this->getCliArg( 'use-jobqueue=' );
+ if ( !isset( $wgJobTypeConf[$name] ) ) {
+ throw new MWException( "No \$wgJobTypeConf entry for '$name'." );
+ }
+ $baseConfig = $wgJobTypeConf[$name];
+ } else {
+ $baseConfig = array( 'class' => 'JobQueueDB' );
+ }
+ $baseConfig['type'] = 'null';
+ $baseConfig['wiki'] = wfWikiID();
+ $this->queueRand = JobQueue::factory(
+ array( 'order' => 'random', 'claimTTL' => 0 ) + $baseConfig );
+ $this->queueRandTTL = JobQueue::factory(
+ array( 'order' => 'random', 'claimTTL' => 10 ) + $baseConfig );
+ $this->queueFifo = JobQueue::factory(
+ array( 'order' => 'fifo', 'claimTTL' => 0 ) + $baseConfig );
+ $this->queueFifoTTL = JobQueue::factory(
+ array( 'order' => 'fifo', 'claimTTL' => 10 ) + $baseConfig );
+ if ( $baseConfig['class'] !== 'JobQueueDB' ) { // DB namespace with prefix or temp tables
+ foreach ( array( 'queueRand', 'queueRandTTL', 'queueFifo', 'queueFifoTTL' ) as $q ) {
+ $this->$q->setTestingPrefix( 'unittests-' . wfRandomString( 32 ) );
+ }
+ }
}
protected function tearDown() {
foreach ( array( 'queueRand', 'queueRandTTL', 'queueFifo', 'queueFifoTTL' ) as $q ) {
do {
$job = $this->$q->pop();
- if ( $job ) $this->$q->ack( $job );
+ if ( $job ) {
+ $this->$q->ack( $job );
+ }
} while ( $job );
}
$this->queueRand = null;
$this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
$this->assertTrue( $queue->batchPush(
- array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
+ array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
"Push worked ($desc)" );
$this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
$this->assertEquals( 0, $queue->getAcquiredCount(), "No jobs active ($desc)" );
$this->assertTrue( $queue->batchPush(
- array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
+ array( $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ) ),
"Push worked ($desc)" );
$this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
$id = wfRandomString( 32 );
$root1 = Job::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
- for ( $i=0; $i<5; ++$i ) {
+ for ( $i = 0; $i < 5; ++$i ) {
$this->assertTrue( $queue->push( $this->newJob( 0, $root1 ) ), "Push worked ($desc)" );
}
$queue->deduplicateRootJob( $this->newJob( 0, $root1 ) );
$root2 = Job::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
$this->assertNotEquals( $root1['rootJobTimestamp'], $root2['rootJobTimestamp'],
"Root job signatures have different timestamps." );
- for ( $i=0; $i<5; ++$i ) {
+ for ( $i = 0; $i < 5; ++$i ) {
$this->assertTrue( $queue->push( $this->newJob( 0, $root2 ) ), "Push worked ($desc)" );
}
$queue->deduplicateRootJob( $this->newJob( 0, $root2 ) );
$jobs[] = $job;
$queue->ack( $job );
}
- if ( $job instanceof DuplicateJob ) ++$dupcount;
+ if ( $job instanceof DuplicateJob ) {
+ ++$dupcount;
+ }
} while ( $job );
$this->assertEquals( 10, count( $jobs ), "Correct number of jobs popped ($desc)" );
$this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
$this->assertEquals( 0, $queue->getAcquiredCount(), "Queue is empty ($desc)" );
- for ( $i=0; $i<10; ++$i ) {
+ for ( $i = 0; $i < 10; ++$i ) {
$this->assertTrue( $queue->push( $this->newJob( $i ) ), "Push worked ($desc)" );
}
- for ( $i=0; $i<10; ++$i ) {
+ for ( $i = 0; $i < 10; ++$i ) {
$job = $queue->pop();
$this->assertTrue( $job instanceof Job, "Jobs popped from queue ($desc)" );
$params = $job->getParams();
$queue->ack( $job );
}
- $this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
+ $this->assertFalse( $queue->pop(), "Queue is not empty ($desc)" );
$queue->flushCaches();
$this->assertEquals( 0, $queue->getSize(), "Queue is empty ($desc)" );
if ( !function_exists( 'json_encode' ) ) {
$this->markTestIncomplete( 'No PHP json support, unable to test' );
return;
- } elseif( strtolower( json_encode( "\xf0\xa0\x80\x80" ) ) != '"\ud840\udc00"' ) {
+ } elseif ( strtolower( json_encode( "\xf0\xa0\x80\x80" ) ) != '"\ud840\udc00"' ) {
$this->markTestIncomplete( 'Have buggy PHP json support, unable to test' );
return;
} else {
$transformedB = CSSJanus::transform( $cssB );
$this->assertEquals( $transformedB, $cssA, 'Test B-A transformation' );
-
- // If no B version is provided, it means
- // the output should equal the input.
} else {
+ // If no B version is provided, it means
+ // the output should equal the input.
$transformedA = CSSJanus::transform( $cssA );
$this->assertEquals( $transformedA, $cssA, 'Nothing was flipped' );
}
$flipped = CSSJanus::transform( $code, $swapLtrRtlInURL, $swapLeftRightInURL );
$this->assertEquals( $expectedOutput, $flipped,
- 'Test flipping, options: url-ltr-rtl=' . ($swapLtrRtlInURL ? 'true' : 'false')
- . ' url-left-right=' . ($swapLeftRightInURL ? 'true' : 'false')
+ 'Test flipping, options: url-ltr-rtl=' . ( $swapLtrRtlInURL ? 'true' : 'false' )
+ . ' url-left-right=' . ( $swapLeftRightInURL ? 'true' : 'false' )
);
}
+
/**
* @dataProvider provideTransformBrokenCases
* @group Broken
public function testUnset( GenericArrayObject $list ) {
if ( $list->isEmpty() ) {
$this->assertTrue( true ); // We cannot test unset if there are no elements
- }
- else {
+ } else {
$offset = $list->getIterator()->key();
$count = $list->count();
$list->offsetUnset( $offset );
$this->assertEquals( $listSize, $list->count() );
- $this->checkTypeChecks( function( GenericArrayObject $list, $element ) {
+ $this->checkTypeChecks( function ( GenericArrayObject $list, $element ) {
$list->append( $element );
} );
}
foreach ( array( 42, 'foo', array(), new stdClass(), 4.2 ) as $element ) {
$validValid = $element instanceof $elementClass;
- try{
+ try {
call_user_func( $function, $list, $element );
$valid = true;
- }
- catch ( InvalidArgumentException $exception ) {
+ } catch ( InvalidArgumentException $exception ) {
$valid = false;
}
$this->assertEquals( count( $elements ), $list->count() );
- $this->checkTypeChecks( function( GenericArrayObject $list, $element ) {
+ $this->checkTypeChecks( function ( GenericArrayObject $list, $element ) {
$list->offsetSet( mt_rand(), $element );
} );
}
*/
class IEUrlExtensionTest extends MediaWikiTestCase {
function testSimple() {
- $this->assertEquals(
+ $this->assertEquals(
'y',
IEUrlExtension::findIE6Extension( 'x.y' ),
'Simple extension'
* At some point there was a bug that caused this comment to be ended at '* /',
* causing /M... to be left as the beginning of a regex.
*/
- array( "/**\n * Foo\n * {\n * 'bar' : {\n * //Multiple rules with configurable operators\n * 'baz' : false\n * }\n */", ""),
+ array( "/**\n * Foo\n * {\n * 'bar' : {\n * //Multiple rules with configurable operators\n * 'baz' : false\n * }\n */", "" ),
/**
* ' Foo \' bar \
array( "switch(x){case y?z:{}/ x/g:{}/ x/g;}", "switch(x){case y?z:{}/x/g:{}/ x/g;}" ),
array( "function x(){}/ x/g", "function x(){}/ x/g" ),
array( "+function x(){}/ x/g", "+function x(){}/x/g" ),
-
+
// Multiline quoted string
array( "var foo=\"\\\nblah\\\n\";", "var foo=\"\\\nblah\\\n\";" ),
// Division vs. regex nastiness
array( "alert( (10+10) / '/'.charCodeAt( 0 ) + '//' );", "alert((10+10)/'/'.charCodeAt(0)+'//');" ),
array( "if(1)/a /g.exec('Pa ss');", "if(1)/a /g.exec('Pa ss');" ),
-
+
// newline insertion after 1000 chars: break after the "++", not before
array( str_repeat( ';', 996 ) . "if(x++);", str_repeat( ';', 996 ) . "if(x++\n);" ),
// Unicode letter characters should pass through ok in identifiers (bug 31187)
- array( "var KaŝSkatolVal = {}", 'var KaŝSkatolVal={}'),
+ array( "var KaŝSkatolVal = {}", 'var KaŝSkatolVal={}' ),
// Per spec unicode char escape values should work in identifiers,
// as long as it's a valid char. In future it might get normalized.
- array( "var Ka\\u015dSkatolVal = {}", 'var Ka\\u015dSkatolVal={}'),
+ array( "var Ka\\u015dSkatolVal = {}", 'var Ka\\u015dSkatolVal={}' ),
// Some structures that might look invalid at first sight
array( "var a = 5.;", "var a=5.;" ),
array(
// This one gets interpreted all together by the prior code;
// no break at the 'E' happens.
- '1.23456789E55',
+ '1.23456789E55',
),
array(
// This one breaks under the bad code; splits between 'E' and '+'
$minified = JavaScriptMinifier::minify( $input );
- $this->assertEquals( $expected, $minified, "Line breaks must not occur in middle of exponent");
+ $this->assertEquals( $expected, $minified, "Line breaks must not occur in middle of exponent" );
}
}
'wgLogActionsHandlers' => array( 'phpunit/test' => 'LogFormatter',
'phpunit/param' => 'LogFormatter' ),
'wgUser' => User::newFromName( 'Testuser' ),
- 'wgExtensionMessagesFiles' => array( 'LogTests' => __DIR__.'/LogTests.i18n.php' ),
+ 'wgExtensionMessagesFiles' => array( 'LogTests' => __DIR__ . '/LogTests.i18n.php' ),
) );
$wgLang->getLocalisationCache()->recache( $wgLang->getCode() );
$messages = array();
$messages['en'] = array(
- 'log-name-phpunit' => 'PHPUnit-log',
+ 'log-name-phpunit' => 'PHPUnit-log',
'log-description-phpunit' => 'Log for PHPUnit-tests',
- 'logentry-phpunit-test' => '$1 {{GENDER:$2|tests}} with page $3',
- 'logentry-phpunit-param' => '$4',
+ 'logentry-phpunit-test' => '$1 {{GENDER:$2|tests}} with page $3',
+ 'logentry-phpunit-param' => '$4',
);
$expected = array(
'x-default' => 'right(iptc)',
- 'en' => 'right translation',
- '_type' => 'lang'
+ 'en' => 'right translation',
+ '_type' => 'lang'
);
-
+
$this->assertArrayHasKey( 'ImageDescription', $meta,
'Did not extract any ImageDescription info?!' );
}
$handler = new BitmapMetadataHandler();
$result = $handler->png( $this->filePath . 'xmp.png' );
- $expected = array (
+ $expected = array(
'frameCount' => 0,
'loopCount' => 1,
'duration' => 0,
'bitDepth' => 1,
'colorType' => 'index-coloured',
- 'metadata' => array (
+ 'metadata' => array(
'SerialNumber' => '123456789',
'_MW_PNG_VERSION' => 1,
),
);
- $this->assertEquals( $expected, $result );
+ $this->assertEquals( $expected, $result );
}
public function testPNGNative() {
$handler = new BitmapMetadataHandler();
$result = $handler->png( $this->filePath . 'Png-native-test.png' );
$expected = 'http://example.com/url';
- $this->assertEquals( $expected, $result['metadata']['Identifier']['x-default'] );
+ $this->assertEquals( $expected, $result['metadata']['Identifier']['x-default'] );
}
public function testTiffByteOrder() {
$this->assertTrue( $valid );
$this->assertEquals( $expectedParams, $params, $msg );
}
-
+
function provideNormaliseParams() {
return array(
- /* Regular resize operations */
+ /* Regular resize operations */
array(
array( 1024, 768 ),
- array(
- 'width' => 512, 'height' => 384,
+ array(
+ 'width' => 512, 'height' => 384,
'physicalWidth' => 512, 'physicalHeight' => 384,
'page' => 1,
),
),
array(
array( 1024, 768 ),
- array(
- 'width' => 512, 'height' => 384,
+ array(
+ 'width' => 512, 'height' => 384,
'physicalWidth' => 512, 'physicalHeight' => 384,
- 'page' => 1,
+ 'page' => 1,
),
array( 'width' => 512, 'height' => 768 ),
'Resizing with height set too high',
),
array(
array( 1024, 768 ),
- array(
- 'width' => 512, 'height' => 384,
+ array(
+ 'width' => 512, 'height' => 384,
'physicalWidth' => 512, 'physicalHeight' => 384,
- 'page' => 1,
+ 'page' => 1,
),
array( 'width' => 1024, 'height' => 384 ),
'Resizing with height set',
),
-
+
/* Very tall images */
array(
array( 1000, 100 ),
- array(
+ array(
'width' => 5, 'height' => 1,
'physicalWidth' => 5, 'physicalHeight' => 1,
- 'page' => 1,
+ 'page' => 1,
),
array( 'width' => 5 ),
'Very wide image',
),
-
+
array(
array( 100, 1000 ),
- array(
+ array(
'width' => 1, 'height' => 10,
'physicalWidth' => 1, 'physicalHeight' => 10,
- 'page' => 1,
+ 'page' => 1,
),
array( 'width' => 1 ),
'Very high image',
),
array(
array( 100, 1000 ),
- array(
+ array(
'width' => 1, 'height' => 5,
'physicalWidth' => 1, 'physicalHeight' => 10,
- 'page' => 1,
+ 'page' => 1,
),
array( 'width' => 10, 'height' => 5 ),
'Very high image with height set',
/* Max image area */
array(
array( 4000, 4000 ),
- array(
+ array(
'width' => 5000, 'height' => 5000,
'physicalWidth' => 4000, 'physicalHeight' => 4000,
- 'page' => 1,
+ 'page' => 1,
),
array( 'width' => 5000 ),
'Bigger than max image size but doesn\'t need scaling',
$file = new FakeDimensionFile( array( 4000, 4000 ) );
$handler = new BitmapHandler;
$params = array( 'width' => '3700' ); // Still bigger than max size.
- $this->assertEquals( 'TransformParameterError',
+ $this->assertEquals( 'TransformParameterError',
get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
}
$file->mustRender = true;
$handler = new BitmapHandler;
$params = array( 'width' => '5000' ); // Still bigger than max size.
- $this->assertEquals( 'TransformParameterError',
+ $this->assertEquals( 'TransformParameterError',
get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
}
-
+
function testImageArea() {
$file = new FakeDimensionFile( array( 7, 9 ) );
$handler = new BitmapHandler;
public $mustRender = false;
public function __construct( $dimensions ) {
- parent::__construct( Title::makeTitle( NS_FILE, 'Test' ),
+ parent::__construct( Title::makeTitle( NS_FILE, 'Test' ),
new NullRepo( null ) );
-
+
$this->dimensions = $dimensions;
}
+
public function getWidth( $page = 1 ) {
return $this->dimensions[0];
}
+
public function getHeight( $page = 1 ) {
return $this->dimensions[1];
}
+
public function mustRender() {
return $this->mustRender;
}
+
public function getPath() {
return '';
}
function testConvertMetadataLatest() {
$metadata = array(
- 'foo' => array( 'First', 'Second', '_type' => 'ol' ),
- 'MEDIAWIKI_EXIF_VERSION' => 2
- );
+ 'foo' => array( 'First', 'Second', '_type' => 'ol' ),
+ 'MEDIAWIKI_EXIF_VERSION' => 2
+ );
$res = $this->handler->convertMetadataVersion( $metadata, 2 );
$this->assertEquals( $metadata, $res );
}
function testConvertMetadataSoftware() {
$metadata = array(
- 'Software' => array( array('GIMP', '1.1' ) ),
+ 'Software' => array( array( 'GIMP', '1.1' ) ),
'MEDIAWIKI_EXIF_VERSION' => 2,
);
$expected = array(
$tmpDir = $this->getNewTempDirectory();
$this->repo = new FSRepo( array(
- 'name' => 'temp',
- 'url' => 'http://localhost/thumbtest',
- 'backend' => new FSFileBackend( array(
- 'name' => 'localtesting',
- 'lockManager' => 'nullLockManager',
+ 'name' => 'temp',
+ 'url' => 'http://localhost/thumbtest',
+ 'backend' => new FSFileBackend( array(
+ 'name' => 'localtesting',
+ 'lockManager' => 'nullLockManager',
'containerPaths' => array( 'temp-thumb' => $tmpDir, 'data' => $filePath )
) )
) );
if ( !BitmapHandler::canRotate() ) {
$this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
}
- foreach( $thumbs as $size => $out ) {
- if( preg_match('/^(\d+)px$/', $size, $matches ) ) {
+ foreach ( $thumbs as $size => $out ) {
+ if ( preg_match( '/^(\d+)px$/', $size, $matches ) ) {
$params = array(
'width' => $matches[1],
);
'height' => $matches[2]
);
} else {
- throw new MWException('bogus test data format ' . $size);
+ throw new MWException( 'bogus test data format ' . $size );
}
$file = $this->dataFile( $name, $type );
$this->assertEquals( $out[1], $thumb->getHeight(), "$name: thumb reported height check for $size" );
$gis = getimagesize( $thumb->getLocalCopyPath() );
- if ($out[0] > $info['width']) {
+ if ( $out[0] > $info['width'] ) {
// Physical image won't be scaled bigger than the original.
- $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size");
- $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size");
+ $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size" );
+ $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size" );
} else {
- $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size");
- $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size");
+ $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size" );
+ $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size" );
}
}
}
global $wgEnableAutoRotation;
$wgEnableAutoRotation = false;
- foreach( $thumbs as $size => $out ) {
- if( preg_match('/^(\d+)px$/', $size, $matches ) ) {
+ foreach ( $thumbs as $size => $out ) {
+ if ( preg_match( '/^(\d+)px$/', $size, $matches ) ) {
$params = array(
'width' => $matches[1],
);
'height' => $matches[2]
);
} else {
- throw new MWException('bogus test data format ' . $size);
+ throw new MWException( 'bogus test data format ' . $size );
}
$file = $this->dataFile( $name, $type );
$this->assertEquals( $out[1], $thumb->getHeight(), "$name: thumb reported height check for $size" );
$gis = getimagesize( $thumb->getLocalCopyPath() );
- if ($out[0] > $info['width']) {
+ if ( $out[0] > $info['width'] ) {
// Physical image won't be scaled bigger than the original.
- $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size");
- $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size");
+ $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size" );
+ $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size" );
} else {
- $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size");
- $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size");
+ $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size" );
+ $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size" );
}
}
$wgEnableAutoRotation = true;
*/
function testBitmapExtractPreRotationDimensions( $rotation, $expected ) {
$result = $this->handler->extractPreRotationDimensions( array(
- 'physicalWidth' => self::TEST_WIDTH,
- 'physicalHeight' => self::TEST_HEIGHT,
- ), $rotation );
+ 'physicalWidth' => self::TEST_WIDTH,
+ 'physicalHeight' => self::TEST_HEIGHT,
+ ), $rotation );
$this->assertEquals( $expected, $result );
}
public function testGPSExtraction() {
$filename = $this->mediaPath . 'exif-gps.jpg';
- $seg = JpegMetadataExtractor::segmentSplitter( $filename );
+ $seg = JpegMetadataExtractor::segmentSplitter( $filename );
$exif = new Exif( $filename, $seg['byteOrder'] );
$data = $exif->getFilteredData();
$expected = array(
public function testUnicodeUserComment() {
$filename = $this->mediaPath . 'exif-user-comment.jpg';
- $seg = JpegMetadataExtractor::segmentSplitter( $filename );
+ $seg = JpegMetadataExtractor::segmentSplitter( $filename );
$exif = new Exif( $filename, $seg['byteOrder'] );
$data = $exif->getFilteredData();
if ( !wfDl( 'exif' ) ) {
$this->markTestSkipped( "This test needs the exif extension." );
}
- $filePath = __DIR__ . '/../../data/media';
+ $filePath = __DIR__ . '/../../data/media';
$this->backend = new FSFileBackend( array(
- 'name' => 'localtesting',
- 'lockManager' => 'nullLockManager',
+ 'name' => 'localtesting',
+ 'lockManager' => 'nullLockManager',
'containerPaths' => array( 'data' => $filePath )
) );
$this->repo = new FSRepo( array(
- 'name' => 'temp',
- 'url' => 'http://localhost/thumbtest',
+ 'name' => 'temp',
+ 'url' => 'http://localhost/thumbtest',
'backend' => $this->backend
) );
public function testInvalidDate() {
$file = $this->dataFile( 'broken_exif_date.jpg', 'image/jpeg' );
-
+
// Throws an error if bug hit
$meta = $file->formatMetadata();
$this->assertNotEquals( false, $meta, 'Valid metadata extracted' );
-
+
// Find date exif entry
$this->assertArrayHasKey( 'visible', $meta );
$dateIndex = null;
}
}
$this->assertNotNull( $dateIndex, 'Date entry exists in metadata' );
- $this->assertEquals( '0000:01:00 00:02:27',
+ $this->assertEquals( '0000:01:00 00:02:27',
$meta['visible'][$dateIndex]['value'],
'File with invalid date metadata (bug 29471)' );
}
$this->mediaPath = __DIR__ . '/../../data/media/';
}
+
/**
* Put in a file, and see if the metadata coming out is as expected.
* @param $filename String
$actual = GIFMetadataExtractor::getMetadata( $this->mediaPath . $filename );
$this->assertEquals( $expected, $actual );
}
+
public static function provideGetMetadata() {
$xmpNugget = <<<EOF
$xmpNugget = str_replace( "\r", '', $xmpNugget ); // Windows compat
return array(
- array( 'nonanimated.gif', array(
- 'comment' => array( 'GIF test file ⁕ Created with GIMP' ),
- 'duration' => 0.1,
- 'frameCount' => 1,
- 'looped' => false,
- 'xmp' => '',
+ array(
+ 'nonanimated.gif',
+ array(
+ 'comment' => array( 'GIF test file ⁕ Created with GIMP' ),
+ 'duration' => 0.1,
+ 'frameCount' => 1,
+ 'looped' => false,
+ 'xmp' => '',
)
),
- array( 'animated.gif', array(
- 'comment' => array( 'GIF test file . Created with GIMP' ),
- 'duration' => 2.4,
- 'frameCount' => 4,
- 'looped' => true,
- 'xmp' => '',
+ array(
+ 'animated.gif',
+ array(
+ 'comment' => array( 'GIF test file . Created with GIMP' ),
+ 'duration' => 2.4,
+ 'frameCount' => 4,
+ 'looped' => true,
+ 'xmp' => '',
)
),
- array( 'animated-xmp.gif', array(
- 'xmp' => $xmpNugget,
- 'duration' => 2.4,
- 'frameCount' => 4,
- 'looped' => true,
- 'comment' => array( 'GIƒ·test·file' ),
+ array(
+ 'animated-xmp.gif',
+ array(
+ 'xmp' => $xmpNugget,
+ 'duration' => 2.4,
+ 'frameCount' => 4,
+ 'looped' => true,
+ 'comment' => array( 'GIƒ·test·file' ),
)
),
);
protected function setUp() {
parent::setUp();
- $this->filePath = __DIR__ . '/../../data/media';
+ $this->filePath = __DIR__ . '/../../data/media';
$this->backend = new FSFileBackend( array(
- 'name' => 'localtesting',
- 'lockManager' => 'nullLockManager',
+ 'name' => 'localtesting',
+ 'lockManager' => 'nullLockManager',
'containerPaths' => array( 'data' => $this->filePath )
) );
$this->repo = new FSRepo( array(
- 'name' => 'temp',
- 'url' => 'http://localhost/thumbtest',
+ 'name' => 'temp',
+ 'url' => 'http://localhost/thumbtest',
'backend' => $this->backend
) );
$this->handler = new GIFHandler();
$actual = $this->handler->isAnimatedImage( $file );
$this->assertEquals( $expected, $actual );
}
+
public static function provideIsAnimated() {
return array(
array( 'animated.gif', true ),
$actual = $this->handler->getImageArea( $file, $file->getWidth(), $file->getHeight() );
$this->assertEquals( $expected, $actual );
}
+
public static function provideGetImageArea() {
return array(
array( 'animated.gif', 5400 ),
$actual = $this->handler->isMetadataValid( null, $metadata );
$this->assertEquals( $expected, $actual );
}
+
public static function provideIsMetadataValid() {
return array(
array( GIFHandler::BROKEN_FILE, GIFHandler::METADATA_GOOD ),
$res = IPTC::Parse( $iptcData );
$this->assertEquals( array( '¼' ), $res['Keywords'] );
}
+
/* This one contains a sequence that's valid iso 8859-1 but not valid utf8 */
/* \xC3 = Ã, \xB8 = ¸ */
public function testIPTCParseNoCharset88591b() {
$res = IPTC::Parse( $iptcData );
$this->assertEquals( array( 'ÃÃø' ), $res['Keywords'] );
}
+
/* Same as testIPTCParseNoCharset88591b, but forcing the charset to utf-8.
* What should happen is the first "\xC3\xC3" should be dropped as invalid,
* leaving \xC3\xB8, which is ø
$res = IPTC::Parse( $iptcData );
$this->assertEquals( array( 'ø' ), $res['Keywords'] );
}
+
public function testIPTCParseNoCharsetUTF8() {
$iptcData = "Photoshop 3.0\08BIM\4\4\0\0\0\0\0\x07\x1c\x02\x19\x00\x02¼";
$res = IPTC::Parse( $iptcData );
$this->assertEquals( array( '¼' ), $res['Keywords'] );
}
+
// Testing something that has 2 values for keyword
public function testIPTCParseMulti() {
$iptcData = /* identifier */ "Photoshop 3.0\08BIM\4\4"
$res = IPTC::Parse( $iptcData );
$this->assertEquals( array( '¼', '¼½' ), $res['Keywords'] );
}
+
public function testIPTCParseUTF8() {
// This has the magic "\x1c\x01\x5A\x00\x03\x1B\x25\x47" which marks content as UTF8.
$iptcData = "Photoshop 3.0\08BIM\4\4\0\0\0\0\0\x0F\x1c\x02\x19\x00\x02¼\x1c\x01\x5A\x00\x03\x1B\x25\x47";
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . $file );
$this->assertEquals( array( 'UTF-8 JPEG Comment — ¼' ), $res['COM'] );
}
+
public static function provideUtf8Comment() {
return array(
array( 'jpeg-comment-utf.jpg' ),
array( 'jpeg-padding-odd.jpg' ),
);
}
+
/** The file is iso-8859-1, but it should get auto converted */
public function testIso88591Comment() {
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-comment-iso8859-1.jpg' );
$this->assertEquals( array( 'ISO-8859-1 JPEG Comment - ¼' ), $res['COM'] );
}
+
/** Comment values that are non-textual (random binary junk) should not be shown.
* The example test file has a comment with a 0x5 byte in it which is a control character
* and considered binary junk for our purposes.
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-comment-binary.jpg' );
$this->assertEmpty( $res['COM'] );
}
+
/* Very rarely a file can have multiple comments.
* Order of comments is based on order inside the file.
*/
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-comment-multiple.jpg' );
$this->assertEquals( array( 'foo', 'bar' ), $res['COM'] );
}
+
public function testXMPExtraction() {
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-xmp-psir.jpg' );
$expected = file_get_contents( $this->filePath . 'jpeg-xmp-psir.xmp' );
$this->assertEquals( $expected, $res['XMP'] );
}
+
public function testPSIRExtraction() {
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-xmp-psir.jpg' );
$expected = '50686f746f73686f7020332e30003842494d04040000000000181c02190004746573741c02190003666f6f1c020000020004';
$this->assertEquals( $expected, bin2hex( $res['PSIR'][0] ) );
}
+
public function testXMPExtractionAltAppId() {
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-xmp-alt.jpg' );
$expected = file_get_contents( $this->filePath . 'jpeg-xmp-psir.xmp' );
$this->assertEquals( 'iptc-no-hash', $res );
}
+
public function testIPTCHashComparisionBadHash() {
$segments = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-iptc-bad-hash.jpg' );
$res = JpegMetadataExtractor::doPSIR( $segments['PSIR'][0] );
$this->assertEquals( 'iptc-bad-hash', $res );
}
+
public function testIPTCHashComparisionGoodHash() {
$segments = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-iptc-good-hash.jpg' );
$res = JpegMetadataExtractor::doPSIR( $segments['PSIR'][0] );
$this->assertEquals( 'iptc-good-hash', $res );
}
+
public function testExifByteOrder() {
$res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'exif-user-comment.jpg' );
$expected = 'BE';
parent::setUp();
$this->filePath = __DIR__ . '/../../data/media/';
}
+
/**
- * Tests zTXt tag (compressed textual metadata)
+ * Tests zTXt tag (compressed textual metadata)
*/
function testPngNativetZtxt() {
$this->checkPHPExtension( 'zlib' );
* Test extraction of pHYs tags, which can tell what the
* actual resolution of the image is (aka in dots per meter).
*/
-/*
+ /*
function testPngPhysTag () {
$meta = PNGMetadataExtractor::getMetadata( $this->filePath .
'Png-native-test.png' );
$this->assertEquals( '2835/100', $meta['YResolution'] );
$this->assertEquals( 3, $meta['ResolutionUnit'] ); // 3 = cm
}
-*/
+ */
/**
* Given a normal static PNG, check the animation metadata returned.
$this->assertEquals( 8, $meta['bitDepth'] );
}
+
function testPngBitDepth1() {
$meta = PNGMetadataExtractor::getMetadata( $this->filePath .
'1bit-png.png' );
$this->assertEquals( 'index-coloured', $meta['colorType'] );
}
+
function testPngRgbColour() {
$meta = PNGMetadataExtractor::getMetadata( $this->filePath .
'rgb-png.png' );
$this->assertEquals( 'truecolour-alpha', $meta['colorType'] );
}
+
function testPngRgbNoAlphaColour() {
$meta = PNGMetadataExtractor::getMetadata( $this->filePath .
'rgb-na-png.png' );
$this->assertEquals( 'truecolour', $meta['colorType'] );
}
+
function testPngGreyscaleColour() {
$meta = PNGMetadataExtractor::getMetadata( $this->filePath .
'greyscale-png.png' );
$this->assertEquals( 'greyscale-alpha', $meta['colorType'] );
}
+
function testPngGreyscaleNoAlphaColour() {
$meta = PNGMetadataExtractor::getMetadata( $this->filePath .
'greyscale-na-png.png' );
protected function setUp() {
parent::setUp();
- $this->filePath = __DIR__ . '/../../data/media';
+ $this->filePath = __DIR__ . '/../../data/media';
$this->backend = new FSFileBackend( array(
- 'name' => 'localtesting',
- 'lockManager' => 'nullLockManager',
+ 'name' => 'localtesting',
+ 'lockManager' => 'nullLockManager',
'containerPaths' => array( 'data' => $this->filePath )
) );
$this->repo = new FSRepo( array(
- 'name' => 'temp',
- 'url' => 'http://localhost/thumbtest',
+ 'name' => 'temp',
+ 'url' => 'http://localhost/thumbtest',
'backend' => $this->backend
) );
$this->handler = new PNGHandler();
$res = $this->handler->getMetadata( null, $this->filePath . '/README' );
$this->assertEquals( PNGHandler::BROKEN_FILE, $res );
}
+
/**
* @param $filename String basename of the file to check
* @param $expected boolean Expected result.
$actual = $this->handler->isAnimatedImage( $file );
$this->assertEquals( $expected, $actual );
}
+
public static function provideIsAnimated() {
return array(
array( 'Animated_PNG_example_bouncing_beach_ball.png', true ),
* @dataProvider provideGetImageArea
*/
public function testGetImageArea( $filename, $expected ) {
- $file = $this->dataFile($filename, 'image/png' );
+ $file = $this->dataFile( $filename, 'image/png' );
$actual = $this->handler->getImageArea( $file, $file->getWidth(), $file->getHeight() );
$this->assertEquals( $expected, $actual );
}
+
public static function provideGetImageArea() {
return array(
array( '1bit-png.png', 2500 ),
$actual = $this->handler->isMetadataValid( null, $metadata );
$this->assertEquals( $expected, $actual );
}
+
public static function provideIsMetadataValid() {
return array(
array( PNGHandler::BROKEN_FILE, PNGHandler::METADATA_GOOD ),
// $this->assertEquals( unserialize( $expected ), unserialize( $actual ) );
$this->assertEquals( ( $expected ), ( $actual ) );
}
+
public static function provideGetMetadata() {
return array(
array( 'rgb-na-png.png', 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}' ),
- array( 'xmp.png', 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:1;s:9:"colorType";s:14:"index-coloured";s:8:"metadata";a:2:{s:12:"SerialNumber";s:9:"123456789";s:15:"_MW_PNG_VERSION";i:1;}}' ),
+ array( 'xmp.png', 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:1;s:9:"colorType";s:14:"index-coloured";s:8:"metadata";a:2:{s:12:"SerialNumber";s:9:"123456789";s:15:"_MW_PNG_VERSION";i:1;}}' ),
);
}
function testGetMetadata( $infile, $expected ) {
$this->assertMetadata( $infile, $expected );
}
-
+
/**
* @dataProvider provideSvgFilesWithXMLMetadata
*/
function testGetXMLMetadata( $infile, $expected ) {
$r = new XMLReader();
- if( !method_exists( $r, 'readInnerXML' ) ) {
+ if ( !method_exists( $r, 'readInnerXML' ) ) {
$this->markTestSkipped( 'XMLReader::readInnerXML() does not exist (libxml >2.6.20 needed).' );
return;
}
public static function provideSvgFilesWithXMLMetadata() {
$base = __DIR__ . '/../../data/media';
- $metadata =
- '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ $metadata = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<ns4:Work xmlns:ns4="http://creativecommons.org/ns#" rdf:about="">
<ns5:format xmlns:ns5="http://purl.org/dc/elements/1.1/">image/svg+xml</ns5:format>
<ns5:type xmlns:ns5="http://purl.org/dc/elements/1.1/" rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
}
public static function provideXMPParse() {
- $xmpPath = __DIR__ . '/../../data/xmp/' ;
+ $xmpPath = __DIR__ . '/../../data/xmp/';
$data = array();
// $xmpFiles format: array of arrays with first arg file base name,
array( 'utf32LE', 'UTF-32LE encoding' ),
array( 'xmpExt', 'Extended XMP missing second part' ),
array( 'gps', 'Handling of exif GPS parameters in XMP' ),
- );
- foreach( $xmpFiles as $file ) {
+ );
+
+ foreach ( $xmpFiles as $file ) {
$xmp = file_get_contents( $xmpPath . $file[0] . '.xmp' );
// I'm not sure if this is the best way to handle getting the
// result array, but it seems kind of big to put directly in the test
$reader->parseExtended( $extendedPacket );
$actual = $reader->getResults();
- $expected = array( 'xmp-exif' =>
- array(
+ $expected = array(
+ 'xmp-exif' => array(
'DigitalZoomRatio' => '0/10',
'Flash' => 9,
'FNumber' => '2/10',
$reader->parseExtended( $extendedPacket );
$actual = $reader->getResults();
- $expected = array( 'xmp-exif' =>
- array(
+ $expected = array(
+ 'xmp-exif' => array(
'DigitalZoomRatio' => '0/10',
'Flash' => 9,
)
$this->assertEquals( $expected, $actual );
}
+
/**
* Have a high offset to simulate a missing packet,
* which should cause it to ignore the ExtendedXMP packet.
$reader->parseExtended( $extendedPacket );
$actual = $reader->getResults();
- $expected = array( 'xmp-exif' =>
- array(
+ $expected = array(
+ 'xmp-exif' => array(
'DigitalZoomRatio' => '0/10',
'Flash' => 9,
)
*/
function XtestAllChars() {
$rep = UTF8_REPLACEMENT;
- for( $i = 0x0; $i < UNICODE_MAX; $i++ ) {
+ for ( $i = 0x0; $i < UNICODE_MAX; $i++ ) {
$char = codepointToUtf8( $i );
$clean = UtfNormal::cleanUp( $char );
$x = sprintf( "%04X", $i );
- if( $i % 0x1000 == 0 ) echo "U+$x\n";
- if( $i == 0x0009 ||
- $i == 0x000a ||
- $i == 0x000d ||
- ($i > 0x001f && $i < UNICODE_SURROGATE_FIRST) ||
- ($i > UNICODE_SURROGATE_LAST && $i < 0xfffe ) ||
- ($i > 0xffff && $i <= UNICODE_MAX ) ) {
- if( isset( UtfNormal::$utfCanonicalComp[$char] ) || isset( UtfNormal::$utfCanonicalDecomp[$char] ) ) {
- $comp = UtfNormal::NFC( $char );
+
+ if ( $i % 0x1000 == 0 ) {
+ echo "U+$x\n";
+ }
+
+ if ( $i == 0x0009 ||
+ $i == 0x000a ||
+ $i == 0x000d ||
+ ( $i > 0x001f && $i < UNICODE_SURROGATE_FIRST ) ||
+ ( $i > UNICODE_SURROGATE_LAST && $i < 0xfffe ) ||
+ ( $i > 0xffff && $i <= UNICODE_MAX )
+ ) {
+ if ( isset( UtfNormal::$utfCanonicalComp[$char] ) || isset( UtfNormal::$utfCanonicalDecomp[$char] ) ) {
+ $comp = UtfNormal::NFC( $char );
$this->assertEquals(
bin2hex( $comp ),
bin2hex( $clean ),
/** @todo document */
function doTestBytes( $head, $tail ) {
- for( $i = 0x0; $i < 256; $i++ ) {
+ for ( $i = 0x0; $i < 256; $i++ ) {
$char = $head . chr( $i ) . $tail;
$clean = UtfNormal::cleanUp( $char );
$x = sprintf( "%02X", $i );
- if( $i == 0x0009 ||
- $i == 0x000a ||
- $i == 0x000d ||
- ($i > 0x001f && $i < 0x80) ) {
+
+ if ( $i == 0x0009 ||
+ $i == 0x000a ||
+ $i == 0x000d ||
+ ( $i > 0x001f && $i < 0x80 )
+ ) {
$this->assertEquals(
bin2hex( $char ),
bin2hex( $clean ),
"ASCII byte $x should be intact" );
- if( $char != $clean ) return;
+ if ( $char != $clean ) {
+ return;
+ }
} else {
$norm = $head . UTF8_REPLACEMENT . $tail;
$this->assertEquals(
bin2hex( $norm ),
bin2hex( $clean ),
"Forbidden byte $x should be rejected" );
- if( $norm != $clean ) return;
+ if ( $norm != $clean ) {
+ return;
+ }
}
}
}
* @todo document
*/
function doTestDoubleBytes( $head, $tail ) {
- for( $first = 0xc0; $first < 0x100; $first+=2 ) {
- for( $second = 0x80; $second < 0x100; $second+=2 ) {
+ for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
+ for ( $second = 0x80; $second < 0x100; $second += 2 ) {
$char = $head . chr( $first ) . chr( $second ) . $tail;
$clean = UtfNormal::cleanUp( $char );
$x = sprintf( "%02X,%02X", $first, $second );
- if( $first > 0xc1 &&
- $first < 0xe0 &&
- $second < 0xc0 ) {
- $norm = UtfNormal::NFC( $char );
+ if ( $first > 0xc1 &&
+ $first < 0xe0 &&
+ $second < 0xc0
+ ) {
+ $norm = UtfNormal::NFC( $char );
$this->assertEquals(
bin2hex( $norm ),
bin2hex( $clean ),
"Pair $x should be intact" );
- if( $norm != $clean ) return;
- } elseif( $first > 0xfd || $second > 0xbf ) {
+ if ( $norm != $clean ) {
+ return;
+ }
+ } elseif ( $first > 0xfd || $second > 0xbf ) {
# fe and ff are not legal head bytes -- expect two replacement chars
$norm = $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail;
$this->assertEquals(
bin2hex( $norm ),
bin2hex( $clean ),
"Forbidden pair $x should be rejected" );
- if( $norm != $clean ) return;
+ if ( $norm != $clean ) {
+ return;
+ }
} else {
$norm = $head . UTF8_REPLACEMENT . $tail;
$this->assertEquals(
bin2hex( $norm ),
bin2hex( $clean ),
"Forbidden pair $x should be rejected" );
- if( $norm != $clean ) return;
+ if ( $norm != $clean ) {
+ return;
+ }
}
}
}
/** @todo document */
function doTestTripleBytes( $head, $tail ) {
- for( $first = 0xc0; $first < 0x100; $first+=2 ) {
- for( $second = 0x80; $second < 0x100; $second+=2 ) {
+ for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
+ for ( $second = 0x80; $second < 0x100; $second += 2 ) {
#for( $third = 0x80; $third < 0x100; $third++ ) {
- for( $third = 0x80; $third < 0x81; $third++ ) {
+ for ( $third = 0x80; $third < 0x81; $third++ ) {
$char = $head . chr( $first ) . chr( $second ) . chr( $third ) . $tail;
$clean = UtfNormal::cleanUp( $char );
$x = sprintf( "%02X,%02X,%02X", $first, $second, $third );
- if( $first >= 0xe0 &&
+
+ if ( $first >= 0xe0 &&
$first < 0xf0 &&
$second < 0xc0 &&
- $third < 0xc0 ) {
- if( $first == 0xe0 && $second < 0xa0 ) {
+ $third < 0xc0
+ ) {
+ if ( $first == 0xe0 && $second < 0xa0 ) {
$this->assertEquals(
bin2hex( $head . UTF8_REPLACEMENT . $tail ),
bin2hex( $clean ),
"Overlong triplet $x should be rejected" );
- } elseif( $first == 0xed &&
- ( chr( $first ) . chr( $second ) . chr( $third )) >= UTF8_SURROGATE_FIRST ) {
+ } elseif ( $first == 0xed &&
+ ( chr( $first ) . chr( $second ) . chr( $third ) ) >= UTF8_SURROGATE_FIRST
+ ) {
$this->assertEquals(
bin2hex( $head . UTF8_REPLACEMENT . $tail ),
bin2hex( $clean ),
bin2hex( $clean ),
"Triplet $x should be intact" );
}
- } elseif( $first > 0xc1 && $first < 0xe0 && $second < 0xc0 ) {
+ } elseif ( $first > 0xc1 && $first < 0xe0 && $second < 0xc0 ) {
$this->assertEquals(
bin2hex( UtfNormal::NFC( $head . chr( $first ) . chr( $second ) ) . UTF8_REPLACEMENT . $tail ),
bin2hex( $clean ),
"Valid 2-byte $x + broken tail" );
- } elseif( $second > 0xc1 && $second < 0xe0 && $third < 0xc0 ) {
+ } elseif ( $second > 0xc1 && $second < 0xe0 && $third < 0xc0 ) {
$this->assertEquals(
bin2hex( $head . UTF8_REPLACEMENT . UtfNormal::NFC( chr( $second ) . chr( $third ) . $tail ) ),
bin2hex( $clean ),
"Broken head + valid 2-byte $x" );
- } elseif( ( $first > 0xfd || $second > 0xfd ) &&
- ( ( $second > 0xbf && $third > 0xbf ) ||
- ( $second < 0xc0 && $third < 0xc0 ) ||
- ( $second > 0xfd ) ||
- ( $third > 0xfd ) ) ) {
+ } elseif ( ( $first > 0xfd || $second > 0xfd ) &&
+ ( ( $second > 0xbf && $third > 0xbf ) ||
+ ( $second < 0xc0 && $third < 0xc0 ) ||
+ ( $second > 0xfd ) ||
+ ( $third > 0xfd ) )
+ ) {
# fe and ff are not legal head bytes -- expect three replacement chars
$this->assertEquals(
bin2hex( $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail ),
bin2hex( $clean ),
"Forbidden triplet $x should be rejected" );
- } elseif( $first > 0xc2 && $second < 0xc0 && $third < 0xc0 ) {
+ } elseif ( $first > 0xc2 && $second < 0xc0 && $third < 0xc0 ) {
$this->assertEquals(
bin2hex( $head . UTF8_REPLACEMENT . $tail ),
bin2hex( $clean ),
/** @todo document */
function testChunkRegression() {
# Check for regression against a chunking bug
- $text = "\x46\x55\xb8" .
- "\xdc\x96" .
- "\xee" .
- "\xe7" .
- "\x44" .
- "\xaa" .
- "\x2f\x25";
+ $text = "\x46\x55\xb8" .
+ "\xdc\x96" .
+ "\xee" .
+ "\xe7" .
+ "\x44" .
+ "\xaa" .
+ "\x2f\x25";
$expect = "\x46\x55\xef\xbf\xbd" .
- "\xdc\x96" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x44" .
- "\xef\xbf\xbd" .
- "\x2f\x25";
+ "\xdc\x96" .
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\x44" .
+ "\xef\xbf\xbd" .
+ "\x2f\x25";
$this->assertEquals(
bin2hex( $expect ),
/** @todo document */
function testInterposeRegression() {
- $text = "\x4e\x30" .
- "\xb1" . # bad tail
- "\x3a" .
- "\x92" . # bad tail
- "\x62\x3a" .
- "\x84" . # bad tail
- "\x43" .
- "\xc6" . # bad head
- "\x3f" .
- "\x92" . # bad tail
- "\xad" . # bad tail
- "\x7d" .
- "\xd9\x95";
+ $text = "\x4e\x30" .
+ "\xb1" . # bad tail
+ "\x3a" .
+ "\x92" . # bad tail
+ "\x62\x3a" .
+ "\x84" . # bad tail
+ "\x43" .
+ "\xc6" . # bad head
+ "\x3f" .
+ "\x92" . # bad tail
+ "\xad" . # bad tail
+ "\x7d" .
+ "\xd9\x95";
$expect = "\x4e\x30" .
- "\xef\xbf\xbd" .
- "\x3a" .
- "\xef\xbf\xbd" .
- "\x62\x3a" .
- "\xef\xbf\xbd" .
- "\x43" .
- "\xef\xbf\xbd" .
- "\x3f" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x7d" .
- "\xd9\x95";
+ "\xef\xbf\xbd" .
+ "\x3a" .
+ "\xef\xbf\xbd" .
+ "\x62\x3a" .
+ "\xef\xbf\xbd" .
+ "\x43" .
+ "\xef\xbf\xbd" .
+ "\x3f" .
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\x7d" .
+ "\xd9\x95";
$this->assertEquals(
bin2hex( $expect ),
/** @todo document */
function testOverlongRegression() {
- $text = "\x67" .
- "\x1a" . # forbidden ascii
- "\xea" . # bad head
- "\xc1\xa6" . # overlong sequence
- "\xad" . # bad tail
- "\x1c" . # forbidden ascii
- "\xb0" . # bad tail
- "\x3c" .
- "\x9e"; # bad tail
+ $text = "\x67" .
+ "\x1a" . # forbidden ascii
+ "\xea" . # bad head
+ "\xc1\xa6" . # overlong sequence
+ "\xad" . # bad tail
+ "\x1c" . # forbidden ascii
+ "\xb0" . # bad tail
+ "\x3c" .
+ "\x9e"; # bad tail
$expect = "\x67" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x3c" .
- "\xef\xbf\xbd";
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\x3c" .
+ "\xef\xbf\xbd";
$this->assertEquals(
bin2hex( $expect ),
bin2hex( UtfNormal::cleanUp( $text ) ) );
/** @todo document */
function testSurrogateRegression() {
- $text = "\xed\xb4\x96" . # surrogate 0xDD16
- "\x83" . # bad tail
- "\xb4" . # bad tail
- "\xac"; # bad head
+ $text = "\xed\xb4\x96" . # surrogate 0xDD16
+ "\x83" . # bad tail
+ "\xb4" . # bad tail
+ "\xac"; # bad head
$expect = "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd";
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd";
$this->assertEquals(
bin2hex( $expect ),
bin2hex( UtfNormal::cleanUp( $text ) ) );
/** @todo document */
function testBomRegression() {
- $text = "\xef\xbf\xbe" . # U+FFFE, illegal char
- "\xb2" . # bad tail
- "\xef" . # bad head
- "\x59";
+ $text = "\xef\xbf\xbe" . # U+FFFE, illegal char
+ "\xb2" . # bad tail
+ "\xef" . # bad head
+ "\x59";
$expect = "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x59";
+ "\xef\xbf\xbd" .
+ "\xef\xbf\xbd" .
+ "\x59";
$this->assertEquals(
bin2hex( $expect ),
bin2hex( UtfNormal::cleanUp( $text ) ) );
/** @todo document */
function testForbiddenRegression() {
- $text = "\xef\xbf\xbf"; # U+FFFF, illegal char
+ $text = "\xef\xbf\xbf"; # U+FFFF, illegal char
$expect = "\xef\xbf\xbd";
$this->assertEquals(
bin2hex( $expect ),
/** @todo document */
function testHangulRegression() {
$text = "\xed\x9c\xaf" . # Hangul char
- "\xe1\x87\x81"; # followed by another final jamo
- $expect = $text; # Should *not* change.
+ "\xe1\x87\x81"; # followed by another final jamo
+ $expect = $text; # Should *not* change.
$this->assertEquals(
bin2hex( $expect ),
bin2hex( UtfNormal::cleanUp( $text ) ) );
$name = $this->getCliArg( 'use-bagostuff=' );
$this->cache = ObjectCache::newFromId( $name );
-
- // no type defined - use simple hash
} else {
+ // no type defined - use simple hash
$this->cache = new HashBagOStuff;
}
* @use int $usleep
* @return int
*/
- $callback = function( BagOStuff $cache, $key, $existingValue ) use ( &$usleep ) {
+ $callback = function ( BagOStuff $cache, $key, $existingValue ) use ( &$usleep ) {
// let's pretend this is an expensive callback to test concurrent merge attempts
usleep( $usleep );
# day
- /** @dataProvider MediaWikiProvide::Days */
+ /**
+ * @dataProvider MediaWikiProvide::Days
+ * @group Database
+ */
function testCurrentdayIsUnPadded( $day ) {
$this->assertUnPadded( 'currentday', $day );
}
- /** @dataProvider MediaWikiProvide::Days */
+
+ /**
+ * @dataProvider MediaWikiProvide::Days
+ * @group Database
+ */
function testCurrentdaytwoIsZeroPadded( $day ) {
$this->assertZeroPadded( 'currentday2', $day );
}
- /** @dataProvider MediaWikiProvide::Days */
+
+ /**
+ * @dataProvider MediaWikiProvide::Days
+ * @group Database
+ */
function testLocaldayIsUnPadded( $day ) {
$this->assertUnPadded( 'localday', $day );
}
- /** @dataProvider MediaWikiProvide::Days */
+
+ /**
+ * @dataProvider MediaWikiProvide::Days
+ * @group Database
+ */
function testLocaldaytwoIsZeroPadded( $day ) {
$this->assertZeroPadded( 'localday2', $day );
}
# month
- /** @dataProvider MediaWikiProvide::Months */
+ /**
+ * @dataProvider MediaWikiProvide::Months
+ * @group Database
+ */
function testCurrentmonthIsZeroPadded( $month ) {
$this->assertZeroPadded( 'currentmonth', $month );
}
- /** @dataProvider MediaWikiProvide::Months */
+
+ /**
+ * @dataProvider MediaWikiProvide::Months
+ * @group Database
+ */
function testCurrentmonthoneIsUnPadded( $month ) {
$this->assertUnPadded( 'currentmonth1', $month );
}
- /** @dataProvider MediaWikiProvide::Months */
+
+ /**
+ * @dataProvider MediaWikiProvide::Months
+ * @group Database
+ */
function testLocalmonthIsZeroPadded( $month ) {
$this->assertZeroPadded( 'localmonth', $month );
}
- /** @dataProvider MediaWikiProvide::Months */
+
+ /**
+ * @dataProvider MediaWikiProvide::Months
+ * @group Database
+ */
function testLocalmonthoneIsUnPadded( $month ) {
$this->assertUnPadded( 'localmonth1', $month );
}
# revision day
- /** @dataProvider MediaWikiProvide::Days */
+ /**
+ * @dataProvider MediaWikiProvide::Days
+ * @group Database
+ */
function testRevisiondayIsUnPadded( $day ) {
$this->assertUnPadded( 'revisionday', $day );
}
- /** @dataProvider MediaWikiProvide::Days */
+
+ /**
+ * @dataProvider MediaWikiProvide::Days
+ * @group Database
+ */
function testRevisiondaytwoIsZeroPadded( $day ) {
$this->assertZeroPadded( 'revisionday2', $day );
}
# revision month
- /** @dataProvider MediaWikiProvide::Months */
+ /**
+ * @dataProvider MediaWikiProvide::Months
+ * @group Database
+ */
function testRevisionmonthIsZeroPadded( $month ) {
$this->assertZeroPadded( 'revisionmonth', $month );
}
- /** @dataProvider MediaWikiProvide::Months */
+
+ /**
+ * @dataProvider MediaWikiProvide::Months
+ * @group Database
+ */
function testRevisionmonthoneIsUnPadded( $month ) {
$this->assertUnPadded( 'revisionmonth1', $month );
}
/**
* Rough tests for {{SERVERNAME}} magic word
* Bug 31176
+ * @group Database
*/
function testServernameFromDifferentProtocols() {
global $wgServer;
- $saved_wgServer= $wgServer;
+ $saved_wgServer = $wgServer;
$wgServer = 'http://localhost/';
$this->assertMagic( 'localhost', 'servername' );
$wgServer = 'https://localhost/';
$this->assertMagic( 'localhost', 'servername' );
- $wgServer = '//localhost/'; # bug 31176
+ $wgServer = '//localhost/'; # bug 31176
$this->assertMagic( 'localhost', 'servername' );
$wgServer = $saved_wgServer;
private function assertMagicPadding( $magic, $value, $format ) {
# Initialize parser timestamp as year 2010 at 12h34 56s.
# month and day are given by the caller ($value). Month < 12!
- if( $value > 12 ) { $month = $value % 12; }
- else { $month = $value; }
+ if ( $value > 12 ) {
+ $month = $value % 12;
+ } else {
+ $month = $value;
+ }
$this->setParserTS(
sprintf( '2010%02d%02d123456', $month, $value )
* Assertion helper to test a magic variable output
*/
private function assertMagic( $expected, $magic ) {
- if( in_array( $magic, $this->expectedAsInteger ) ) {
+ if ( in_array( $magic, $this->expectedAsInteger ) ) {
$expected = (int)$expected;
}
/**
* The UnitTest must be either a class that inherits from MediaWikiTestCase
- * or a class that provides a public static suite() method which returns
+ * or a class that provides a public static suite() method which returns
* an PHPUnit_Framework_Test object
- *
+ *
* @group Parser
* @group Database
*/
* @group Stub
*/
class NewParserTest extends MediaWikiTestCase {
- static protected $articles = array(); // Array of test articles defined by the tests
+ static protected $articles = array(); // Array of test articles defined by the tests
/* The data provider is run on a different instance than the test, so it must be static
* When running tests from several files, all tests will see all articles.
*/
protected $file = false;
protected function setUp() {
- global $wgContLang, $wgLanguageCode;
global $wgNamespaceProtection, $wgNamespaceAliases;
global $wgHooks, $IP;
parent::setUp();
- $wgLanguageCode = 'en';
- $wgContLang = Language::factory( 'en' );
-
//Setup CLI arguments
if ( $this->getCliArg( 'regex=' ) ) {
$this->regex = $this->getCliArg( 'regex=' );
$tmpGlobals = array();
+ $tmpGlobals['wgLanguageCode'] = 'en';
+ $tmpGlobals['wgContLang'] = Language::factory( 'en' );
$tmpGlobals['wgScript'] = '/index.php';
$tmpGlobals['wgScriptPath'] = '/';
$tmpGlobals['wgArticlePath'] = '/wiki/$1';
$tmpGlobals['wgStylePath'] = '/skins';
$tmpGlobals['wgThumbnailScriptPath'] = false;
$tmpGlobals['wgLocalFileRepo'] = array(
- 'class' => 'LocalRepo',
- 'name' => 'local',
- 'url' => 'http://example.com/images',
- 'hashLevels' => 2,
+ 'class' => 'LocalRepo',
+ 'name' => 'local',
+ 'url' => 'http://example.com/images',
+ 'hashLevels' => 2,
'transformVia404' => false,
- 'backend' => 'local-backend'
+ 'backend' => 'local-backend'
);
$tmpGlobals['wgForeignFileRepos'] = array();
$tmpGlobals['wgEnableParserCache'] = false;
# Hack: insert a few Wikipedia in-project interwiki prefixes,
# for testing inter-language links
$this->db->insert( 'interwiki', array(
- array( 'iw_prefix' => 'wikipedia',
- 'iw_url' => 'http://en.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 0 ),
- array( 'iw_prefix' => 'meatball',
- 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 0 ),
- array( 'iw_prefix' => 'zh',
- 'iw_url' => 'http://zh.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
- array( 'iw_prefix' => 'es',
- 'iw_url' => 'http://es.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
- array( 'iw_prefix' => 'fr',
- 'iw_url' => 'http://fr.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
- array( 'iw_prefix' => 'ru',
- 'iw_url' => 'http://ru.wikipedia.org/wiki/$1',
- 'iw_api' => '',
- 'iw_wikiid' => '',
- 'iw_local' => 1 ),
- /**
- * @todo Fixme! Why are we inserting duplicate data here? Shouldn't
- * need this IGNORE or shouldn't need the insert at all.
- */
+ array( 'iw_prefix' => 'wikipedia',
+ 'iw_url' => 'http://en.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 0 ),
+ array( 'iw_prefix' => 'meatball',
+ 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 0 ),
+ array( 'iw_prefix' => 'zh',
+ 'iw_url' => 'http://zh.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
+ array( 'iw_prefix' => 'es',
+ 'iw_url' => 'http://es.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
+ array( 'iw_prefix' => 'fr',
+ 'iw_url' => 'http://fr.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
+ array( 'iw_prefix' => 'ru',
+ 'iw_url' => 'http://ru.wikipedia.org/wiki/$1',
+ 'iw_api' => '',
+ 'iw_wikiid' => '',
+ 'iw_local' => 1 ),
+ /**
+ * @todo Fixme! Why are we inserting duplicate data here? Shouldn't
+ * need this IGNORE or shouldn't need the insert at all.
+ */
), __METHOD__, array( 'IGNORE' )
);
-
# Update certain things in site_stats
$this->db->insert( 'site_stats',
array( 'ss_row_id' => 1, 'ss_images' => 2, 'ss_good_articles' => 1 ),
'Upload of some lame file',
'Some lame file',
array(
- 'size' => 12345,
- 'width' => 1941,
- 'height' => 220,
- 'bits' => 24,
- 'media_type' => MEDIATYPE_BITMAP,
- 'mime' => 'image/jpeg',
- 'metadata' => serialize( array() ),
- 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
- 'fileExists' => true ),
+ 'size' => 12345,
+ 'width' => 1941,
+ 'height' => 220,
+ 'bits' => 24,
+ 'media_type' => MEDIATYPE_BITMAP,
+ 'mime' => 'image/jpeg',
+ 'metadata' => serialize( array() ),
+ 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
+ 'fileExists' => true ),
$this->db->timestamp( '20010115123500' ), $user
);
}
'zomgnotcensored',
'Borderline image',
array(
- 'size' => 12345,
- 'width' => 320,
- 'height' => 240,
- 'bits' => 24,
- 'media_type' => MEDIATYPE_BITMAP,
- 'mime' => 'image/jpeg',
- 'metadata' => serialize( array() ),
- 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
- 'fileExists' => true ),
+ 'size' => 12345,
+ 'width' => 320,
+ 'height' => 240,
+ 'bits' => 24,
+ 'media_type' => MEDIATYPE_BITMAP,
+ 'mime' => 'image/jpeg',
+ 'metadata' => serialize( array() ),
+ 'sha1' => wfBaseConvert( '', 16, 36, 31 ),
+ 'fileExists' => true ),
$this->db->timestamp( '20010115123500' ), $user
);
}
}
-
-
-
//ParserTest setup/teardown functions
/**
* Set up the global variables for a consistent environment for each test.
* Ideally this should replace the global configuration entirely.
*/
- protected function setupGlobals( $opts = '', $config = '' ) {
+ protected function setupGlobals( $opts = array(), $config = '' ) {
global $wgFileBackends;
# Find out values for some special options.
$lang =
}
} else {
$backend = new FSFileBackend( array(
- 'name' => 'local-backend',
+ 'name' => 'local-backend',
'lockManager' => 'nullLockManager',
'containerPaths' => array(
'local-public' => "$uploadDir",
- 'local-thumb' => "$uploadDir/thumb",
+ 'local-thumb' => "$uploadDir/thumb",
)
) );
}
$settings = array(
- 'wgServer' => 'http://Britney-Spears',
+ 'wgServer' => 'http://example.org',
'wgScript' => '/index.php',
'wgScriptPath' => '/',
'wgArticlePath' => '/wiki/$1',
'wgExtensionAssetsPath' => '/extensions',
'wgActionPaths' => array(),
'wgLocalFileRepo' => array(
- 'class' => 'LocalRepo',
- 'name' => 'local',
- 'url' => 'http://example.com/images',
- 'hashLevels' => 2,
+ 'class' => 'LocalRepo',
+ 'name' => 'local',
+ 'url' => 'http://example.com/images',
+ 'hashLevels' => 2,
'transformVia404' => false,
- 'backend' => $backend
+ 'backend' => $backend
),
'wgEnableUploads' => self::getOptionValue( 'wgEnableUploads', $opts, true ),
'wgStylePath' => '/skins',
'wgRawHtml' => isset( $opts['rawhtml'] ),
'wgLang' => null,
'wgContLang' => null,
- 'wgNamespacesWithSubpages' => array( 0 => isset( $opts['subpage'] ) ),
+ 'wgNamespacesWithSubpages' => array( NS_MAIN => isset( $opts['subpage'] ) ),
'wgMaxTocLevel' => $maxtoclevel,
'wgCapitalLinks' => true,
'wgNoFollowLinks' => true,
'wgVariantArticlePath' => false,
'wgGroupPermissions' => array( '*' => array(
'createaccount' => true,
- 'read' => true,
- 'edit' => true,
- 'createpage' => true,
- 'createtalk' => true,
+ 'read' => true,
+ 'edit' => true,
+ 'createpage' => true,
+ 'createtalk' => true,
) ),
'wgNamespaceProtection' => array( NS_MEDIAWIKI => 'editinterface' ),
'wgDefaultExternalStore' => array(),
$base = $this->getBaseDir();
// delete the files first, then the dirs.
self::deleteFiles(
- array (
+ array(
"$base/local-public/3/3a/Foobar.jpg",
"$base/local-thumb/3/3a/Foobar.jpg/180px-Foobar.jpg",
"$base/local-thumb/3/3a/Foobar.jpg/200px-Foobar.jpg",
// @todo: When setting up pages, force the content model. Only skip if
// $wgtContentModelUseDB is false.
$this->markTestSkipped( "Main namespace does not support wikitext,"
- . "skipping parser test: $desc" );
+ . "skipping parser test: $desc" );
}
wfDebug( "Running parser test: $desc\n" );
if ( isset( $opts['title'] ) ) {
$titleText = $opts['title'];
- }
- else {
+ } else {
$titleText = 'Parser test';
}
$files = $wgParserTestFiles;
- if( $this->getCliArg( 'file=' ) ) {
+ if ( $this->getCliArg( 'file=' ) ) {
$files = array( $this->getCliArg( 'file=' ) );
}
*/
public function requireHook( $name ) {
global $wgParser;
- $wgParser->firstCallInit( ); // make sure hooks are loaded.
+ $wgParser->firstCallInit(); // make sure hooks are loaded.
return isset( $wgParser->mTagHooks[$name] );
}
public function requireFunctionHook( $name ) {
global $wgParser;
- $wgParser->firstCallInit( ); // make sure hooks are loaded.
+ $wgParser->firstCallInit(); // make sure hooks are loaded.
return isset( $wgParser->mFunctionHooks[$name] );
}
+
//Various "cleanup" functions
/**
public function removeEndingNewline( $s ) {
if ( substr( $s, -1 ) === "\n" ) {
return substr( $s, 0, -1 );
- }
- else {
+ } else {
return $s;
}
}
public static function providePreSaveTransform() {
return array(
array( 'hello this is ~~~',
- "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
+ "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
),
array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
- 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+ 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
),
);
}
);
}
- function assertPreloaded( $expected, $text, $msg='') {
+ function assertPreloaded( $expected, $text, $msg = '' ) {
$this->assertEquals(
$expected,
$this->testParser->getPreloadText(
array( "Foo\n=\n==\n=\n", "<root>Foo\n=\n==\n=\n</root>" ),
array( "{{Foo}}", "<root><template><title>Foo</title></template></root>" ),
array( "\n{{Foo}}", "<root>\n<template lineStart=\"1\"><title>Foo</title></template></root>" ),
- array( "{{Foo|bar}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template></root>" ),
- array( "{{Foo|bar}}a", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template>a</root>" ),
- array( "{{Foo|bar|baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name index=\"2\" /><value>baz</value></part></template></root>" ),
+ array( "{{Foo|bar}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template></root>" ),
+ array( "{{Foo|bar}}a", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template>a</root>" ),
+ array( "{{Foo|bar|baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name index=\"2\" /><value>baz</value></part></template></root>" ),
array( "{{Foo|1=bar}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part></template></root>" ),
array( "{{Foo|=bar}}", "<root><template><title>Foo</title><part><name></name>=<value>bar</value></part></template></root>" ),
- array( "{{Foo|bar=baz}}", "<root><template><title>Foo</title><part><name>bar</name>=<value>baz</value></part></template></root>" ),
+ array( "{{Foo|bar=baz}}", "<root><template><title>Foo</title><part><name>bar</name>=<value>baz</value></part></template></root>" ),
array( "{{Foo|{{bar}}=baz}}", "<root><template><title>Foo</title><part><name><template><title>bar</title></template></name>=<value>baz</value></part></template></root>" ),
- array( "{{Foo|1=bar|baz}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name index=\"1\" /><value>baz</value></part></template></root>" ),
+ array( "{{Foo|1=bar|baz}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name index=\"1\" /><value>baz</value></part></template></root>" ),
array( "{{Foo|1=bar|2=baz}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name>2</name>=<value>baz</value></part></template></root>" ),
- array( "{{Foo|bar|foo=baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name>foo</name>=<value>baz</value></part></template></root>" ),
+ array( "{{Foo|bar|foo=baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name>foo</name>=<value>baz</value></part></template></root>" ),
array( "{{{1}}}", "<root><tplarg><title>1</title></tplarg></root>" ),
array( "{{{1|}}}", "<root><tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg></root>" ),
array( "{{{Foo}}}", "<root><tplarg><title>Foo</title></tplarg></root>" ),
array( "Foo <gallery bar=\"baz\" />", "<root>Foo <ext><name>gallery</name><attr> bar="baz" </attr></ext></root>" ),
array( "Foo <gallery bar=\"1\" baz=2 />", "<root>Foo <ext><name>gallery</name><attr> bar="1" baz=2 </attr></ext></root>" ),
array( "</foo>Foo<//foo>", "<root><ext><name>/foo</name><attr></attr><inner>Foo</inner><close><//foo></close></ext></root>" ), # Worth blacklisting IMHO
- array( "{{#ifexpr: ({{{1|1}}} = 2) | Foo | Bar }}", "<root><template><title>#ifexpr: (<tplarg><title>1</title><part><name index=\"1\" /><value>1</value></part></tplarg> = 2) </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>"),
- array( "{{#if: {{{1|}}} | Foo | {{Bar}} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> <template><title>Bar</title></template> </value></part></template></root>"),
- array( "{{#if: {{{1|}}} | Foo | [[Bar]] }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> [[Bar]] </value></part></template></root>"),
- array( "{{#if: {{{1|}}} | [[Foo]] | Bar }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> [[Foo]] </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>"),
- array( "{{#if: {{{1|}}} | 1 | {{#if: {{{1|}}} | 2 | 3 }} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 1 </value></part><part><name index=\"2\" /><value> <template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 2 </value></part><part><name index=\"2\" /><value> 3 </value></part></template> </value></part></template></root>"),
- array( "{{ {{Foo}}", "<root>{{ <template><title>Foo</title></template></root>"),
- array( "{{Foobar {{Foo}} {{Bar}} {{Baz}} ", "<root>{{Foobar <template><title>Foo</title></template> <template><title>Bar</title></template> <template><title>Baz</title></template> </root>"),
- array( "[[Foo]] |", "<root>[[Foo]] |</root>"),
- array( "{{Foo|Bar|", "<root>{{Foo|Bar|</root>"),
- array( "[[Foo]", "<root>[[Foo]</root>"),
- array( "[[Foo|Bar]", "<root>[[Foo|Bar]</root>"),
- array( "{{Foo| [[Bar] }}", "<root>{{Foo| [[Bar] }}</root>"),
- array( "{{Foo| [[Bar|Baz] }}", "<root>{{Foo| [[Bar|Baz] }}</root>"),
- array( "{{Foo|bar=[[baz]}}", "<root>{{Foo|bar=[[baz]}}</root>"),
- array( "{{foo|", "<root>{{foo|</root>"),
- array( "{{foo|}", "<root>{{foo|}</root>"),
- array( "{{foo|} }}", "<root><template><title>foo</title><part><name index=\"1\" /><value>} </value></part></template></root>"),
- array( "{{foo|bar=|}", "<root>{{foo|bar=|}</root>"),
- array( "{{Foo|} Bar=", "<root>{{Foo|} Bar=</root>"),
- array( "{{Foo|} Bar=}}", "<root><template><title>Foo</title><part><name>} Bar</name>=<value></value></part></template></root>"),
+ array( "{{#ifexpr: ({{{1|1}}} = 2) | Foo | Bar }}", "<root><template><title>#ifexpr: (<tplarg><title>1</title><part><name index=\"1\" /><value>1</value></part></tplarg> = 2) </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>" ),
+ array( "{{#if: {{{1|}}} | Foo | {{Bar}} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> <template><title>Bar</title></template> </value></part></template></root>" ),
+ array( "{{#if: {{{1|}}} | Foo | [[Bar]] }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> [[Bar]] </value></part></template></root>" ),
+ array( "{{#if: {{{1|}}} | [[Foo]] | Bar }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> [[Foo]] </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>" ),
+ array( "{{#if: {{{1|}}} | 1 | {{#if: {{{1|}}} | 2 | 3 }} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 1 </value></part><part><name index=\"2\" /><value> <template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 2 </value></part><part><name index=\"2\" /><value> 3 </value></part></template> </value></part></template></root>" ),
+ array( "{{ {{Foo}}", "<root>{{ <template><title>Foo</title></template></root>" ),
+ array( "{{Foobar {{Foo}} {{Bar}} {{Baz}} ", "<root>{{Foobar <template><title>Foo</title></template> <template><title>Bar</title></template> <template><title>Baz</title></template> </root>" ),
+ array( "[[Foo]] |", "<root>[[Foo]] |</root>" ),
+ array( "{{Foo|Bar|", "<root>{{Foo|Bar|</root>" ),
+ array( "[[Foo]", "<root>[[Foo]</root>" ),
+ array( "[[Foo|Bar]", "<root>[[Foo|Bar]</root>" ),
+ array( "{{Foo| [[Bar] }}", "<root>{{Foo| [[Bar] }}</root>" ),
+ array( "{{Foo| [[Bar|Baz] }}", "<root>{{Foo| [[Bar|Baz] }}</root>" ),
+ array( "{{Foo|bar=[[baz]}}", "<root>{{Foo|bar=[[baz]}}</root>" ),
+ array( "{{foo|", "<root>{{foo|</root>" ),
+ array( "{{foo|}", "<root>{{foo|}</root>" ),
+ array( "{{foo|} }}", "<root><template><title>foo</title><part><name index=\"1\" /><value>} </value></part></template></root>" ),
+ array( "{{foo|bar=|}", "<root>{{foo|bar=|}</root>" ),
+ array( "{{Foo|} Bar=", "<root>{{Foo|} Bar=</root>" ),
+ array( "{{Foo|} Bar=}}", "<root><template><title>Foo</title><part><name>} Bar</name>=<value></value></part></template></root>" ),
/* array( file_get_contents( __DIR__ . '/QuoteQuran.txt' ), file_get_contents( __DIR__ . '/QuoteQuranExpanded.txt' ) ), */
);
}
* Tests from Bug 28642 · https://bugzilla.wikimedia.org/28642
*/
function provideHeadings() {
- return array( /* These should become headings: */
+ return array( /* These should become headings: */
array( "== h ==<!--c1-->", "<root><h level=\"2\" i=\"1\">== h ==<comment><!--c1--></comment></h></root>" ),
array( "== h == <!--c1-->", "<root><h level=\"2\" i=\"1\">== h == <comment><!--c1--></comment></h></root>" ),
array( "== h ==<!--c1--> ", "<root><h level=\"2\" i=\"1\">== h ==<comment><!--c1--></comment> </h></root>" ),
* @group Parser
*/
class TagHookTest extends MediaWikiTestCase {
-
public static function provideValidNames() {
return array( array( 'foo' ), array( 'foo-bar' ), array( 'foo_bar' ), array( 'FOO-BAR' ), array( 'foo bar' ) );
}
public static function provideBadNames() {
- return array( array( "foo<bar" ), array( "foo>bar" ), array( "foo\nbar" ), array( "foo\rbar" ) );
+ return array( array( "foo<bar" ), array( "foo>bar" ), array( "foo\nbar" ), array( "foo\rbar" ) );
}
protected function setUp() {
/**
* @dataProvider provideValidNames
+ * @group Database
*/
function testTagHooks( $tag ) {
global $wgParserConf, $wgContLang;
$parser = new Parser( $wgParserConf );
-
+
$parser->setHook( $tag, array( $this, 'tagCallback' ) );
$parserOutput = $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
$this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
-
+
$parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle
}
-
+
/**
* @dataProvider provideBadNames
* @expectedException MWException
function testBadTagHooks( $tag ) {
global $wgParserConf, $wgContLang;
$parser = new Parser( $wgParserConf );
-
+
$parser->setHook( $tag, array( $this, 'tagCallback' ) );
$parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
- $this->fail('Exception not thrown.');
+ $this->fail( 'Exception not thrown.' );
}
-
+
/**
* @dataProvider provideValidNames
+ * @group Database
*/
function testFunctionTagHooks( $tag ) {
global $wgParserConf, $wgContLang;
$parser = new Parser( $wgParserConf );
-
+
$parser->setFunctionTagHook( $tag, array( $this, 'functionTagCallback' ), 0 );
$parserOutput = $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
$this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
-
+
$parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle
}
-
+
/**
* @dataProvider provideBadNames
* @expectedException MWException
function testBadFunctionTagHooks( $tag ) {
global $wgParserConf, $wgContLang;
$parser = new Parser( $wgParserConf );
-
+
$parser->setFunctionTagHook( $tag, array( $this, 'functionTagCallback' ), SFH_OBJECT_ARGS );
$parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
- $this->fail('Exception not thrown.');
+ $this->fail( 'Exception not thrown.' );
}
-
+
function tagCallback( $text, $params, $parser ) {
return str_rot13( $text );
}
-
+
function functionTagCallback( &$parser, $frame, $code, $attribs ) {
return str_rot13( $code );
}
# Get database type and version
$dbType = $this->db->getType();
$dbSupported =
- ($dbType === 'mysql')
- || ( $dbType === 'sqlite' && $this->db->getFulltextSearchModule() == 'FTS3' );
+ ( $dbType === 'mysql' )
+ || ( $dbType === 'sqlite' && $this->db->getFulltextSearchModule() == 'FTS3' );
- if( !$dbSupported ) {
+ if ( !$dbSupported ) {
$this->markTestSkipped( "MySQL or SQLite with FTS3 only" );
}
return;
}
- $this->insertPage( "Not_Main_Page", "This is not a main page", 0 );
- $this->insertPage( 'Talk:Not_Main_Page', 'This is not a talk page to the main page, see [[smithee]]', 1 );
- $this->insertPage( 'Smithee', 'A smithee is one who smiths. See also [[Alan Smithee]]', 0 );
- $this->insertPage( 'Talk:Smithee', 'This article sucks.', 1 );
- $this->insertPage( 'Unrelated_page', 'Nothing in this page is about the S word.', 0 );
- $this->insertPage( 'Another_page', 'This page also is unrelated.', 0 );
- $this->insertPage( 'Help:Help', 'Help me!', 4 );
- $this->insertPage( 'Thppt', 'Blah blah', 0 );
- $this->insertPage( 'Alan_Smithee', 'yum', 0 );
- $this->insertPage( 'Pages', 'are\'food', 0 );
- $this->insertPage( 'HalfOneUp', 'AZ', 0 );
- $this->insertPage( 'FullOneUp', 'AZ', 0 );
- $this->insertPage( 'HalfTwoLow', 'az', 0 );
- $this->insertPage( 'FullTwoLow', 'az', 0 );
- $this->insertPage( 'HalfNumbers', '1234567890', 0 );
- $this->insertPage( 'FullNumbers', '1234567890', 0 );
- $this->insertPage( 'DomainName', 'example.com', 0 );
+ $this->insertPage( "Not_Main_Page", "This is not a main page", 0 );
+ $this->insertPage( 'Talk:Not_Main_Page', 'This is not a talk page to the main page, see [[smithee]]', 1 );
+ $this->insertPage( 'Smithee', 'A smithee is one who smiths. See also [[Alan Smithee]]', 0 );
+ $this->insertPage( 'Talk:Smithee', 'This article sucks.', 1 );
+ $this->insertPage( 'Unrelated_page', 'Nothing in this page is about the S word.', 0 );
+ $this->insertPage( 'Another_page', 'This page also is unrelated.', 0 );
+ $this->insertPage( 'Help:Help', 'Help me!', 4 );
+ $this->insertPage( 'Thppt', 'Blah blah', 0 );
+ $this->insertPage( 'Alan_Smithee', 'yum', 0 );
+ $this->insertPage( 'Pages', 'are\'food', 0 );
+ $this->insertPage( 'HalfOneUp', 'AZ', 0 );
+ $this->insertPage( 'FullOneUp', 'AZ', 0 );
+ $this->insertPage( 'HalfTwoLow', 'az', 0 );
+ $this->insertPage( 'FullTwoLow', 'az', 0 );
+ $this->insertPage( 'HalfNumbers', '1234567890', 0 );
+ $this->insertPage( 'FullNumbers', '1234567890', 0 );
+ $this->insertPage( 'DomainName', 'example.com', 0 );
}
function fetchIds( $results ) {
if ( !$this->isWikitextNS( NS_MAIN ) ) {
$this->markTestIncomplete( __CLASS__ . " does no yet support non-wikitext content "
- . "in the main namespace");
+ . "in the main namespace" );
}
$this->assertTrue( is_object( $results ) );
function testTextSearch() {
$this->assertEquals(
- array( 'Smithee' ),
- $this->fetchIds( $this->search->searchText( 'smithee' ) ),
- "Plain search failed" );
+ array( 'Smithee' ),
+ $this->fetchIds( $this->search->searchText( 'smithee' ) ),
+ "Plain search failed" );
}
function testTextPowerSearch() {
public function testGetSiteByGlobalId( SiteList $sites ) {
if ( $sites->isEmpty() ) {
$this->assertTrue( true );
- }
- else {
+ } else {
/**
* @var Site $site
*/
protected function assertTypeOrFalse( $type, $value ) {
if ( $value === false ) {
$this->assertTrue( true );
- }
- else {
+ } else {
$this->assertInternalType( $type, $value );
}
}
parent::__construct();
global $wgQueryPages;
- foreach( $wgQueryPages as $page ) {
+ foreach ( $wgQueryPages as $page ) {
$class = $page[0];
- if( ! in_array( $class, $this->manualTest ) ) {
+ if ( !in_array( $class, $this->manualTest ) ) {
$this->queryPages[$class] = new $class;
}
}
function testQuerypageSqlQuery() {
global $wgDBtype;
- foreach( $this->queryPages as $page ) {
+ foreach ( $this->queryPages as $page ) {
// With MySQL, skips special pages reopening a temporary table
// See http://bugs.mysql.com/bug.php?id=10327
- if(
+ if (
$wgDBtype === 'mysql'
&& in_array( $page->getName(), $this->reopensTempTable )
) {
- $this->markTestSkipped( "SQL query for page {$page->getName()} can not be tested on MySQL backend (it reopens a temporary table)" );
- continue;
- }
+ $this->markTestSkipped( "SQL query for page {$page->getName()} can not be tested on MySQL backend (it reopens a temporary table)" );
+ continue;
+ }
- $msg = "SQL query for page {$page->getName()} should give a result wrapper object" ;
+ $msg = "SQL query for page {$page->getName()} should give a result wrapper object";
$result = $page->reallyDoQuery( 50 );
- if( $result instanceof ResultWrapper ) {
+ if ( $result instanceof ResultWrapper ) {
$this->assertTrue( true, $msg );
} else {
$this->assertFalse( false, $msg );
/** return false if condition begin with 'rc_timestamp ' */
private static function filterOutRcTimestampCondition( $var ) {
- return (false === strpos( $var, 'rc_timestamp ' ));
+ return ( false === strpos( $var, 'rc_timestamp ' ) );
}
'namespace' => NS_MAIN,
'invert' => 1,
),
- "rc conditions with namespace inverted"
+ "rc conditions with namespace inverted"
);
}
'namespace' => $ns1,
'associated' => 1,
),
- "rc conditions with namespace inverted"
+ "rc conditions with namespace inverted"
);
}
1 => sprintf( "(rc_namespace != '%s' AND rc_namespace != '%s')", $ns1, $ns2 ),
),
array(
- 'namespace' => $ns1,
+ 'namespace' => $ns1,
'associated' => 1,
- 'invert' => 1,
+ 'invert' => 1,
),
- "rc conditions with namespace inverted"
+ "rc conditions with namespace inverted"
);
}
*/
public static function provideNamespacesAssociations() {
return array( # (NS => Associated_NS)
- array( NS_MAIN, NS_TALK),
- array( NS_TALK, NS_MAIN),
+ array( NS_MAIN, NS_TALK ),
+ array( NS_TALK, NS_MAIN ),
);
}
'ns6'=>true,
) ));
*/
- $context->setRequest( new FauxRequest( $requested ));
+ $context->setRequest( new FauxRequest( $requested ) );
$search = new SpecialSearch();
$search->setContext( $context );
$search->load();
$this->assertEquals(
array( /** Expected: */
'ProfileName' => $expectedProfile,
- 'Namespaces' => $expectedNS,
+ 'Namespaces' => $expectedNS,
)
, array( /** Actual: */
'ProfileName' => $search->getProfile(),
- 'Namespaces' => $search->getNamespaces(),
+ 'Namespaces' => $search->getNamespaces(),
)
, $message
);
function provideSearchOptionsTests() {
$defaultNS = SearchEngine::defaultNamespaces();
$EMPTY_REQUEST = array();
- $NO_USER_PREF = null;
+ $NO_USER_PREF = null;
return array(
/**
* Parameters:
- * <Web Request>, <User options>
+ * <Web Request>, <User options>
* Followed by expected values:
- * <ProfileName>, <NSList>
+ * <ProfileName>, <NSList>
* Then an optional message.
*/
array(
),
array(
array( 'ns5' => 1 ), $NO_USER_PREF,
- 'advanced', array( 5),
+ 'advanced', array( 5 ),
'Web request with specific NS should override user preference'
),
array(
$EMPTY_REQUEST, array(
- 'searchNs2' => 1,
- 'searchNs14' => 1,
- ) + array_fill_keys( array_map( function( $ns ) {
- return "searchNs$ns";
- }, $defaultNS ), 0 ),
+ 'searchNs2' => 1,
+ 'searchNs14' => 1,
+ ) + array_fill_keys( array_map( function ( $ns ) {
+ return "searchNs$ns";
+ }, $defaultNS ), 0 ),
'advanced', array( 2, 14 ),
'Bug 33583: search with no option should honor User search preferences'
- . ' and have all other namespace disabled'
+ . ' and have all other namespace disabled'
),
);
}
* User remains anonymous though
*/
function newUserWithSearchNS( $opt = null ) {
- $u = User::newFromId(0);
- if( $opt === null ) {
+ $u = User::newFromId( 0 );
+ if ( $opt === null ) {
return $u;
}
- foreach($opt as $name => $value) {
+ foreach ( $opt as $name => $value ) {
$u->setOption( $name, $value );
}
return $u;
# Initialize [[Special::Search]]
$search = new SpecialSearch();
- $search->getContext()->setTitle( Title::newFromText('Special:Search' ) );
+ $search->getContext()->setTitle( Title::newFromText( 'Special:Search' ) );
$search->load();
# Simulate a user searching for a given term
*/
protected function deleteFile( $name ) {
$t = Title::newFromText( $name, NS_FILE );
- $this->assertTrue($t->exists(), "File '$name' exists");
+ $this->assertTrue( $t->exists(), "File '$name' exists" );
if ( $t->exists() ) {
$file = wfFindFile( $name, array( 'ignoreRedirect' => true ) );
}
$t = Title::newFromText( $name, NS_FILE );
- $this->assertFalse($t->exists(), "File '$name' was deleted");
+ $this->assertFalse( $t->exists(), "File '$name' was deleted" );
}
- }
+}
}
public function testValidRequest() {
- $request = new FauxRequest( array( 'wpFileKey' => 'foo') );
- $this->assertFalse( UploadFromStash::isValidRequest($request), 'Check failure on bad wpFileKey' );
+ $request = new FauxRequest( array( 'wpFileKey' => 'foo' ) );
+ $this->assertFalse( UploadFromStash::isValidRequest( $request ), 'Check failure on bad wpFileKey' );
- $request = new FauxRequest( array( 'wpSessionKey' => 'foo') );
- $this->assertFalse( UploadFromStash::isValidRequest($request), 'Check failure on bad wpSessionKey' );
+ $request = new FauxRequest( array( 'wpSessionKey' => 'foo' ) );
+ $this->assertFalse( UploadFromStash::isValidRequest( $request ), 'Check failure on bad wpSessionKey' );
- $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test') );
- $this->assertTrue( UploadFromStash::isValidRequest($request), 'Check good wpFileKey' );
+ $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test' ) );
+ $this->assertTrue( UploadFromStash::isValidRequest( $request ), 'Check good wpFileKey' );
- $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test') );
- $this->assertTrue( UploadFromStash::isValidRequest($request), 'Check good wpSessionKey' );
+ $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test' ) );
+ $this->assertTrue( UploadFromStash::isValidRequest( $request ), 'Check good wpSessionKey' );
- $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test', 'wpSessionKey' => 'foo') );
- $this->assertTrue( UploadFromStash::isValidRequest($request), 'Check key precedence' );
+ $request = new FauxRequest( array( 'wpFileKey' => 'testkey-test.test', 'wpSessionKey' => 'foo' ) );
+ $this->assertTrue( UploadFromStash::isValidRequest( $request ), 'Check key precedence' );
}
}
$this->upload = new UploadTestHandler;
$this->hooks = $wgHooks;
- $wgHooks['InterwikiLoadPrefix'][] = function( $prefix, &$data ) {
+ $wgHooks['InterwikiLoadPrefix'][] = function ( $prefix, &$data ) {
return false;
};
}
/**
* First checks the return code
* of UploadBase::getTitle() and then the actual returned title
- *
+ *
* @dataProvider provideTestTitleValidation
*/
public function testTitleValidation( $srcFilename, $dstFilename, $code, $msg ) {
"$msg text" );
}
}
-
+
/**
* Test various forms of valid and invalid titles that can be supplied.
*/
public static function provideTestTitleValidation() {
return array(
/* Test a valid title */
- array( 'ValidTitle.jpg', 'ValidTitle.jpg', UploadBase::OK,
+ array( 'ValidTitle.jpg', 'ValidTitle.jpg', UploadBase::OK,
'upload valid title' ),
/* A title with a slash */
- array( 'A/B.jpg', 'B.jpg', UploadBase::OK,
+ array( 'A/B.jpg', 'B.jpg', UploadBase::OK,
'upload title with slash' ),
/* A title with illegal char */
- array( 'A:B.jpg', 'A-B.jpg', UploadBase::OK,
+ array( 'A:B.jpg', 'A-B.jpg', UploadBase::OK,
'upload title with colon' ),
/* Stripping leading File: prefix */
- array( 'File:C.jpg', 'C.jpg', UploadBase::OK,
+ array( 'File:C.jpg', 'C.jpg', UploadBase::OK,
'upload title with File prefix' ),
/* Test illegal suggested title (r94601) */
- array( '%281%29.JPG', null, UploadBase::ILLEGAL_FILENAME,
+ array( '%281%29.JPG', null, UploadBase::ILLEGAL_FILENAME,
'illegal title for upload' ),
/* A title without extension */
- array( 'A', null, UploadBase::FILETYPE_MISSING,
+ array( 'A', null, UploadBase::FILETYPE_MISSING,
'upload title without extension' ),
/* A title with no basename */
- array( '.jpg', null, UploadBase::MIN_LENGTH_PARTNAME,
+ array( '.jpg', null, UploadBase::MIN_LENGTH_PARTNAME,
'upload title without basename' ),
/* A title that is longer than 255 bytes */
- array( str_repeat( 'a', 255 ) . '.jpg', null, UploadBase::FILENAME_TOO_LONG,
+ array( str_repeat( 'a', 255 ) . '.jpg', null, UploadBase::FILENAME_TOO_LONG,
'upload title longer than 255 bytes' ),
/* A title that is longer than 240 bytes */
- array( str_repeat( 'a', 240 ) . '.jpg', null, UploadBase::FILENAME_TOO_LONG,
+ array( str_repeat( 'a', 240 ) . '.jpg', null, UploadBase::FILENAME_TOO_LONG,
'upload title longer than 240 bytes' ),
);
}
$wgMaxUploadSize = 100;
$filename = $this->createFileOfSize( $wgMaxUploadSize );
- $this->upload->initializePathInfo( basename($filename) . '.txt', $filename, 100 );
+ $this->upload->initializePathInfo( basename( $filename ) . '.txt', $filename, 100 );
$result = $this->upload->verifyUpload();
unlink( $filename );
$this->assertEquals(
array( 'status' => UploadBase::OK ), $result );
- $wgMaxUploadSize = $savedGlobal; // restore global
+ $wgMaxUploadSize = $savedGlobal; // restore global
}
}
class UploadTestHandler extends UploadBase {
- public function initializeFromRequest( &$request ) { }
- public function testTitleValidation( $name ) {
- $this->mTitle = false;
- $this->mDesiredDestName = $name;
- $this->mTitleError = UploadBase::OK;
- $this->getTitle();
- return $this->mTitleError;
- }
+ public function initializeFromRequest( &$request ) {}
+
+ public function testTitleValidation( $name ) {
+ $this->mTitle = false;
+ $this->mDesiredDestName = $name;
+ $this->mTitleError = UploadBase::OK;
+ $this->getTitle();
+ return $this->mTitleError;
+ }
}
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'one', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
),
);
}
+
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
+ $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
+
function providePlural() {
- return array (
+ return array(
array( 'zero', 0 ),
array( 'one', 1 ),
array( 'two', 2 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'many', 'other' );
+ $forms = array( 'one', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'many', 11 ),
array( 'one', 91 ),
'bug 23156: U+2019 conversion to U+0027'
);
}
+
/** see bug 23156 & r64981 */
function testCommafy() {
$this->assertEquals( '1,234,567', $this->getLang()->commafy( '1234567' ) );
- $this->assertEquals( '12,345', $this->getLang()->commafy( '12345' ) );
+ $this->assertEquals( '12,345', $this->getLang()->commafy( '12345' ) );
}
+
/** see bug 23156 & r64981 */
function testDoesNotCommafyFourDigitsNumber() {
- $this->assertEquals( '1234', $this->getLang()->commafy( '1234' ) );
+ $this->assertEquals( '1234', $this->getLang()->commafy( '1234' ) );
}
+
/** @dataProvider providePluralFourForms */
function testPluralFourForms( $result, $value ) {
- $forms = array( 'one', 'few', 'many', 'other' );
+ $forms = array( 'one', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePluralFourForms() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'many', 11 ),
array( 'one', 91 ),
array( 'many', 120 ),
);
}
+
/** @dataProvider providePluralTwoForms */
function testPluralTwoForms( $result, $value ) {
- $forms = array( 'one', 'several' );
+ $forms = array( 'one', 'several' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
+
function providePluralTwoForms() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'several', 11 ),
array( 'several', 91 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'one', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'many', 'other' );
+ $forms = array( 'one', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'many', 0 ),
array( 'one', 1 ),
array( 'few', 2 ),
/**
* Regex used to find out the language code out of the class name
* used by setUpBeforeClass
- */
+ */
private static $reExtractLangFromClass = '/Language(.*)Test/';
/**
$m[1] = 'en';
wfDebug(
__METHOD__ . " could not extract a language name "
- . "out of " . get_called_class() . " failling back to 'en'\n"
+ . "out of " . get_called_class() . " failling back to 'en'\n"
);
}
// TODO: validate $m[1] which should be a valid language code
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'other' );
+ $forms = array( 'one', 'few', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'few', 2 ),
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'many', 'other' );
+ $forms = array( 'one', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'few', 2 ),
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
+ $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'zero', 0 ),
array( 'one', 1 ),
array( 'two', 2 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'two', 'few', 'other' );
+ $forms = array( 'one', 'two', 'few', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'one', 101 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'one', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'two', 'other' );
+ $forms = array( 'one', 'two', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'two', 2 ),
<?php
/**
* @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
+ * @copyright Copyright © 2012-2013, Santhosh Thottingal
* @file
*/
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- // The CLDR ticket for this plural forms is not same as mw plural forms. See http://unicode.org/cldr/trac/ticket/2883
- $forms = array( 'Form 1', 'Form 2', 'Form 3', 'Form 4', 'Form 5', 'Form 6' );
+ $forms = array( 'one', 'two', 'few', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
+
function providerPlural() {
return array (
- array( 'Form 6', 0 ),
- array( 'Form 1', 1 ),
- array( 'Form 2', 2 ),
- array( 'Form 3', 11 ),
- array( 'Form 4', 12 ),
- array( 'Form 5', 3 ),
- array( 'Form 5', 19 ),
- array( 'Form 6', 200 ),
+ array( 'other', 0 ),
+ array( 'one', 1 ),
+ array( 'two', 2 ),
+ array( 'one', 11 ),
+ array( 'two', 12 ),
+ array( 'few', 3 ),
+ array( 'few', 19 ),
+ array( 'other', 200 ),
);
}
+ /** @dataProvider providerPluralExplicit */
+ function testExplicitPlural( $result, $value ) {
+ $forms = array( 'one', 'two', 'few', 'other', '11=Form11', '12=Form12' );
+ $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+ }
+
+ function providerPluralExplicit() {
+ return array (
+ array( 'other', 0 ),
+ array( 'one', 1 ),
+ array( 'two', 2 ),
+ array( 'Form11', 11 ),
+ array( 'Form12', 12 ),
+ array( 'few', 3 ),
+ array( 'few', 19 ),
+ array( 'other', 200 ),
+ );
+ }
}
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
// This is not compatible with CLDR plural rules http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#gv
- $forms = array( 'Form 1', 'Form 2', 'Form 3', 'Form 4' );
+ $forms = array( 'Form 1', 'Form 2', 'Form 3', 'Form 4' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
+
function providerPlural() {
- return array (
+ return array(
array( 'Form 4', 0 ),
array( 'Form 2', 1 ),
array( 'Form 3', 2 ),
}
function providerPluralDual() {
- return array (
+ return array(
array( 'other', 0 ), // Zero -> plural
array( 'one', 1 ), // Singular
array( 'two', 2 ), // Dual
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ), // Zero -> plural
array( 'one', 1 ), // Singular
array( 'other', 2 ), // Plural, no dual provided
// The comments in the beginning of the line help avoid RTL problems
// with text editors.
function providerGrammar() {
- return array (
+ return array(
array(
/* result */ 'וויקיפדיה',
/* word */ 'ויקיפדיה',
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'one', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'many', 'other' );
+ $forms = array( 'one', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'many', 0 ),
array( 'one', 1 ),
array( 'few', 2 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'two', 'few', 'other' );
+ $forms = array( 'one', 'two', 'few', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'one', 101 ),
}
function providePlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other', 'zero' );
+ $forms = array( 'one', 'other', 'zero' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'zero', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'one', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider provideOneFewOtherCases */
function testOneFewOtherPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'other' );
+ $forms = array( 'one', 'few', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
-
+
/** @dataProvider provideOneFewCases */
function testOneFewPlural( $result, $value ) {
- $forms = array( 'one', 'few' );
+ $forms = array( 'one', 'few' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function provideOneFewOtherCases() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'few', 2 ),
array( 'one', 40001 ),
);
}
-
+
function provideOneFewCases() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'few', 15 ),
);
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ), #this must be zero form as per CLDR
array( 'one', 1 ),
array( 'other', 11 ),
/** @dataProvider providePlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePlural() {
- return array (
+ return array(
array( 'one', 0 ),
array( 'one', 1 ),
array( 'other', 2 ),
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'other', 11 ),
class LanguageMlTest extends LanguageClassesTestCase {
/** see bug 29495 */
- /** @dataProvider providerFormatNum*/
+ /** @dataProvider providerFormatNum */
function testFormatNum( $result, $value ) {
$this->assertEquals( $result, $this->getLang()->formatNum( $value ) );
}
function providerFormatNum() {
return array(
- array( '12,34,567', '1234567' ),
+ array( '12,34,567', '1234567' ),
array( '12,345', '12345' ),
array( '1', '1' ),
- array( '123', '123' ) ,
+ array( '123', '123' ),
array( '1,234', '1234' ),
array( '12,345.56', '12345.56' ),
array( '12,34,56,79,81,23,45,678', '12345679812345678' ),
array( '-12,00,000', '-1200000' ),
array( '-98', '-98' ),
array( '-98', -98 ),
- array( '-1,23,45,678', -12345678 ),
+ array( '-1,23,45,678', -12345678 ),
array( '', '' ),
array( '', null ),
);
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'other' );
+ $forms = array( 'one', 'few', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
- array( 'few', 0 ),
- array( 'one', 1 ),
- array( 'few', 2 ),
- array( 'few', 19 ),
+ return array(
+ array( 'few', 0 ),
+ array( 'one', 1 ),
+ array( 'few', 2 ),
+ array( 'few', 19 ),
array( 'other', 20 ),
array( 'other', 99 ),
array( 'other', 100 ),
- array( 'few', 101 ),
- array( 'few', 119 ),
+ array( 'few', 101 ),
+ array( 'few', 119 ),
array( 'other', 120 ),
array( 'other', 200 ),
- array( 'few', 201 ),
- array( 'few', 219 ),
+ array( 'few', 201 ),
+ array( 'few', 219 ),
array( 'other', 220 ),
);
}
}
function providerPluralAllForms() {
- return array (
- array( 'few', 0 ),
- array( 'one', 1 ),
- array( 'few', 2 ),
- array( 'few', 10 ),
- array( 'many', 11 ),
- array( 'many', 19 ),
+ return array(
+ array( 'few', 0 ),
+ array( 'one', 1 ),
+ array( 'few', 2 ),
+ array( 'few', 10 ),
+ array( 'many', 11 ),
+ array( 'many', 19 ),
array( 'other', 20 ),
array( 'other', 99 ),
array( 'other', 100 ),
array( 'other', 101 ),
- array( 'few', 102 ),
- array( 'few', 110 ),
- array( 'many', 111 ),
- array( 'many', 119 ),
+ array( 'few', 102 ),
+ array( 'few', 110 ),
+ array( 'many', 111 ),
+ array( 'many', 119 ),
array( 'other', 120 ),
array( 'other', 201 ),
);
}
function providerPluralTwoForms() {
- return array (
- array( 'many', 0 ),
- array( 'one', 1 ),
- array( 'many', 2 ),
- array( 'many', 10 ),
- array( 'many', 11 ),
- array( 'many', 19 ),
- array( 'many', 20 ),
- array( 'many', 99 ),
- array( 'many', 100 ),
- array( 'many', 101 ),
- array( 'many', 102 ),
- array( 'many', 110 ),
- array( 'many', 111 ),
- array( 'many', 119 ),
- array( 'many', 120 ),
- array( 'many', 201 ),
+ return array(
+ array( 'many', 0 ),
+ array( 'one', 1 ),
+ array( 'many', 2 ),
+ array( 'many', 10 ),
+ array( 'many', 11 ),
+ array( 'many', 19 ),
+ array( 'many', 20 ),
+ array( 'many', 99 ),
+ array( 'many', 100 ),
+ array( 'many', 101 ),
+ array( 'many', 102 ),
+ array( 'many', 110 ),
+ array( 'many', 111 ),
+ array( 'many', 119 ),
+ array( 'many', 120 ),
+ array( 'many', 201 ),
);
}
}
}
function providerPlural() {
- return array (
- array( 'one', 0 ),
- array( 'one', 1 ),
+ return array(
+ array( 'one', 0 ),
+ array( 'one', 1 ),
array( 'many', 2 ),
);
}
}
function providerPluralFourForms() {
- return array (
- array( 'many', 0 ),
- array( 'one', 1 ),
- array( 'few', 2 ),
- array( 'few', 3 ),
- array( 'few', 4 ),
- array( 'many', 5 ),
- array( 'many', 9 ),
- array( 'many', 10 ),
- array( 'many', 11 ),
- array( 'many', 21 ),
- array( 'few', 22 ),
- array( 'few', 23 ),
- array( 'few', 24 ),
- array( 'many', 25 ),
- array( 'many', 200 ),
- array( 'many', 201 ),
+ return array(
+ array( 'many', 0 ),
+ array( 'one', 1 ),
+ array( 'few', 2 ),
+ array( 'few', 3 ),
+ array( 'few', 4 ),
+ array( 'many', 5 ),
+ array( 'many', 9 ),
+ array( 'many', 10 ),
+ array( 'many', 11 ),
+ array( 'many', 21 ),
+ array( 'few', 22 ),
+ array( 'few', 23 ),
+ array( 'few', 24 ),
+ array( 'many', 25 ),
+ array( 'many', 200 ),
+ array( 'many', 201 ),
);
}
}
function providerPlural() {
- return array (
- array( 'many', 0 ),
- array( 'one', 1 ),
- array( 'many', 2 ),
- array( 'many', 3 ),
- array( 'many', 4 ),
- array( 'many', 5 ),
- array( 'many', 9 ),
- array( 'many', 10 ),
- array( 'many', 11 ),
- array( 'many', 21 ),
- array( 'many', 22 ),
- array( 'many', 23 ),
- array( 'many', 24 ),
- array( 'many', 25 ),
- array( 'many', 200 ),
- array( 'many', 201 ),
+ return array(
+ array( 'many', 0 ),
+ array( 'one', 1 ),
+ array( 'many', 2 ),
+ array( 'many', 3 ),
+ array( 'many', 4 ),
+ array( 'many', 5 ),
+ array( 'many', 9 ),
+ array( 'many', 10 ),
+ array( 'many', 11 ),
+ array( 'many', 21 ),
+ array( 'many', 22 ),
+ array( 'many', 23 ),
+ array( 'many', 24 ),
+ array( 'many', 25 ),
+ array( 'many', 200 ),
+ array( 'many', 201 ),
);
}
}
/** @dataProvider providerPlural */
function testPlural( $result, $value ) {
- $forms = array( 'one', 'few', 'other' );
+ $forms = array( 'one', 'few', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providerPlural() {
- return array (
- array( 'few', 0 ),
- array( 'one', 1 ),
- array( 'few', 2 ),
- array( 'few', 19 ),
+ return array(
+ array( 'few', 0 ),
+ array( 'one', 1 ),
+ array( 'few', 2 ),
+ array( 'few', 19 ),
array( 'other', 20 ),
array( 'other', 99 ),
array( 'other', 100 ),
- array( 'few', 101 ),
- array( 'few', 119 ),
+ array( 'few', 101 ),
+ array( 'few', 119 ),
array( 'other', 120 ),
array( 'other', 200 ),
- array( 'few', 201 ),
- array( 'few', 219 ),
+ array( 'few', 201 ),
+ array( 'few', 219 ),
array( 'other', 220 ),
);
}
}
function providerPluralThreeForms() {
- return array (
+ return array(
array( 'other', 0 ),
- array( 'one', 1 ),
- array( 'two', 2 ),
+ array( 'one', 1 ),
+ array( 'two', 2 ),
array( 'other', 3 ),
);
}
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
- array( 'one', 1 ),
+ array( 'one', 1 ),
array( 'other', 2 ),
array( 'other', 3 ),
);
}
function providePluralAllForms() {
- return array (
- array( 'many', 0 ),
- array( 'one', 1 ),
- array( 'few', 2 ),
+ return array(
+ array( 'many', 0 ),
+ array( 'one', 1 ),
+ array( 'few', 2 ),
array( 'other', 3 ),
- array( 'many', 10 ),
- array( 'many', 11 ),
- array( 'many', 12 ),
- array( 'many', 19 ),
+ array( 'many', 10 ),
+ array( 'many', 11 ),
+ array( 'many', 12 ),
+ array( 'many', 19 ),
array( 'other', 20 ),
- array( 'many', 100 ),
- array( 'one', 101 ),
- array( 'many', 111 ),
- array( 'many', 112 ),
+ array( 'many', 100 ),
+ array( 'one', 101 ),
+ array( 'many', 111 ),
+ array( 'many', 112 ),
);
}
/** @dataProvider providePluralTwoForms */
function testPluralTwoForms( $result, $value ) {
- $forms = array( 'one', 'other' );
+ $forms = array( 'one', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
function providePluralTwoForms() {
- return array (
+ return array(
array( 'other', 0 ),
- array( 'one', 1 ),
+ array( 'one', 1 ),
array( 'other', 2 ),
array( 'other', 3 ),
array( 'other', 10 ),
array( 'other', 19 ),
array( 'other', 20 ),
array( 'other', 100 ),
- array( 'one', 101 ),
+ array( 'one', 101 ),
array( 'other', 111 ),
array( 'other', 112 ),
);
}
function providerPlural() {
- return array (
+ return array(
array( 'many', 0 ),
- array( 'one', 1 ),
+ array( 'one', 1 ),
array( 'many', 2 ),
);
}
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
array( 'one', 1 ),
array( 'few', 2 ),
}
function providerPlural() {
- return array (
- array( 'zero', 0 ),
- array( 'one', 1 ),
- array( 'two', 2 ),
- array( 'few', 3 ),
- array( 'few', 4 ),
+ return array(
+ array( 'zero', 0 ),
+ array( 'one', 1 ),
+ array( 'two', 2 ),
+ array( 'few', 3 ),
+ array( 'few', 4 ),
array( 'other', 5 ),
array( 'other', 99 ),
array( 'other', 100 ),
- array( 'one', 101 ),
- array( 'two', 102 ),
- array( 'few', 103 ),
- array( 'one', 201 ),
+ array( 'one', 101 ),
+ array( 'two', 102 ),
+ array( 'few', 103 ),
+ array( 'one', 201 ),
);
}
}
}
function providerPluralThreeForms() {
- return array (
+ return array(
array( 'other', 0 ),
- array( 'one', 1 ),
- array( 'two', 2 ),
+ array( 'one', 1 ),
+ array( 'two', 2 ),
array( 'other', 3 ),
);
}
}
function providerPlural() {
- return array (
+ return array(
array( 'other', 0 ),
- array( 'one', 1 ),
+ array( 'one', 1 ),
array( 'other', 2 ),
array( 'other', 3 ),
);
##### TESTS #######################################################
- function testEasyConversions( ) {
+ function testEasyConversions() {
$this->assertCyrillic(
'шђчћжШЂЧЋЖ',
'Cyrillic guessing characters'
}
function providePluralFourForms() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'many', 11 ),
array( 'one', 91 ),
array( 'many', 120 ),
);
}
+
/** @dataProvider providePluralTwoForms */
function testPluralTwoForms( $result, $value ) {
$forms = array( 'one', 'several' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
+
function providePluralTwoForms() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'several', 11 ),
array( 'several', 91 ),
$msg
);
}
+
/**
* Wrapper to verify a text is different once converted to a variant.
* @param $text string Text to convert
$this->assertUnConverted( $text, 'sr-ec', $msg );
$this->assertConverted( $text, 'sr-el', $msg );
}
+
/**
* Verifiy the given Latin text is not converted when using
* using the Latin variant and converted to Cyrillic when using
return $this->getLang()
->mConverter
->convertTo(
- $text, $variant
- );
+ $text, $variant
+ );
}
+
function convertToCyrillic( $text ) {
return $this->convertTo( $text, 'sr-ec' );
}
+
function convertToLatin( $text ) {
return $this->convertTo( $text, 'sr-el' );
}
function provideLanguageCodes() {
return array(
- array( 'fr' , 'Two letters, minor case' ),
- array( 'EN' , 'Two letters, upper case' ),
- array( 'tyv' , 'Three letters' ),
- array( 'tokipona' , 'long language code' ),
+ array( 'fr', 'Two letters, minor case' ),
+ array( 'EN', 'Two letters, upper case' ),
+ array( 'tyv', 'Three letters' ),
+ array( 'tokipona', 'long language code' ),
array( 'be-tarask', 'With dash' ),
array( 'Zh-classical', 'Begin with upper case, dash' ),
array( 'Be-x-old', 'With extension (two dashes)' ),
*/
function testKnownLanguageTag( $code, $message = '' ) {
$this->assertTrue(
- (bool) Language::isKnownLanguageTag( $code ),
+ (bool)Language::isKnownLanguageTag( $code ),
"validating code $code - $message"
);
}
*/
function testKnownCldrLanguageTag() {
if ( !class_exists( 'LanguageNames' ) ) {
- $this->markTestSkipped( 'reason' );
+ $this->markTestSkipped( 'The LanguageNames class is not available. The cldr extension is probably not installed.' );
}
$this->assertTrue(
- (bool) Language::isKnownLanguageTag( 'pal' ),
+ (bool)Language::isKnownLanguageTag( 'pal' ),
'validating code "pal" an ancient language, which probably will not appear in Names.php, but appears in CLDR in English'
);
}
*/
function testUnknownLanguageTag( $code, $message = '' ) {
$this->assertFalse(
- (bool) Language::isKnownLanguageTag( $code ),
+ (bool)Language::isKnownLanguageTag( $code ),
"checking that code $code is invalid - $message"
);
}
"sprintfDate('$format', '$ts'): $msg"
);
}
+
/**
* bug 33454. sprintfDate should always use UTC.
* @dataProvider provideSprintfDateSamples
}
-
/**
* @dataProvider provideFormatDuration
*/
function testCheckTitleEncoding( $s ) {
$this->assertEquals(
$s,
- $this->getLang()->checkTitleEncoding($s),
+ $this->getLang()->checkTitleEncoding( $s ),
"checkTitleEncoding('$s')"
);
}
function provideCheckTitleEncodingData() {
- return array (
+ return array(
array( "" ),
array( "United States of America" ), // 7bit ASCII
array( rawurldecode( "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e" ) ),
array( 7000, 'MMMMMMM' ),
array( 8000, 'MMMMMMMM' ),
array( 9000, 'MMMMMMMMM' ),
- array( 9999, 'MMMMMMMMMCMXCIX'),
+ array( 9999, 'MMMMMMMMMCMXCIX' ),
array( 10000, 'MMMMMMMMMM' ),
);
}
function providePluralData() {
return array(
+ array( 'plural', 0, array(
+ 'singular', 'plural'
+ ) ),
array( 'explicit zero', 0, array(
'0=explicit zero', 'singular', 'plural'
) ),
array( 'plural', 3, array(
'0=explicit zero', '1=explicit one', 'singular', 'plural'
) ),
+ array( 'explicit elevan', 11, array(
+ 'singular', 'plural', '11=explicit elevan',
+ ) ),
+ array( 'plural', 12, array(
+ 'singular', 'plural', '11=explicit twelve',
+ ) ),
+ array( 'plural', 12, array(
+ 'singular', 'plural', '=explicit form',
+ ) ),
);
}
$s = $lang->getMessageFromDB( 'word-separator' );
$c = $lang->getMessageFromDB( 'comma-separator' );
- $this->assertEquals( '', $lang->listToText( array( ) ) );
+ $this->assertEquals( '', $lang->listToText( array() ) );
$this->assertEquals( 'a', $lang->listToText( array( 'a' ) ) );
$this->assertEquals( "a{$and}{$s}b", $lang->listToText( array( 'a', 'b' ) ) );
$this->assertEquals( "a{$c}b{$and}{$s}c", $lang->listToText( array( 'a', 'b', 'c' ) ) );
}
function providerPlural() {
- return array (
- array( 'one', 0 ),
- array( 'one', 1 ),
+ return array(
+ array( 'one', 0 ),
+ array( 'one', 1 ),
array( 'many', 2 ),
);
}
}
function providerPlural() {
- return array (
- array( 'one', 0 ),
- array( 'one', 1 ),
+ return array(
+ array( 'one', 0 ),
+ array( 'one', 1 ),
array( 'many', 2 ),
);
}
* @dataProvider provideDottedAndDotlessI
*/
function testDottedAndDotlessI( $func, $input, $inputCase, $expected ) {
- if( $func == 'ucfirst' ) {
+ if ( $func == 'ucfirst' ) {
$res = $this->getLang()->ucfirst( $input );
- } elseif( $func == 'lcfirst' ) {
+ } elseif ( $func == 'lcfirst' ) {
$res = $this->getLang()->lcfirst( $input );
} else {
throw new MWException( __METHOD__ . " given an invalid function name '$func'" );
}
function providePluralFourForms() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'many', 11 ),
array( 'one', 91 ),
array( 'many', 120 ),
);
}
+
/** @dataProvider providePluralTwoForms */
function testPluralTwoForms( $result, $value ) {
$forms = array( 'one', 'several' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
+
function providePluralTwoForms() {
- return array (
+ return array(
array( 'one', 1 ),
array( 'several', 11 ),
array( 'several', 91 ),
$msg
);
}
+
/**
* Wrapper to verify a text is different once converted to a variant.
* @param $text string Text to convert
$this->assertUnConverted( $text, 'uz-cyrl', $msg );
$this->assertConverted( $text, 'uz-latn', $msg );
}
+
/**
* Verifiy the given Latin text is not converted when using
* using the Latin variant and converted to Cyrillic when using
function convertTo( $text, $variant ) {
return $this->getLang()->mConverter->convertTo( $text, $variant );
}
+
function convertToCyrillic( $text ) {
return $this->convertTo( $text, 'uz-cyrl' );
}
+
function convertToLatin( $text ) {
return $this->convertTo( $text, 'uz-latn' );
}
}
function providerPlural() {
- return array (
- array( 'one', 0 ),
- array( 'one', 1 ),
+ return array(
+ array( 'one', 0 ),
+ array( 'one', 1 ),
array( 'many', 2 ),
);
}
array( 1, 'n is 1', 1.1, 'float number and is' ),
array( 1, 'n is 1', 2, 'float number and is' ),
- array( 0, 'n in 1,3,5', 3, '' ),
+ array( 0, 'n in 1,3,5', 3, '' ),
array( 1, 'n not in 1,3,5', 5, '' ),
- array( 1, 'n in 1,3,5', 2, '' ),
+ array( 1, 'n in 1,3,5', 2, '' ),
array( 0, 'n not in 1,3,5', 4, '' ),
- array( 0, 'n in 1..3', 2, '' ),
- array( 0, 'n in 1..3', 3, 'in is inclusive' ),
- array( 1, 'n in 1..3', 0, '' ),
+ array( 0, 'n in 1..3', 2, '' ),
+ array( 0, 'n in 1..3', 3, 'in is inclusive' ),
+ array( 1, 'n in 1..3', 0, '' ),
- array( 1, 'n not in 1..3', 2, '' ),
- array( 1, 'n not in 1..3', 3, 'in is inclusive' ),
- array( 0, 'n not in 1..3', 0, '' ),
+ array( 1, 'n not in 1..3', 2, '' ),
+ array( 1, 'n not in 1..3', 3, 'in is inclusive' ),
+ array( 0, 'n not in 1..3', 0, '' ),
array( 1, 'n is not 1 and n is not 2 and n is not 3', 1, 'and relation' ),
array( 0, 'n is not 1 and n is not 2 and n is not 4', 3, 'and relation' ),
protected function skipToNodeEnd( $name ) {
while ( $this->xml->read() ) {
if ( $this->xml->nodeType == XMLReader::END_ELEMENT &&
- $this->xml->name == $name ) {
+ $this->xml->name == $name
+ ) {
return true;
}
}
protected function skipWhitespace() {
$cont = true;
while ( $cont && ( ( $this->xml->nodeType == XMLReader::WHITESPACE )
- || ( $this->xml->nodeType == XMLReader::SIGNIFICANT_WHITESPACE ) ) ) {
+ || ( $this->xml->nodeType == XMLReader::SIGNIFICANT_WHITESPACE ) ) ) {
$cont = $this->xml->read();
}
}
* @param $parentid int|false: (optional) id of the parent revision
*/
protected function assertRevision( $id, $summary, $text_id, $text_bytes, $text_sha1, $text = false, $parentid = false,
- $model = CONTENT_MODEL_WIKITEXT, $format = CONTENT_FORMAT_WIKITEXT ) {
+ $model = CONTENT_MODEL_WIKITEXT, $format = CONTENT_FORMAT_WIKITEXT ) {
$this->assertNodeStart( "revision" );
$this->skipWhitespace();
$this->assertFalse( $this->xml->hasValue, "Revision has text" );
$this->assertTrue( $this->xml->read(), "Skipping text start tag" );
if ( ( $this->xml->nodeType == XMLReader::END_ELEMENT )
- && ( $this->xml->name == "text" ) ) {
+ && ( $this->xml->name == "text" )
+ ) {
$this->xml->read();
}
return;
}
- return call_user_func_array ( array( "parent", __FUNCTION__ ), func_get_args() );
+ return call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() );
}
/**
* Safety net around register_shutdown_function of Maintenance.php
*/
public function __destruct() {
- if ( ! $this->shutdownSimulated ) {
+ if ( !$this->shutdownSimulated ) {
// Someone generated a MaintenanceFixup instance without calling
// simulateShutdown. We'd have to raise a PHPUnit exception to correctly
// flag this illegal usage. However, we are already in a destruktor, which
}
-
// --- Making protected functions visible for test
public function output( $out, $channel = null ) {
// Maintenance::output signature. However, we do not use (or rely on)
// those variables. Instead we pass to Maintenance::output whatever we
// receive at runtime.
- return call_user_func_array ( array( "parent", __FUNCTION__ ), func_get_args() );
+ return call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() );
}
-
// --- Requirements for getting instance of abstract class
public function execute() {
private function assertOutputPrePostShutdown( $preShutdownOutput, $expectNLAppending ) {
$this->assertEquals( $preShutdownOutput, $this->getActualOutput(),
- "Output before shutdown simulation" );
+ "Output before shutdown simulation" );
$this->m->simulateShutdown();
$this->m = null;
$m2->output( "bar" );
$this->assertEquals( "foobar", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foobar", false );
}
$m2->output( "bar", null );
$this->assertEquals( "foobar", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foobar", false );
}
$m2->output( "bar", "bazChannel" );
$this->assertEquals( "foobar", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foobar\n", true );
}
$m2->output( "bar\n", null );
$this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foo\nbar\n", false );
}
$m2->output( "bar\n", "bazChannel" );
$this->assertEquals( "foobar", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foobar\n", true );
}
$m2->outputChanneled( "bar" );
$this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foo\nbar\n", false );
}
$m2->outputChanneled( "bar", null );
$this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foo\nbar\n", false );
}
$m2->outputChanneled( "bar", "bazChannel" );
$this->assertEquals( "foobar", $this->getActualOutput(),
- "Output before shutdown simulation (m2)" );
+ "Output before shutdown simulation (m2)" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foobar\n", true );
}
$m2->outputChanneled( "bar", "bazChannel" );
$this->assertEquals( "foobar", $this->getActualOutput(),
- "Output before first cleanup" );
+ "Output before first cleanup" );
$this->m->cleanupChanneled();
$this->assertEquals( "foobar\n", $this->getActualOutput(),
- "Output after first cleanup" );
+ "Output after first cleanup" );
$m2->cleanupChanneled();
$this->assertEquals( "foobar\n\n", $this->getActualOutput(),
- "Output after second cleanup" );
+ "Output after second cleanup" );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foobar\n\n", false );
foreach ( $requested_pages as $i ) {
$this->assertTrue( array_key_exists( $i, $available_pages ),
"Check for availability of requested page " . $i );
- $content .= $available_pages[ $i ];
+ $content .= $available_pages[$i];
}
$content .= $tail;
$this->assertEquals( strlen( $content ), file_put_contents(
- $fname, $content ), "Length of prepared prefetch" );
+ $fname, $content ), "Length of prepared prefetch" );
return $fname;
}
if ( $ns === NS_TALK ) {
//@todo: work around this.
throw new MWException( "The default wikitext namespace is the talk namespace. "
- . " We can't currently deal with that.");
+ . " We can't currently deal with that." );
}
$title = Title::newFromText( 'BackupDumperTestP1', NS_TALK );
// Setting up the dump
$nameStub = $this->setUpStub();
$nameFull = $this->getNewTempFile();
- $dumper = new TextPassDumper( array ( "--stub=file:" . $nameStub,
- "--output=file:" . $nameFull ) );
+ $dumper = new TextPassDumper( array( "--stub=file:" . $nameStub,
+ "--output=file:" . $nameFull ) );
$dumper->reporting = false;
$dumper->setDb( $this->db );
// Setting up of the dump
$nameStub = $this->setUpStub();
$nameFull = $this->getNewTempFile();
- $dumper = new TextPassDumper( array ( "--stub=file:"
- . $nameStub, "--output=file:" . $nameFull ) );
+ $dumper = new TextPassDumper( array( "--stub=file:"
+ . $nameStub, "--output=file:" . $nameFull ) );
$dumper->prefetch = $prefetchMock;
$dumper->reporting = false;
$dumper->setDb( $this->db );
$this->assertTrue( wfMkdirParents( $nameOutputDir ),
"Creating temporary output directory " );
$this->setUpStub( $nameStub, $iterations );
- $dumper = new TextPassDumper( array ( "--stub=file:" . $nameStub,
- "--output=" . $checkpointFormat . ":" . $nameOutputDir . "/full",
- "--maxtime=1" /*This is in minutes. Fixup is below*/,
- "--checkpointfile=checkpoint-%s-%s.xml.gz" ) );
+ $dumper = new TextPassDumper( array( "--stub=file:" . $nameStub,
+ "--output=" . $checkpointFormat . ":" . $nameOutputDir . "/full",
+ "--maxtime=1" /*This is in minutes. Fixup is below*/,
+ "--checkpointfile=checkpoint-%s-%s.xml.gz" ) );
$dumper->setDb( $this->db );
$dumper->maxTimeAllowed = $checkpointAfter; // Patching maxTime from 1 minute
$dumper->stderr = $stderr;
$this->assertLessThan( 50000, $iterations,
"Emergency stop against infinitely increasing iteration "
- . "count ( last duration: $lastDuration )" );
+ . "count ( last duration: $lastDuration )" );
}
}
// Each run of the following loop body tries to handle exactly 1 /page/ (not
// iteration of stub content). $i is only increased after having treated page 4.
- for ( $i = 0 ; $i < $iterations ; ) {
+ for ( $i = 0; $i < $iterations; ) {
// 1. Assuring a file is opened and ready. Skipping across header if
// necessary.
- if ( ! $fileOpened ) {
+ if ( !$fileOpened ) {
$this->assertNotEmpty( $files, "No more existing dump files, "
. "but not yet all pages found" );
$fname = array_shift( $files );
// 2. Performing a single page check
switch ( $lookingForPage ) {
- case 1:
- // Page 1
- $this->assertPageStart( $this->pageId1 + $i * self::$numOfPages, NS_MAIN,
- "BackupDumperTestP1" );
- $this->assertRevision( $this->revId1_1 + $i * self::$numOfRevs, "BackupDumperTestP1Summary1",
- $this->textId1_1, false, "0bolhl6ol7i6x0e7yq91gxgaan39j87",
- "BackupDumperTestP1Text1" );
- $this->assertPageEnd();
-
- $lookingForPage = 2;
- break;
-
- case 2:
- // Page 2
- $this->assertPageStart( $this->pageId2 + $i * self::$numOfPages, NS_MAIN,
- "BackupDumperTestP2" );
- $this->assertRevision( $this->revId2_1 + $i * self::$numOfRevs, "BackupDumperTestP2Summary1",
- $this->textId2_1, false, "jprywrymfhysqllua29tj3sc7z39dl2",
- "BackupDumperTestP2Text1" );
- $this->assertRevision( $this->revId2_2 + $i * self::$numOfRevs, "BackupDumperTestP2Summary2",
- $this->textId2_2, false, "b7vj5ks32po5m1z1t1br4o7scdwwy95",
- "BackupDumperTestP2Text2", $this->revId2_1 + $i * self::$numOfRevs );
- $this->assertRevision( $this->revId2_3 + $i * self::$numOfRevs, "BackupDumperTestP2Summary3",
- $this->textId2_3, false, "jfunqmh1ssfb8rs43r19w98k28gg56r",
- "BackupDumperTestP2Text3", $this->revId2_2 + $i * self::$numOfRevs );
- $this->assertRevision( $this->revId2_4 + $i * self::$numOfRevs,
- "BackupDumperTestP2Summary4 extra",
- $this->textId2_4, false, "6o1ciaxa6pybnqprmungwofc4lv00wv",
- "BackupDumperTestP2Text4 some additional Text",
- $this->revId2_3 + $i * self::$numOfRevs );
- $this->assertPageEnd();
-
- $lookingForPage = 4;
- break;
-
- case 4:
- // Page 4
- $this->assertPageStart( $this->pageId4 + $i * self::$numOfPages, NS_TALK,
- "Talk:BackupDumperTestP1" );
- $this->assertRevision( $this->revId4_1 + $i * self::$numOfRevs,
- "Talk BackupDumperTestP1 Summary1",
- $this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe",
- "Talk about BackupDumperTestP1 Text1" );
- $this->assertPageEnd();
-
- $lookingForPage = 1;
-
- // We dealt with the whole iteration.
- $i++;
- break;
-
- default:
- $this->fail( "Bad setting for lookingForPage ($lookingForPage)" );
+ case 1:
+ // Page 1
+ $this->assertPageStart( $this->pageId1 + $i * self::$numOfPages, NS_MAIN,
+ "BackupDumperTestP1" );
+ $this->assertRevision( $this->revId1_1 + $i * self::$numOfRevs, "BackupDumperTestP1Summary1",
+ $this->textId1_1, false, "0bolhl6ol7i6x0e7yq91gxgaan39j87",
+ "BackupDumperTestP1Text1" );
+ $this->assertPageEnd();
+
+ $lookingForPage = 2;
+ break;
+
+ case 2:
+ // Page 2
+ $this->assertPageStart( $this->pageId2 + $i * self::$numOfPages, NS_MAIN,
+ "BackupDumperTestP2" );
+ $this->assertRevision( $this->revId2_1 + $i * self::$numOfRevs, "BackupDumperTestP2Summary1",
+ $this->textId2_1, false, "jprywrymfhysqllua29tj3sc7z39dl2",
+ "BackupDumperTestP2Text1" );
+ $this->assertRevision( $this->revId2_2 + $i * self::$numOfRevs, "BackupDumperTestP2Summary2",
+ $this->textId2_2, false, "b7vj5ks32po5m1z1t1br4o7scdwwy95",
+ "BackupDumperTestP2Text2", $this->revId2_1 + $i * self::$numOfRevs );
+ $this->assertRevision( $this->revId2_3 + $i * self::$numOfRevs, "BackupDumperTestP2Summary3",
+ $this->textId2_3, false, "jfunqmh1ssfb8rs43r19w98k28gg56r",
+ "BackupDumperTestP2Text3", $this->revId2_2 + $i * self::$numOfRevs );
+ $this->assertRevision( $this->revId2_4 + $i * self::$numOfRevs,
+ "BackupDumperTestP2Summary4 extra",
+ $this->textId2_4, false, "6o1ciaxa6pybnqprmungwofc4lv00wv",
+ "BackupDumperTestP2Text4 some additional Text",
+ $this->revId2_3 + $i * self::$numOfRevs );
+ $this->assertPageEnd();
+
+ $lookingForPage = 4;
+ break;
+
+ case 4:
+ // Page 4
+ $this->assertPageStart( $this->pageId4 + $i * self::$numOfPages, NS_TALK,
+ "Talk:BackupDumperTestP1" );
+ $this->assertRevision( $this->revId4_1 + $i * self::$numOfRevs,
+ "Talk BackupDumperTestP1 Summary1",
+ $this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe",
+ "Talk about BackupDumperTestP1 Text1" );
+ $this->assertPageEnd();
+
+ $lookingForPage = 1;
+
+ // We dealt with the whole iteration.
+ $i++;
+ break;
+
+ default:
+ $this->fail( "Bad setting for lookingForPage ($lookingForPage)" );
}
// 3. Checking for the end of the current checkpoint file
if ( $this->xml->nodeType == XMLReader::END_ELEMENT
- && $this->xml->name == "mediawiki" ) {
-
+ && $this->xml->name == "mediawiki"
+ ) {
$this->assertDumpEnd();
$fileOpened = false;
}
}
$content .= $tail;
$this->assertEquals( strlen( $content ), file_put_contents(
- $fname, $content ), "Length of prepared stub" );
+ $fname, $content ), "Length of prepared stub" );
return $fname;
}
-
}
* @return int id of the added log entry
*/
private function addLogEntry( $type, $subtype, User $user, $ns, $title,
- $comment = null, $parameters = null ) {
-
- $logEntry = new ManualLogEntry( $type, $subtype );
+ $comment = null, $parameters = null
+ ) {
+ $logEntry = new ManualLogEntry( $type, $subtype );
$logEntry->setPerformer( $user );
$logEntry->setTarget( Title::newFromText( $title, $ns ) );
- if ( $comment !== null ) {
+ if ( $comment !== null ) {
$logEntry->setComment( $comment );
}
- if ( $parameters !== null ) {
+ if ( $parameters !== null ) {
$logEntry->setParameters( $parameters );
}
- return $logEntry->insert();
+ return $logEntry->insert();
}
function addDBData() {
$this->logId3 = $this->addLogEntry( 'move', 'delete',
$user2, NS_MAIN, "PageA", "SomeOtherComment",
- array( 'key1' => 1, 3 => 'value3' ) );
+ array( 'key1' => 1, 3 => 'value3' ) );
$this->assertGreaterThan( 0, $this->logId3 );
} catch ( Exception $e ) {
* @param $parameters array: (optional) unserialized data accompanying the log entry
*/
private function assertLogItem( $id, $user_name, $user_id, $comment, $type,
- $subtype, $title, $parameters = array() ) {
+ $subtype, $title, $parameters = array()
+ ) {
$this->assertNodeStart( "logitem" );
$this->skipWhitespace();
$this->skipWhitespace();
}
- function testPlain () {
+ function testPlain() {
global $wgContLang;
// Preparing the dump
$fname = $this->getNewTempFile();
- $dumper = new BackupDumper( array ( "--output=file:" . $fname ) );
+ $dumper = new BackupDumper( array( "--output=file:" . $fname ) );
$dumper->startId = $this->logId1;
$dumper->endId = $this->logId3 + 1;
$dumper->reporting = false;
// Preparing the dump
$fname = $this->getNewTempFile();
- $dumper = new BackupDumper( array ( "--output=gzip:" . $fname,
- "--reporting=2" ) );
+ $dumper = new BackupDumper( array( "--output=gzip:" . $fname,
+ "--reporting=2" ) );
$dumper->startId = $this->logId1;
$dumper->endId = $this->logId3 + 1;
$dumper->setDb( $this->db );
$this->setMwGlobals( array(
'wgLanguageCode' => 'en',
'wgContLang' => Language::factory( 'en' ),
- ));
+ ) );
$this->tablesUsed[] = 'page';
$this->tablesUsed[] = 'revision';
if ( $this->namespace === $this->talk_namespace ) {
//@todo: work around this.
throw new MWException( "The default wikitext namespace is the talk namespace. "
- . " We can't currently deal with that.");
+ . " We can't currently deal with that." );
}
$this->pageTitle1 = Title::newFromText( 'BackupDumperTestP1', $this->namespace );
}
- function testFullTextPlain () {
+ function testFullTextPlain() {
// Preparing the dump
$fname = $this->getNewTempFile();
- $dumper = new BackupDumper( array ( "--output=file:" . $fname ) );
+ $dumper = new BackupDumper( array( "--output=file:" . $fname ) );
$dumper->startId = $this->pageId1;
$dumper->endId = $this->pageId4 + 1;
$dumper->reporting = false;
$this->assertDumpEnd();
}
- function testFullStubPlain () {
+ function testFullStubPlain() {
// Preparing the dump
$fname = $this->getNewTempFile();
- $dumper = new BackupDumper( array ( "--output=file:" . $fname ) );
+ $dumper = new BackupDumper( array( "--output=file:" . $fname ) );
$dumper->startId = $this->pageId1;
$dumper->endId = $this->pageId4 + 1;
$dumper->reporting = false;
$this->assertDumpEnd();
}
- function testCurrentStubPlain () {
+ function testCurrentStubPlain() {
// Preparing the dump
$fname = $this->getNewTempFile();
- $dumper = new BackupDumper( array ( "--output=file:" . $fname ) );
+ $dumper = new BackupDumper( array( "--output=file:" . $fname ) );
$dumper->startId = $this->pageId1;
$dumper->endId = $this->pageId4 + 1;
$dumper->reporting = false;
$this->assertDumpEnd();
}
- function testCurrentStubGzip () {
+ function testCurrentStubGzip() {
$this->checkHasGzip();
// Preparing the dump
$fname = $this->getNewTempFile();
- $dumper = new BackupDumper( array ( "--output=gzip:" . $fname ) );
+ $dumper = new BackupDumper( array( "--output=gzip:" . $fname ) );
$dumper->startId = $this->pageId1;
$dumper->endId = $this->pageId4 + 1;
$dumper->reporting = false;
}
-
- function testXmlDumpsBackupUseCase () {
+ function testXmlDumpsBackupUseCase() {
// xmldumps-backup typically performs a single dump that that writes
// out three files
// * gzipped stubs of everything (meta-history)
$fnameMetaCurrent = $this->getNewTempFile();
$fnameArticles = $this->getNewTempFile();
- $dumper = new BackupDumper( array ( "--output=gzip:" . $fnameMetaHistory,
- "--output=gzip:" . $fnameMetaCurrent, "--filter=latest",
- "--output=gzip:" . $fnameArticles, "--filter=latest",
- "--filter=notalk", "--filter=namespace:!NS_USER",
- "--reporting=1000" ) );
+ $dumper = new BackupDumper( array( "--output=gzip:" . $fnameMetaHistory,
+ "--output=gzip:" . $fnameMetaCurrent, "--filter=latest",
+ "--output=gzip:" . $fnameArticles, "--filter=latest",
+ "--filter=notalk", "--filter=namespace:!NS_USER",
+ "--reporting=1000" ) );
$dumper->startId = $this->pageId1;
$dumper->endId = $this->pageId4 + 1;
$dumper->setDb( $this->db );
}
-
}
private $mockInvocations = array( 'getStdin' => 0 );
-
/**
* Data for the fake stdin
*
"Tried to get stdin with non null parameter" );
}
- if ( ! $this->mockSetUp ) {
+ if ( !$this->mockSetUp ) {
throw new PHPUnit_Framework_ExpectationFailedException(
"Tried to get stdin before setting up rerouting" );
}
}
-
// Instead of the following functions, a data provider would be great.
// However, as data providers are evaluated /before/ addDBData, a data
// provider would not know the required ids.
function testExistingSeveral() {
$this->assertFilter( "$this->textId1\n$this->textId5\n"
- . "$this->textId3\n$this->textId3",
+ . "$this->textId3\n$this->textId3",
implode( "", array(
- $this->textId1 . "\n23\nFetchTextTestPage1Text1",
- $this->textId5 . "\n44\nFetchTextTestPage2Text4 "
+ $this->textId1 . "\n23\nFetchTextTestPage1Text1",
+ $this->textId5 . "\n44\nFetchTextTestPage2Text4 "
. "some additional Text",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2"
- ) ) );
+ $this->textId3 . "\n23\nFetchTextTestPage2Text2",
+ $this->textId3 . "\n23\nFetchTextTestPage2Text2"
+ ) ) );
}
function testEmpty() {
function testMix() {
$this->assertFilter( "ab\n" . $this->textId4 . ".5cd\n\nefg\n" . $this->textId2
- . "\n" . $this->textId3,
+ . "\n" . $this->textId3,
implode( "", array(
- "0\n-1\n",
- $this->textId4 . "\n23\nFetchTextTestPage2Text3",
- "0\n-1\n",
- "0\n-1\n",
- $this->textId2 . "\n23\nFetchTextTestPage2Text1",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2"
- ) ) );
+ "0\n-1\n",
+ $this->textId4 . "\n23\nFetchTextTestPage2Text3",
+ "0\n-1\n",
+ "0\n-1\n",
+ $this->textId2 . "\n23\nFetchTextTestPage2Text1",
+ $this->textId3 . "\n23\nFetchTextTestPage2Text2"
+ ) ) );
}
}
function __construct() {
parent::__construct();
- $this->addOption( 'with-phpunitdir'
- , 'Directory to include PHPUnit from, for example when using a git fetchout from upstream. Path will be prepended to PHP `include_path`.'
- , false # not required
- , true # need arg
+ $this->addOption( 'with-phpunitdir',
+ 'Directory to include PHPUnit from, for example when using a git fetchout from upstream. Path will be prepended to PHP `include_path`.',
+ false, # not required
+ true # need arg
);
}
// Assume UTC for testing purposes
$wgLocaltimezone = 'UTC';
- $wgLocalisationCacheConf['storeClass'] = 'LCStore_Null';
+ $wgLocalisationCacheConf['storeClass'] = 'LCStore_Null';
}
public function execute() {
global $IP;
# Make sure we have --configuration or PHPUnit might complain
- if( !in_array( '--configuration', $_SERVER['argv'] ) ) {
+ if ( !in_array( '--configuration', $_SERVER['argv'] ) ) {
//Hack to eliminate the need to use the Makefile (which sucks ATM)
array_splice( $_SERVER['argv'], 1, 0,
array( '--configuration', $IP . '/tests/phpunit/suite.xml' ) );
}
# --with-phpunitdir let us override the default PHPUnit version
- if( $phpunitDir = $this->getOption( 'with-phpunitdir' ) ) {
+ if ( $phpunitDir = $this->getOption( 'with-phpunitdir' ) ) {
# Sanity checks
- if( !is_dir($phpunitDir) ) {
+ if ( !is_dir( $phpunitDir ) ) {
$this->error( "--with-phpunitdir should be set to an existing directory", 1 );
}
- if( !is_readable( $phpunitDir."/PHPUnit/Runner/Version.php" ) ) {
+ if ( !is_readable( $phpunitDir . "/PHPUnit/Runner/Version.php" ) ) {
$this->error( "No usable PHPUnit installation in $phpunitDir.\nAborting.\n", 1 );
}
# Cleanup $args array so the option and its value do not
# pollute PHPUnit
$key = array_search( '--with-phpunitdir', $_SERVER['argv'] );
- unset( $_SERVER['argv'][$key] ); // the option
- unset( $_SERVER['argv'][$key+1] ); // its value
+ unset( $_SERVER['argv'][$key] ); // the option
+ unset( $_SERVER['argv'][$key + 1] ); // its value
$_SERVER['argv'] = array_values( $_SERVER['argv'] );
}
require_once( 'PHPUnit/Runner/Version.php' );
-if( PHPUnit_Runner_Version::id() !== '@package_version@'
- && version_compare( PHPUnit_Runner_Version::id(), '3.6.7', '<' ) ) {
+if ( PHPUnit_Runner_Version::id() !== '@package_version@'
+ && version_compare( PHPUnit_Runner_Version::id(), '3.6.7', '<' )
+) {
die( 'PHPUnit 3.6.7 or later required, you have ' . PHPUnit_Runner_Version::id() . ".\n" );
}
require_once( 'PHPUnit/Autoload.php' );
foreach ( $rl->getModuleNames() as $moduleName ) {
$module = $rl->getModule( $moduleName );
- if ( ! $module instanceof ResourceLoaderFileModule ) {
+ if ( !$module instanceof ResourceLoaderFileModule ) {
continue;
}
'helppage',
);
- foreach( $URL_messages as $m ) {
- $titleName = MessageCache::singleton()->get($m);
+ foreach ( $URL_messages as $m ) {
+ $titleName = MessageCache::singleton()->get( $m );
$title = Title::newFromText( $titleName );
$this->messages[$m]['href'] = $title->getLocalURL();
}
$this->skin = new SkinTemplate();
$this->skin->getContext()->setLanguage( Language::factory( 'en' ) );
}
+
protected function tearDown() {
parent::tearDown();
$this->skin = null;
function testSidebarWithOnlyTwoTitles() {
$this->assertSideBar(
- array(
- 'Title1' => array(),
- 'Title2' => array(),
- ),
-'* Title1
+ array(
+ 'Title1' => array(),
+ 'Title2' => array(),
+ ),
+ '* Title1
* Title2
'
);
function testExpandMessages() {
$this->assertSidebar(
- array( 'Title' => array(
- array(
- 'text' => 'Help',
- 'href' => $this->messages['helppage']['href'],
- 'id' => 'n-help',
- 'active' => null
- )
- )),
-'* Title
+ array( 'Title' => array(
+ array(
+ 'text' => 'Help',
+ 'href' => $this->messages['helppage']['href'],
+ 'id' => 'n-help',
+ 'active' => null
+ )
+ ) ),
+ '* Title
** helppage|help
'
);
function testExternalUrlsRequireADescription() {
$this->assertSidebar(
- array( 'Title' => array(
- # ** http://www.mediawiki.org/| Home
- array(
- 'text' => 'Home',
- 'href' => 'http://www.mediawiki.org/',
- 'id' => 'n-Home',
- 'active' => null,
- 'rel' => 'nofollow',
- ),
- # ** http://valid.no.desc.org/
- # ... skipped since it is missing a pipe with a description
- )),
-'* Title
+ array( 'Title' => array(
+ # ** http://www.mediawiki.org/| Home
+ array(
+ 'text' => 'Home',
+ 'href' => 'http://www.mediawiki.org/',
+ 'id' => 'n-Home',
+ 'active' => null,
+ 'rel' => 'nofollow',
+ ),
+ # ** http://valid.no.desc.org/
+ # ... skipped since it is missing a pipe with a description
+ ) ),
+ '* Title
** http://www.mediawiki.org/| Home
** http://valid.no.desc.org/
'
-
);
}
+
/**
* bug 33321 - Make sure there's a | after transforming.
* @group Database
*/
function testTrickyPipe() {
$this->assertSidebar(
- array( 'Title' => array(
- # The first 2 are skipped
- # Doesn't really test the url properly
- # because it will vary with $wgArticlePath et al.
- # ** Baz|Fred
- array(
- 'text' => 'Fred',
- 'href' => Title::newFromText( 'Baz' )->getLocalUrl(),
- 'id' => 'n-Fred',
- 'active' => null,
- ),
- array(
- 'text' => 'title-to-display',
- 'href' => Title::newFromText( 'page-to-go-to' )->getLocalUrl(),
- 'id' => 'n-title-to-display',
- 'active' => null,
- ),
- )),
-'* Title
+ array( 'Title' => array(
+ # The first 2 are skipped
+ # Doesn't really test the url properly
+ # because it will vary with $wgArticlePath et al.
+ # ** Baz|Fred
+ array(
+ 'text' => 'Fred',
+ 'href' => Title::newFromText( 'Baz' )->getLocalUrl(),
+ 'id' => 'n-Fred',
+ 'active' => null,
+ ),
+ array(
+ 'text' => 'title-to-display',
+ 'href' => Title::newFromText( 'page-to-go-to' )->getLocalUrl(),
+ 'id' => 'n-title-to-display',
+ 'active' => null,
+ ),
+ ) ),
+ '* Title
** {{PAGENAME|Foo}}
** Bar
** Baz|Fred
** {{PLURAL:1|page-to-go-to{{int:pipe-separator/en}}title-to-display|branch not taken}}
'
);
-
}
#### Attributes for external links ##########################
- private function getAttribs( ) {
+ private function getAttribs() {
# Sidebar text we will use everytime
$text = '* Title
** http://www.mediawiki.org/| Home';
-<?php
+<?php
/**
* This test suite runs unit tests registered by extensions.
* See http://www.mediawiki.org/wiki/Manual:Hooks/UnitTestsList for details of how to register your tests.
protected function setUp() {
global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc,
- $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache,
- $wgNamespaceAliases, $wgNamespaceProtection, $parserMemc;
+ $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache,
+ $wgNamespaceAliases, $wgNamespaceProtection, $parserMemc;
$tmpGlobals = array();
$tmpGlobals['wgStylePath'] = '/skins';
$tmpGlobals['wgThumbnailScriptPath'] = false;
$tmpGlobals['wgLocalFileRepo'] = array(
- 'class' => 'LocalRepo',
- 'name' => 'local',
- 'url' => 'http://example.com/images',
- 'hashLevels' => 2,
+ 'class' => 'LocalRepo',
+ 'name' => 'local',
+ 'url' => 'http://example.com/images',
+ 'hashLevels' => 2,
'transformVia404' => false,
- 'backend' => new FSFileBackend( array(
- 'name' => 'local-backend',
+ 'backend' => new FSFileBackend( array(
+ 'name' => 'local-backend',
'lockManager' => 'fsLockManager',
'containerPaths' => array(
- 'local-public' => wfTempDir() . '/test-repo/public',
- 'local-thumb' => wfTempDir() . '/test-repo/thumb',
- 'local-temp' => wfTempDir() . '/test-repo/temp',
+ 'local-public' => wfTempDir() . '/test-repo/public',
+ 'local-thumb' => wfTempDir() . '/test-repo/thumb',
+ 'local-temp' => wfTempDir() . '/test-repo/temp',
'local-deleted' => wfTempDir() . '/test-repo/delete',
)
) ),
$wgRequest = $context->getRequest();
if ( $wgStyleDirectory === false ) {
- $wgStyleDirectory = "$IP/skins";
+ $wgStyleDirectory = "$IP/skins";
}
RepoGroup::destroySingleton();
// delete the files first, then the dirs.
self::deleteFiles(
- array (
+ array(
"$dir/3/3a/Foobar.jpg",
"$dir/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg",
"$dir/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg",
);
self::deleteDirs(
- array (
+ array(
"$dir/3/3a",
"$dir/3",
"$dir/thumb/6/65",
);
public function __construct() {
- parent::__construct();
- $this->mDescription = 'Create a specification for message parsing ini JSON format';
- // add any other options here
+ parent::__construct();
+ $this->mDescription = 'Create a specification for message parsing ini JSON format';
+ // add any other options here
}
public function execute() {
$tests = array();
foreach ( array( 'en', 'fr', 'ar', 'jp', 'zh' ) as $languageCode ) {
foreach ( self::$keyToTestArgs as $key => $testArgs ) {
- foreach ($testArgs as $args) {
+ foreach ( $testArgs as $args ) {
// Get the raw message, without any transformations.
$template = wfMessage( $key )->inLanguage( $languageCode )->plain();
$output =
"// This file stores the output from the PHP parser for various messages, arguments,\n"
- . "// languages, and parser modes. Intended for use by a unit test framework by looping\n"
- . "// through the object and comparing its parser return value with the 'result' property.\n"
- . '// Last generated with ' . basename( __FILE__ ) . ' at ' . gmdate( 'r' ) . "\n"
- // This file will contain unquoted JSON strings as javascript native object literals,
- // flip the quotemark convention for this file.
- . "/*jshint quotmark: double */\n"
- . "\n"
- . 'mediaWiki.libs.phpParserData = ' . FormatJson::encode( $phpParserData, true ) . ";\n";
+ . "// languages, and parser modes. Intended for use by a unit test framework by looping\n"
+ . "// through the object and comparing its parser return value with the 'result' property.\n"
+ . '// Last generated with ' . basename( __FILE__ ) . ' at ' . gmdate( 'r' ) . "\n"
+ // This file will contain unquoted JSON strings as javascript native object literals,
+ // flip the quotemark convention for this file.
+ . "/*jshint quotmark: double */\n"
+ . "\n"
+ . 'mediaWiki.libs.phpParserData = ' . FormatJson::encode( $phpParserData, true ) . ";\n";
$fp = file_put_contents( $dataSpecFile, $output );
if ( $fp === false ) {
QUnit.start();
-QUnit.assert.ok( true, 'Successfully loaded!');
+QUnit.assert.ok( true, 'Successfully loaded!' );
sleep( $wait );
-$css = "
+$css = "
/**
- * Generated " . gmdate( 'r' ) . ".
+ * Generated " . gmdate( 'r' ) . ".
* Waited {$wait}s.
*/
/**
* CompletenessTest
*/
- // Adds toggle checkbox to header
+ // Adds toggle checkbox to header
QUnit.config.urlConfig.push( {
id: 'completenesstest',
label: 'Run CompletenessTest',
/**
* Test environment recommended for all QUnit test modules
*/
- // Whether to log environment changes to the console
+ // Whether to log environment changes to the console
QUnit.config.urlConfig.push( 'mwlogenv' );
/**
liveMessages = mw.messages.values;
function freshConfigCopy( custom ) {
- // "deep=true" is important here.
- // Otherwise we just create a new object with values referring to live config.
- // e.g. mw.config.set( 'wgFileExtensions', [] ) would not effect liveConfig,
- // but mw.config.get( 'wgFileExtensions' ).push( 'png' ) would as the array
- // was passed by reference in $.extend's loop.
- return $.extend( /*deep=*/true, {}, liveConfig, custom );
+ // Tests should mock all factors that directly influence the tested code.
+ // For backwards compatibility though we set mw.config to a copy of the live config
+ // and extend it with the (optionally) given custom settings for this test
+ // (instead of starting blank with only the given custmo settings).
+ // This is a shallow copy, so we don't end up with settings taking an array value
+ // extended with the custom settings - setting a config property means you override it,
+ // not extend it.
+ return $.extend( {}, liveConfig, custom );
}
function freshMessagesCopy( custom ) {
- return $.extend( /*deep=*/true, {}, liveMessages, custom );
+ return $.extend( /*deep=*/true, {}, liveMessages, custom );
}
log = QUnit.urlParams.mwlogenv ? mw.log : function () {};
// Whether this one fails or not, forwards it to
// the 'done' (resolve) callback of the alternative promise.
arg.always( alt.resolve );
- });
+ } );
return $.when.apply( $, altPromises );
};
* initializations defined above in this file.
*/
envExecCount = 0;
- QUnit.module( 'mediawiki.tests.qunit.testrunner', QUnit.newMwEnvironment({
+ QUnit.module( 'mediawiki.tests.qunit.testrunner', QUnit.newMwEnvironment( {
setup: function () {
envExecCount += 1;
this.mwHtmlLive = mw.html;
messages: {
testMsg: 'Foo.'
}
- }) );
+ } ) );
QUnit.test( 'Setup', 3, function ( assert ) {
assert.equal( mw.html.escape( 'foo' ), 'mocked-1', 'extra setup() callback was ran.' );
mw.config.set( 'testVar', 'bar' );
mw.messages.set( 'testMsg', 'Bar.' );
- });
+ } );
QUnit.test( 'Teardown', 3, function ( assert ) {
assert.equal( mw.html.escape( 'foo' ), 'mocked-2', 'extra setup() callback was re-ran.' );
assert.equal( mw.config.get( 'testVar' ), 'foo', 'config object restored and re-applied after test()' );
assert.equal( mw.messages.get( 'testMsg' ), 'Foo.', 'messages object restored and re-applied after test()' );
- });
+ } );
QUnit.module( 'mediawiki.tests.qunit.testrunner-after', QUnit.newMwEnvironment() );
assert.equal( mw.html.escape( '<' ), '<', 'extra teardown() callback was ran.' );
assert.equal( mw.config.get( 'testVar' ), null, 'config object restored to live in next module()' );
assert.equal( mw.messages.get( 'testMsg' ), null, 'messages object restored to live in next module()' );
- });
+ } );
}( jQuery, mediaWiki, QUnit ) );
} else {
assert.gt( $span.width(), $span.parent().width(), 'Fit is maximal (adding two characters makes it not fit any more)' );
}
- });
+ } );
}( jQuery ) );
QUnit.module( 'jquery.byteLength', QUnit.newMwEnvironment() );
QUnit.test( 'Simple text', 5, function ( assert ) {
- var azLc = 'abcdefghijklmnopqrstuvwxyz',
+ var azLc = 'abcdefghijklmnopqrstuvwxyz',
azUc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
num = '0123456789',
x = '*',
// Basic sendkey-implementation
function addChars( $input, charstr ) {
var c, len;
+
function x( $input, i ) {
// Add character to the value
return $input.val() + charstr.charAt( i );
}
+
for ( c = 0, len = charstr.length; c < len; c += 1 ) {
$input
.val( x( $input, c ) )
* The limit should be less than 20 (the sample data's length)
*/
function byteLimitTest( options ) {
- var opt = $.extend({
+ var opt = $.extend( {
description: '',
$input: null,
sample: '',
hasLimit: false,
expected: '',
limit: null
- }, options);
+ }, options );
QUnit.asyncTest( opt.description, opt.hasLimit ? 3 : 2, function ( assert ) {
- setTimeout( function () {
- var rawVal, fn, effectiveVal;
-
- opt.$input.appendTo( '#qunit-fixture' );
-
- // Simulate pressing keys for each of the sample characters
- addChars( opt.$input, opt.sample );
-
- rawVal = opt.$input.val();
- fn = opt.$input.data( 'byteLimit.callback' );
- effectiveVal = fn ? fn( rawVal ) : rawVal;
-
- if ( opt.hasLimit ) {
- assert.ltOrEq(
- $.byteLength( effectiveVal ),
- opt.limit,
- 'Prevent keypresses after byteLimit was reached, length never exceeded the limit'
- );
- assert.equal(
- $.byteLength( rawVal ),
- $.byteLength( opt.expected ),
- 'Not preventing keypresses too early, length has reached the expected length'
- );
- assert.equal( rawVal, opt.expected, 'New value matches the expected string' );
-
- } else {
- assert.equal(
- $.byteLength( effectiveVal ),
- $.byteLength( opt.expected ),
- 'Unlimited scenarios are not affected, expected length reached'
- );
- assert.equal( rawVal, opt.expected, 'New value matches the expected string' );
- }
- QUnit.start();
- }, 10 );
+ setTimeout( function () {
+ var rawVal, fn, effectiveVal;
+
+ opt.$input.appendTo( '#qunit-fixture' );
+
+ // Simulate pressing keys for each of the sample characters
+ addChars( opt.$input, opt.sample );
+
+ rawVal = opt.$input.val();
+ fn = opt.$input.data( 'byteLimit.callback' );
+ effectiveVal = fn ? fn( rawVal ) : rawVal;
+
+ if ( opt.hasLimit ) {
+ assert.ltOrEq(
+ $.byteLength( effectiveVal ),
+ opt.limit,
+ 'Prevent keypresses after byteLimit was reached, length never exceeded the limit'
+ );
+ assert.equal(
+ $.byteLength( rawVal ),
+ $.byteLength( opt.expected ),
+ 'Not preventing keypresses too early, length has reached the expected length'
+ );
+ assert.equal( rawVal, opt.expected, 'New value matches the expected string' );
+
+ } else {
+ assert.equal(
+ $.byteLength( effectiveVal ),
+ $.byteLength( opt.expected ),
+ 'Unlimited scenarios are not affected, expected length reached'
+ );
+ assert.equal( rawVal, opt.expected, 'New value matches the expected string' );
+ }
+ QUnit.start();
+ }, 10 );
} );
}
- byteLimitTest({
+ byteLimitTest( {
description: 'Plain text input',
$input: $( '<input type="text"/>' ),
sample: simpleSample,
hasLimit: false,
expected: simpleSample
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Plain text input. Calling byteLimit with no parameters and no maxlength attribute (bug 36310)',
$input: $( '<input type="text"/>' )
.byteLimit(),
sample: simpleSample,
hasLimit: false,
expected: simpleSample
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Limit using the maxlength attribute',
$input: $( '<input type="text"/>' )
.attr( 'maxlength', '10' )
hasLimit: true,
limit: 10,
expected: '1234567890'
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Limit using a custom value',
$input: $( '<input type="text"/>' )
.byteLimit( 10 ),
hasLimit: true,
limit: 10,
expected: '1234567890'
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Limit using a custom value, overriding maxlength attribute',
$input: $( '<input type="text"/>' )
.attr( 'maxlength', '10' )
hasLimit: true,
limit: 15,
expected: '123456789012345'
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Limit using a custom value (multibyte)',
$input: $( '<input type="text"/>' )
.byteLimit( 14 ),
hasLimit: true,
limit: 14,
expected: '1234567890' + U_20AC + '1'
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Limit using a custom value (multibyte) overlapping a byte',
$input: $( '<input type="text"/>' )
.byteLimit( 12 ),
hasLimit: true,
limit: 12,
expected: '1234567890' + '12'
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Pass the limit and a callback as input filter',
$input: $( '<input type="text"/>' )
.byteLimit( 6, function ( val ) {
hasLimit: true,
limit: 6, // 'Sample' length
expected: 'User:Sample'
- });
+ } );
- byteLimitTest({
+ byteLimitTest( {
description: 'Limit using the maxlength attribute and pass a callback as input filter',
$input: $( '<input type="text"/>' )
.attr( 'maxlength', '6' )
hasLimit: true,
limit: 6, // 'Sample' length
expected: 'User:Sample'
- });
+ } );
QUnit.test( 'Confirm properties and attributes set', 4, function ( assert ) {
var $el, $elA, $elB;
assert.strictEqual( $el.length, 2, 'Verify that there are no other elements clashing with this test suite' );
$el.byteLimit();
- });
+ } );
QUnit.test( 'Trim from insertion when limit exceeded', 2, function ( assert ) {
var $el;
.val( 'azbc' ).trigger( 'change' );
assert.strictEqual( $el.val(), 'abc', 'Trim from the insertion point (at 1), not the end' );
- });
-
+ } );
}( jQuery, mediaWiki ) );
};
$.each( uas, function () {
uacount++;
- });
+ } );
return uas;
}() );
QUnit.test( 'profile userAgent support', uacount, function ( assert ) {
// Generate a client profile object and compare recursively
- var uaTest = function( rawUserAgent, data ) {
+ var uaTest = function ( rawUserAgent, data ) {
var ret = $.client.profile( {
userAgent: rawUserAgent,
platform: data.platform
QUnit.test( 'profile return validation for current user agent', 7, function ( assert ) {
var p = $.client.profile();
+
function unknownOrType( val, type, summary ) {
assert.ok( typeof val === type || val === 'unknown', summary );
}
unknownOrType( p.version, 'string', 'p.version is a string (or "unknown")' );
unknownOrType( p.versionBase, 'string', 'p.versionBase is a string (or "unknown")' );
assert.equal( typeof p.versionNumber, 'number', 'p.versionNumber is a number' );
- });
+ } );
// Example from WikiEditor
// Make sure to use raw numbers, a string like "7.0" would fail on a
assert.equal( typeof testMatch, 'boolean', 'test returns a boolean value' );
- });
+ } );
QUnit.test( 'User-agent matches against WikiEditor\'s compatibility map', uacount * 2, function ( assert ) {
- var $body = $( 'body' ),
+ var $body = $( 'body' ),
bodyClasses = $body.attr( 'class' );
// Loop through and run tests
$body.removeClass( dir );
assert.equal( testMatch, data.wikiEditor[dir], 'testing comparison based on ' + dir + ', ' + agent );
- });
- });
+ } );
+ } );
// Restore body classes
$body.attr( 'class', bodyClasses );
- });
+ } );
}( jQuery ) );
assert.deepEqual( $.colorUtil.getRGB( 'lightGreen' ), [144, 238, 144], 'Color names (lightGreen)' );
assert.deepEqual( $.colorUtil.getRGB( 'transparent' ), [255, 255, 255], 'Color names (transparent)' );
assert.strictEqual( $.colorUtil.getRGB( 'mediaWiki' ), undefined, 'Inexisting color name' );
- });
+ } );
QUnit.test( 'rgbToHsl', 1, function ( assert ) {
var hsl, ret;
function dualDecimals( a ) {
return Math.round( a * 100 ) / 100;
}
+
// Re-create the rgbToHsl return array items, limited to two decimals.
hsl = $.colorUtil.rgbToHsl( 144, 238, 144 );
ret = [ dualDecimals( hsl[0] ), dualDecimals( hsl[1] ), dualDecimals( hsl[2] ) ];
assert.deepEqual( ret, [0.33, 0.73, 0.75], 'rgb(144, 238, 144): hsl(0.33, 0.73, 0.75)' );
- });
+ } );
QUnit.test( 'hslToRgb', 1, function ( assert ) {
var rgb, ret;
rgb = $.colorUtil.hslToRgb( 0.3, 0.7, 0.8 );
// Re-create the hslToRgb return array items, rounded to whole numbers.
- ret = [ Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2]) ];
+ ret = [ Math.round( rgb[0] ), Math.round( rgb[1] ), Math.round( rgb[2] ) ];
- assert.deepEqual( ret ,[183, 240, 168], 'hsl(0.3, 0.7, 0.8): rgb(183, 240, 168)' );
- });
+ assert.deepEqual( ret, [183, 240, 168], 'hsl(0.3, 0.7, 0.8): rgb(183, 240, 168)' );
+ } );
QUnit.test( 'getColorBrightness', 2, function ( assert ) {
var a, b;
b = $.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
assert.equal( b, 'rgb(118,29,29)', 'Start with rgb string "rgb(200,50,50)", darken 20%' );
- });
+ } );
}( jQuery ) );
( function ( $ ) {
- QUnit.asyncTest('jquery.delayedBind with data option', 2, function ( assert ) {
- var $fixture = $('<div>').appendTo('#qunit-fixture'),
+ QUnit.asyncTest( 'jquery.delayedBind with data option', 2, function ( assert ) {
+ var $fixture = $( '<div>' ).appendTo( '#qunit-fixture' ),
data = {
magic: 'beeswax'
},
delay = 50;
- $fixture.delayedBind(delay, 'testevent', data, function ( e ) {
- assert.ok( true, 'testevent fired');
- assert.ok( e.data === data, 'data is passed through delayedBind');
+ $fixture.delayedBind( delay, 'testevent', data, function ( e ) {
+ assert.ok( true, 'testevent fired' );
+ assert.ok( e.data === data, 'data is passed through delayedBind' );
QUnit.start();
- });
+ } );
// We'll trigger it thrice, but it should only happen once.
$fixture.trigger( 'testevent', {} );
$fixture.trigger( 'testevent', {} );
$fixture.trigger( 'testevent', {} );
$fixture.trigger( 'testevent', {} );
- });
+ } );
- QUnit.asyncTest('jquery.delayedBind without data option', 1, function ( assert ) {
- var $fixture = $('<div>').appendTo('#qunit-fixture'),
+ QUnit.asyncTest( 'jquery.delayedBind without data option', 1, function ( assert ) {
+ var $fixture = $( '<div>' ).appendTo( '#qunit-fixture' ),
delay = 50;
- $fixture.delayedBind(delay, 'testevent', function () {
- assert.ok(true, 'testevent fired');
+ $fixture.delayedBind( delay, 'testevent', function () {
+ assert.ok( true, 'testevent fired' );
QUnit.start();
- });
+ } );
// We'll trigger it thrice, but it should only happen once.
$fixture.trigger( 'testevent', {} );
$fixture.trigger( 'testevent', {} );
$fixture.trigger( 'testevent', {} );
$fixture.trigger( 'testevent', {} );
- });
+ } );
}( jQuery ) );
QUnit.module( 'jquery.getAttrs', QUnit.newMwEnvironment() );
QUnit.test( 'Check', 1, function ( assert ) {
- var attrs = {
+ var attrs = {
foo: 'bar',
'class': 'lorem'
},
( function ( $ ) {
QUnit.module( 'jquery.hidpi', QUnit.newMwEnvironment() );
- QUnit.test( 'devicePixelRatio', function ( assert ) {
+ QUnit.test( 'devicePixelRatio', 1, function ( assert ) {
var devicePixelRatio = $.devicePixelRatio();
assert.equal( typeof devicePixelRatio, 'number', '$.devicePixelRatio() returns a number' );
- });
+ } );
- QUnit.test( 'matchSrcSet', function ( assert ) {
+ QUnit.test( 'matchSrcSet', 6, function ( assert ) {
var srcset = 'onefive.png 1.5x, two.png 2x';
// Nice exact matches
assert.equal( $.matchSrcSet( 1.25, srcset ), null, '1.25 gives no match' );
assert.equal( $.matchSrcSet( 1.75, srcset ), 'onefive.png', '1.75 gives match to 1.5' );
assert.equal( $.matchSrcSet( 2.25, srcset ), 'two.png', '2.25 gives match to 2' );
- });
+ } );
}( jQuery ) );
assert.strictEqual( $lc.length, 1, 'link is created' );
assert.strictEqual( $lc.text(), 'link', 'the link text got added' );
} );
-}( jQuery, mediaWiki ) ) ;
+}( jQuery, mediaWiki ) );
( function ( $ ) {
QUnit.module( 'jquery.mwExtension', QUnit.newMwEnvironment() );
- QUnit.test( 'String functions', function ( assert ) {
-
+ QUnit.test( 'String functions', 7, function ( assert ) {
assert.equal( $.trimLeft( ' foo bar ' ), 'foo bar ', 'trimLeft' );
assert.equal( $.trimRight( ' foo bar ' ), ' foo bar', 'trimRight' );
assert.equal( $.ucFirst( 'foo' ), 'Foo', 'ucFirst' );
assert.equal( $.escapeRE( '<!-- ([{+mW+}]) $^|?>' ),
- '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?>', 'escapeRE - Escape specials' );
+ '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?>', 'escapeRE - Escape specials' );
assert.equal( $.escapeRE( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ),
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'escapeRE - Leave uppercase alone' );
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'escapeRE - Leave uppercase alone' );
assert.equal( $.escapeRE( 'abcdefghijklmnopqrstuvwxyz' ),
- 'abcdefghijklmnopqrstuvwxyz', 'escapeRE - Leave lowercase alone' );
+ 'abcdefghijklmnopqrstuvwxyz', 'escapeRE - Leave lowercase alone' );
assert.equal( $.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
- });
-
- QUnit.test( 'Is functions', function ( assert ) {
+ } );
+ QUnit.test( 'Is functions', 15, function ( assert ) {
assert.strictEqual( $.isDomElement( document.getElementById( 'qunit-header' ) ), true,
- 'isDomElement: #qunit-header Node' );
+ 'isDomElement: #qunit-header Node' );
assert.strictEqual( $.isDomElement( document.getElementById( 'random-name' ) ), false,
- 'isDomElement: #random-name (null)' );
+ 'isDomElement: #random-name (null)' );
assert.strictEqual( $.isDomElement( document.getElementsByTagName( 'div' ) ), false,
- 'isDomElement: getElementsByTagName Array' );
+ 'isDomElement: getElementsByTagName Array' );
assert.strictEqual( $.isDomElement( document.getElementsByTagName( 'div' )[0] ), true,
- 'isDomElement: getElementsByTagName(..)[0] Node' );
+ 'isDomElement: getElementsByTagName(..)[0] Node' );
assert.strictEqual( $.isDomElement( $( 'div' ) ), false,
- 'isDomElement: jQuery object' );
- assert.strictEqual( $.isDomElement( $( 'div' ).get(0) ), true,
- 'isDomElement: jQuery object > Get node' );
+ 'isDomElement: jQuery object' );
+ assert.strictEqual( $.isDomElement( $( 'div' ).get( 0 ) ), true,
+ 'isDomElement: jQuery object > Get node' );
assert.strictEqual( $.isDomElement( document.createElement( 'div' ) ), true,
- 'isDomElement: createElement' );
+ 'isDomElement: createElement' );
assert.strictEqual( $.isDomElement( { foo: 1 } ), false,
- 'isDomElement: Object' );
+ 'isDomElement: Object' );
- assert.strictEqual( $.isEmpty( 'string' ), false, 'isEmptry: "string"' );
- assert.strictEqual( $.isEmpty( '0' ), true, 'isEmptry: "0"' );
- assert.strictEqual( $.isEmpty( '' ), true, 'isEmptry: ""' );
- assert.strictEqual( $.isEmpty( 1 ), false, 'isEmptry: 1' );
- assert.strictEqual( $.isEmpty( [] ), true, 'isEmptry: []' );
- assert.strictEqual( $.isEmpty( {} ), true, 'isEmptry: {}' );
+ assert.strictEqual( $.isEmpty( 'string' ), false, 'isEmpty: "string"' );
+ assert.strictEqual( $.isEmpty( '0' ), true, 'isEmpty: "0"' );
+ assert.strictEqual( $.isEmpty( '' ), true, 'isEmpty: ""' );
+ assert.strictEqual( $.isEmpty( 1 ), false, 'isEmpty: 1' );
+ assert.strictEqual( $.isEmpty( [] ), true, 'isEmpty: []' );
+ assert.strictEqual( $.isEmpty( {} ), true, 'isEmpty: {}' );
// Documented behaviour
- assert.strictEqual( $.isEmpty( { length: 0 } ), true, 'isEmptry: { length: 0 }' );
- });
-
- QUnit.test( 'Comparison functions', function ( assert ) {
+ assert.strictEqual( $.isEmpty( { length: 0 } ), true, 'isEmpty: { length: 0 }' );
+ } );
+ QUnit.test( 'Comparison functions', 5, function ( assert ) {
assert.ok( $.compareArray( [0, 'a', [], [2, 'b'] ], [0, 'a', [], [2, 'b'] ] ),
- 'compareArray: Two deep arrays that are excactly the same' );
+ 'compareArray: Two deep arrays that are excactly the same' );
assert.ok( !$.compareArray( [1], [2] ), 'compareArray: Two different arrays (false)' );
assert.ok( $.compareObject( {}, {} ), 'compareObject: Two empty objects' );
assert.ok( $.compareObject( { foo: 1 }, { foo: 1 } ), 'compareObject: Two the same objects' );
assert.ok( !$.compareObject( { bar: true }, { baz: false } ),
- 'compareObject: Two different objects (false)' );
- });
+ 'compareObject: Two different objects (false)' );
+ } );
}( jQuery ) );
QUnit.test( 'firstTabIndex', 2, function ( assert ) {
var html, $testA, $testB;
- html =
- '<form>' +
- '<input tabindex="7" />' +
- '<input tabindex="9" />' +
- '<textarea tabindex="2">Foobar</textarea>' +
- '<textarea tabindex="5">Foobar</textarea>' +
- '</form>';
+ html = '<form>' +
+ '<input tabindex="7" />' +
+ '<input tabindex="9" />' +
+ '<textarea tabindex="2">Foobar</textarea>' +
+ '<textarea tabindex="5">Foobar</textarea>' +
+ '</form>';
$testA = $( '<div>' ).html( html ).appendTo( '#qunit-fixture' );
assert.strictEqual( $testA.firstTabIndex(), 2, 'First tabindex should be 2 within this context.' );
$testB = $( '<div>' );
assert.strictEqual( $testB.firstTabIndex(), null, 'Return null if none available.' );
- });
+ } );
QUnit.test( 'lastTabIndex', 2, function ( assert ) {
var html, $testA, $testB;
- html =
- '<form>' +
- '<input tabindex="7" />' +
- '<input tabindex="9" />' +
- '<textarea tabindex="2">Foobar</textarea>' +
- '<textarea tabindex="5">Foobar</textarea>' +
- '</form>';
+ html = '<form>' +
+ '<input tabindex="7" />' +
+ '<input tabindex="9" />' +
+ '<textarea tabindex="2">Foobar</textarea>' +
+ '<textarea tabindex="5">Foobar</textarea>' +
+ '</form>';
$testA = $( '<div>' ).html( html ).appendTo( '#qunit-fixture' );
assert.strictEqual( $testA.lastTabIndex(), 9, 'Last tabindex should be 9 within this context.' );
$testB = $( '<div>' );
assert.strictEqual( $testB.lastTabIndex(), null, 'Return null if none available.' );
- });
+ } );
}( jQuery ) );
wgContentLanguage: 'en'
};
- QUnit.module( 'jquery.tablesorter', QUnit.newMwEnvironment({ config: config }) );
+ QUnit.module( 'jquery.tablesorter', QUnit.newMwEnvironment( { config: config } ) );
/**
* Create an HTML table from an array of row arrays containing text strings.
* @param {String[][]} data
* @return jQuery
*/
- function tableCreate( header, data ) {
+ function tableCreate( header, data ) {
var i,
$table = $( '<table class="sortable"><thead></thead><tbody></tbody></table>' ),
$thead = $table.find( 'thead' ),
$.each( header, function ( i, str ) {
var $th = $( '<th>' );
$th.text( str ).appendTo( $tr );
- });
+ } );
$tr.appendTo( $thead );
for ( i = 0; i < data.length; i++ ) {
$.each( data[i], function ( j, str ) {
var $td = $( '<td>' );
$td.text( str ).appendTo( $tr );
- });
+ } );
$tr.appendTo( $tbody );
}
return $table;
function tableExtract( $table ) {
var data = [];
- $table.find( 'tbody' ).find( 'tr' ).each( function( i, tr ) {
+ $table.find( 'tbody' ).find( 'tr' ).each( function ( i, tr ) {
var row = [];
- $( tr ).find( 'td,th' ).each( function( i, td ) {
+ $( tr ).find( 'td,th' ).each( function ( i, td ) {
row.push( $( td ).text() );
- });
+ } );
data.push( row );
- });
+ } );
return data;
}
// to asynchronous, we'll need a timeout or a callback here.
var extracted = tableExtract( $table );
assert.deepEqual( extracted, expected, msg );
- });
+ } );
}
- function reversed(arr) {
+ function reversed( arr ) {
// Clone array
- var arr2 = arr.slice(0);
+ var arr2 = arr.slice( 0 );
arr2.reverse();
}
// Sample data set using planets named and their radius
- var header = [ 'Planet' , 'Radius (km)'],
+ var header = [ 'Planet' , 'Radius (km)'],
mercury = [ 'Mercury', '2439.7' ],
- venus = [ 'Venus' , '6051.8' ],
- earth = [ 'Earth' , '6371.0' ],
- mars = [ 'Mars' , '3390.0' ],
- jupiter = [ 'Jupiter', '69911' ],
- saturn = [ 'Saturn' , '58232' ];
+ venus = [ 'Venus' , '6051.8' ],
+ earth = [ 'Earth' , '6371.0' ],
+ mars = [ 'Mars' , '3390.0' ],
+ jupiter = [ 'Jupiter', '69911' ],
+ saturn = [ 'Saturn' , '58232' ];
// Initial data set
- var planets = [mercury, venus, earth, mars, jupiter, saturn];
- var ascendingName = [earth, jupiter, mars, mercury, saturn, venus];
+ var planets = [mercury, venus, earth, mars, jupiter, saturn];
+ var ascendingName = [earth, jupiter, mars, mercury, saturn, venus];
var ascendingRadius = [mercury, mars, venus, earth, saturn, jupiter];
tableTest(
planets,
ascendingName,
function ( $table ) {
- $table.tablesorter( { sortList: [ { 0: 'asc' } ] } );
+ $table.tablesorter( { sortList: [
+ { 0: 'asc' }
+ ] } );
}
);
tableTest(
'Basic planet table: sorting initially - descending by radius',
header,
planets,
- reversed(ascendingRadius),
+ reversed( ascendingRadius ),
function ( $table ) {
- $table.tablesorter( { sortList: [ { 1: 'desc' } ] } );
+ $table.tablesorter( { sortList: [
+ { 1: 'desc' }
+ ] } );
}
);
tableTest(
'Basic planet table: descending by name',
header,
planets,
- reversed(ascendingName),
+ reversed( ascendingName ),
function ( $table ) {
$table.tablesorter();
$table.find( '.headerSort:eq(0)' ).click().click();
'Basic planet table: descending radius',
header,
planets,
- reversed(ascendingRadius),
+ reversed( ascendingRadius ),
function ( $table ) {
$table.tablesorter();
$table.find( '.headerSort:eq(1)' ).click().click();
asc,
function ( $table ) {
$table.tablesorter(
- { sortList: [ { 0: 'asc' }, { 1: 'asc' } ] }
+ { sortList: [
+ { 0: 'asc' },
+ { 1: 'asc' }
+ ] }
);
}
);
function ( $table ) {
$table.tablesorter();
$table.data( 'tablesorter' ).sort(
- [ { 0: 'desc' }, { 1: 'asc' } ]
+ [
+ { 0: 'desc' },
+ { 1: 'asc' }
+ ]
);
}
);
asc,
function ( $table ) {
$table.tablesorter(
- { sortList: [ { 0: 'asc' }, { 1: 'asc' } ] }
+ { sortList: [
+ { 0: 'asc' },
+ { 1: 'asc' }
+ ] }
);
$table.data( 'tablesorter' ).sort(
- [ { 0: 'desc' }, { 1: 'asc' } ]
+ [
+ { 0: 'desc' },
+ { 1: 'asc' }
+ ]
);
$table.data( 'tablesorter' ).sort();
}
QUnit.test( 'Reset sorting making table appear unsorted', 3, function ( assert ) {
var $table = tableCreate( header, initial );
$table.tablesorter(
- { sortList: [ { 0: 'desc' }, { 1: 'asc' } ] }
+ { sortList: [
+ { 0: 'desc' },
+ { 1: 'asc' }
+ ] }
);
$table.data( 'tablesorter' ).sort( [] );
tableTest(
'Bug 28775: German-style (dmy) short numeric dates',
['Date'],
- [ // German-style dates are day-month-year
+ [
+ // German-style dates are day-month-year
['11.11.2011'],
['01.11.2011'],
['02.10.2011'],
['03.08.2011'],
['09.11.2011']
],
- [ // Sorted by ascending date
+ [
+ // Sorted by ascending date
['03.08.2011'],
['02.10.2011'],
['01.11.2011'],
tableTest(
'Bug 28775: American-style (mdy) short numeric dates',
['Date'],
- [ // American-style dates are month-day-year
+ [
+ // American-style dates are month-day-year
['11.11.2011'],
['01.11.2011'],
['02.10.2011'],
['03.08.2011'],
['09.11.2011']
],
- [ // Sorted by ascending date
+ [
+ // Sorted by ascending date
['01.11.2011'],
['02.10.2011'],
['03.08.2011'],
'Bug 17141: IPv4 address sorting (reverse)',
['IP'],
ipv4,
- reversed(ipv4Sorted),
+ reversed( ipv4Sorted ),
function ( $table ) {
$table.tablesorter();
$table.find( '.headerSort:eq(0)' ).click().click();
'ä': 'ae',
'ö': 'oe',
'ß': 'ss',
- 'ü':'ue'
+ 'ü': 'ue'
} );
$table.tablesorter();
3,
'Rowspan not exploded'
);
- });
+ } );
- var planetsRowspan = [ [ 'Earth', '6051.8' ], jupiter, [ 'Mars', '6051.8' ], mercury, saturn, venus ];
+ var planetsRowspan = [
+ [ 'Earth', '6051.8' ],
+ jupiter,
+ [ 'Mars', '6051.8' ],
+ mercury,
+ saturn,
+ venus
+ ];
var planetsRowspanII = [ jupiter, mercury, saturn, venus, [ 'Venus', '6371.0' ], [ 'Venus', '3390.0' ] ];
tableTest(
// This covers the removed cell in the 4th and 5th row.
$table.find( 'tr:eq(2) td:eq(1)' ).prop( 'rowspan', '3' );
- $table.tablesorter( { sortList: [ { 0: 'asc' } ] } );
+ $table.tablesorter( { sortList: [
+ { 0: 'asc' }
+ ] } );
}
);
tableTest(
}
);
- var ascendingNameLegacy = ascendingName.slice(0);
+ var ascendingNameLegacy = ascendingName.slice( 0 );
ascendingNameLegacy[4] = ascendingNameLegacy[5];
ascendingNameLegacy.pop();
header,
planets,
ascendingNameLegacy,
- function( $table ) {
+ function ( $table ) {
$table.find( 'tr:last' ).addClass( 'sortbottom' );
$table.tablesorter();
$table.find( '.headerSort:eq(0)' ).click();
var $table;
$table = $(
'<table class="sortable">' +
- '<caption>CAPTION</caption>' +
- '<tr><th>THEAD</th></tr>' +
- '<tr><td>1</td></tr>' +
- '<tr class="sortbottom"><td>text</td></tr>' +
- '</table>'
+ '<caption>CAPTION</caption>' +
+ '<tr><th>THEAD</th></tr>' +
+ '<tr><td>1</td></tr>' +
+ '<tr class="sortbottom"><td>text</td></tr>' +
+ '</table>'
);
$table.tablesorter();
$table.find( '.headerSort:eq(0)' ).click();
var $table;
$table = $(
'<table class="sortable">' +
- '<caption>CAPTION</caption>' +
- '<tr><th>THEAD</th></tr>' +
- '<tr><td>A</td></tr>' +
- '<tr><td>B</td></tr>' +
- '<tr class="sortbottom"><td>TFOOT</td></tr>' +
- '</table>'
- );
+ '<caption>CAPTION</caption>' +
+ '<tr><th>THEAD</th></tr>' +
+ '<tr><td>A</td></tr>' +
+ '<tr><td>B</td></tr>' +
+ '<tr class="sortbottom"><td>TFOOT</td></tr>' +
+ '</table>'
+ );
$table.tablesorter();
assert.equal(
- $table.children( ).get( 0 ).nodeName,
+ $table.children().get( 0 ).nodeName,
'CAPTION',
'First element after <thead> must be <caption> (bug 32047)'
);
- });
+ } );
QUnit.test( 'data-sort-value attribute, when available, should override sorting position', function ( assert ) {
var $table, data;
'<tr><td data-sort-value="Bananna">Ferret</td></tr>' +
'<tr><td data-sort-value="Drupe">Elephant</td></tr>' +
'<tr><td data-sort-value="Cherry">Dolphin</td></tr>' +
- '</tbody></table>'
+ '</tbody></table>'
);
$table.tablesorter().find( '.headerSort:eq(0)' ).click();
data = [];
- $table.find( 'tbody > tr' ).each( function( i, tr ) {
- $( tr ).find( 'td' ).each( function( i, td ) {
+ $table.find( 'tbody > tr' ).each( function ( i, tr ) {
+ $( tr ).find( 'td' ).each( function ( i, td ) {
data.push( {
data: $( td ).data( 'sortValue' ),
text: $( td ).text()
} );
- });
- });
+ } );
+ } );
assert.deepEqual( data, [
{
data: 'Apple',
text: 'Bird'
- }, {
+ },
+ {
data: 'Bananna',
text: 'Ferret'
- }, {
+ },
+ {
data: undefined,
text: 'Cheetah'
- }, {
+ },
+ {
data: 'Cherry',
text: 'Dolphin'
- }, {
+ },
+ {
data: 'Drupe',
text: 'Elephant'
}
'<tr><td>B</td></tr>' +
'<tr><td>G</td></tr>' +
'<tr><td data-sort-value="F">C</td></tr>' +
- '</tbody></table>'
+ '</tbody></table>'
);
$table.tablesorter().find( '.headerSort:eq(0)' ).click();
data: $( td ).data( 'sortValue' ),
text: $( td ).text()
} );
- });
- });
+ } );
+ } );
assert.deepEqual( data, [
{
data: undefined,
text: 'B'
- }, {
+ },
+ {
data: undefined,
text: 'D'
- }, {
+ },
+ {
data: 'E',
text: 'A'
- }, {
+ },
+ {
data: 'F',
text: 'C'
- }, {
+ },
+ {
data: undefined,
text: 'G'
}
'<tr><td>B</td></tr>' +
'<tr><td data-sort-value="2">G</td></tr>' +
'<tr><td>C</td></tr>' +
- '</tbody></table>'
+ '</tbody></table>'
);
// initialize table sorter and sort once
$table
$table.find( '.headerSort:eq(0)' ).click();
data = [];
- $table.find( 'tbody > tr' ).each( function( i, tr ) {
- $( tr ).find( 'td' ).each( function( i, td ) {
+ $table.find( 'tbody > tr' ).each( function ( i, tr ) {
+ $( tr ).find( 'td' ).each( function ( i, td ) {
data.push( {
data: $( td ).data( 'sortValue' ),
text: $( td ).text()
} );
- });
- });
+ } );
+ } );
assert.deepEqual( data, [
{
data: 1,
text: 'B'
- }, {
+ },
+ {
data: 2,
text: 'G'
- }, {
+ },
+ {
data: 3,
text: 'A'
- }, {
+ },
+ {
data: undefined,
text: 'C'
- }, {
+ },
+ {
data: undefined,
text: 'D'
}
], 'Order matches expected order, using the current sortValue in $.data()' );
- });
+ } );
var numbers = [
[ '12' ],
tableTest( 'bug 8115: sort numbers with commas (ascending)',
['Numbers'], numbers, numbersAsc,
- function( $table ) {
+ function ( $table ) {
$table.tablesorter();
$table.find( '.headerSort:eq(0)' ).click();
}
);
tableTest( 'bug 8115: sort numbers with commas (descending)',
- ['Numbers'], numbers, reversed(numbersAsc),
- function( $table ) {
+ ['Numbers'], numbers, reversed( numbersAsc ),
+ function ( $table ) {
$table.tablesorter();
$table.find( '.headerSort:eq(0)' ).click().click();
}
var $table;
$table = $(
'<table class="sortable" id="mw-bug-32888">' +
- '<tr><th>header<table id="mw-bug-32888-2">'+
+ '<tr><th>header<table id="mw-bug-32888-2">' +
'<tr><th>1</th><th>2</th></tr>' +
- '</table></th></tr>' +
- '<tr><td>A</td></tr>' +
- '<tr><td>B</td></tr>' +
- '</table>'
- );
+ '</table></th></tr>' +
+ '<tr><td>A</td></tr>' +
+ '<tr><td>B</td></tr>' +
+ '</table>'
+ );
$table.tablesorter();
assert.equal(
- $table.find('> thead:eq(0) > tr > th.headerSort').length,
+ $table.find( '> thead:eq(0) > tr > th.headerSort' ).length,
1,
'Child tables inside a headercell should not interfere with sortable headers (bug 32888)'
);
assert.equal(
- $( '#mw-bug-32888-2' ).find('th.headerSort').length,
+ $( '#mw-bug-32888-2' ).find( 'th.headerSort' ).length,
0,
'The headers of child tables inside a headercell should not be sortable themselves (bug 32888)'
);
- });
+ } );
var correctDateSorting1 = [
}
);
-QUnit.test( 'Sorting images using alt text', function ( assert ) {
- var $table = $(
- '<table class="sortable">' +
- '<tr><th>THEAD</th></tr>' +
- '<tr><td><img alt="2"/></td></tr>' +
- '<tr><td>1</td></tr>' +
- '</table>'
- );
- $table.tablesorter().find( '.headerSort:eq(0)' ).click();
+ QUnit.test( 'Sorting images using alt text', function ( assert ) {
+ var $table = $(
+ '<table class="sortable">' +
+ '<tr><th>THEAD</th></tr>' +
+ '<tr><td><img alt="2"/></td></tr>' +
+ '<tr><td>1</td></tr>' +
+ '</table>'
+ );
+ $table.tablesorter().find( '.headerSort:eq(0)' ).click();
- assert.equal(
- $table.find( 'td' ).first().text(),
- '1',
- 'Applied correct sorting order'
- );
-} );
-
-QUnit.test( 'Sorting images using alt text (complex)', function ( assert ) {
- var $table = $(
- '<table class="sortable">' +
- '<tr><th>THEAD</th></tr>' +
- '<tr><td><img alt="D" />A</td></tr>' +
- '<tr><td>CC</td></tr>' +
- '<tr><td><a><img alt="A" /></a>F</tr>' +
- '<tr><td><img alt="A" /><strong>E</strong></tr>' +
- '<tr><td><strong><img alt="A" />D</strong></tr>' +
- '<tr><td><img alt="A" />C</tr>' +
- '</table>'
- );
- $table.tablesorter().find( '.headerSort:eq(0)' ).click();
+ assert.equal(
+ $table.find( 'td' ).first().text(),
+ '1',
+ 'Applied correct sorting order'
+ );
+ } );
- assert.equal(
- $table.find( 'td' ).text(),
- 'CDEFCCA',
- 'Applied correct sorting order'
- );
-} );
-
-QUnit.test( 'Sorting images using alt text (with format autodetection)', function ( assert ) {
- var $table = $(
- '<table class="sortable">' +
- '<tr><th>THEAD</th></tr>' +
- '<tr><td><img alt="1" />7</td></tr>' +
- '<tr><td>1<img alt="6" /></td></tr>' +
- '<tr><td>5</td></tr>' +
- '<tr><td>4</td></tr>' +
- '</table>'
- );
- $table.tablesorter().find( '.headerSort:eq(0)' ).click();
+ QUnit.test( 'Sorting images using alt text (complex)', function ( assert ) {
+ var $table = $(
+ '<table class="sortable">' +
+ '<tr><th>THEAD</th></tr>' +
+ '<tr><td><img alt="D" />A</td></tr>' +
+ '<tr><td>CC</td></tr>' +
+ '<tr><td><a><img alt="A" /></a>F</tr>' +
+ '<tr><td><img alt="A" /><strong>E</strong></tr>' +
+ '<tr><td><strong><img alt="A" />D</strong></tr>' +
+ '<tr><td><img alt="A" />C</tr>' +
+ '</table>'
+ );
+ $table.tablesorter().find( '.headerSort:eq(0)' ).click();
- assert.equal(
- $table.find( 'td' ).text(),
- '4517',
- 'Applied correct sorting order'
- );
-} );
+ assert.equal(
+ $table.find( 'td' ).text(),
+ 'CDEFCCA',
+ 'Applied correct sorting order'
+ );
+ } );
+ QUnit.test( 'Sorting images using alt text (with format autodetection)', function ( assert ) {
+ var $table = $(
+ '<table class="sortable">' +
+ '<tr><th>THEAD</th></tr>' +
+ '<tr><td><img alt="1" />7</td></tr>' +
+ '<tr><td>1<img alt="6" /></td></tr>' +
+ '<tr><td>5</td></tr>' +
+ '<tr><td>4</td></tr>' +
+ '</table>'
+ );
+ $table.tablesorter().find( '.headerSort:eq(0)' ).click();
+
+ assert.equal(
+ $table.find( 'td' ).text(),
+ '4517',
+ 'Applied correct sorting order'
+ );
+ } );
}( jQuery, mediaWiki ) );
* params {object} add'l parameters for $().textSelection( 'encapsulateText' )
*/
function encapsulateTest( options ) {
- var opt = $.extend({
+ var opt = $.extend( {
description: '',
before: {},
after: {},
replace: {}
- }, options);
+ }, options );
- opt.before = $.extend({
+ opt.before = $.extend( {
text: '',
start: 0,
end: 0
- }, opt.before);
- opt.after = $.extend({
+ }, opt.before );
+ opt.after = $.extend( {
text: '',
selected: null
- }, opt.after);
+ }, opt.after );
QUnit.test( opt.description, function ( assert ) {
/*jshint onevar: false */
//$textarea.textSelection( 'setContents', opt.before.text); // this method is actually missing atm...
$textarea.val( opt.before.text ); // won't work with the WikiEditor iframe?
- var start = opt.before.start,
+ var start = opt.before.start,
end = opt.before.end;
if ( window.opera ) {
// Compensate for Opera's craziness converting \n to \r\n and counting that as two chars
- var newLinesBefore = opt.before.text.substring( 0, start ).split( '\n' ).length - 1,
+ var newLinesBefore = opt.before.text.substring( 0, start ).split( '\n' ).length - 1,
newLinesInside = opt.before.text.substring( start, end ).split( '\n' ).length - 1;
start += newLinesBefore;
end += newLinesBefore + newLinesInside;
splitlines: true
};
- encapsulateTest({
+ encapsulateTest( {
description: 'Adding sig to end of text',
before: {
text: 'Wikilove dude! ',
selected: ''
},
replace: sig
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'Adding bold to empty',
before: {
text: '',
selected: 'Bold text' // selected because it's the default
},
replace: bold
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'Adding bold to existing text',
before: {
text: 'Now is the time for all good men to come to the aid of their country',
selected: '' // empty because it's not the default'
},
replace: bold
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'ownline option: adding new h2',
before: {
- text:'Before\nAfter',
+ text: 'Before\nAfter',
start: 7,
end: 7
},
selected: 'Heading 2'
},
replace: h2
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'ownline option: turn a whole line into new h2',
before: {
- text:'Before\nMy heading\nAfter',
+ text: 'Before\nMy heading\nAfter',
start: 7,
end: 17
},
selected: ''
},
replace: h2
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'ownline option: turn a partial line into new h2',
before: {
- text:'BeforeMy headingAfter',
+ text: 'BeforeMy headingAfter',
start: 6,
end: 16
},
selected: ''
},
replace: h2
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'splitlines option: no selection, insert new list item',
before: {
text: 'Before\nAfter',
text: 'Before\n* Bulleted list item\nAfter'
},
replace: ulist
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'splitlines option: single partial line selection, insert new list item',
before: {
text: 'BeforeMy List ItemAfter',
text: 'Before\n* My List Item\nAfter'
},
replace: ulist
- });
+ } );
- encapsulateTest({
+ encapsulateTest( {
description: 'splitlines option: multiple lines',
before: {
text: 'Before\nFirst\nSecond\nThird\nAfter',
text: 'Before\n* First\n* Second\n* Third\nAfter'
},
replace: ulist
- });
+ } );
function caretTest( options ) {
$( '#qunit-fixture' ).append( $textarea );
if ( options.mode === 'set' ) {
- $textarea.textSelection('setSelection', {
+ $textarea.textSelection( 'setSelection', {
start: options.start,
end: options.end
- });
+ } );
}
function among( actual, expected, message ) {
if ( $.isArray( expected ) ) {
- assert.ok( $.inArray( actual, expected ) !== -1 , message + ' (got ' + actual + '; expected one of ' + expected.join(', ') + ')' );
+ assert.ok( $.inArray( actual, expected ) !== -1, message + ' (got ' + actual + '; expected one of ' + expected.join( ', ' ) + ')' );
} else {
assert.equal( actual, expected, message );
}
}
- pos = $textarea.textSelection( 'getCaretPosition', { startAndEnd: true });
- among(pos[0], options.start, 'Caret start should be where we set it.');
- among(pos[1], options.end, 'Caret end should be where we set it.');
- });
+ pos = $textarea.textSelection( 'getCaretPosition', { startAndEnd: true } );
+ among( pos[0], options.start, 'Caret start should be where we set it.' );
+ among( pos[1], options.end, 'Caret end should be where we set it.' );
+ } );
}
caretSample = 'Some big text that we like to work with. Nothing fancy... you know what I mean?';
/*
- // @broken: Disabled per bug 34820
- caretTest({
- description: 'getCaretPosition with original/empty selection - bug 31847 with IE 6/7/8',
- text: caretSample,
- start: [0, caretSample.length], // Opera and Firefox (prior to FF 6.0) default caret to the end of the box (caretSample.length)
- end: [0, caretSample.length], // Other browsers default it to the beginning (0), so check both.
- mode: 'get'
- });
- */
+ // @broken: Disabled per bug 34820
+ caretTest({
+ description: 'getCaretPosition with original/empty selection - bug 31847 with IE 6/7/8',
+ text: caretSample,
+ start: [0, caretSample.length], // Opera and Firefox (prior to FF 6.0) default caret to the end of the box (caretSample.length)
+ end: [0, caretSample.length], // Other browsers default it to the beginning (0), so check both.
+ mode: 'get'
+ });
+ */
- caretTest({
+ caretTest( {
description: 'set/getCaretPosition with forced empty selection',
text: caretSample,
start: 7,
end: 7,
mode: 'set'
- });
+ } );
- caretTest({
+ caretTest( {
description: 'set/getCaretPosition with small selection',
text: caretSample,
start: 6,
end: 11,
mode: 'set'
- });
+ } );
}( jQuery ) );
assert.equal( $res.find( 'b' ).text(), 'Hello world', 'Bold tag wraps the entire, same, text' );
QUnit.start();
- });
- });
+ } );
+ } );
}( mediaWiki, jQuery ) );
d1 = api.get( {} )
.done( function ( data ) {
assert.deepEqual( data, [], 'If request succeeds without errors, resolve deferred' );
- });
+ } );
- d2 = api.get({
- action: 'doesntexist'
- })
+ d2 = api.get( {
+ action: 'doesntexist'
+ } )
.fail( function ( errorCode ) {
assert.equal( errorCode, 'unknown_action', 'API error (e.g. "unknown_action") should reject the deferred' );
- });
+ } );
d3 = api.post( {} )
.done( function ( data ) {
assert.deepEqual( data, [], 'Simple POST request' );
- });
+ } );
// After all are completed, continue the test suite.
QUnit.whenPromisesComplete( d1, d2, d3 ).always( function () {
QUnit.start();
- });
- });
+ } );
+ } );
QUnit.asyncTest( 'Deprecated callback methods', function ( assert ) {
var api, d1, d2, d3;
d1 = api.get( {}, function () {
assert.ok( true, 'Function argument treated as success callback.' );
- });
+ } );
d2 = api.get( {}, {
ok: function () {
assert.ok( true, '"ok" property treated as success callback.' );
}
- });
+ } );
- d3 = api.get({
- action: 'doesntexist'
- }, {
+ d3 = api.get( {
+ action: 'doesntexist'
+ }, {
err: function () {
assert.ok( true, '"err" property treated as error callback.' );
}
- });
+ } );
QUnit.whenPromisesComplete( d1, d2, d3 ).always( function () {
QUnit.start();
- });
- });
+ } );
+ } );
}( mediaWiki ) );
var selectHtml, $env, $options;
// from Special:Recentchanges
- selectHtml =
- '<select id="namespace" name="namespace" class="namespaceselector">'
- + '<option value="" selected="selected">all</option>'
- + '<option value="0">(Main)</option>'
- + '<option value="1">Talk</option>'
- + '<option value="2">User</option>'
- + '<option value="3">User talk</option>'
- + '<option value="4">ProjectName</option>'
- + '<option value="5">ProjectName talk</option>'
- + '</select>'
- + '<input name="invert" type="checkbox" value="1" id="nsinvert" title="no title" />'
- + '<label for="nsinvert" title="no title">Invert selection</label>'
- + '<input name="associated" type="checkbox" value="1" id="nsassociated" title="no title" />'
- + '<label for="nsassociated" title="no title">Associated namespace</label>'
- + '<input type="submit" value="Go" />'
- + '<input type="hidden" value="Special:RecentChanges" name="title" />'
- ;
+ selectHtml = '<select id="namespace" name="namespace" class="namespaceselector">'
+ + '<option value="" selected="selected">all</option>'
+ + '<option value="0">(Main)</option>'
+ + '<option value="1">Talk</option>'
+ + '<option value="2">User</option>'
+ + '<option value="3">User talk</option>'
+ + '<option value="4">ProjectName</option>'
+ + '<option value="5">ProjectName talk</option>'
+ + '</select>'
+ + '<input name="invert" type="checkbox" value="1" id="nsinvert" title="no title" />'
+ + '<label for="nsinvert" title="no title">Invert selection</label>'
+ + '<input name="associated" type="checkbox" value="1" id="nsassociated" title="no title" />'
+ + '<label for="nsassociated" title="no title">Associated namespace</label>'
+ + '<input type="submit" value="Go" />'
+ + '<input type="hidden" value="Special:RecentChanges" name="title" />';
$env = $( '<div>' ).html( selectHtml ).appendTo( 'body' );
// select second option...
$options = $( '#namespace' ).find( 'option' );
- $options.eq(0).removeProp( 'selected' );
- $options.eq(1).prop( 'selected', true );
+ $options.eq( 0 ).removeProp( 'selected' );
+ $options.eq( 1 ).prop( 'selected', true );
$( '#namespace' ).change();
// ... and checkboxes should be enabled again
assert.strictEqual( $( '#nsassociated' ).prop( 'disabled' ), false );
// select first option ( 'all' namespace)...
- $options.eq(1).removeProp( 'selected' );
- $options.eq(0).prop( 'selected', true );
+ $options.eq( 1 ).removeProp( 'selected' );
+ $options.eq( 0 ).prop( 'selected', true );
$( '#namespace' ).change();
// ... and checkboxes should now be disabled
// DOM cleanup
$env.remove();
- });
+ } );
}( mediaWiki, jQuery ) );
( function ( mw ) {
+ // mw.Title relies on these three config vars
+ // Restore them after each test run
+ var config = {
+ wgFormattedNamespaces: {
+ '-2': 'Media',
+ '-1': 'Special',
+ 0: '',
+ 1: 'Talk',
+ 2: 'User',
+ 3: 'User talk',
+ 4: 'Wikipedia',
+ 5: 'Wikipedia talk',
+ 6: 'File',
+ 7: 'File talk',
+ 8: 'MediaWiki',
+ 9: 'MediaWiki talk',
+ 10: 'Template',
+ 11: 'Template talk',
+ 12: 'Help',
+ 13: 'Help talk',
+ 14: 'Category',
+ 15: 'Category talk',
+ // testing custom / localized namespace
+ 100: 'Penguins'
+ },
+ wgNamespaceIds: {
+ /*jshint camelcase: false */
+ media: -2,
+ special: -1,
+ '': 0,
+ talk: 1,
+ user: 2,
+ user_talk: 3,
+ wikipedia: 4,
+ wikipedia_talk: 5,
+ file: 6,
+ file_talk: 7,
+ mediawiki: 8,
+ mediawiki_talk: 9,
+ template: 10,
+ template_talk: 11,
+ help: 12,
+ help_talk: 13,
+ category: 14,
+ category_talk: 15,
+ image: 6,
+ image_talk: 7,
+ project: 4,
+ project_talk: 5,
+ /* testing custom / alias */
+ penguins: 100,
+ antarctic_waterfowl: 100
+ },
+ wgCaseSensitiveNamespaces: []
+ };
+
+ QUnit.module( 'mediawiki.Title', QUnit.newMwEnvironment( { config: config } ) );
+
+ QUnit.test( 'Transformation', 8, function ( assert ) {
+ var title;
+
+ title = new mw.Title( 'File:quux pif.jpg' );
+ assert.equal( title.getName(), 'Quux_pif' );
+
+ title = new mw.Title( 'File:Glarg_foo_glang.jpg' );
+ assert.equal( title.getNameText(), 'Glarg foo glang' );
+
+ title = new mw.Title( 'User:ABC.DEF' );
+ assert.equal( title.toText(), 'User:ABC.DEF' );
+ assert.equal( title.getNamespaceId(), 2 );
+ assert.equal( title.getNamespacePrefix(), 'User:' );
+
+ title = new mw.Title( 'uSEr:hAshAr' );
+ assert.equal( title.toText(), 'User:HAshAr' );
+ assert.equal( title.getNamespaceId(), 2 );
+
+ title = new mw.Title( ' MediaWiki: Foo bar .js ' );
+ // Don't ask why, it's the way the backend works. One space is kept of each set
+ assert.equal( title.getName(), 'Foo_bar_.js', 'Merge multiple spaces to a single space.' );
+ } );
+
+ QUnit.test( 'Main text for filename', 8, function ( assert ) {
+ var title = new mw.Title( 'File:foo_bar.JPG' );
+
+ assert.equal( title.getNamespaceId(), 6 );
+ assert.equal( title.getNamespacePrefix(), 'File:' );
+ assert.equal( title.getName(), 'Foo_bar' );
+ assert.equal( title.getNameText(), 'Foo bar' );
+ assert.equal( title.getMain(), 'Foo_bar.JPG' );
+ assert.equal( title.getMainText(), 'Foo bar.JPG' );
+ assert.equal( title.getExtension(), 'JPG' );
+ assert.equal( title.getDotExtension(), '.JPG' );
+ } );
+
+ QUnit.test( 'Namespace detection and conversion', 6, function ( assert ) {
+ var title;
+
+ title = new mw.Title( 'something.PDF', 6 );
+ assert.equal( title.toString(), 'File:Something.PDF' );
+
+ title = new mw.Title( 'NeilK', 3 );
+ assert.equal( title.toString(), 'User_talk:NeilK' );
+ assert.equal( title.toText(), 'User talk:NeilK' );
+
+ title = new mw.Title( 'Frobisher', 100 );
+ assert.equal( title.toString(), 'Penguins:Frobisher' );
+
+ title = new mw.Title( 'antarctic_waterfowl:flightless_yet_cute.jpg' );
+ assert.equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
+
+ title = new mw.Title( 'Penguins:flightless_yet_cute.jpg' );
+ assert.equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
+ } );
+
+ QUnit.test( 'Throw error on invalid title', 1, function ( assert ) {
+ assert.throws( function () {
+ return new mw.Title( '' );
+ }, 'Throw error on empty string' );
+ } );
+
+ QUnit.test( 'Case-sensivity', 3, function ( assert ) {
+ var title;
+
+ // Default config
+ mw.config.set( 'wgCaseSensitiveNamespaces', [] );
+
+ title = new mw.Title( 'article' );
+ assert.equal( title.toString(), 'Article', 'Default config: No sensitive namespaces by default. First-letter becomes uppercase' );
+
+ // $wgCapitalLinks = false;
+ mw.config.set( 'wgCaseSensitiveNamespaces', [0, -2, 1, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15] );
+
+ title = new mw.Title( 'article' );
+ assert.equal( title.toString(), 'article', '$wgCapitalLinks=false: Article namespace is sensitive, first-letter case stays lowercase' );
+
+ title = new mw.Title( 'john', 2 );
+ assert.equal( title.toString(), 'User:John', '$wgCapitalLinks=false: User namespace is insensitive, first-letter becomes uppercase' );
+ } );
+
+ QUnit.test( 'toString / toText', 2, function ( assert ) {
+ var title = new mw.Title( 'Some random page' );
+
+ assert.equal( title.toString(), title.getPrefixedDb() );
+ assert.equal( title.toText(), title.getPrefixedText() );
+ } );
-// mw.Title relies on these three config vars
-// Restore them after each test run
-var config = {
- wgFormattedNamespaces: {
- '-2': 'Media',
- '-1': 'Special',
- 0: '',
- 1: 'Talk',
- 2: 'User',
- 3: 'User talk',
- 4: 'Wikipedia',
- 5: 'Wikipedia talk',
- 6: 'File',
- 7: 'File talk',
- 8: 'MediaWiki',
- 9: 'MediaWiki talk',
- 10: 'Template',
- 11: 'Template talk',
- 12: 'Help',
- 13: 'Help talk',
- 14: 'Category',
- 15: 'Category talk',
- // testing custom / localized namespace
- 100: 'Penguins'
- },
- wgNamespaceIds: {
- /*jshint camelcase: false */
- media: -2,
- special: -1,
- '': 0,
- talk: 1,
- user: 2,
- user_talk: 3,
- wikipedia: 4,
- wikipedia_talk: 5,
- file: 6,
- file_talk: 7,
- mediawiki: 8,
- mediawiki_talk: 9,
- template: 10,
- template_talk: 11,
- help: 12,
- help_talk: 13,
- category: 14,
- category_talk: 15,
- image: 6,
- image_talk: 7,
- project: 4,
- project_talk: 5,
- /* testing custom / alias */
- penguins: 100,
- antarctic_waterfowl: 100
- },
- wgCaseSensitiveNamespaces: []
-};
-
-QUnit.module( 'mediawiki.Title', QUnit.newMwEnvironment({ config: config }) );
-
-
-QUnit.test( 'Transformation', 8, function ( assert ) {
- var title;
-
- title = new mw.Title( 'File:quux pif.jpg' );
- assert.equal( title.getName(), 'Quux_pif' );
-
- title = new mw.Title( 'File:Glarg_foo_glang.jpg' );
- assert.equal( title.getNameText(), 'Glarg foo glang' );
-
- title = new mw.Title( 'User:ABC.DEF' );
- assert.equal( title.toText(), 'User:ABC.DEF' );
- assert.equal( title.getNamespaceId(), 2 );
- assert.equal( title.getNamespacePrefix(), 'User:' );
-
- title = new mw.Title( 'uSEr:hAshAr' );
- assert.equal( title.toText(), 'User:HAshAr' );
- assert.equal( title.getNamespaceId(), 2 );
-
- title = new mw.Title( ' MediaWiki: Foo bar .js ' );
- // Don't ask why, it's the way the backend works. One space is kept of each set
- assert.equal( title.getName(), 'Foo_bar_.js', 'Merge multiple spaces to a single space.' );
-});
-
-QUnit.test( 'Main text for filename', 8, function ( assert ) {
- var title = new mw.Title( 'File:foo_bar.JPG' );
-
- assert.equal( title.getNamespaceId(), 6 );
- assert.equal( title.getNamespacePrefix(), 'File:' );
- assert.equal( title.getName(), 'Foo_bar' );
- assert.equal( title.getNameText(), 'Foo bar' );
- assert.equal( title.getMain(), 'Foo_bar.JPG' );
- assert.equal( title.getMainText(), 'Foo bar.JPG' );
- assert.equal( title.getExtension(), 'JPG' );
- assert.equal( title.getDotExtension(), '.JPG' );
-});
-
-QUnit.test( 'Namespace detection and conversion', 6, function ( assert ) {
- var title;
-
- title = new mw.Title( 'something.PDF', 6 );
- assert.equal( title.toString(), 'File:Something.PDF' );
-
- title = new mw.Title( 'NeilK', 3 );
- assert.equal( title.toString(), 'User_talk:NeilK' );
- assert.equal( title.toText(), 'User talk:NeilK' );
-
- title = new mw.Title( 'Frobisher', 100 );
- assert.equal( title.toString(), 'Penguins:Frobisher' );
-
- title = new mw.Title( 'antarctic_waterfowl:flightless_yet_cute.jpg' );
- assert.equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
-
- title = new mw.Title( 'Penguins:flightless_yet_cute.jpg' );
- assert.equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
-});
-
-QUnit.test( 'Throw error on invalid title', 1, function ( assert ) {
- assert.throws(function () {
- return new mw.Title( '' );
- }, 'Throw error on empty string' );
-});
-
-QUnit.test( 'Case-sensivity', 3, function ( assert ) {
- var title;
-
- // Default config
- mw.config.set( 'wgCaseSensitiveNamespaces', [] );
-
- title = new mw.Title( 'article' );
- assert.equal( title.toString(), 'Article', 'Default config: No sensitive namespaces by default. First-letter becomes uppercase' );
-
- // $wgCapitalLinks = false;
- mw.config.set( 'wgCaseSensitiveNamespaces', [0, -2, 1, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15] );
-
- title = new mw.Title( 'article' );
- assert.equal( title.toString(), 'article', '$wgCapitalLinks=false: Article namespace is sensitive, first-letter case stays lowercase' );
-
- title = new mw.Title( 'john', 2 );
- assert.equal( title.toString(), 'User:John', '$wgCapitalLinks=false: User namespace is insensitive, first-letter becomes uppercase' );
-});
+ QUnit.test( 'getExtension', 7, function ( assert ) {
+ function extTest( pagename, ext, description ) {
+ var title = new mw.Title( pagename );
+ assert.equal( title.getExtension(), ext, description || pagename );
+ }
-QUnit.test( 'toString / toText', 2, function ( assert ) {
- var title = new mw.Title( 'Some random page' );
+ extTest( 'MediaWiki:Vector.js', 'js' );
+ extTest( 'User:Example/common.css', 'css' );
+ extTest( 'File:Example.longextension', 'longextension', 'Extension parsing not limited (bug 36151)' );
+ extTest( 'Example/information.json', 'json', 'Extension parsing not restricted from any namespace' );
+ extTest( 'Foo.', null, 'Trailing dot is not an extension' );
+ extTest( 'Foo..', null, 'Trailing dots are not an extension' );
+ extTest( 'Foo.a.', null, 'Page name with dots and ending in a dot does not have an extension' );
- assert.equal( title.toString(), title.getPrefixedDb() );
- assert.equal( title.toText(), title.getPrefixedText() );
-});
+ // @broken: Throws an exception
+ // extTest( '.NET', null, 'Leading dot is (or is not?) an extension' );
+ } );
-QUnit.test( 'getExtension', 7, function ( assert ) {
+ QUnit.test( 'exists', 3, function ( assert ) {
+ var title;
- function extTest( pagename, ext, description ) {
- var title = new mw.Title( pagename );
- assert.equal( title.getExtension(), ext, description || pagename );
- }
+ // Empty registry, checks default to null
- extTest( 'MediaWiki:Vector.js', 'js' );
- extTest( 'User:Example/common.css', 'css' );
- extTest( 'File:Example.longextension', 'longextension', 'Extension parsing not limited (bug 36151)' );
- extTest( 'Example/information.json', 'json', 'Extension parsing not restricted from any namespace' );
- extTest( 'Foo.', null, 'Trailing dot is not an extension' );
- extTest( 'Foo..', null, 'Trailing dots are not an extension' );
- extTest( 'Foo.a.', null, 'Page name with dots and ending in a dot does not have an extension' );
+ title = new mw.Title( 'Some random page', 4 );
+ assert.strictEqual( title.exists(), null, 'Return null with empty existance registry' );
- // @broken: Throws an exception
- // extTest( '.NET', null, 'Leading dot is (or is not?) an extension' );
-});
+ // Basic registry, checks default to boolean
+ mw.Title.exist.set( ['Does_exist', 'User_talk:NeilK', 'Wikipedia:Sandbox_rules'], true );
+ mw.Title.exist.set( ['Does_not_exist', 'User:John', 'Foobar'], false );
-QUnit.test( 'exists', 3, function ( assert ) {
- var title;
+ title = new mw.Title( 'Project:Sandbox rules' );
+ assert.assertTrue( title.exists(), 'Return true for page titles marked as existing' );
+ title = new mw.Title( 'Foobar' );
+ assert.assertFalse( title.exists(), 'Return false for page titles marked as nonexistent' );
- // Empty registry, checks default to null
+ } );
- title = new mw.Title( 'Some random page', 4 );
- assert.strictEqual( title.exists(), null, 'Return null with empty existance registry' );
+ QUnit.test( 'getUrl', 2, function ( assert ) {
+ var title;
- // Basic registry, checks default to boolean
- mw.Title.exist.set( ['Does_exist', 'User_talk:NeilK', 'Wikipedia:Sandbox_rules'], true );
- mw.Title.exist.set( ['Does_not_exist', 'User:John', 'Foobar'], false );
+ // Config
+ mw.config.set( 'wgArticlePath', '/wiki/$1' );
- title = new mw.Title( 'Project:Sandbox rules' );
- assert.assertTrue( title.exists(), 'Return true for page titles marked as existing' );
- title = new mw.Title( 'Foobar' );
- assert.assertFalse( title.exists(), 'Return false for page titles marked as nonexistent' );
+ title = new mw.Title( 'Foobar' );
+ assert.equal( title.getUrl(), '/wiki/Foobar', 'Basic functionally, toString passing to wikiGetlink' );
-});
+ title = new mw.Title( 'John Doe', 3 );
+ assert.equal( title.getUrl(), '/wiki/User_talk:John_Doe', 'Escaping in title and namespace for urls' );
+ } );
-QUnit.test( 'getUrl', 2, function ( assert ) {
- var title;
-
- // Config
- mw.config.set( 'wgArticlePath', '/wiki/$1' );
-
- title = new mw.Title( 'Foobar' );
- assert.equal( title.getUrl(), '/wiki/Foobar', 'Basic functionally, toString passing to wikiGetlink' );
-
- title = new mw.Title( 'John Doe', 3 );
- assert.equal( title.getUrl(), '/wiki/User_talk:John_Doe', 'Escaping in title and namespace for urls' );
-});
-
-}( mediaWiki ) );
\ No newline at end of file
+}( mediaWiki ) );
( function ( mw, $ ) {
- QUnit.module( 'mediawiki.Uri', QUnit.newMwEnvironment({
+ QUnit.module( 'mediawiki.Uri', QUnit.newMwEnvironment( {
setup: function () {
this.mwUriOrg = mw.Uri;
mw.Uri = mw.UriRelative( 'http://example.org/w/index.php' );
mw.Uri = this.mwUriOrg;
delete this.mwUriOrg;
}
- }) );
+ } ) );
$.each( [true, false], function ( i, strictMode ) {
QUnit.test( 'Basic construction and properties (' + ( strictMode ? '' : 'non-' ) + 'strict mode)', 2, function ( assert ) {
uriString = 'http://www.ietf.org/rfc/rfc2396.txt';
uri = new mw.Uri( uriString, {
strictMode: strictMode
- });
+ } );
assert.deepEqual(
{
},
'construct composite components of URI on request'
);
-
- });
- });
+ } );
+ } );
QUnit.test( 'Constructor( String[, Object ] )', 10, function ( assert ) {
var uri;
uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
overrideKeys: true
- });
+ } );
// Strict comparison to assert that numerical values stay strings
assert.strictEqual( uri.query.n, '1', 'Simple parameter with overrideKeys:true' );
uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
overrideKeys: false
- });
+ } );
assert.strictEqual( uri.query.n, '1', 'Simple parameter with overrideKeys:false' );
assert.strictEqual( uri.query.m[0], 'foo', 'Order of multi-value parameters with overrideKeys:true' );
function () {
return new mw.Uri( 'foo.com/bar/baz', {
strictMode: true
- });
+ } );
},
function ( e ) {
return e.message === 'Bad constructor arguments';
uri = new mw.Uri( 'foo.com/bar/baz', {
strictMode: false
- });
+ } );
assert.equal( uri.toString(), 'http://foo.com/bar/baz', 'normalize URI without protocol or // in loose mode' );
- });
+ } );
QUnit.test( 'Constructor( Object )', 3, function ( assert ) {
- var uri = new mw.Uri({
+ var uri = new mw.Uri( {
protocol: 'http',
host: 'www.foo.local',
path: '/this'
- });
+ } );
assert.equal( uri.toString(), 'http://www.foo.local/this', 'Basic properties' );
- uri = new mw.Uri({
+ uri = new mw.Uri( {
protocol: 'http',
host: 'www.foo.local',
path: '/this',
query: { hi: 'there' },
fragment: 'blah'
- });
+ } );
assert.equal( uri.toString(), 'http://www.foo.local/this?hi=there#blah', 'More complex properties' );
assert.throws(
function () {
- return new mw.Uri({
+ return new mw.Uri( {
protocol: 'http',
host: 'www.foo.local'
- });
+ } );
},
function ( e ) {
return e.message === 'Bad constructor arguments';
uri = uriBase.clone();
uri.query.foo = 'bar';
assert.equal( uri.toString(), 'http://en.wiki.local/w/api.php?foo=bar', 'extend query arguments' );
- uri.extend({
+ uri.extend( {
foo: 'quux',
pif: 'paf'
- });
+ } );
assert.ok( uri.toString().indexOf( 'foo=quux' ) >= 0, 'extend query arguments' );
assert.ok( uri.toString().indexOf( 'foo=bar' ) === -1, 'extend query arguments' );
- assert.ok( uri.toString().indexOf( 'pif=paf' ) >= 0 , 'extend query arguments' );
+ assert.ok( uri.toString().indexOf( 'pif=paf' ) >= 0, 'extend query arguments' );
} );
QUnit.test( '.getQueryString()', 2, function ( assert ) {
uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
overrideKeys: true
- });
+ } );
uri.query.n = [ 'x', 'y', 'z' ];
uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
overrideKeys: false
- });
+ } );
// Change query values
uri.query.n = [ 'x', 'y', 'z' ];
( function ( mw, $ ) {
+ var mwLanguageCache = {}, oldGetOuterHtml, formatnumTests, specialCharactersPageName,
+ expectedListUsers, expectedEntrypoints;
-var mwLanguageCache = {}, oldGetOuterHtml, formatnumTests, specialCharactersPageName,
- expectedListUsers, expectedEntrypoints;
-
-QUnit.module( 'mediawiki.jqueryMsg', QUnit.newMwEnvironment( {
- setup: function () {
- this.orgMwLangauge = mw.language;
- mw.language = $.extend( true, {}, this.orgMwLangauge );
- oldGetOuterHtml = $.fn.getOuterHtml;
- $.fn.getOuterHtml = function () {
- var $div = $( '<div>' ), html;
- $div.append( $( this ).eq( 0 ).clone() );
- html = $div.html();
- $div.empty();
- $div = undefined;
- return html;
- };
+ QUnit.module( 'mediawiki.jqueryMsg', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.orgMwLangauge = mw.language;
+ mw.language = $.extend( true, {}, this.orgMwLangauge );
+ oldGetOuterHtml = $.fn.getOuterHtml;
+ $.fn.getOuterHtml = function () {
+ var $div = $( '<div>' ), html;
+ $div.append( $( this ).eq( 0 ).clone() );
+ html = $div.html();
+ $div.empty();
+ $div = undefined;
+ return html;
+ };
- // Messages that are reused in multiple tests
- mw.messages.set( {
- // The values for gender are not significant,
- // what matters is which of the values is choosen by the parser
- 'gender-msg': '$1: {{GENDER:$2|blue|pink|green}}',
+ // Messages that are reused in multiple tests
+ mw.messages.set( {
+ // The values for gender are not significant,
+ // what matters is which of the values is choosen by the parser
+ 'gender-msg': '$1: {{GENDER:$2|blue|pink|green}}',
- 'plural-msg': 'Found $1 {{PLURAL:$1|item|items}}',
+ 'plural-msg': 'Found $1 {{PLURAL:$1|item|items}}',
- // Assume the grammar form grammar_case_foo is not valid in any language
- 'grammar-msg': 'Przeszukaj {{GRAMMAR:grammar_case_foo|{{SITENAME}}}}',
+ // Assume the grammar form grammar_case_foo is not valid in any language
+ 'grammar-msg': 'Przeszukaj {{GRAMMAR:grammar_case_foo|{{SITENAME}}}}',
- 'formatnum-msg': '{{formatnum:$1}}',
+ 'formatnum-msg': '{{formatnum:$1}}',
- 'portal-url': 'Project:Community portal',
- 'see-portal-url': '{{Int:portal-url}} is an important community page.',
+ 'portal-url': 'Project:Community portal',
+ 'see-portal-url': '{{Int:portal-url}} is an important community page.',
- 'jquerymsg-test-statistics-users': '注册[[Special:ListUsers|用户]]',
+ 'jquerymsg-test-statistics-users': '注册[[Special:ListUsers|用户]]',
- 'jquerymsg-test-version-entrypoints-index-php': '[https://www.mediawiki.org/wiki/Manual:index.php index.php]',
+ 'jquerymsg-test-version-entrypoints-index-php': '[https://www.mediawiki.org/wiki/Manual:index.php index.php]',
- 'external-link-replace': 'Foo [$1 bar]'
- } );
+ 'external-link-replace': 'Foo [$1 bar]'
+ } );
- specialCharactersPageName = '"Who" wants to be a millionaire & live on \'Exotic Island\'?';
+ specialCharactersPageName = '"Who" wants to be a millionaire & live on \'Exotic Island\'?';
- expectedListUsers = '注册' + $( '<a>' ).attr( {
- title: 'Special:ListUsers',
- href: mw.util.wikiGetlink( 'Special:ListUsers' )
- } ).text( '用户' ).getOuterHtml();
-
- expectedEntrypoints = '<a href="https://www.mediawiki.org/wiki/Manual:index.php">index.php</a>';
- },
- teardown: function () {
- mw.language = this.orgMwLangauge;
- $.fn.getOuterHtml = oldGetOuterHtml;
- }
-}) );
+ expectedListUsers = '注册' + $( '<a>' ).attr( {
+ title: 'Special:ListUsers',
+ href: mw.util.wikiGetlink( 'Special:ListUsers' )
+ } ).text( '用户' ).getOuterHtml();
-function getMwLanguage( langCode, cb ) {
- if ( mwLanguageCache[langCode] !== undefined ) {
+ expectedEntrypoints = '<a href="https://www.mediawiki.org/wiki/Manual:index.php">index.php</a>';
+ },
+ teardown: function () {
+ mw.language = this.orgMwLangauge;
+ $.fn.getOuterHtml = oldGetOuterHtml;
+ }
+ } ) );
+
+ function getMwLanguage( langCode, cb ) {
+ if ( mwLanguageCache[langCode] !== undefined ) {
+ mwLanguageCache[langCode].add( cb );
+ return;
+ }
+ mwLanguageCache[langCode] = $.Callbacks( 'once memory' );
mwLanguageCache[langCode].add( cb );
- return;
+ $.ajax( {
+ url: mw.util.wikiScript( 'load' ),
+ data: {
+ skin: mw.config.get( 'skin' ),
+ lang: langCode,
+ debug: mw.config.get( 'debug' ),
+ modules: [
+ 'mediawiki.language.data',
+ 'mediawiki.language'
+ ].join( '|' ),
+ only: 'scripts'
+ },
+ dataType: 'script'
+ } ).done(function () {
+ mwLanguageCache[langCode].fire( mw.language );
+ } ).fail( function () {
+ mwLanguageCache[langCode].fire( false );
+ } );
}
- mwLanguageCache[langCode] = $.Callbacks( 'once memory' );
- mwLanguageCache[langCode].add( cb );
- $.ajax({
- url: mw.util.wikiScript( 'load' ),
- data: {
- skin: mw.config.get( 'skin' ),
- lang: langCode,
- debug: mw.config.get( 'debug' ),
- modules: [
- 'mediawiki.language.data',
- 'mediawiki.language'
- ].join( '|' ),
- only: 'scripts'
- },
- dataType: 'script'
- }).done( function () {
- mwLanguageCache[langCode].fire( mw.language );
- }).fail( function () {
- mwLanguageCache[langCode].fire( false );
- });
-}
-
-QUnit.test( 'Replace', 9, function ( assert ) {
- var parser = mw.jqueryMsg.getMessageFunction();
-
- mw.messages.set( 'simple', 'Foo $1 baz $2' );
-
- assert.equal( parser( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' );
- assert.equal( parser( 'simple', 'bar' ), 'Foo bar baz $2', 'Replacements with less substitutes' );
- assert.equal( parser( 'simple', 'bar', 'quux' ), 'Foo bar baz quux', 'Replacements with all substitutes' );
-
- mw.messages.set( 'plain-input', '<foo foo="foo">x$1y<</foo>z' );
-
- assert.equal(
- parser( 'plain-input', 'bar' ),
- '<foo foo="foo">xbary&lt;</foo>z',
- 'Input is not considered html'
- );
-
- mw.messages.set( 'plain-replace', 'Foo $1' );
-
- assert.equal(
- parser( 'plain-replace', '<bar bar="bar">></bar>' ),
- 'Foo <bar bar="bar">&gt;</bar>',
- 'Replacement is not considered html'
- );
-
- mw.messages.set( 'object-replace', 'Foo $1' );
-
- assert.equal(
- parser( 'object-replace', $( '<div class="bar">></div>' ) ),
- 'Foo <div class="bar">></div>',
- 'jQuery objects are preserved as raw html'
- );
-
- assert.equal(
- parser( 'object-replace', $( '<div class="bar">></div>' ).get( 0 ) ),
- 'Foo <div class="bar">></div>',
- 'HTMLElement objects are preserved as raw html'
- );
-
- assert.equal(
- parser( 'object-replace', $( '<div class="bar">></div>' ).toArray() ),
- 'Foo <div class="bar">></div>',
- 'HTMLElement[] arrays are preserved as raw html'
- );
-
- assert.equal(
- parser( 'external-link-replace', 'http://example.org/?x=y&z' ),
- 'Foo <a href="http://example.org/?x=y&z">bar</a>',
- 'Href is not double-escaped in wikilink function'
- );
-} );
-
-QUnit.test( 'Plural', 3, function ( assert ) {
- var parser = mw.jqueryMsg.getMessageFunction();
- assert.equal( parser( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' );
- assert.equal( parser( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' );
- assert.equal( parser( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' );
-} );
-
-QUnit.test( 'Gender', 11, function ( assert ) {
- // TODO: These tests should be for mw.msg once mw.msg integrated with mw.jqueryMsg
- // TODO: English may not be the best language for these tests. Use a language like Arabic or Russian
- var user = mw.user,
- parser = mw.jqueryMsg.getMessageFunction();
-
- user.options.set( 'gender', 'male' );
- assert.equal(
- parser( 'gender-msg', 'Bob', 'male' ),
- 'Bob: blue',
- 'Masculine from string "male"'
- );
- assert.equal(
- parser( 'gender-msg', 'Bob', user ),
- 'Bob: blue',
- 'Masculine from mw.user object'
- );
-
- user.options.set( 'gender', 'unknown' );
- assert.equal(
- parser( 'gender-msg', 'Foo', user ),
- 'Foo: green',
- 'Neutral from mw.user object' );
- assert.equal(
- parser( 'gender-msg', 'Alice', 'female' ),
- 'Alice: pink',
- 'Feminine from string "female"' );
- assert.equal(
- parser( 'gender-msg', 'User' ),
- 'User: green',
- 'Neutral when no parameter given' );
- assert.equal(
- parser( 'gender-msg', 'User', 'unknown' ),
- 'User: green',
- 'Neutral from string "unknown"'
- );
-
- mw.messages.set( 'gender-msg-one-form', '{{GENDER:$1|User}}: $2 {{PLURAL:$2|edit|edits}}' );
-
- assert.equal(
- parser( 'gender-msg-one-form', 'male', 10 ),
- 'User: 10 edits',
- 'Gender neutral and plural form'
- );
- assert.equal(
- parser( 'gender-msg-one-form', 'female', 1 ),
- 'User: 1 edit',
- 'Gender neutral and singular form'
- );
-
- mw.messages.set( 'gender-msg-lowercase', '{{gender:$1|he|she}} is awesome' );
- assert.equal(
- parser( 'gender-msg-lowercase', 'male' ),
- 'he is awesome',
- 'Gender masculine'
- );
- assert.equal(
- parser( 'gender-msg-lowercase', 'female' ),
- 'she is awesome',
- 'Gender feminine'
- );
-
- mw.messages.set( 'gender-msg-wrong', '{{gender}} test' );
- assert.equal(
- parser( 'gender-msg-wrong', 'female' ),
- ' test',
- 'Invalid syntax should result in {{gender}} simply being stripped away'
- );
-} );
-
-QUnit.test( 'Grammar', 2, function ( assert ) {
- var parser = mw.jqueryMsg.getMessageFunction();
-
- assert.equal( parser( 'grammar-msg' ), 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar Test with sitename' );
-
- mw.messages.set( 'grammar-msg-wrong-syntax', 'Przeszukaj {{GRAMMAR:grammar_case_xyz}}' );
- assert.equal( parser( 'grammar-msg-wrong-syntax' ), 'Przeszukaj ' , 'Grammar Test with wrong grammar template syntax' );
-} );
-
-QUnit.test( 'Match PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) {
- mw.messages.set( mw.libs.phpParserData.messages );
- $.each( mw.libs.phpParserData.tests, function ( i, test ) {
- QUnit.stop();
- getMwLanguage( test.lang, function ( langClass ) {
- QUnit.start();
- if ( !langClass ) {
- assert.ok( false, 'Language "' + test.lang + '" failed to load' );
- return;
- }
- mw.config.set( 'wgUserLanguage', test.lang ) ;
- var parser = new mw.jqueryMsg.parser( { language: langClass } );
- assert.equal(
- parser.parse( test.key, test.args ).html(),
- test.result,
- test.name
- );
- } );
+ QUnit.test( 'Replace', 7, function ( assert ) {
+ var parser = mw.jqueryMsg.getMessageFunction();
+
+ mw.messages.set( 'simple', 'Foo $1 baz $2' );
+
+ assert.equal( parser( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' );
+ assert.equal( parser( 'simple', 'bar' ), 'Foo bar baz $2', 'Replacements with less substitutes' );
+ assert.equal( parser( 'simple', 'bar', 'quux' ), 'Foo bar baz quux', 'Replacements with all substitutes' );
+
+ /* Temporarily disabling until 2013-03 --Kaldari
+ mw.messages.set( 'plain-input', '<foo foo="foo">x$1y<</foo>z' );
+
+ assert.equal(
+ parser( 'plain-input', 'bar' ),
+ '<foo foo="foo">xbary&lt;</foo>z',
+ 'Input is not considered html'
+ );
+
+ mw.messages.set( 'plain-replace', 'Foo $1' );
+
+ assert.equal(
+ parser( 'plain-replace', '<bar bar="bar">></bar>' ),
+ 'Foo <bar bar="bar">&gt;</bar>',
+ 'Replacement is not considered html'
+ );
+ */
+
+ mw.messages.set( 'object-replace', 'Foo $1' );
+
+ assert.equal(
+ parser( 'object-replace', $( '<div class="bar">></div>' ) ),
+ 'Foo <div class="bar">></div>',
+ 'jQuery objects are preserved as raw html'
+ );
+
+ assert.equal(
+ parser( 'object-replace', $( '<div class="bar">></div>' ).get( 0 ) ),
+ 'Foo <div class="bar">></div>',
+ 'HTMLElement objects are preserved as raw html'
+ );
+
+ assert.equal(
+ parser( 'object-replace', $( '<div class="bar">></div>' ).toArray() ),
+ 'Foo <div class="bar">></div>',
+ 'HTMLElement[] arrays are preserved as raw html'
+ );
+
+ assert.equal(
+ parser( 'external-link-replace', 'http://example.org/?x=y&z' ),
+ 'Foo <a href="http://example.org/?x=y&z">bar</a>',
+ 'Href is not double-escaped in wikilink function'
+ );
} );
-});
-
-QUnit.test( 'Links', 6, function ( assert ) {
- var parser = mw.jqueryMsg.getMessageFunction(),
- expectedDisambiguationsText,
- expectedMultipleBars,
- expectedSpecialCharacters;
-
- /*
- The below three are all identical to or based on real messages. For disambiguations-text,
- the bold was removed because it is not yet implemented.
- */
- assert.equal(
- parser( 'jquerymsg-test-statistics-users' ),
- expectedListUsers,
- 'Piped wikilink'
- );
-
- expectedDisambiguationsText = 'The following pages contain at least one link to a disambiguation page.\nThey may have to link to a more appropriate page instead.\nA page is treated as a disambiguation page if it uses a template that is linked from ' +
- $( '<a>' ).attr( {
- title: 'MediaWiki:Disambiguationspage',
- href: mw.util.wikiGetlink( 'MediaWiki:Disambiguationspage' )
- } ).text( 'MediaWiki:Disambiguationspage' ).getOuterHtml() + '.';
- mw.messages.set( 'disambiguations-text', 'The following pages contain at least one link to a disambiguation page.\nThey may have to link to a more appropriate page instead.\nA page is treated as a disambiguation page if it uses a template that is linked from [[MediaWiki:Disambiguationspage]].' );
- assert.equal(
- parser( 'disambiguations-text' ),
- expectedDisambiguationsText,
- 'Wikilink without pipe'
- );
-
- assert.equal(
- parser( 'jquerymsg-test-version-entrypoints-index-php' ),
- expectedEntrypoints,
- 'External link'
- );
-
- // Pipe trick is not supported currently, but should not parse as text either.
- mw.messages.set( 'pipe-trick', '[[Tampa, Florida|]]' );
- assert.equal(
- parser( 'pipe-trick' ),
- 'pipe-trick: Parse error at position 0 in input: [[Tampa, Florida|]]',
- 'Pipe trick should return error string.'
- );
-
- expectedMultipleBars = $( '<a>' ).attr( {
- title: 'Main Page',
- href: mw.util.wikiGetlink( 'Main Page' )
- } ).text( 'Main|Page' ).getOuterHtml();
- mw.messages.set( 'multiple-bars', '[[Main Page|Main|Page]]' );
- assert.equal(
- parser( 'multiple-bars' ),
- expectedMultipleBars,
- 'Bar in anchor'
- );
-
- expectedSpecialCharacters = $( '<a>' ).attr( {
- title: specialCharactersPageName,
- href: mw.util.wikiGetlink( specialCharactersPageName )
- } ).text( specialCharactersPageName ).getOuterHtml();
-
- mw.messages.set( 'special-characters', '[[' + specialCharactersPageName + ']]' );
- assert.equal(
- parser( 'special-characters' ),
- expectedSpecialCharacters,
- 'Special characters'
- );
-});
+ QUnit.test( 'Plural', 3, function ( assert ) {
+ var parser = mw.jqueryMsg.getMessageFunction();
-// Tests that {{-transformation vs. general parsing are done as requested
-QUnit.test( 'Curly brace transformation', 14, function ( assert ) {
- var formatText, formatParse, oldUserLang;
-
- oldUserLang = mw.config.get( 'wgUserLanguage' ) ;
-
- formatText= mw.jqueryMsg.getMessageFunction( {
- format: 'text'
+ assert.equal( parser( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' );
+ assert.equal( parser( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' );
+ assert.equal( parser( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' );
} );
- formatParse = mw.jqueryMsg.getMessageFunction( {
- format: 'parse'
+ QUnit.test( 'Gender', 11, function ( assert ) {
+ // TODO: These tests should be for mw.msg once mw.msg integrated with mw.jqueryMsg
+ // TODO: English may not be the best language for these tests. Use a language like Arabic or Russian
+ var user = mw.user,
+ parser = mw.jqueryMsg.getMessageFunction();
+
+ user.options.set( 'gender', 'male' );
+ assert.equal(
+ parser( 'gender-msg', 'Bob', 'male' ),
+ 'Bob: blue',
+ 'Masculine from string "male"'
+ );
+ assert.equal(
+ parser( 'gender-msg', 'Bob', user ),
+ 'Bob: blue',
+ 'Masculine from mw.user object'
+ );
+
+ user.options.set( 'gender', 'unknown' );
+ assert.equal(
+ parser( 'gender-msg', 'Foo', user ),
+ 'Foo: green',
+ 'Neutral from mw.user object' );
+ assert.equal(
+ parser( 'gender-msg', 'Alice', 'female' ),
+ 'Alice: pink',
+ 'Feminine from string "female"' );
+ assert.equal(
+ parser( 'gender-msg', 'User' ),
+ 'User: green',
+ 'Neutral when no parameter given' );
+ assert.equal(
+ parser( 'gender-msg', 'User', 'unknown' ),
+ 'User: green',
+ 'Neutral from string "unknown"'
+ );
+
+ mw.messages.set( 'gender-msg-one-form', '{{GENDER:$1|User}}: $2 {{PLURAL:$2|edit|edits}}' );
+
+ assert.equal(
+ parser( 'gender-msg-one-form', 'male', 10 ),
+ 'User: 10 edits',
+ 'Gender neutral and plural form'
+ );
+ assert.equal(
+ parser( 'gender-msg-one-form', 'female', 1 ),
+ 'User: 1 edit',
+ 'Gender neutral and singular form'
+ );
+
+ mw.messages.set( 'gender-msg-lowercase', '{{gender:$1|he|she}} is awesome' );
+ assert.equal(
+ parser( 'gender-msg-lowercase', 'male' ),
+ 'he is awesome',
+ 'Gender masculine'
+ );
+ assert.equal(
+ parser( 'gender-msg-lowercase', 'female' ),
+ 'she is awesome',
+ 'Gender feminine'
+ );
+
+ mw.messages.set( 'gender-msg-wrong', '{{gender}} test' );
+ assert.equal(
+ parser( 'gender-msg-wrong', 'female' ),
+ ' test',
+ 'Invalid syntax should result in {{gender}} simply being stripped away'
+ );
} );
- // When the expected result is the same in both modes
- function assertBothModes( parserArguments, expectedResult, assertMessage) {
- assert.equal( formatText.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'text\'' );
- assert.equal( formatParse.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'parse\'' );
- }
+ QUnit.test( 'Grammar', 2, function ( assert ) {
+ var parser = mw.jqueryMsg.getMessageFunction();
- assertBothModes( ['gender-msg', 'Bob', 'male'], 'Bob: blue', 'gender is resolved' );
-
- assertBothModes( ['plural-msg', 5], 'Found 5 items', 'plural is resolved' );
-
- assertBothModes( ['grammar-msg'], 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'grammar is resolved' );
-
- mw.config.set( 'wgUserLanguage', 'en' ) ;
- assertBothModes( ['formatnum-msg', '987654321.654321'], '987654321.654321', 'formatnum is resolved' );
-
- // Test non-{{ wikitext, where behavior differs
-
- // Wikilink
- assert.equal(
- formatText( 'jquerymsg-test-statistics-users' ),
- mw.messages.get( 'jquerymsg-test-statistics-users' ),
- 'Internal link message unchanged when format is \'text\''
- );
- assert.equal(
- formatParse( 'jquerymsg-test-statistics-users' ),
- expectedListUsers,
- 'Internal link message parsed when format is \'parse\''
- );
-
- // External link
- assert.equal(
- formatText( 'jquerymsg-test-version-entrypoints-index-php' ),
- mw.messages.get( 'jquerymsg-test-version-entrypoints-index-php' ),
- 'External link message unchanged when format is \'text\''
- );
- assert.equal(
- formatParse( 'jquerymsg-test-version-entrypoints-index-php' ),
- expectedEntrypoints,
- 'External link message processed when format is \'parse\''
- );
-
- // External link with parameter
- assert.equal(
- formatText( 'external-link-replace', 'http://example.com' ),
- 'Foo [http://example.com bar]',
- 'External link message only substitutes parameter when format is \'text\''
- );
- assert.equal(
- formatParse( 'external-link-replace', 'http://example.com' ),
- 'Foo <a href="http://example.com">bar</a>',
- 'External link message processed when format is \'parse\''
- );
-
- mw.config.set( 'wgUserLanguage', oldUserLang );
-} );
-
-QUnit.test( 'Int', 4, function ( assert ) {
- var parser = mw.jqueryMsg.getMessageFunction(),
- newarticletextSource = 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the [[{{Int:Helppage}}|help page]] for more info). If you are here by mistake, click your browser\'s back button.',
- expectedNewarticletext;
+ assert.equal( parser( 'grammar-msg' ), 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar Test with sitename' );
- mw.messages.set( 'helppage', 'Help:Contents' );
+ mw.messages.set( 'grammar-msg-wrong-syntax', 'Przeszukaj {{GRAMMAR:grammar_case_xyz}}' );
+ assert.equal( parser( 'grammar-msg-wrong-syntax' ), 'Przeszukaj ', 'Grammar Test with wrong grammar template syntax' );
+ } );
- expectedNewarticletext = 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the ' +
- $( '<a>' ).attr( {
- title: mw.msg( 'helppage' ),
- href: mw.util.wikiGetlink( mw.msg( 'helppage' ) )
- } ).text( 'help page' ).getOuterHtml() + ' for more info). If you are here by mistake, click your browser\'s back button.';
+ QUnit.test( 'Match PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) {
+ mw.messages.set( mw.libs.phpParserData.messages );
+ $.each( mw.libs.phpParserData.tests, function ( i, test ) {
+ QUnit.stop();
+ getMwLanguage( test.lang, function ( langClass ) {
+ QUnit.start();
+ if ( !langClass ) {
+ assert.ok( false, 'Language "' + test.lang + '" failed to load' );
+ return;
+ }
+ mw.config.set( 'wgUserLanguage', test.lang );
+ var parser = new mw.jqueryMsg.parser( { language: langClass } );
+ assert.equal(
+ parser.parse( test.key, test.args ).html(),
+ test.result,
+ test.name
+ );
+ } );
+ } );
+ } );
- mw.messages.set( 'newarticletext', newarticletextSource );
+ QUnit.test( 'Links', 6, function ( assert ) {
+ var parser = mw.jqueryMsg.getMessageFunction(),
+ expectedDisambiguationsText,
+ expectedMultipleBars,
+ expectedSpecialCharacters;
+
+ /*
+ The below three are all identical to or based on real messages. For disambiguations-text,
+ the bold was removed because it is not yet implemented.
+ */
+
+ assert.equal(
+ parser( 'jquerymsg-test-statistics-users' ),
+ expectedListUsers,
+ 'Piped wikilink'
+ );
+
+ expectedDisambiguationsText = 'The following pages contain at least one link to a disambiguation page.\nThey may have to link to a more appropriate page instead.\nA page is treated as a disambiguation page if it uses a template that is linked from ' +
+ $( '<a>' ).attr( {
+ title: 'MediaWiki:Disambiguationspage',
+ href: mw.util.wikiGetlink( 'MediaWiki:Disambiguationspage' )
+ } ).text( 'MediaWiki:Disambiguationspage' ).getOuterHtml() + '.';
+ mw.messages.set( 'disambiguations-text', 'The following pages contain at least one link to a disambiguation page.\nThey may have to link to a more appropriate page instead.\nA page is treated as a disambiguation page if it uses a template that is linked from [[MediaWiki:Disambiguationspage]].' );
+ assert.equal(
+ parser( 'disambiguations-text' ),
+ expectedDisambiguationsText,
+ 'Wikilink without pipe'
+ );
+
+ assert.equal(
+ parser( 'jquerymsg-test-version-entrypoints-index-php' ),
+ expectedEntrypoints,
+ 'External link'
+ );
+
+ // Pipe trick is not supported currently, but should not parse as text either.
+ mw.messages.set( 'pipe-trick', '[[Tampa, Florida|]]' );
+ assert.equal(
+ parser( 'pipe-trick' ),
+ 'pipe-trick: Parse error at position 0 in input: [[Tampa, Florida|]]',
+ 'Pipe trick should return error string.'
+ );
+
+ expectedMultipleBars = $( '<a>' ).attr( {
+ title: 'Main Page',
+ href: mw.util.wikiGetlink( 'Main Page' )
+ } ).text( 'Main|Page' ).getOuterHtml();
+ mw.messages.set( 'multiple-bars', '[[Main Page|Main|Page]]' );
+ assert.equal(
+ parser( 'multiple-bars' ),
+ expectedMultipleBars,
+ 'Bar in anchor'
+ );
+
+ expectedSpecialCharacters = $( '<a>' ).attr( {
+ title: specialCharactersPageName,
+ href: mw.util.wikiGetlink( specialCharactersPageName )
+ } ).text( specialCharactersPageName ).getOuterHtml();
+
+ mw.messages.set( 'special-characters', '[[' + specialCharactersPageName + ']]' );
+ assert.equal(
+ parser( 'special-characters' ),
+ expectedSpecialCharacters,
+ 'Special characters'
+ );
+ } );
- assert.equal(
- parser( 'newarticletext' ),
- expectedNewarticletext,
- 'Link with nested message'
- );
+// Tests that {{-transformation vs. general parsing are done as requested
+ QUnit.test( 'Curly brace transformation', 14, function ( assert ) {
+ var formatText, formatParse, oldUserLang;
- assert.equal(
- parser( 'see-portal-url' ),
- 'Project:Community portal is an important community page.',
- 'Nested message'
- );
+ oldUserLang = mw.config.get( 'wgUserLanguage' );
- mw.messages.set( 'newarticletext-lowercase',
- newarticletextSource.replace( 'Int:Helppage', 'int:helppage' ) );
+ formatText = mw.jqueryMsg.getMessageFunction( {
+ format: 'text'
+ } );
- assert.equal(
- parser( 'newarticletext-lowercase' ),
- expectedNewarticletext,
- 'Link with nested message, lowercase include'
- );
+ formatParse = mw.jqueryMsg.getMessageFunction( {
+ format: 'parse'
+ } );
- mw.messages.set( 'uses-missing-int', '{{int:doesnt-exist}}' );
+ // When the expected result is the same in both modes
+ function assertBothModes( parserArguments, expectedResult, assertMessage ) {
+ assert.equal( formatText.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'text\'' );
+ assert.equal( formatParse.apply( null, parserArguments ), expectedResult, assertMessage + ' when format is \'parse\'' );
+ }
+
+ assertBothModes( ['gender-msg', 'Bob', 'male'], 'Bob: blue', 'gender is resolved' );
+
+ assertBothModes( ['plural-msg', 5], 'Found 5 items', 'plural is resolved' );
+
+ assertBothModes( ['grammar-msg'], 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'grammar is resolved' );
+
+ mw.config.set( 'wgUserLanguage', 'en' );
+ assertBothModes( ['formatnum-msg', '987654321.654321'], '987,654,321.654', 'formatnum is resolved' );
+
+ // Test non-{{ wikitext, where behavior differs
+
+ // Wikilink
+ assert.equal(
+ formatText( 'jquerymsg-test-statistics-users' ),
+ mw.messages.get( 'jquerymsg-test-statistics-users' ),
+ 'Internal link message unchanged when format is \'text\''
+ );
+ assert.equal(
+ formatParse( 'jquerymsg-test-statistics-users' ),
+ expectedListUsers,
+ 'Internal link message parsed when format is \'parse\''
+ );
+
+ // External link
+ assert.equal(
+ formatText( 'jquerymsg-test-version-entrypoints-index-php' ),
+ mw.messages.get( 'jquerymsg-test-version-entrypoints-index-php' ),
+ 'External link message unchanged when format is \'text\''
+ );
+ assert.equal(
+ formatParse( 'jquerymsg-test-version-entrypoints-index-php' ),
+ expectedEntrypoints,
+ 'External link message processed when format is \'parse\''
+ );
+
+ // External link with parameter
+ assert.equal(
+ formatText( 'external-link-replace', 'http://example.com' ),
+ 'Foo [http://example.com bar]',
+ 'External link message only substitutes parameter when format is \'text\''
+ );
+ assert.equal(
+ formatParse( 'external-link-replace', 'http://example.com' ),
+ 'Foo <a href="http://example.com">bar</a>',
+ 'External link message processed when format is \'parse\''
+ );
+
+ mw.config.set( 'wgUserLanguage', oldUserLang );
+ } );
- assert.equal(
- parser( 'uses-missing-int' ),
- '[doesnt-exist]',
- 'int: where nested message does not exist'
- );
-});
+ QUnit.test( 'Int', 4, function ( assert ) {
+ var parser = mw.jqueryMsg.getMessageFunction(),
+ newarticletextSource = 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the [[{{Int:Helppage}}|help page]] for more info). If you are here by mistake, click your browser\'s back button.',
+ expectedNewarticletext;
+
+ mw.messages.set( 'helppage', 'Help:Contents' );
+
+ expectedNewarticletext = 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the ' +
+ $( '<a>' ).attr( {
+ title: mw.msg( 'helppage' ),
+ href: mw.util.wikiGetlink( mw.msg( 'helppage' ) )
+ } ).text( 'help page' ).getOuterHtml() + ' for more info). If you are here by mistake, click your browser\'s back button.';
+
+ mw.messages.set( 'newarticletext', newarticletextSource );
+
+ assert.equal(
+ parser( 'newarticletext' ),
+ expectedNewarticletext,
+ 'Link with nested message'
+ );
+
+ assert.equal(
+ parser( 'see-portal-url' ),
+ 'Project:Community portal is an important community page.',
+ 'Nested message'
+ );
+
+ mw.messages.set( 'newarticletext-lowercase',
+ newarticletextSource.replace( 'Int:Helppage', 'int:helppage' ) );
+
+ assert.equal(
+ parser( 'newarticletext-lowercase' ),
+ expectedNewarticletext,
+ 'Link with nested message, lowercase include'
+ );
+
+ mw.messages.set( 'uses-missing-int', '{{int:doesnt-exist}}' );
+
+ assert.equal(
+ parser( 'uses-missing-int' ),
+ '[doesnt-exist]',
+ 'int: where nested message does not exist'
+ );
+ } );
// Tests that getMessageFunction is used for non-plain messages with curly braces or
// square brackets, but not otherwise.
-QUnit.test( 'mw.Message.prototype.parser monkey-patch', 22, function ( assert ) {
- var oldGMF, outerCalled, innerCalled;
-
- mw.messages.set( {
- 'curly-brace': '{{int:message}}',
- 'single-square-bracket': '[https://www.mediawiki.org/ MediaWiki]',
- 'double-square-bracket': '[[Some page]]',
- 'regular': 'Other message'
- } );
+ QUnit.test( 'mw.Message.prototype.parser monkey-patch', 22, function ( assert ) {
+ var oldGMF, outerCalled, innerCalled;
+
+ mw.messages.set( {
+ 'curly-brace': '{{int:message}}',
+ 'single-square-bracket': '[https://www.mediawiki.org/ MediaWiki]',
+ 'double-square-bracket': '[[Some page]]',
+ 'regular': 'Other message'
+ } );
- oldGMF = mw.jqueryMsg.getMessageFunction;
+ oldGMF = mw.jqueryMsg.getMessageFunction;
- mw.jqueryMsg.getMessageFunction = function() {
- outerCalled = true;
- return function() {
- innerCalled = true;
+ mw.jqueryMsg.getMessageFunction = function () {
+ outerCalled = true;
+ return function () {
+ innerCalled = true;
+ };
};
- };
-
- function verifyGetMessageFunction( key, format, shouldCall ) {
- var message;
- outerCalled = false;
- innerCalled = false;
- message = mw.message( key );
- message[format]();
- assert.strictEqual( outerCalled, shouldCall, 'Outer function called for ' + key );
- assert.strictEqual( innerCalled, shouldCall, 'Inner function called for ' + key );
- }
- verifyGetMessageFunction( 'curly-brace', 'parse', true );
- verifyGetMessageFunction( 'curly-brace', 'plain', false );
+ function verifyGetMessageFunction( key, format, shouldCall ) {
+ var message;
+ outerCalled = false;
+ innerCalled = false;
+ message = mw.message( key );
+ message[format]();
+ assert.strictEqual( outerCalled, shouldCall, 'Outer function called for ' + key );
+ assert.strictEqual( innerCalled, shouldCall, 'Inner function called for ' + key );
+ }
- verifyGetMessageFunction( 'single-square-bracket', 'parse', true );
- verifyGetMessageFunction( 'single-square-bracket', 'plain', false );
+ verifyGetMessageFunction( 'curly-brace', 'parse', true );
+ verifyGetMessageFunction( 'curly-brace', 'plain', false );
- verifyGetMessageFunction( 'double-square-bracket', 'parse', true );
- verifyGetMessageFunction( 'double-square-bracket', 'plain', false );
+ verifyGetMessageFunction( 'single-square-bracket', 'parse', true );
+ verifyGetMessageFunction( 'single-square-bracket', 'plain', false );
- verifyGetMessageFunction( 'regular', 'parse', false );
- verifyGetMessageFunction( 'regular', 'plain', false );
+ verifyGetMessageFunction( 'double-square-bracket', 'parse', true );
+ verifyGetMessageFunction( 'double-square-bracket', 'plain', false );
- verifyGetMessageFunction( 'jquerymsg-test-pagetriage-del-talk-page-notify-summary', 'plain', false );
- verifyGetMessageFunction( 'jquerymsg-test-categorytree-collapse-bullet', 'plain', false );
- verifyGetMessageFunction( 'jquerymsg-test-wikieditor-toolbar-help-content-signature-result', 'plain', false );
+ verifyGetMessageFunction( 'regular', 'parse', false );
+ verifyGetMessageFunction( 'regular', 'plain', false );
- mw.jqueryMsg.getMessageFunction = oldGMF;
-} );
+ verifyGetMessageFunction( 'jquerymsg-test-pagetriage-del-talk-page-notify-summary', 'plain', false );
+ verifyGetMessageFunction( 'jquerymsg-test-categorytree-collapse-bullet', 'plain', false );
+ verifyGetMessageFunction( 'jquerymsg-test-wikieditor-toolbar-help-content-signature-result', 'plain', false );
+
+ mw.jqueryMsg.getMessageFunction = oldGMF;
+ } );
formatnumTests = [
{
lang: 'en',
number: 987654321.654321,
- result: '987654321.654321',
+ result: '987,654,321.654',
description: 'formatnum test for English, decimal seperator'
},
{
lang: 'ar',
number: 987654321.654321,
- result: '٩٨٧٦٥٤٣٢١٫٦٥٤٣٢١',
+ result: '٩٨٧٬٦٥٤٬٣٢١٫٦٥٤',
description: 'formatnum test for Arabic, with decimal seperator'
},
{
{
lang: 'nl',
number: 987654321.654321,
- result: '987654321,654321',
+ result: '987.654.321,654',
description: 'formatnum test for Nederlands, decimal seperator'
},
{
result: '-12,89',
description: 'formatnum test for Nederlands, negative number'
},
+ {
+ lang: 'nl',
+ number: '.89',
+ result: '0,89',
+ description: 'formatnum test for Nederlands'
+ },
{
lang: 'nl',
number: 'invalidnumber',
result: 'invalidnumber',
description: 'formatnum test for Nederlands, invalid number'
+ },
+ {
+ lang: 'ml',
+ number: '1000000000',
+ result: '1,00,00,00,000',
+ description: 'formatnum test for Malayalam'
+ },
+ {
+ lang: 'ml',
+ number: '-1000000000',
+ result: '-1,00,00,00,000',
+ description: 'formatnum test for Malayalam, negative number'
+ },
+ /*
+ * This will fail because of wrong pattern for ml in MW(different from CLDR)
+ {
+ lang: 'ml',
+ number: '1000000000.000',
+ result: '1,00,00,00,000.000',
+ description: 'formatnum test for Malayalam with decimal place'
+ },
+ */
+ {
+ lang: 'hi',
+ number: '123456789.123456789',
+ result: '१२,३४,५६,७८९',
+ description: 'formatnum test for Hindi'
+ },
+ {
+ lang: 'hi',
+ number: '१२,३४,५६,७८९',
+ result: '१२,३४,५६,७८९',
+ description: 'formatnum test for Hindi, Devanagari digits passed'
+ },
+ {
+ lang: 'hi',
+ number: '१२३४५६,७८९',
+ result: '123456',
+ integer: true,
+ description: 'formatnum test for Hindi, Devanagari digits passed to get integer value'
}
];
QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) {
+ mw.messages.set( 'formatnum-msg', '{{formatnum:$1}}' );
mw.messages.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
$.each( formatnumTests, function ( i, test ) {
QUnit.stop();
);
} );
} );
-});
+} );
}( mediaWiki, jQuery ) );
assert.deepEqual( ŝablono, orig, 'ŝablono' );
assert.deepEqual( \u015dablono, orig, '\\u015dablono' );
assert.deepEqual( \u015Dablono, orig, '\\u015Dablono' );
- });
+ } );
/*
// Not that we need this. ;)
}
for ( n = 0; n < maxn; n++ ) {
- expected = repeat('\n', n) + 'some text';
+ expected = repeat( '\n', n ) + 'some text';
- $textarea = $('<textarea>\n' + expected + '</textarea>');
+ $textarea = $( '<textarea>\n' + expected + '</textarea>' );
assert.equal( $textarea.val(), expected, 'Expecting ' + n + ' newlines (HTML contained ' + (n + 1) + ')' );
- $textarea = $('<textarea>').val( expected );
+ $textarea = $( '<textarea>' ).val( expected );
assert.equal( $textarea.val(), expected, 'Expecting ' + n + ' newlines (from DOM set with ' + n + ')' );
}
- });
+ } );
}( jQuery ) );
( function ( mw, $ ) {
+ 'use strict';
- QUnit.module( 'mediawiki.language', QUnit.newMwEnvironment({
+ QUnit.module( 'mediawiki.language', QUnit.newMwEnvironment( {
setup: function () {
this.liveLangData = mw.language.data.values;
mw.language.data.values = $.extend( true, {}, this.liveLangData );
teardown: function () {
mw.language.data.values = this.liveLangData;
}
- }) );
+ } ) );
QUnit.test( 'mw.language getData and setData', 2, function ( assert ) {
mw.language.setData( 'en', 'testkey', 'testvalue' );
- assert.equal( mw.language.getData( 'en', 'testkey' ), 'testvalue', 'Getter setter test for mw.language' );
- assert.equal( mw.language.getData( 'en', 'invalidkey' ), undefined, 'Getter setter test for mw.language with invalid key' );
+ assert.equal( mw.language.getData( 'en', 'testkey' ), 'testvalue', 'Getter setter test for mw.language' );
+ assert.equal( mw.language.getData( 'en', 'invalidkey' ), undefined, 'Getter setter test for mw.language with invalid key' );
} );
function grammarTest( langCode, test ) {
QUnit.test( 'Grammar test for lang=' + langCode, function ( assert ) {
QUnit.expect( test.length );
- for ( var i = 0 ; i < test.length; i++ ) {
+ for ( var i = 0; i < test.length; i++ ) {
assert.equal(
mw.language.convertGrammar( test[i].word, test[i].grammarForm ),
test[i].expected,
test[i].description
);
}
- });
+ } );
}
+ // These tests run only for the current UI language.
var grammarTests = {
bs: [
{
word: 'тесть',
grammarForm: 'genitive',
expected: 'тестя',
- description: 'Grammar test for genitive case'
+ description: 'Grammar test for genitive case, тесть -> тестя'
},
{
word: 'привилегия',
grammarForm: 'genitive',
expected: 'привилегии',
- description: 'Grammar test for genitive case'
+ description: 'Grammar test for genitive case, привилегия -> привилегии'
},
{
word: 'установка',
grammarForm: 'genitive',
expected: 'установки',
- description: 'Grammar test for genitive case'
+ description: 'Grammar test for genitive case, установка -> установки'
},
{
word: 'похоти',
grammarForm: 'genitive',
expected: 'похотей',
- description: 'Grammar test for genitive case'
+ description: 'Grammar test for genitive case, похоти -> похотей'
},
{
word: 'доводы',
grammarForm: 'genitive',
expected: 'доводов',
- description: 'Grammar test for genitive case'
+ description: 'Grammar test for genitive case, доводы -> доводов'
},
{
word: 'песчаник',
grammarForm: 'genitive',
expected: 'песчаника',
- description: 'Grammar test for genitive case'
+ description: 'Grammar test for genitive case, песчаник -> песчаника'
+ },
+ {
+ word: 'данные',
+ grammarForm: 'genitive',
+ expected: 'данных',
+ description: 'Grammar test for genitive case, данные -> данных'
+ },
+ {
+ word: 'тесть',
+ grammarForm: 'prepositional',
+ expected: 'тесте',
+ description: 'Grammar test for prepositional case, тесть -> тесте'
+ },
+ {
+ word: 'привилегия',
+ grammarForm: 'prepositional',
+ expected: 'привилегии',
+ description: 'Grammar test for prepositional case, привилегия -> привилегии'
+ },
+ {
+ word: 'установка',
+ grammarForm: 'prepositional',
+ expected: 'установке',
+ description: 'Grammar test for prepositional case, установка -> установке'
+ },
+ {
+ word: 'похоти',
+ grammarForm: 'prepositional',
+ expected: 'похотях',
+ description: 'Grammar test for prepositional case, похоти -> похотях'
+ },
+ {
+ word: 'доводы',
+ grammarForm: 'prepositional',
+ expected: 'доводах',
+ description: 'Grammar test for prepositional case, доводы -> доводах'
+ },
+ {
+ word: 'песчаник',
+ grammarForm: 'prepositional',
+ expected: 'песчанике',
+ description: 'Grammar test for prepositional case, песчаник -> песчанике'
+ },
+ {
+ word: 'данные',
+ grammarForm: 'prepositional',
+ expected: 'данных',
+ description: 'Grammar test for prepositional case, данные -> данных'
}
],
-
hu: [
{
word: 'Wikipédiá',
if ( langCode === mw.config.get( 'wgUserLanguage' ) ) {
grammarTest( langCode, test );
}
- });
+ } );
}( mediaWiki, jQuery ) );
( function ( mw, $ ) {
+ var specialCharactersPageName;
+
+ // Since QUnitTestResources.php loads both mediawiki and mediawiki.jqueryMsg as
+ // dependencies, this only tests the monkey-patched behavior with the two of them combined.
+
+ // See mediawiki.jqueryMsg.test.js for unit tests for jqueryMsg-specific functionality.
+
+ QUnit.module( 'mediawiki', QUnit.newMwEnvironment( {
+ setup: function () {
+ // Messages used in multiple tests
+ mw.messages.set( {
+ 'other-message': 'Other Message',
+ 'mediawiki-test-pagetriage-del-talk-page-notify-summary': 'Notifying author of deletion nomination for [[$1]]',
+ 'gender-plural-msg': '{{GENDER:$1|he|she|they}} {{PLURAL:$2|is|are}} awesome',
+ 'grammar-msg': 'Przeszukaj {{GRAMMAR:grammar_case_foo|{{SITENAME}}}}',
+ 'formatnum-msg': '{{formatnum:$1}}',
+ 'int-msg': 'Some {{int:other-message}}'
+ } );
-var specialCharactersPageName;
+ // For formatnum tests
+ mw.config.set( 'wgUserLanguage', 'en' );
+ specialCharactersPageName = '"Who" wants to be a millionaire & live on \'Exotic Island\'?';
+ }
+ } ) );
+
+ QUnit.test( 'Initial check', 8, function ( assert ) {
+ assert.ok( window.jQuery, 'jQuery defined' );
+ assert.ok( window.$, '$j defined' );
+ assert.ok( window.$j, '$j defined' );
+ assert.strictEqual( window.$, window.jQuery, '$ alias to jQuery' );
+ assert.strictEqual( window.$j, window.jQuery, '$j alias to jQuery' );
+
+ assert.ok( window.mediaWiki, 'mediaWiki defined' );
+ assert.ok( window.mw, 'mw defined' );
+ assert.strictEqual( window.mw, window.mediaWiki, 'mw alias to mediaWiki' );
+ } );
+
+ QUnit.test( 'mw.Map', 17, function ( assert ) {
+ var arry, conf, funky, globalConf, nummy, someValues;
+
+ assert.ok( mw.Map, 'mw.Map defined' );
+
+ conf = new mw.Map();
+ // Dummy variables
+ funky = function () {};
+ arry = [];
+ nummy = 7;
+
+ // Tests for input validation
+ assert.strictEqual( conf.get( 'inexistantKey' ), null, 'Map.get returns null if selection was a string and the key was not found' );
+ assert.strictEqual( conf.set( 'myKey', 'myValue' ), true, 'Map.set returns boolean true if a value was set for a valid key string' );
+ assert.strictEqual( conf.set( funky, 'Funky' ), false, 'Map.set returns boolean false if key was invalid (Function)' );
+ assert.strictEqual( conf.set( arry, 'Arry' ), false, 'Map.set returns boolean false if key was invalid (Array)' );
+ assert.strictEqual( conf.set( nummy, 'Nummy' ), false, 'Map.set returns boolean false if key was invalid (Number)' );
+ assert.equal( conf.get( 'myKey' ), 'myValue', 'Map.get returns a single value value correctly' );
+ assert.strictEqual( conf.get( nummy ), null, 'Map.get ruturns null if selection was invalid (Number)' );
+ assert.strictEqual( conf.get( funky ), null, 'Map.get ruturns null if selection was invalid (Function)' );
+
+ // Multiple values at once
+ someValues = {
+ 'foo': 'bar',
+ 'lorem': 'ipsum',
+ 'MediaWiki': true
+ };
+ assert.strictEqual( conf.set( someValues ), true, 'Map.set returns boolean true if multiple values were set by passing an object' );
+ assert.deepEqual( conf.get( ['foo', 'lorem'] ), {
+ 'foo': 'bar',
+ 'lorem': 'ipsum'
+ }, 'Map.get returns multiple values correctly as an object' );
+
+ assert.deepEqual( conf.get( ['foo', 'notExist'] ), {
+ 'foo': 'bar',
+ 'notExist': null
+ }, 'Map.get return includes keys that were not found as null values' );
+
+ assert.strictEqual( conf.exists( 'foo' ), true, 'Map.exists returns boolean true if a key exists' );
+ assert.strictEqual( conf.exists( 'notExist' ), false, 'Map.exists returns boolean false if a key does not exists' );
+
+ // Interacting with globals and accessing the values object
+ assert.strictEqual( conf.get(), conf.values, 'Map.get returns the entire values object by reference (if called without arguments)' );
+
+ conf.set( 'globalMapChecker', 'Hi' );
+
+ assert.ok( false === 'globalMapChecker' in window, 'new mw.Map did not store its values in the global window object by default' );
+
+ globalConf = new mw.Map( true );
+ globalConf.set( 'anotherGlobalMapChecker', 'Hello' );
+
+ assert.ok( 'anotherGlobalMapChecker' in window, 'new mw.Map( true ) did store its values in the global window object' );
+
+ // Whitelist this global variable for QUnit's 'noglobal' mode
+ if ( QUnit.config.noglobals ) {
+ QUnit.config.pollution.push( 'anotherGlobalMapChecker' );
+ }
+ } );
-// Since QUnitTestResources.php loads both mediawiki and mediawiki.jqueryMsg as
-// dependencies, this only tests the monkey-patched behavior with the two of them combined.
+ QUnit.test( 'mw.config', 1, function ( assert ) {
+ assert.ok( mw.config instanceof mw.Map, 'mw.config instance of mw.Map' );
+ } );
-// See mediawiki.jqueryMsg.test.js for unit tests for jqueryMsg-specific functionality.
+ QUnit.test( 'mw.message & mw.messages', 54, function ( assert ) {
+ var goodbye, hello;
-QUnit.module( 'mediawiki', QUnit.newMwEnvironment( {
- setup: function () {
- // Messages used in multiple tests
- mw.messages.set( {
- 'other-message': 'Other Message',
- 'mediawiki-test-pagetriage-del-talk-page-notify-summary': 'Notifying author of deletion nomination for [[$1]]',
- 'gender-plural-msg': '{{GENDER:$1|he|she|they}} {{PLURAL:$2|is|are}} awesome',
- 'grammar-msg': 'Przeszukaj {{GRAMMAR:grammar_case_foo|{{SITENAME}}}}',
- 'formatnum-msg': '{{formatnum:$1}}',
- 'int-msg': 'Some {{int:other-message}}'
- } );
+ // Convenience method for asserting the same result for multiple formats
+ function assertMultipleFormats( messageArguments, formats, expectedResult, assertMessage ) {
+ var len = formats.length, format, i;
+ for ( i = 0; i < len; i++ ) {
+ format = formats[i];
+ assert.equal( mw.message.apply( null, messageArguments )[format](), expectedResult, assertMessage + ' when format is ' + format );
+ }
+ }
- // For formatnum tests
- mw.config.set( 'wgUserLanguage', 'en' );
+ assert.ok( mw.messages, 'messages defined' );
+ assert.ok( mw.messages instanceof mw.Map, 'mw.messages instance of mw.Map' );
+ assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
- specialCharactersPageName = '"Who" wants to be a millionaire & live on \'Exotic Island\'?';
- }
-} ) );
-
-QUnit.test( 'Initial check', 8, function ( assert ) {
- assert.ok( window.jQuery, 'jQuery defined' );
- assert.ok( window.$, '$j defined' );
- assert.ok( window.$j, '$j defined' );
- assert.strictEqual( window.$, window.jQuery, '$ alias to jQuery' );
- assert.strictEqual( window.$j, window.jQuery, '$j alias to jQuery' );
-
- assert.ok( window.mediaWiki, 'mediaWiki defined' );
- assert.ok( window.mw, 'mw defined' );
- assert.strictEqual( window.mw, window.mediaWiki, 'mw alias to mediaWiki' );
-});
-
-QUnit.test( 'mw.Map', 17, function ( assert ) {
- var arry, conf, funky, globalConf, nummy, someValues;
-
- assert.ok( mw.Map, 'mw.Map defined' );
-
- conf = new mw.Map();
- // Dummy variables
- funky = function () {};
- arry = [];
- nummy = 7;
-
- // Tests for input validation
- assert.strictEqual( conf.get( 'inexistantKey' ), null, 'Map.get returns null if selection was a string and the key was not found' );
- assert.strictEqual( conf.set( 'myKey', 'myValue' ), true, 'Map.set returns boolean true if a value was set for a valid key string' );
- assert.strictEqual( conf.set( funky, 'Funky' ), false, 'Map.set returns boolean false if key was invalid (Function)' );
- assert.strictEqual( conf.set( arry, 'Arry' ), false, 'Map.set returns boolean false if key was invalid (Array)' );
- assert.strictEqual( conf.set( nummy, 'Nummy' ), false, 'Map.set returns boolean false if key was invalid (Number)' );
- assert.equal( conf.get( 'myKey' ), 'myValue', 'Map.get returns a single value value correctly' );
- assert.strictEqual( conf.get( nummy ), null, 'Map.get ruturns null if selection was invalid (Number)' );
- assert.strictEqual( conf.get( funky ), null, 'Map.get ruturns null if selection was invalid (Function)' );
-
- // Multiple values at once
- someValues = {
- 'foo': 'bar',
- 'lorem': 'ipsum',
- 'MediaWiki': true
- };
- assert.strictEqual( conf.set( someValues ), true, 'Map.set returns boolean true if multiple values were set by passing an object' );
- assert.deepEqual( conf.get( ['foo', 'lorem'] ), {
- 'foo': 'bar',
- 'lorem': 'ipsum'
- }, 'Map.get returns multiple values correctly as an object' );
-
- assert.deepEqual( conf.get( ['foo', 'notExist'] ), {
- 'foo': 'bar',
- 'notExist': null
- }, 'Map.get return includes keys that were not found as null values' );
-
- assert.strictEqual( conf.exists( 'foo' ), true, 'Map.exists returns boolean true if a key exists' );
- assert.strictEqual( conf.exists( 'notExist' ), false, 'Map.exists returns boolean false if a key does not exists' );
-
- // Interacting with globals and accessing the values object
- assert.strictEqual( conf.get(), conf.values, 'Map.get returns the entire values object by reference (if called without arguments)' );
-
- conf.set( 'globalMapChecker', 'Hi' );
-
- assert.ok( false === 'globalMapChecker' in window, 'new mw.Map did not store its values in the global window object by default' );
-
- globalConf = new mw.Map( true );
- globalConf.set( 'anotherGlobalMapChecker', 'Hello' );
-
- assert.ok( 'anotherGlobalMapChecker' in window, 'new mw.Map( true ) did store its values in the global window object' );
-
- // Whitelist this global variable for QUnit's 'noglobal' mode
- if ( QUnit.config.noglobals ) {
- QUnit.config.pollution.push( 'anotherGlobalMapChecker' );
- }
-});
+ hello = mw.message( 'hello' );
-QUnit.test( 'mw.config', 1, function ( assert ) {
- assert.ok( mw.config instanceof mw.Map, 'mw.config instance of mw.Map' );
-});
+ // https://bugzilla.wikimedia.org/show_bug.cgi?id=44459
+ assert.equal( hello.format, 'text', 'Message property "format" defaults to "text"' );
-QUnit.test( 'mw.message & mw.messages', 54, function ( assert ) {
- var goodbye, hello;
+ assert.strictEqual( hello.map, mw.messages, 'Message property "map" defaults to the global instance in mw.messages' );
+ assert.equal( hello.key, 'hello', 'Message property "key" (currect key)' );
+ assert.deepEqual( hello.parameters, [], 'Message property "parameters" defaults to an empty array' );
- // Convenience method for asserting the same result for multiple formats
- function assertMultipleFormats( messageArguments, formats, expectedResult, assertMessage) {
- var len = formats.length, format, i;
- for ( i = 0; i < len; i++ ) {
- format = formats[i];
- assert.equal( mw.message.apply( null, messageArguments )[format](), expectedResult, assertMessage + ' when format is ' + format);
- }
- }
+ // Todo
+ assert.ok( hello.params, 'Message prototype "params"' );
- assert.ok( mw.messages, 'messages defined' );
- assert.ok( mw.messages instanceof mw.Map, 'mw.messages instance of mw.Map' );
- assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
+ hello.format = 'plain';
+ assert.equal( hello.toString(), 'Hello <b>awesome</b> world', 'Message.toString returns the message as a string with the current "format"' );
- hello = mw.message( 'hello' );
+ assert.equal( hello.escaped(), 'Hello <b>awesome</b> world', 'Message.escaped returns the escaped message' );
+ assert.equal( hello.format, 'escaped', 'Message.escaped correctly updated the "format" property' );
- // https://bugzilla.wikimedia.org/show_bug.cgi?id=44459
- assert.equal( hello.format, 'text', 'Message property "format" defaults to "text"' );
+ assert.ok( mw.messages.set( 'escaped-with-curly-brace', '"{{SITENAME}}" is the home of {{int:other-message}}' ) );
+ assert.equal( mw.message( 'escaped-with-curly-brace' ).escaped(), mw.html.escape( '"' + mw.config.get( 'wgSiteName' ) + '" is the home of Other Message' ), 'Escaped format works correctly for curly brace message' );
- assert.strictEqual( hello.map, mw.messages, 'Message property "map" defaults to the global instance in mw.messages' );
- assert.equal( hello.key, 'hello', 'Message property "key" (currect key)' );
- assert.deepEqual( hello.parameters, [], 'Message property "parameters" defaults to an empty array' );
+ assert.ok( mw.messages.set( 'escaped-with-square-brackets', 'Visit the [[Project:Community portal|community portal]] & [[Project:Help desk|help desk]]' ) );
+ assert.equal( mw.message( 'escaped-with-square-brackets' ).escaped(), 'Visit the [[Project:Community portal|community portal]] & [[Project:Help desk|help desk]]', 'Escaped format works correctly for square bracket message' );
- // Todo
- assert.ok( hello.params, 'Message prototype "params"' );
+ hello.parse();
+ assert.equal( hello.format, 'parse', 'Message.parse correctly updated the "format" property' );
- hello.format = 'plain';
- assert.equal( hello.toString(), 'Hello <b>awesome</b> world', 'Message.toString returns the message as a string with the current "format"' );
+ hello.plain();
+ assert.equal( hello.format, 'plain', 'Message.plain correctly updated the "format" property' );
- assert.equal( hello.escaped(), 'Hello <b>awesome</b> world', 'Message.escaped returns the escaped message' );
- assert.equal( hello.format, 'escaped', 'Message.escaped correctly updated the "format" property' );
+ hello.text();
+ assert.equal( hello.format, 'text', 'Message.text correctly updated the "format" property' );
- assert.ok( mw.messages.set( 'escaped-with-curly-brace', '"{{SITENAME}}" is the home of {{int:other-message}}' ) );
- assert.equal( mw.message( 'escaped-with-curly-brace' ).escaped(), mw.html.escape( '"' + mw.config.get( 'wgSiteName') + '" is the home of Other Message' ), 'Escaped format works correctly for curly brace message' );
+ assert.strictEqual( hello.exists(), true, 'Message.exists returns true for existing messages' );
- assert.ok( mw.messages.set( 'escaped-with-square-brackets', 'Visit the [[Project:Community portal|community portal]] & [[Project:Help desk|help desk]]' ) );
- assert.equal( mw.message( 'escaped-with-square-brackets' ).escaped(), 'Visit the [[Project:Community portal|community portal]] & [[Project:Help desk|help desk]]', 'Escaped format works correctly for square bracket message' );
+ goodbye = mw.message( 'goodbye' );
+ assert.strictEqual( goodbye.exists(), false, 'Message.exists returns false for nonexistent messages' );
- hello.parse();
- assert.equal( hello.format, 'parse', 'Message.parse correctly updated the "format" property' );
+ assertMultipleFormats( ['goodbye'], ['plain', 'text'], '<goodbye>', 'Message.toString returns <key> if key does not exist' );
+ // bug 30684
+ assertMultipleFormats( ['goodbye'], ['parse', 'escaped'], '<goodbye>', 'Message.toString returns properly escaped <key> if key does not exist' );
- hello.plain();
- assert.equal( hello.format, 'plain', 'Message.plain correctly updated the "format" property' );
+ assert.ok( mw.messages.set( 'plural-test-msg', 'There {{PLURAL:$1|is|are}} $1 {{PLURAL:$1|result|results}}' ), 'mw.messages.set: Register' );
+ assertMultipleFormats( ['plural-test-msg', 6], ['text', 'parse', 'escaped'], 'There are 6 results', 'plural get resolved' );
+ assert.equal( mw.message( 'plural-test-msg', 6 ).plain(), 'There {{PLURAL:6|is|are}} 6 {{PLURAL:6|result|results}}', 'Parameter is substituted but plural is not resolved in plain' );
- hello.text();
- assert.equal( hello.format, 'text', 'Message.text correctly updated the "format" property' );
+ assertMultipleFormats( ['mediawiki-test-pagetriage-del-talk-page-notify-summary'], ['plain', 'text'], mw.messages.get( 'mediawiki-test-pagetriage-del-talk-page-notify-summary' ), 'Double square brackets with no parameters unchanged' );
- assert.strictEqual( hello.exists(), true, 'Message.exists returns true for existing messages' );
+ assertMultipleFormats( ['mediawiki-test-pagetriage-del-talk-page-notify-summary', specialCharactersPageName], ['plain', 'text'], 'Notifying author of deletion nomination for [[' + specialCharactersPageName + ']]', 'Double square brackets with one parameter' );
- goodbye = mw.message( 'goodbye' );
- assert.strictEqual( goodbye.exists(), false, 'Message.exists returns false for nonexistent messages' );
+ assert.equal( mw.message( 'mediawiki-test-pagetriage-del-talk-page-notify-summary', specialCharactersPageName ).escaped(), 'Notifying author of deletion nomination for [[' + mw.html.escape( specialCharactersPageName ) + ']]', 'Double square brackets with one parameter, when escaped' );
- assertMultipleFormats( ['goodbye'], ['plain', 'text'], '<goodbye>', 'Message.toString returns <key> if key does not exist' );
- // bug 30684
- assertMultipleFormats( ['goodbye'], ['parse', 'escaped'], '<goodbye>', 'Message.toString returns properly escaped <key> if key does not exist' );
- assert.ok( mw.messages.set( 'plural-test-msg', 'There {{PLURAL:$1|is|are}} $1 {{PLURAL:$1|result|results}}' ), 'mw.messages.set: Register' );
- assertMultipleFormats( ['plural-test-msg', 6], ['text', 'parse', 'escaped'], 'There are 6 results', 'plural get resolved' );
- assert.equal( mw.message( 'plural-test-msg', 6 ).plain(), 'There {{PLURAL:6|is|are}} 6 {{PLURAL:6|result|results}}', 'Parameter is substituted but plural is not resolved in plain' );
+ assert.ok( mw.messages.set( 'mediawiki-test-categorytree-collapse-bullet', '[<b>−</b>]' ), 'mw.messages.set: Register' );
+ assert.equal( mw.message( 'mediawiki-test-categorytree-collapse-bullet' ).plain(), mw.messages.get( 'mediawiki-test-categorytree-collapse-bullet' ), 'Single square brackets unchanged in plain mode' );
- assertMultipleFormats( ['mediawiki-test-pagetriage-del-talk-page-notify-summary'], ['plain', 'text'], mw.messages.get( 'mediawiki-test-pagetriage-del-talk-page-notify-summary' ), 'Double square brackets with no parameters unchanged' );
+ assert.ok( mw.messages.set( 'mediawiki-test-wikieditor-toolbar-help-content-signature-result', '<a href=\'#\' title=\'{{#special:mypage}}\'>Username</a> (<a href=\'#\' title=\'{{#special:mytalk}}\'>talk</a>)' ) );
+ assert.equal( mw.message( 'mediawiki-test-wikieditor-toolbar-help-content-signature-result' ).plain(), mw.messages.get( 'mediawiki-test-wikieditor-toolbar-help-content-signature-result' ), 'HTML message with curly braces is not changed in plain mode' );
- assertMultipleFormats( ['mediawiki-test-pagetriage-del-talk-page-notify-summary', specialCharactersPageName], ['plain', 'text'], 'Notifying author of deletion nomination for [[' + specialCharactersPageName + ']]', 'Double square brackets with one parameter' );
+ assertMultipleFormats( ['gender-plural-msg', 'male', 1], ['text', 'parse', 'escaped'], 'he is awesome', 'Gender and plural are resolved' );
+ assert.equal( mw.message( 'gender-plural-msg', 'male', 1 ).plain(), '{{GENDER:male|he|she|they}} {{PLURAL:1|is|are}} awesome', 'Parameters are substituted, but gender and plural are not resolved in plain mode' );
- assert.equal( mw.message( 'mediawiki-test-pagetriage-del-talk-page-notify-summary', specialCharactersPageName ).escaped(), 'Notifying author of deletion nomination for [[' + mw.html.escape( specialCharactersPageName ) + ']]', 'Double square brackets with one parameter, when escaped' );
+ assert.equal( mw.message( 'grammar-msg' ).plain(), mw.messages.get( 'grammar-msg' ), 'Grammar is not resolved in plain mode' );
+ assertMultipleFormats( ['grammar-msg'], ['text', 'parse'], 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar is resolved' );
+ assert.equal( mw.message( 'grammar-msg' ).escaped(), 'Przeszukaj ' + mw.html.escape( mw.config.get( 'wgSiteName' ) ), 'Grammar is resolved in escaped mode' );
+ assertMultipleFormats( ['formatnum-msg', '987654321.654321'], ['text', 'parse', 'escaped'], '987,654,321.654', 'formatnum is resolved' );
+ assert.equal( mw.message( 'formatnum-msg' ).plain(), mw.messages.get( 'formatnum-msg' ), 'formatnum is not resolved in plain mode' );
- assert.ok( mw.messages.set( 'mediawiki-test-categorytree-collapse-bullet', '[<b>−</b>]' ), 'mw.messages.set: Register' );
- assert.equal( mw.message( 'mediawiki-test-categorytree-collapse-bullet' ).plain(), mw.messages.get( 'mediawiki-test-categorytree-collapse-bullet' ), 'Single square brackets unchanged in plain mode' );
+ assertMultipleFormats( ['int-msg'], ['text', 'parse', 'escaped'], 'Some Other Message', 'int is resolved' );
+ assert.equal( mw.message( 'int-msg' ).plain(), mw.messages.get( 'int-msg' ), 'int is not resolved in plain mode' );
+ } );
- assert.ok( mw.messages.set( 'mediawiki-test-wikieditor-toolbar-help-content-signature-result', '<a href=\'#\' title=\'{{#special:mypage}}\'>Username</a> (<a href=\'#\' title=\'{{#special:mytalk}}\'>talk</a>)' ) );
- assert.equal( mw.message( 'mediawiki-test-wikieditor-toolbar-help-content-signature-result' ).plain(), mw.messages.get( 'mediawiki-test-wikieditor-toolbar-help-content-signature-result' ), 'HTML message with curly braces is not changed in plain mode' );
+ QUnit.test( 'mw.msg', 14, function ( assert ) {
+ assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
+ assert.equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'Gets message with default options (existing message)' );
+ assert.equal( mw.msg( 'goodbye' ), '<goodbye>', 'Gets message with default options (nonexistent message)' );
- assertMultipleFormats( ['gender-plural-msg', 'male', 1], ['text', 'parse', 'escaped'], 'he is awesome', 'Gender and plural are resolved' );
- assert.equal( mw.message( 'gender-plural-msg', 'male', 1 ).plain(), '{{GENDER:male|he|she|they}} {{PLURAL:1|is|are}} awesome', 'Parameters are substituted, but gender and plural are not resolved in plain mode' );
+ assert.ok( mw.messages.set( 'plural-item', 'Found $1 {{PLURAL:$1|item|items}}' ) );
+ assert.equal( mw.msg( 'plural-item', 5 ), 'Found 5 items', 'Apply plural for count 5' );
+ assert.equal( mw.msg( 'plural-item', 0 ), 'Found 0 items', 'Apply plural for count 0' );
+ assert.equal( mw.msg( 'plural-item', 1 ), 'Found 1 item', 'Apply plural for count 1' );
- assert.equal( mw.message( 'grammar-msg' ).plain(), mw.messages.get( 'grammar-msg' ), 'Grammar is not resolved in plain mode' );
- assertMultipleFormats( ['grammar-msg'], ['text', 'parse'], 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar is resolved' );
- assert.equal( mw.message( 'grammar-msg' ).escaped(), 'Przeszukaj ' + mw.html.escape( mw.config.get( 'wgSiteName' ) ), 'Grammar is resolved in escaped mode' );
+ assert.equal( mw.msg( 'mediawiki-test-pagetriage-del-talk-page-notify-summary', specialCharactersPageName ), 'Notifying author of deletion nomination for [[' + specialCharactersPageName + ']]', 'Double square brackets in mw.msg one parameter' );
- assertMultipleFormats( ['formatnum-msg', '987654321.654321'], ['text', 'parse', 'escaped'], '987654321.654321', 'formatnum is resolved' );
- assert.equal( mw.message( 'formatnum-msg' ).plain(), mw.messages.get( 'formatnum-msg' ), 'formatnum is not resolved in plain mode' );
+ assert.equal( mw.msg( 'gender-plural-msg', 'male', 1 ), 'he is awesome', 'Gender test for male, plural count 1' );
+ assert.equal( mw.msg( 'gender-plural-msg', 'female', '1' ), 'she is awesome', 'Gender test for female, plural count 1' );
+ assert.equal( mw.msg( 'gender-plural-msg', 'unknown', 10 ), 'they are awesome', 'Gender test for neutral, plural count 10' );
- assertMultipleFormats( ['int-msg'], ['text', 'parse', 'escaped'], 'Some Other Message', 'int is resolved' );
- assert.equal( mw.message( 'int-msg' ).plain(), mw.messages.get( 'int-msg' ), 'int is not resolved in plain mode' );
-});
+ assert.equal( mw.msg( 'grammar-msg' ), 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar is resolved' );
-QUnit.test( 'mw.msg', 14, function ( assert ) {
- assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
- assert.equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'Gets message with default options (existing message)' );
- assert.equal( mw.msg( 'goodbye' ), '<goodbye>', 'Gets message with default options (nonexistent message)' );
+ assert.equal( mw.msg( 'formatnum-msg', '987654321.654321' ), '987,654,321.654', 'formatnum is resolved' );
- assert.ok( mw.messages.set( 'plural-item' , 'Found $1 {{PLURAL:$1|item|items}}' ) );
- assert.equal( mw.msg( 'plural-item', 5 ), 'Found 5 items', 'Apply plural for count 5' );
- assert.equal( mw.msg( 'plural-item', 0 ), 'Found 0 items', 'Apply plural for count 0' );
- assert.equal( mw.msg( 'plural-item', 1 ), 'Found 1 item', 'Apply plural for count 1' );
+ assert.equal( mw.msg( 'int-msg' ), 'Some Other Message', 'int is resolved' );
+ } );
- assert.equal( mw.msg( 'mediawiki-test-pagetriage-del-talk-page-notify-summary', specialCharactersPageName ), 'Notifying author of deletion nomination for [[' + specialCharactersPageName + ']]', 'Double square brackets in mw.msg one parameter' );
+ /**
+ * The sync style load test (for @import). This is, in a way, also an open bug for
+ * ResourceLoader ("execute js after styles are loaded"), but browsers don't offer a
+ * way to get a callback from when a stylesheet is loaded (that is, including any
+ * @import rules inside). To work around this, we'll have a little time loop to check
+ * if the styles apply.
+ * Note: This test originally used new Image() and onerror to get a callback
+ * when the url is loaded, but that is fragile since it doesn't monitor the
+ * same request as the css @import, and Safari 4 has issues with
+ * onerror/onload not being fired at all in weird cases like this.
+ */
+ function assertStyleAsync( assert, $element, prop, val, fn ) {
+ var styleTestStart,
+ el = $element.get( 0 ),
+ styleTestTimeout = ( QUnit.config.testTimeout - 200 ) || 5000;
- assert.equal( mw.msg( 'gender-plural-msg', 'male', 1 ), 'he is awesome', 'Gender test for male, plural count 1' );
- assert.equal( mw.msg( 'gender-plural-msg', 'female', '1' ), 'she is awesome', 'Gender test for female, plural count 1' );
- assert.equal( mw.msg( 'gender-plural-msg', 'unknown', 10 ), 'they are awesome', 'Gender test for neutral, plural count 10' );
+ function isCssImportApplied() {
+ // Trigger reflow, repaint, redraw, whatever (cross-browser)
+ var x = $element.css( 'height' );
+ x = el.innerHTML;
+ el.className = el.className;
+ x = document.documentElement.clientHeight;
- assert.equal( mw.msg( 'grammar-msg' ), 'Przeszukaj ' + mw.config.get( 'wgSiteName'), 'Grammar is resolved' );
+ return $element.css( prop ) === val;
+ }
- assert.equal( mw.msg( 'formatnum-msg', '987654321.654321' ), '987654321.654321', 'formatnum is resolved' );
+ function styleTestLoop() {
+ var styleTestSince = new Date().getTime() - styleTestStart;
+ // If it is passing or if we timed out, run the real test and stop the loop
+ if ( isCssImportApplied() || styleTestSince > styleTestTimeout ) {
+ assert.equal( $element.css( prop ), val,
+ 'style "' + prop + ': ' + val + '" from url is applied (after ' + styleTestSince + 'ms)'
+ );
- assert.equal( mw.msg( 'int-msg' ), 'Some Other Message', 'int is resolved' );
-});
+ if ( fn ) {
+ fn();
+ }
-/**
- * The sync style load test (for @import). This is, in a way, also an open bug for
- * ResourceLoader ("execute js after styles are loaded"), but browsers don't offer a
- * way to get a callback from when a stylesheet is loaded (that is, including any
- * @import rules inside). To work around this, we'll have a little time loop to check
- * if the styles apply.
- * Note: This test originally used new Image() and onerror to get a callback
- * when the url is loaded, but that is fragile since it doesn't monitor the
- * same request as the css @import, and Safari 4 has issues with
- * onerror/onload not being fired at all in weird cases like this.
- */
-function assertStyleAsync( assert, $element, prop, val, fn ) {
- var styleTestStart,
- el = $element.get( 0 ),
- styleTestTimeout = ( QUnit.config.testTimeout - 200 ) || 5000;
+ return;
+ }
+ // Otherwise, keep polling
+ setTimeout( styleTestLoop, 150 );
+ }
- function isCssImportApplied() {
- // Trigger reflow, repaint, redraw, whatever (cross-browser)
- var x = $element.css( 'height' );
- x = el.innerHTML;
- el.className = el.className;
- x = document.documentElement.clientHeight;
+ // Start the loop
+ styleTestStart = new Date().getTime();
+ styleTestLoop();
+ }
- return $element.css( prop ) === val;
+ function urlStyleTest( selector, prop, val ) {
+ return QUnit.fixurl(
+ mw.config.get( 'wgScriptPath' ) +
+ '/tests/qunit/data/styleTest.css.php?' +
+ $.param( {
+ selector: selector,
+ prop: prop,
+ val: val
+ } )
+ );
}
- function styleTestLoop() {
- var styleTestSince = new Date().getTime() - styleTestStart;
- // If it is passing or if we timed out, run the real test and stop the loop
- if ( isCssImportApplied() || styleTestSince > styleTestTimeout ) {
- assert.equal( $element.css( prop ), val,
- 'style "' + prop + ': ' + val + '" from url is applied (after ' + styleTestSince + 'ms)'
- );
+ QUnit.asyncTest( 'mw.loader', 2, function ( assert ) {
+ var isAwesomeDone;
- if ( fn ) {
- fn();
- }
+ mw.loader.testCallback = function () {
+ QUnit.start();
+ assert.strictEqual( isAwesomeDone, undefined, 'Implementing module is.awesome: isAwesomeDone should still be undefined' );
+ isAwesomeDone = true;
+ };
- return;
- }
- // Otherwise, keep polling
- setTimeout( styleTestLoop, 150 );
- }
+ mw.loader.implement( 'test.callback', [QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/callMwLoaderTestCallback.js' )], {}, {} );
- // Start the loop
- styleTestStart = new Date().getTime();
- styleTestLoop();
-}
-
-function urlStyleTest( selector, prop, val ) {
- return QUnit.fixurl(
- mw.config.get( 'wgScriptPath' ) +
- '/tests/qunit/data/styleTest.css.php?' +
- $.param( {
- selector: selector,
- prop: prop,
- val: val
- } )
- );
-}
-
-QUnit.asyncTest( 'mw.loader', 2, function ( assert ) {
- var isAwesomeDone;
-
- mw.loader.testCallback = function () {
- QUnit.start();
- assert.strictEqual( isAwesomeDone, undefined, 'Implementing module is.awesome: isAwesomeDone should still be undefined');
- isAwesomeDone = true;
- };
-
- mw.loader.implement( 'test.callback', [QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/callMwLoaderTestCallback.js' )], {}, {} );
-
- mw.loader.using( 'test.callback', function () {
-
- // /sample/awesome.js declares the "mw.loader.testCallback" function
- // which contains a call to start() and ok()
- assert.strictEqual( isAwesomeDone, true, 'test.callback module should\'ve caused isAwesomeDone to be true' );
- delete mw.loader.testCallback;
-
- }, function () {
- QUnit.start();
- assert.ok( false, 'Error callback fired while loader.using "test.callback" module' );
- });
-});
-
-QUnit.test( 'mw.loader.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) {
- var $element = $( '<div class="mw-test-implement-a"></div>' ).appendTo( '#qunit-fixture' );
-
- assert.notEqual(
- $element.css( 'float' ),
- 'right',
- 'style is clear'
- );
-
- mw.loader.implement(
- 'test.implement.a',
- function () {
- assert.equal(
- $element.css( 'float' ),
- 'right',
- 'style is applied'
- );
- },
- {
- 'all': '.mw-test-implement-a { float: right; }'
- },
- {}
- );
-
- mw.loader.load([
- 'test.implement.a'
- ]);
-} );
-
-QUnit.asyncTest( 'mw.loader.implement( styles={ "url": { <media>: [url, ..] } } )', 7, function ( assert ) {
- var $element1 = $( '<div class="mw-test-implement-b1"></div>' ).appendTo( '#qunit-fixture' ),
- $element2 = $( '<div class="mw-test-implement-b2"></div>' ).appendTo( '#qunit-fixture' ),
- $element3 = $( '<div class="mw-test-implement-b3"></div>' ).appendTo( '#qunit-fixture' );
-
- assert.notEqual(
- $element1.css( 'text-align' ),
- 'center',
- 'style is clear'
- );
- assert.notEqual(
- $element2.css( 'float' ),
- 'left',
- 'style is clear'
- );
- assert.notEqual(
- $element3.css( 'text-align' ),
- 'right',
- 'style is clear'
- );
-
- mw.loader.implement(
- 'test.implement.b',
- function () {
- // Note: QUnit.start() must only be called when the entire test is
- // complete. So, make sure that we don't start until *both*
- // assertStyleAsync calls have completed.
- var pending = 2;
- assertStyleAsync( assert, $element2, 'float', 'left', function () {
- assert.notEqual( $element1.css( 'text-align' ), 'center', 'print style is not applied' );
-
- pending--;
- if ( pending === 0 ) {
- QUnit.start();
- }
- } );
- assertStyleAsync( assert, $element3, 'float', 'right', function () {
- assert.notEqual( $element1.css( 'text-align' ), 'center', 'print style is not applied' );
+ mw.loader.using( 'test.callback', function () {
- pending--;
- if ( pending === 0 ) {
- QUnit.start();
+ // /sample/awesome.js declares the "mw.loader.testCallback" function
+ // which contains a call to start() and ok()
+ assert.strictEqual( isAwesomeDone, true, 'test.callback module should\'ve caused isAwesomeDone to be true' );
+ delete mw.loader.testCallback;
+
+ }, function () {
+ QUnit.start();
+ assert.ok( false, 'Error callback fired while loader.using "test.callback" module' );
+ } );
+ } );
+
+ QUnit.test( 'mw.loader.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) {
+ var $element = $( '<div class="mw-test-implement-a"></div>' ).appendTo( '#qunit-fixture' );
+
+ assert.notEqual(
+ $element.css( 'float' ),
+ 'right',
+ 'style is clear'
+ );
+
+ mw.loader.implement(
+ 'test.implement.a',
+ function () {
+ assert.equal(
+ $element.css( 'float' ),
+ 'right',
+ 'style is applied'
+ );
+ },
+ {
+ 'all': '.mw-test-implement-a { float: right; }'
+ },
+ {}
+ );
+
+ mw.loader.load( [
+ 'test.implement.a'
+ ] );
+ } );
+
+ QUnit.asyncTest( 'mw.loader.implement( styles={ "url": { <media>: [url, ..] } } )', 7, function ( assert ) {
+ var $element1 = $( '<div class="mw-test-implement-b1"></div>' ).appendTo( '#qunit-fixture' ),
+ $element2 = $( '<div class="mw-test-implement-b2"></div>' ).appendTo( '#qunit-fixture' ),
+ $element3 = $( '<div class="mw-test-implement-b3"></div>' ).appendTo( '#qunit-fixture' );
+
+ assert.notEqual(
+ $element1.css( 'text-align' ),
+ 'center',
+ 'style is clear'
+ );
+ assert.notEqual(
+ $element2.css( 'float' ),
+ 'left',
+ 'style is clear'
+ );
+ assert.notEqual(
+ $element3.css( 'text-align' ),
+ 'right',
+ 'style is clear'
+ );
+
+ mw.loader.implement(
+ 'test.implement.b',
+ function () {
+ // Note: QUnit.start() must only be called when the entire test is
+ // complete. So, make sure that we don't start until *both*
+ // assertStyleAsync calls have completed.
+ var pending = 2;
+ assertStyleAsync( assert, $element2, 'float', 'left', function () {
+ assert.notEqual( $element1.css( 'text-align' ), 'center', 'print style is not applied' );
+
+ pending--;
+ if ( pending === 0 ) {
+ QUnit.start();
+ }
+ } );
+ assertStyleAsync( assert, $element3, 'float', 'right', function () {
+ assert.notEqual( $element1.css( 'text-align' ), 'center', 'print style is not applied' );
+
+ pending--;
+ if ( pending === 0 ) {
+ QUnit.start();
+ }
+ } );
+ },
+ {
+ 'url': {
+ 'print': [urlStyleTest( '.mw-test-implement-b1', 'text-align', 'center' )],
+ 'screen': [
+ // bug 40834: Make sure it actually works with more than 1 stylesheet reference
+ urlStyleTest( '.mw-test-implement-b2', 'float', 'left' ),
+ urlStyleTest( '.mw-test-implement-b3', 'float', 'right' )
+ ]
}
- } );
- },
- {
- 'url': {
- 'print': [urlStyleTest( '.mw-test-implement-b1', 'text-align', 'center' )],
- 'screen': [
- // bug 40834: Make sure it actually works with more than 1 stylesheet reference
- urlStyleTest( '.mw-test-implement-b2', 'float', 'left' ),
- urlStyleTest( '.mw-test-implement-b3', 'float', 'right' )
- ]
- }
- },
- {}
- );
+ },
+ {}
+ );
- mw.loader.load([
- 'test.implement.b'
- ]);
-} );
+ mw.loader.load( [
+ 'test.implement.b'
+ ] );
+ } );
// Backwards compatibility
-QUnit.test( 'mw.loader.implement( styles={ <media>: text } ) (back-compat)', 2, function ( assert ) {
- var $element = $( '<div class="mw-test-implement-c"></div>' ).appendTo( '#qunit-fixture' );
-
- assert.notEqual(
- $element.css( 'float' ),
- 'right',
- 'style is clear'
- );
-
- mw.loader.implement(
- 'test.implement.c',
- function () {
- assert.equal(
- $element.css( 'float' ),
- 'right',
- 'style is applied'
- );
- },
- {
- 'all': '.mw-test-implement-c { float: right; }'
- },
- {}
- );
-
- mw.loader.load([
- 'test.implement.c'
- ]);
-} );
+ QUnit.test( 'mw.loader.implement( styles={ <media>: text } ) (back-compat)', 2, function ( assert ) {
+ var $element = $( '<div class="mw-test-implement-c"></div>' ).appendTo( '#qunit-fixture' );
+
+ assert.notEqual(
+ $element.css( 'float' ),
+ 'right',
+ 'style is clear'
+ );
+
+ mw.loader.implement(
+ 'test.implement.c',
+ function () {
+ assert.equal(
+ $element.css( 'float' ),
+ 'right',
+ 'style is applied'
+ );
+ },
+ {
+ 'all': '.mw-test-implement-c { float: right; }'
+ },
+ {}
+ );
+
+ mw.loader.load( [
+ 'test.implement.c'
+ ] );
+ } );
// Backwards compatibility
-QUnit.asyncTest( 'mw.loader.implement( styles={ <media>: [url, ..] } ) (back-compat)', 4, function ( assert ) {
- var $element = $( '<div class="mw-test-implement-d"></div>' ).appendTo( '#qunit-fixture' ),
- $element2 = $( '<div class="mw-test-implement-d2"></div>' ).appendTo( '#qunit-fixture' );
-
- assert.notEqual(
- $element.css( 'float' ),
- 'right',
- 'style is clear'
- );
- assert.notEqual(
- $element2.css( 'text-align' ),
- 'center',
- 'style is clear'
- );
-
- mw.loader.implement(
- 'test.implement.d',
- function () {
- assertStyleAsync( assert, $element, 'float', 'right', function () {
-
- assert.notEqual( $element2.css( 'text-align' ), 'center', 'print style is not applied (bug 40500)' );
+ QUnit.asyncTest( 'mw.loader.implement( styles={ <media>: [url, ..] } ) (back-compat)', 4, function ( assert ) {
+ var $element = $( '<div class="mw-test-implement-d"></div>' ).appendTo( '#qunit-fixture' ),
+ $element2 = $( '<div class="mw-test-implement-d2"></div>' ).appendTo( '#qunit-fixture' );
+
+ assert.notEqual(
+ $element.css( 'float' ),
+ 'right',
+ 'style is clear'
+ );
+ assert.notEqual(
+ $element2.css( 'text-align' ),
+ 'center',
+ 'style is clear'
+ );
+
+ mw.loader.implement(
+ 'test.implement.d',
+ function () {
+ assertStyleAsync( assert, $element, 'float', 'right', function () {
+
+ assert.notEqual( $element2.css( 'text-align' ), 'center', 'print style is not applied (bug 40500)' );
- QUnit.start();
- } );
- },
- {
- 'all': [urlStyleTest( '.mw-test-implement-d', 'float', 'right' )],
- 'print': [urlStyleTest( '.mw-test-implement-d2', 'text-align', 'center' )]
- },
- {}
- );
-
- mw.loader.load([
- 'test.implement.d'
- ]);
-} );
+ QUnit.start();
+ } );
+ },
+ {
+ 'all': [urlStyleTest( '.mw-test-implement-d', 'float', 'right' )],
+ 'print': [urlStyleTest( '.mw-test-implement-d2', 'text-align', 'center' )]
+ },
+ {}
+ );
+
+ mw.loader.load( [
+ 'test.implement.d'
+ ] );
+ } );
// @import (bug 31676)
-QUnit.asyncTest( 'mw.loader.implement( styles has @import)', 5, function ( assert ) {
- var isJsExecuted, $element;
-
- mw.loader.implement(
- 'test.implement.import',
- function () {
- assert.strictEqual( isJsExecuted, undefined, 'javascript not executed multiple times' );
- isJsExecuted = true;
+ QUnit.asyncTest( 'mw.loader.implement( styles has @import)', 5, function ( assert ) {
+ var isJsExecuted, $element;
- assert.equal( mw.loader.getState( 'test.implement.import' ), 'ready', 'module state is "ready" while implement() is executing javascript' );
+ mw.loader.implement(
+ 'test.implement.import',
+ function () {
+ assert.strictEqual( isJsExecuted, undefined, 'javascript not executed multiple times' );
+ isJsExecuted = true;
- $element = $( '<div class="mw-test-implement-import">Foo bar</div>' ).appendTo( '#qunit-fixture' );
+ assert.equal( mw.loader.getState( 'test.implement.import' ), 'ready', 'module state is "ready" while implement() is executing javascript' );
- assert.equal( mw.msg( 'test-foobar' ), 'Hello Foobar, $1!', 'Messages are loaded before javascript execution' );
+ $element = $( '<div class="mw-test-implement-import">Foo bar</div>' ).appendTo( '#qunit-fixture' );
- assertStyleAsync( assert, $element, 'float', 'right', function () {
- assert.equal( $element.css( 'text-align' ),'center',
- 'CSS styles after the @import rule are working'
- );
+ assert.equal( mw.msg( 'test-foobar' ), 'Hello Foobar, $1!', 'Messages are loaded before javascript execution' );
- QUnit.start();
- } );
- },
- {
- 'css': [
- '@import url(\''
- + urlStyleTest( '.mw-test-implement-import', 'float', 'right' )
- + '\');\n'
- + '.mw-test-implement-import { text-align: center; }'
- ]
- },
- {
- 'test-foobar': 'Hello Foobar, $1!'
- }
- );
-
- mw.loader.load( 'test.implement' );
-
-});
-
-QUnit.asyncTest( 'mw.loader.implement( only messages )' , 2, function ( assert ) {
- assert.assertFalse( mw.messages.exists( 'bug_29107' ), 'Verify that the test message doesn\'t exist yet' );
-
- mw.loader.implement( 'test.implement.msgs', [], {}, { 'bug_29107': 'loaded' } );
- mw.loader.using( 'test.implement.msgs', function() {
- QUnit.start();
- assert.ok( mw.messages.exists( 'bug_29107' ), 'Bug 29107: messages-only module should implement ok' );
- }, function() {
- QUnit.start();
- assert.ok( false, 'Error callback fired while implementing "test.implement.msgs" module' );
- });
-});
-
-QUnit.test( 'mw.loader erroneous indirect dependency', 3, function ( assert ) {
- mw.loader.register( [
- ['test.module1', '0'],
- ['test.module2', '0', ['test.module1']],
- ['test.module3', '0', ['test.module2']]
- ] );
- mw.loader.implement( 'test.module1', function () { throw new Error( 'expected' ); }, {}, {} );
- assert.strictEqual( mw.loader.getState( 'test.module1' ), 'error', 'Expected "error" state for test.module1' );
- assert.strictEqual( mw.loader.getState( 'test.module2' ), 'error', 'Expected "error" state for test.module2' );
- assert.strictEqual( mw.loader.getState( 'test.module3' ), 'error', 'Expected "error" state for test.module3' );
-} );
-
-QUnit.test( 'mw.loader out-of-order implementation', 9, function ( assert ) {
- mw.loader.register( [
- ['test.module4', '0'],
- ['test.module5', '0', ['test.module4']],
- ['test.module6', '0', ['test.module5']]
- ] );
- mw.loader.implement( 'test.module4', function () {}, {}, {} );
- assert.strictEqual( mw.loader.getState( 'test.module4' ), 'ready', 'Expected "ready" state for test.module4' );
- assert.strictEqual( mw.loader.getState( 'test.module5' ), 'registered', 'Expected "registered" state for test.module5' );
- assert.strictEqual( mw.loader.getState( 'test.module6' ), 'registered', 'Expected "registered" state for test.module6' );
- mw.loader.implement( 'test.module6', function () {}, {}, {} );
- assert.strictEqual( mw.loader.getState( 'test.module4' ), 'ready', 'Expected "ready" state for test.module4' );
- assert.strictEqual( mw.loader.getState( 'test.module5' ), 'registered', 'Expected "registered" state for test.module5' );
- assert.strictEqual( mw.loader.getState( 'test.module6' ), 'loaded', 'Expected "loaded" state for test.module6' );
- mw.loader.implement( 'test.module5', function() {}, {}, {} );
- assert.strictEqual( mw.loader.getState( 'test.module4' ), 'ready', 'Expected "ready" state for test.module4' );
- assert.strictEqual( mw.loader.getState( 'test.module5' ), 'ready', 'Expected "ready" state for test.module5' );
- assert.strictEqual( mw.loader.getState( 'test.module6' ), 'ready', 'Expected "ready" state for test.module6' );
-} );
-
-QUnit.test( 'mw.loader missing dependency', 13, function ( assert ) {
- mw.loader.register( [
- ['test.module7', '0'],
- ['test.module8', '0', ['test.module7']],
- ['test.module9', '0', ['test.module8']]
- ] );
- mw.loader.implement( 'test.module8', function () {}, {}, {} );
- assert.strictEqual( mw.loader.getState( 'test.module7' ), 'registered', 'Expected "registered" state for test.module7' );
- assert.strictEqual( mw.loader.getState( 'test.module8' ), 'loaded', 'Expected "loaded" state for test.module8' );
- assert.strictEqual( mw.loader.getState( 'test.module9' ), 'registered', 'Expected "registered" state for test.module9' );
- mw.loader.state( 'test.module7', 'missing' );
- assert.strictEqual( mw.loader.getState( 'test.module7' ), 'missing', 'Expected "missing" state for test.module7' );
- assert.strictEqual( mw.loader.getState( 'test.module8' ), 'error', 'Expected "error" state for test.module8' );
- assert.strictEqual( mw.loader.getState( 'test.module9' ), 'error', 'Expected "error" state for test.module9' );
- mw.loader.implement( 'test.module9', function () {}, {}, {} );
- assert.strictEqual( mw.loader.getState( 'test.module7' ), 'missing', 'Expected "missing" state for test.module7' );
- assert.strictEqual( mw.loader.getState( 'test.module8' ), 'error', 'Expected "error" state for test.module8' );
- assert.strictEqual( mw.loader.getState( 'test.module9' ), 'error', 'Expected "error" state for test.module9' );
- mw.loader.using(
- ['test.module7'],
- function () {
- assert.ok( false, 'Success fired despite missing dependency' );
- assert.ok( true , 'QUnit expected() count dummy' );
- },
- function ( e, dependencies ) {
- assert.strictEqual( $.isArray( dependencies ), true, 'Expected array of dependencies' );
- assert.deepEqual( dependencies, ['test.module7'], 'Error callback called with module test.module7' );
- }
- );
- mw.loader.using(
- ['test.module9'],
- function () {
- assert.ok( false, 'Success fired despite missing dependency' );
- assert.ok( true , 'QUnit expected() count dummy' );
- },
- function ( e, dependencies ) {
- assert.strictEqual( $.isArray( dependencies ), true, 'Expected array of dependencies' );
- dependencies.sort();
- assert.deepEqual(
- dependencies,
- ['test.module7', 'test.module8', 'test.module9'],
- 'Error callback called with all three modules as dependencies'
- );
- }
- );
-} );
-
-QUnit.asyncTest( 'mw.loader dependency handling', 5, function ( assert ) {
- mw.loader.addSource(
- 'testloader',
- {
- loadScript: QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/load.mock.php' )
- }
- );
-
- mw.loader.register( [
- // [module, version, dependencies, group, source]
- ['testMissing', '1', [], null, 'testloader'],
- ['testUsesMissing', '1', ['testMissing'], null, 'testloader'],
- ['testUsesNestedMissing', '1', ['testUsesMissing'], null, 'testloader']
- ] );
-
- function verifyModuleStates() {
- assert.equal( mw.loader.getState( 'testMissing' ), 'missing', 'Module not known to server must have state "missing"' );
- assert.equal( mw.loader.getState( 'testUsesMissing' ), 'error', 'Module with missing dependency must have state "error"' );
- assert.equal( mw.loader.getState( 'testUsesNestedMissing' ), 'error', 'Module with indirect missing dependency must have state "error"' );
- }
+ assertStyleAsync( assert, $element, 'float', 'right', function () {
+ assert.equal( $element.css( 'text-align' ), 'center',
+ 'CSS styles after the @import rule are working'
+ );
- mw.loader.using( ['testUsesNestedMissing'],
- function () {
- assert.ok( false, 'Error handler should be invoked.' );
- assert.ok( true ); // Dummy to reach QUnit expect()
+ QUnit.start();
+ } );
+ },
+ {
+ 'css': [
+ '@import url(\''
+ + urlStyleTest( '.mw-test-implement-import', 'float', 'right' )
+ + '\');\n'
+ + '.mw-test-implement-import { text-align: center; }'
+ ]
+ },
+ {
+ 'test-foobar': 'Hello Foobar, $1!'
+ }
+ );
- verifyModuleStates();
+ mw.loader.load( 'test.implement' );
- QUnit.start();
- },
- function ( e, badmodules ) {
- assert.ok( true, 'Error handler should be invoked.' );
- // As soon as server spits out state('testMissing', 'missing');
- // it will bubble up and trigger the error callback.
- // Therefor the badmodules array is not testUsesMissing or testUsesNestedMissing.
- assert.deepEqual( badmodules, ['testMissing'], 'Bad modules as expected.' );
+ } );
- verifyModuleStates();
+ QUnit.asyncTest( 'mw.loader.implement( only messages )', 2, function ( assert ) {
+ assert.assertFalse( mw.messages.exists( 'bug_29107' ), 'Verify that the test message doesn\'t exist yet' );
+ mw.loader.implement( 'test.implement.msgs', [], {}, { 'bug_29107': 'loaded' } );
+ mw.loader.using( 'test.implement.msgs', function () {
QUnit.start();
+ assert.ok( mw.messages.exists( 'bug_29107' ), 'Bug 29107: messages-only module should implement ok' );
+ }, function () {
+ QUnit.start();
+ assert.ok( false, 'Error callback fired while implementing "test.implement.msgs" module' );
+ } );
+ } );
+
+ QUnit.test( 'mw.loader erroneous indirect dependency', 3, function ( assert ) {
+ mw.loader.register( [
+ ['test.module1', '0'],
+ ['test.module2', '0', ['test.module1']],
+ ['test.module3', '0', ['test.module2']]
+ ] );
+ mw.loader.implement( 'test.module1', function () {
+ throw new Error( 'expected' );
+ }, {}, {} );
+ assert.strictEqual( mw.loader.getState( 'test.module1' ), 'error', 'Expected "error" state for test.module1' );
+ assert.strictEqual( mw.loader.getState( 'test.module2' ), 'error', 'Expected "error" state for test.module2' );
+ assert.strictEqual( mw.loader.getState( 'test.module3' ), 'error', 'Expected "error" state for test.module3' );
+ } );
+
+ QUnit.test( 'mw.loader out-of-order implementation', 9, function ( assert ) {
+ mw.loader.register( [
+ ['test.module4', '0'],
+ ['test.module5', '0', ['test.module4']],
+ ['test.module6', '0', ['test.module5']]
+ ] );
+ mw.loader.implement( 'test.module4', function () {
+ }, {}, {} );
+ assert.strictEqual( mw.loader.getState( 'test.module4' ), 'ready', 'Expected "ready" state for test.module4' );
+ assert.strictEqual( mw.loader.getState( 'test.module5' ), 'registered', 'Expected "registered" state for test.module5' );
+ assert.strictEqual( mw.loader.getState( 'test.module6' ), 'registered', 'Expected "registered" state for test.module6' );
+ mw.loader.implement( 'test.module6', function () {
+ }, {}, {} );
+ assert.strictEqual( mw.loader.getState( 'test.module4' ), 'ready', 'Expected "ready" state for test.module4' );
+ assert.strictEqual( mw.loader.getState( 'test.module5' ), 'registered', 'Expected "registered" state for test.module5' );
+ assert.strictEqual( mw.loader.getState( 'test.module6' ), 'loaded', 'Expected "loaded" state for test.module6' );
+ mw.loader.implement( 'test.module5', function () {
+ }, {}, {} );
+ assert.strictEqual( mw.loader.getState( 'test.module4' ), 'ready', 'Expected "ready" state for test.module4' );
+ assert.strictEqual( mw.loader.getState( 'test.module5' ), 'ready', 'Expected "ready" state for test.module5' );
+ assert.strictEqual( mw.loader.getState( 'test.module6' ), 'ready', 'Expected "ready" state for test.module6' );
+ } );
+
+ QUnit.test( 'mw.loader missing dependency', 13, function ( assert ) {
+ mw.loader.register( [
+ ['test.module7', '0'],
+ ['test.module8', '0', ['test.module7']],
+ ['test.module9', '0', ['test.module8']]
+ ] );
+ mw.loader.implement( 'test.module8', function () {
+ }, {}, {} );
+ assert.strictEqual( mw.loader.getState( 'test.module7' ), 'registered', 'Expected "registered" state for test.module7' );
+ assert.strictEqual( mw.loader.getState( 'test.module8' ), 'loaded', 'Expected "loaded" state for test.module8' );
+ assert.strictEqual( mw.loader.getState( 'test.module9' ), 'registered', 'Expected "registered" state for test.module9' );
+ mw.loader.state( 'test.module7', 'missing' );
+ assert.strictEqual( mw.loader.getState( 'test.module7' ), 'missing', 'Expected "missing" state for test.module7' );
+ assert.strictEqual( mw.loader.getState( 'test.module8' ), 'error', 'Expected "error" state for test.module8' );
+ assert.strictEqual( mw.loader.getState( 'test.module9' ), 'error', 'Expected "error" state for test.module9' );
+ mw.loader.implement( 'test.module9', function () {
+ }, {}, {} );
+ assert.strictEqual( mw.loader.getState( 'test.module7' ), 'missing', 'Expected "missing" state for test.module7' );
+ assert.strictEqual( mw.loader.getState( 'test.module8' ), 'error', 'Expected "error" state for test.module8' );
+ assert.strictEqual( mw.loader.getState( 'test.module9' ), 'error', 'Expected "error" state for test.module9' );
+ mw.loader.using(
+ ['test.module7'],
+ function () {
+ assert.ok( false, 'Success fired despite missing dependency' );
+ assert.ok( true, 'QUnit expected() count dummy' );
+ },
+ function ( e, dependencies ) {
+ assert.strictEqual( $.isArray( dependencies ), true, 'Expected array of dependencies' );
+ assert.deepEqual( dependencies, ['test.module7'], 'Error callback called with module test.module7' );
+ }
+ );
+ mw.loader.using(
+ ['test.module9'],
+ function () {
+ assert.ok( false, 'Success fired despite missing dependency' );
+ assert.ok( true, 'QUnit expected() count dummy' );
+ },
+ function ( e, dependencies ) {
+ assert.strictEqual( $.isArray( dependencies ), true, 'Expected array of dependencies' );
+ dependencies.sort();
+ assert.deepEqual(
+ dependencies,
+ ['test.module7', 'test.module8', 'test.module9'],
+ 'Error callback called with all three modules as dependencies'
+ );
+ }
+ );
+ } );
+
+ QUnit.asyncTest( 'mw.loader dependency handling', 5, function ( assert ) {
+ mw.loader.addSource(
+ 'testloader',
+ {
+ loadScript: QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/load.mock.php' )
+ }
+ );
+
+ mw.loader.register( [
+ // [module, version, dependencies, group, source]
+ ['testMissing', '1', [], null, 'testloader'],
+ ['testUsesMissing', '1', ['testMissing'], null, 'testloader'],
+ ['testUsesNestedMissing', '1', ['testUsesMissing'], null, 'testloader']
+ ] );
+
+ function verifyModuleStates() {
+ assert.equal( mw.loader.getState( 'testMissing' ), 'missing', 'Module not known to server must have state "missing"' );
+ assert.equal( mw.loader.getState( 'testUsesMissing' ), 'error', 'Module with missing dependency must have state "error"' );
+ assert.equal( mw.loader.getState( 'testUsesNestedMissing' ), 'error', 'Module with indirect missing dependency must have state "error"' );
}
- );
-} );
-QUnit.asyncTest( 'mw.loader( "//protocol-relative" ) (bug 30825)', 2, function ( assert ) {
- // This bug was actually already fixed in 1.18 and later when discovered in 1.17.
- // Test is for regressions!
+ mw.loader.using( ['testUsesNestedMissing'],
+ function () {
+ assert.ok( false, 'Error handler should be invoked.' );
+ assert.ok( true ); // Dummy to reach QUnit expect()
+
+ verifyModuleStates();
+
+ QUnit.start();
+ },
+ function ( e, badmodules ) {
+ assert.ok( true, 'Error handler should be invoked.' );
+ // As soon as server spits out state('testMissing', 'missing');
+ // it will bubble up and trigger the error callback.
+ // Therefor the badmodules array is not testUsesMissing or testUsesNestedMissing.
+ assert.deepEqual( badmodules, ['testMissing'], 'Bad modules as expected.' );
- // Forge an URL to the test callback script
- var target = QUnit.fixurl(
- mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/qunitOkCall.js'
- );
+ verifyModuleStates();
- // Confirm that mw.loader.load() works with protocol-relative URLs
- target = target.replace( /https?:/, '' );
+ QUnit.start();
+ }
+ );
+ } );
- assert.equal( target.substr( 0, 2 ), '//',
- 'URL must be relative to test relative URLs!'
- );
+ QUnit.asyncTest( 'mw.loader( "//protocol-relative" ) (bug 30825)', 2, function ( assert ) {
+ // This bug was actually already fixed in 1.18 and later when discovered in 1.17.
+ // Test is for regressions!
- // Async!
- // The target calls QUnit.start
- mw.loader.load( target );
-});
+ // Forge an URL to the test callback script
+ var target = QUnit.fixurl(
+ mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/qunitOkCall.js'
+ );
-QUnit.test( 'mw.html', 13, function ( assert ) {
- assert.throws( function () {
- mw.html.escape();
- }, TypeError, 'html.escape throws a TypeError if argument given is not a string' );
+ // Confirm that mw.loader.load() works with protocol-relative URLs
+ target = target.replace( /https?:/, '' );
- assert.equal( mw.html.escape( '<mw awesome="awesome" value=\'test\' />' ),
- '<mw awesome="awesome" value='test' />', 'escape() escapes special characters to html entities' );
+ assert.equal( target.substr( 0, 2 ), '//',
+ 'URL must be relative to test relative URLs!'
+ );
- assert.equal( mw.html.element(),
- '<undefined/>', 'element() always returns a valid html string (even without arguments)' );
+ // Async!
+ // The target calls QUnit.start
+ mw.loader.load( target );
+ } );
- assert.equal( mw.html.element( 'div' ), '<div/>', 'element() Plain DIV (simple)' );
+ QUnit.test( 'mw.html', 13, function ( assert ) {
+ assert.throws( function () {
+ mw.html.escape();
+ }, TypeError, 'html.escape throws a TypeError if argument given is not a string' );
- assert.equal( mw.html.element( 'div', {}, '' ), '<div></div>', 'element() Basic DIV (simple)' );
+ assert.equal( mw.html.escape( '<mw awesome="awesome" value=\'test\' />' ),
+ '<mw awesome="awesome" value='test' />', 'escape() escapes special characters to html entities' );
- assert.equal(
- mw.html.element(
- 'div', {
- id: 'foobar'
- }
- ),
- '<div id="foobar"/>',
- 'html.element DIV (attribs)' );
-
- assert.equal( mw.html.element( 'p', null, 12 ), '<p>12</p>', 'Numbers are valid content and should be casted to a string' );
-
- assert.equal( mw.html.element( 'p', { title: 12 }, '' ), '<p title="12"></p>', 'Numbers are valid attribute values' );
-
- // Example from https://www.mediawiki.org/wiki/ResourceLoader/Default_modules#mediaWiki.html
- assert.equal(
- mw.html.element(
- 'div',
- {},
- new mw.html.Raw(
- mw.html.element( 'img', { src: '<' } )
- )
- ),
- '<div><img src="<"/></div>',
- 'Raw inclusion of another element'
- );
-
- assert.equal(
- mw.html.element(
- 'option', {
- selected: true
- }, 'Foo'
- ),
- '<option selected="selected">Foo</option>',
- 'Attributes may have boolean values. True copies the attribute name to the value.'
- );
-
- assert.equal(
- mw.html.element(
- 'option', {
- value: 'foo',
- selected: false
- }, 'Foo'
- ),
- '<option value="foo">Foo</option>',
- 'Attributes may have boolean values. False keeps the attribute from output.'
- );
-
- assert.equal( mw.html.element( 'div',
+ assert.equal( mw.html.element(),
+ '<undefined/>', 'element() always returns a valid html string (even without arguments)' );
+
+ assert.equal( mw.html.element( 'div' ), '<div/>', 'element() Plain DIV (simple)' );
+
+ assert.equal( mw.html.element( 'div', {}, '' ), '<div></div>', 'element() Basic DIV (simple)' );
+
+ assert.equal(
+ mw.html.element(
+ 'div', {
+ id: 'foobar'
+ }
+ ),
+ '<div id="foobar"/>',
+ 'html.element DIV (attribs)' );
+
+ assert.equal( mw.html.element( 'p', null, 12 ), '<p>12</p>', 'Numbers are valid content and should be casted to a string' );
+
+ assert.equal( mw.html.element( 'p', { title: 12 }, '' ), '<p title="12"></p>', 'Numbers are valid attribute values' );
+
+ // Example from https://www.mediawiki.org/wiki/ResourceLoader/Default_modules#mediaWiki.html
+ assert.equal(
+ mw.html.element(
+ 'div',
+ {},
+ new mw.html.Raw(
+ mw.html.element( 'img', { src: '<' } )
+ )
+ ),
+ '<div><img src="<"/></div>',
+ 'Raw inclusion of another element'
+ );
+
+ assert.equal(
+ mw.html.element(
+ 'option', {
+ selected: true
+ }, 'Foo'
+ ),
+ '<option selected="selected">Foo</option>',
+ 'Attributes may have boolean values. True copies the attribute name to the value.'
+ );
+
+ assert.equal(
+ mw.html.element(
+ 'option', {
+ value: 'foo',
+ selected: false
+ }, 'Foo'
+ ),
+ '<option value="foo">Foo</option>',
+ 'Attributes may have boolean values. False keeps the attribute from output.'
+ );
+
+ assert.equal( mw.html.element( 'div',
null, 'a' ),
- '<div>a</div>',
- 'html.element DIV (content)' );
+ '<div>a</div>',
+ 'html.element DIV (content)' );
- assert.equal( mw.html.element( 'a',
+ assert.equal( mw.html.element( 'a',
{ href: 'http://mediawiki.org/w/index.php?title=RL&action=history' }, 'a' ),
- '<a href="http://mediawiki.org/w/index.php?title=RL&action=history">a</a>',
- 'html.element DIV (attribs + content)' );
+ '<a href="http://mediawiki.org/w/index.php?title=RL&action=history">a</a>',
+ 'html.element DIV (attribs + content)' );
-});
+ } );
}( mediaWiki, jQuery ) );
( function ( mw, $ ) {
-
-QUnit.module( 'mediawiki.user', QUnit.newMwEnvironment() );
-
-QUnit.test( 'options', 1, function ( assert ) {
- assert.ok( mw.user.options instanceof mw.Map, 'options instance of mw.Map' );
-});
-
-QUnit.test( 'user status', 9, function ( assert ) {
- /**
- * Tests can be run under three different conditions:
- * 1) From tests/qunit/index.html, user will be anonymous.
- * 2) Logged in on [[Special:JavaScriptTest/qunit]]
- * 3) Anonymously at the same special page.
- */
-
- // Forge an anonymous user:
- mw.config.set( 'wgUserName', null );
-
- assert.strictEqual( mw.user.getName(), null, 'user.getName() returns null when anonymous' );
- assert.strictEqual( mw.user.name(), null, 'user.name() compatibility' );
- assert.assertTrue( mw.user.isAnon(), 'user.isAnon() returns true when anonymous' );
- assert.assertTrue( mw.user.anonymous(), 'user.anonymous() compatibility' );
-
- // Not part of startUp module
- mw.config.set( 'wgUserName', 'John' );
-
- assert.equal( mw.user.getName(), 'John', 'user.getName() returns username when logged-in' );
- assert.equal( mw.user.name(), 'John', 'user.name() compatibility' );
- assert.assertFalse( mw.user.isAnon(), 'user.isAnon() returns false when logged-in' );
- assert.assertFalse( mw.user.anonymous(), 'user.anonymous() compatibility' );
-
- assert.equal( mw.user.id(), 'John', 'user.id Returns username when logged-in' );
-});
-
-QUnit.asyncTest( 'getGroups', 3, function ( assert ) {
- mw.user.getGroups( function ( groups ) {
- // First group should always be '*'
- assert.equal( $.type( groups ), 'array', 'Callback gets an array' );
- assert.notStrictEqual( $.inArray( '*', groups ), -1, '"*"" is in the list' );
- // Sort needed because of different methods if creating the arrays,
- // only the content matters.
- assert.deepEqual( groups.sort(), mw.config.get( 'wgUserGroups' ).sort(), 'Array contains all groups, just like wgUserGroups' );
- QUnit.start();
- });
-});
-
-QUnit.asyncTest( 'getRights', 1, function ( assert ) {
- mw.user.getRights( function ( rights ) {
- assert.equal( $.type( rights ), 'array', 'Callback gets an array' );
- QUnit.start();
- });
-});
-
+ QUnit.module( 'mediawiki.user', QUnit.newMwEnvironment() );
+
+ QUnit.test( 'options', 1, function ( assert ) {
+ assert.ok( mw.user.options instanceof mw.Map, 'options instance of mw.Map' );
+ } );
+
+ QUnit.test( 'user status', 9, function ( assert ) {
+ /**
+ * Tests can be run under three different conditions:
+ * 1) From tests/qunit/index.html, user will be anonymous.
+ * 2) Logged in on [[Special:JavaScriptTest/qunit]]
+ * 3) Anonymously at the same special page.
+ */
+
+ // Forge an anonymous user:
+ mw.config.set( 'wgUserName', null );
+
+ assert.strictEqual( mw.user.getName(), null, 'user.getName() returns null when anonymous' );
+ assert.strictEqual( mw.user.name(), null, 'user.name() compatibility' );
+ assert.assertTrue( mw.user.isAnon(), 'user.isAnon() returns true when anonymous' );
+ assert.assertTrue( mw.user.anonymous(), 'user.anonymous() compatibility' );
+
+ // Not part of startUp module
+ mw.config.set( 'wgUserName', 'John' );
+
+ assert.equal( mw.user.getName(), 'John', 'user.getName() returns username when logged-in' );
+ assert.equal( mw.user.name(), 'John', 'user.name() compatibility' );
+ assert.assertFalse( mw.user.isAnon(), 'user.isAnon() returns false when logged-in' );
+ assert.assertFalse( mw.user.anonymous(), 'user.anonymous() compatibility' );
+
+ assert.equal( mw.user.id(), 'John', 'user.id Returns username when logged-in' );
+ } );
+
+ QUnit.asyncTest( 'getGroups', 3, function ( assert ) {
+ mw.user.getGroups( function ( groups ) {
+ // First group should always be '*'
+ assert.equal( $.type( groups ), 'array', 'Callback gets an array' );
+ assert.notStrictEqual( $.inArray( '*', groups ), -1, '"*"" is in the list' );
+ // Sort needed because of different methods if creating the arrays,
+ // only the content matters.
+ assert.deepEqual( groups.sort(), mw.config.get( 'wgUserGroups' ).sort(), 'Array contains all groups, just like wgUserGroups' );
+ QUnit.start();
+ } );
+ } );
+
+ QUnit.asyncTest( 'getRights', 1, function ( assert ) {
+ mw.user.getRights( function ( rights ) {
+ assert.equal( $.type( rights ), 'array', 'Callback gets an array' );
+ QUnit.start();
+ } );
+ } );
}( mediaWiki, jQuery ) );
QUnit.test( 'rawurlencode', 1, function ( assert ) {
assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
- });
+ } );
QUnit.test( 'wikiUrlencode', 1, function ( assert ) {
assert.equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
- });
+ } );
QUnit.test( 'wikiGetlink', 3, function ( assert ) {
// Not part of startUp module
href = mw.util.wikiGetlink();
assert.equal( href, '/wiki/Foobar', 'Default title; Get link for current page ("Foobar")' );
- });
+ } );
QUnit.test( 'wikiScript', 4, function ( assert ) {
- mw.config.set({
+ mw.config.set( {
'wgScript': '/w/i.php', // customized wgScript for bug 39103
'wgLoadScript': '/w/l.php', // customized wgLoadScript for bug 39103
'wgScriptPath': '/w',
'wgScriptExtension': '.php'
- });
+ } );
assert.equal( mw.util.wikiScript(), mw.config.get( 'wgScript' ),
'wikiScript() returns wgScript'
'wikiScript( load ) returns wgLoadScript'
);
assert.equal( mw.util.wikiScript( 'api' ), '/w/api.php', 'API path' );
- });
+ } );
QUnit.test( 'addCSS', 3, function ( assert ) {
var $el, style;
// Clean up
$( style.ownerNode ).remove();
- });
+ } );
QUnit.asyncTest( 'toggleToc', 4, function ( assert ) {
var tocHtml, $toggleLink;
assert.strictEqual( mw.util.toggleToc(), null, 'Return null if there is no table of contents on the page.' );
- tocHtml =
- '<table id="toc" class="toc"><tr><td>' +
- '<div id="toctitle">' +
- '<h2>Contents</h2>' +
- '<span class="toctoggle"> [<a href="#" class="internal" id="togglelink">Hide</a> ]</span>' +
- '</div>' +
- '<ul><li></li></ul>' +
+ tocHtml = '<table id="toc" class="toc"><tr><td>' +
+ '<div id="toctitle">' +
+ '<h2>Contents</h2>' +
+ '<span class="toctoggle"> [<a href="#" class="internal" id="togglelink">Hide</a> ]</span>' +
+ '</div>' +
+ '<ul><li></li></ul>' +
'</td></tr></table>';
- $(tocHtml).appendTo( '#qunit-fixture' ),
- $toggleLink = $( '#togglelink' );
+ $( tocHtml ).appendTo( '#qunit-fixture' ),
+ $toggleLink = $( '#togglelink' );
assert.strictEqual( $toggleLink.length, 1, 'Toggle link is appended to the page.' );
actionA();
- });
+ } );
QUnit.test( 'getParamValue', 5, function ( assert ) {
- var url;
+ var url;
url = 'http://example.org/?foo=wrong&foo=right#&foo=bad';
assert.equal( mw.util.getParamValue( 'foo', url ), 'right', 'Use latest one, ignore hash' );
url = 'http://example.org/#&foo=bad';
assert.strictEqual( mw.util.getParamValue( 'foo', url ), null, 'Ignore hash if param is not in querystring but in hash (bug 27427)' );
- url = 'example.org?' + $.param({ 'TEST': 'a b+c' });
+ url = 'example.org?' + $.param( { 'TEST': 'a b+c' } );
assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c', 'Bug 30441: getParamValue must understand "+" encoding of space' );
- url = 'example.org?' + $.param({ 'TEST': 'a b+c d' }); // check for sloppy code from r95332 :)
+ url = 'example.org?' + $.param( { 'TEST': 'a b+c d' } ); // check for sloppy code from r95332 :)
assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
- });
+ } );
QUnit.test( 'tooltipAccessKey', 3, function ( assert ) {
assert.equal( typeof mw.util.tooltipAccessKeyPrefix, 'string', 'mw.util.tooltipAccessKeyPrefix must be a string' );
assert.ok( mw.util.tooltipAccessKeyRegexp instanceof RegExp, 'mw.util.tooltipAccessKeyRegexp instance of RegExp' );
assert.ok( mw.util.updateTooltipAccessKeys, 'mw.util.updateTooltipAccessKeys' );
- });
+ } );
QUnit.test( '$content', 2, function ( assert ) {
assert.ok( mw.util.$content instanceof jQuery, 'mw.util.$content instance of jQuery' );
assert.strictEqual( mw.util.$content.length, 1, 'mw.util.$content must have length of 1' );
- });
-
+ } );
/**
* Portlet names are prefixed with 'p-test' to avoid conflict with core
assert.equal( $tbMW.next().attr( 'id' ), 't-rl', 'Link is in the correct position (by passing nextnode)' );
cuQuux = mw.util.addPortletLink( 'p-test-custom', '#', 'Quux' );
- $cuQuux = $(cuQuux);
+ $cuQuux = $( cuQuux );
assert.equal(
$( '#p-test-custom #c-barmenu ul li' ).length,
caFoo = mw.util.addPortletLink( 'p-test-views', '#', 'Foo' );
- assert.strictEqual( $tbMW.find( 'span').length, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
- assert.strictEqual( $( caFoo ).find( 'span').length, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
- });
+ assert.strictEqual( $tbMW.find( 'span' ).length, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
+ assert.strictEqual( $( caFoo ).find( 'span' ).length, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
+ } );
QUnit.test( 'jsMessage', 1, function ( assert ) {
var a = mw.util.jsMessage( 'MediaWiki is <b>Awesome</b>.' );
// Clean up
$( '#mw-js-message' ).remove();
- });
+ } );
QUnit.test( 'validateEmail', 6, function ( assert ) {
assert.strictEqual( mw.util.validateEmail( '' ), null, 'Should return null for empty string ' );
// testEmailWithHyphens
assert.strictEqual( mw.util.validateEmail( 'user-foo@example.org' ), true, 'Emails may contain a hyphen' );
assert.strictEqual( mw.util.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
- });
+ } );
QUnit.test( 'isIPv6Address', 40, function ( assert ) {
// Shortcuts
function assertFalseIPv6( addy, summary ) {
return assert.strictEqual( mw.util.isIPv6Address( addy ), false, summary );
}
+
function assertTrueIPv6( addy, summary ) {
return assert.strictEqual( mw.util.isIPv6Address( addy ), true, summary );
}
assertFalseIPv6( 'fc:100:300', 'IPv6 with only 3 words' );
$.each(
- ['fc:100::',
- 'fc:100:a::',
- 'fc:100:a:d::',
- 'fc:100:a:d:1::',
- 'fc:100:a:d:1:e::',
- 'fc:100:a:d:1:e:ac::'], function ( i, addy ){
- assertTrueIPv6( addy, addy + ' is a valid IP' );
- });
+ ['fc:100::',
+ 'fc:100:a::',
+ 'fc:100:a:d::',
+ 'fc:100:a:d:1::',
+ 'fc:100:a:d:1:e::',
+ 'fc:100:a:d:1:e:ac::'], function ( i, addy ) {
+ assertTrueIPv6( addy, addy + ' is a valid IP' );
+ } );
assertFalseIPv6( 'fc:100:a:d:1:e:ac:0::', 'IPv6 with 8 words ending with "::"' );
assertFalseIPv6( 'fc:100:a:d:1:e:ac:0:1::', 'IPv6 with 9 words ending with "::"' );
assertTrueIPv6( '::', 'IPv6 zero address' );
$.each(
- ['::0',
- '::fc',
- '::fc:100',
- '::fc:100:a',
- '::fc:100:a:d',
- '::fc:100:a:d:1',
- '::fc:100:a:d:1:e',
- '::fc:100:a:d:1:e:ac',
-
- 'fc:100:a:d:1:e:ac:0'], function ( i, addy ){
- assertTrueIPv6( addy, addy + ' is a valid IP' );
- });
+ ['::0',
+ '::fc',
+ '::fc:100',
+ '::fc:100:a',
+ '::fc:100:a:d',
+ '::fc:100:a:d:1',
+ '::fc:100:a:d:1:e',
+ '::fc:100:a:d:1:e:ac',
+
+ 'fc:100:a:d:1:e:ac:0'], function ( i, addy ) {
+ assertTrueIPv6( addy, addy + ' is a valid IP' );
+ } );
assertFalseIPv6( '::fc:100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' );
assertFalseIPv6( '::fc:100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' );
assertFalseIPv6( 'fc::100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' );
assertFalseIPv6( 'fc::100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' );
- });
+ } );
QUnit.test( 'isIPv4Address', 11, function ( assert ) {
// Shortcuts
function assertFalseIPv4( addy, summary ) {
assert.strictEqual( mw.util.isIPv4Address( addy ), false, summary );
}
+
function assertTrueIPv4( addy, summary ) {
assert.strictEqual( mw.util.isIPv4Address( addy ), true, summary );
}
assertTrueIPv4( '124.24.52.13', '124.24.52.134 is a valid IP' );
assertTrueIPv4( '1.24.52.13', '1.24.52.13 is a valid IP' );
assertFalseIPv4( '74.24.52.13/20', 'IPv4 ranges are not recogzized as valid IPs' );
- });
+ } );
}( mediaWiki, jQuery ) );
public function start() {
$this->tester = new Testing_Selenium( $this->browser, self::$url, $this->host,
$this->port, $this->timeout );
- if ( method_exists( $this->tester, "setVerbose" ) ) $this->tester->setVerbose( $this->verbose );
+ if ( method_exists( $this->tester, "setVerbose" ) ) {
+ $this->tester->setVerbose( $this->verbose );
+ }
$this->tester->start();
$this->isStarted = true;
$this->logger = $logger;
}
- public function getLogger( ) {
+ public function getLogger() {
return $this->logger;
}
self::$url = $url;
}
- static public function getUrl() {
+ public static function getUrl() {
return self::$url;
}
$this->user = $user;
}
- // Function to get username
- public function getUser() {
+ // Function to get username
+ public function getUser() {
return $this->user;
}
-
+
public function setPass( $pass ) {
$this->pass = $pass;
}
- //add function to get password
- public function getPass( ) {
+ //add function to get password
+ public function getPass() {
return $this->pass;
}
-
-
+
public function setHost( $host ) {
$this->host = $host;
}
$this->junitlogfile = $junitlogfile;
}
- public function getJUnitLogfile( ) {
+ public function getJUnitLogfile() {
return $this->junitlogfile;
}
}
public function setBrowser( $b ) {
- if ($this->runagainstgrid) {
+ if ( $this->runagainstgrid ) {
$this->browser = $b;
return true;
}
}
// Prevent external cloning
- protected function __clone() { }
+ protected function __clone() {}
// Prevent external construction
// protected function __construct() {}
}
* See sample config file in selenium_settings.ini.sample
*
*/
-
- public static function getSeleniumSettings ( &$seleniumSettings,
- &$seleniumBrowsers,
- &$seleniumTestSuites,
- $seleniumConfigFile = null ) {
+ public static function getSeleniumSettings( &$seleniumSettings,
+ &$seleniumBrowsers,
+ &$seleniumTestSuites,
+ $seleniumConfigFile = null ) {
if ( strlen( $seleniumConfigFile ) == 0 ) {
global $wgSeleniumConfigFile;
- if ( isset( $wgSeleniumConfigFile ) ) $seleniumConfigFile = $wgSeleniumConfigFile ;
+ if ( isset( $wgSeleniumConfigFile ) ) {
+ $seleniumConfigFile = $wgSeleniumConfigFile;
+ }
}
if ( strlen( $seleniumConfigFile ) == 0 || !file_exists( $seleniumConfigFile ) ) {
throw new MWException( "Error parsing " . $seleniumConfigFile . "\n" );
}
- if ( array_key_exists( 'SeleniumSettings', $configArray) ) {
+ if ( array_key_exists( 'SeleniumSettings', $configArray ) ) {
wfSuppressWarnings();
//we may need to change how this is set. But for now leave it in the ini file
$seleniumBrowsers = $configArray['SeleniumSettings']['browsers'];
wfRestoreWarnings();
}
- if ( array_key_exists( 'SeleniumTests', $configArray) ) {
+ if ( array_key_exists( 'SeleniumTests', $configArray ) ) {
wfSuppressWarnings();
$seleniumTestSuites = $configArray['SeleniumTests']['testSuite'];
wfRestoreWarnings();
private $SeleniumServerExecPath;
public function __construct( $startServer,
- $serverPort,
- $serverExecPath ) {
- $this->OS = (string) PHP_OS;
- if ( isset( $startServer ) )
+ $serverPort,
+ $serverExecPath ) {
+ $this->OS = (string)PHP_OS;
+
+ if ( isset( $startServer ) ) {
$this->SeleniumStartServer = $startServer;
- if ( isset( $serverPort ) )
+ }
+
+ if ( isset( $serverPort ) ) {
$this->SeleniumServerPort = $serverPort;
- if ( isset( $serverExecPath ) )
+ }
+
+ if ( isset( $serverExecPath ) ) {
$this->SeleniumServerExecPath = $serverExecPath;
+ }
+
return;
}
// to true, since after server is started, it is shut down by stop().
public function setSeleniumStartServer( $startServer ) {
- if ( $startServer == true ) $this->SeleniumStartServer = true;
+ if ( $startServer == true ) {
+ $this->SeleniumStartServer = true;
+ }
}
// return values are: 1) started - server started, 2) failed -
public function start() {
- if ( !$this->SeleniumStartServer ) return 'failed';
+ if ( !$this->SeleniumStartServer ) {
+ return 'failed';
+ }
// commented out cases are untested
$output = array();
$user = $_ENV['USER'];
// @todo FIXME: This should be a little more generalized :)
- if (PHP_OS == 'Darwin') {
+ if ( PHP_OS == 'Darwin' ) {
// Mac OS X's ps barfs on the 'w' param, but doesn't need it.
$ps = "ps -U %s";
} else {
// Good on Linux
$ps = "ps -U %s w";
}
- $psCommand = sprintf($ps, escapeshellarg($user));
- exec($psCommand . " | grep -i selenium-server", $output);
+ $psCommand = sprintf( $ps, escapeshellarg( $user ) );
+ exec( $psCommand . " | grep -i selenium-server", $output );
// Start server. If there is already a server running,
// return running.
// The echo guarentees it is put into $op when
// the exec command is run.
- $commandSuffix = ' > /dev/null 2>&1'. ' & echo $!';
+ $commandSuffix = ' > /dev/null 2>&1' . ' & echo $!';
$portText = ' -port ' . $this->SeleniumServerPort;
$command = "java -jar " .
- escapeshellarg($this->SeleniumServerExecPath) .
+ escapeshellarg( $this->SeleniumServerExecPath ) .
$portText . $commandSuffix;
- exec($command ,$op);
+ exec( $command, $op );
$pid = (int)$op[0];
- if ( $pid != "" )
+ if ( $pid != "" ) {
$this->SeleniumServerPid = $pid;
- else {
+ } else {
$this->SeleniumServerPid = 'NaN';
// Server start failed.
return 'failed';
for ( $cnt = 1;
$cnt <= $this->SeleniumServerStartTimeout;
$cnt++ ) {
- $fp = fsockopen ( 'localhost',
+ $fp = fsockopen( 'localhost',
$this->SeleniumServerPort,
$errno, $errstr, 0 );
if ( !$fp ) {
sleep( 1 );
continue;
- // Server start succeeded.
+ // Server start succeeded.
} else {
- fclose ( $fp );
+ fclose( $fp );
return 'started';
}
}
wfRestoreWarnings();
echo ( "Starting Selenium server timed out.\n" );
return 'failed';
+ } else {
+ // server already running.
+ return 'running';
}
- // server already running.
- else return 'running';
}
- // No Server execution path defined.
+
+ // No Server execution path defined.
return 'failed';
}
private function stopServerOnUnix() {
if ( !empty( $this->SeleniumServerPid ) &&
- $this->SeleniumServerPid != 'NaN' ) {
+ $this->SeleniumServerPid != 'NaN'
+ ) {
exec( "kill -9 " . $this->SeleniumServerPid );
return 'stopped';
+ } else {
+ return 'failed';
}
- else return 'failed';
}
private function stopServerOnWindows() {
<?php
-include("SeleniumTestConstants.php");
+include( "SeleniumTestConstants.php" );
class SeleniumTestCase extends PHPUnit_Framework_TestCase { // PHPUnit_Extensions_SeleniumTestCase
protected $selenium;
*/
function createTestPageIfMissing( $pageName = null ) {
if ( $pageName == null ) {
- $pageName = SeleniumTestConstants::WIKI_INTERNAL_LINK;
+ $pageName = SeleniumTestConstants::WIKI_INTERNAL_LINK;
}
- $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, $pageName );
+ $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, $pageName );
$this->click( SeleniumTestConstants::BUTTON_SEARCH );
$this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
$this->click( SeleniumTestConstants::LINK_START . $pageName );
$this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $location = $this->getLocation() . "\n";
- if ( strpos( $location, '&redlink=1') !== false ) {
- $this->type( SeleniumTestConstants::TEXT_EDITOR, "Test fixture page. No real content here" );
+ $location = $this->getLocation() . "\n";
+ if ( strpos( $location, '&redlink=1' ) !== false ) {
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, "Test fixture page. No real content here" );
$this->click( SeleniumTestConstants::BUTTON_SAVE );
$this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
$this->assertTrue( $this->isTextPresent( $pageName ),
- $this->getText( SeleniumTestConstants::TEXT_PAGE_HEADING ) );
+ $this->getText( SeleniumTestConstants::TEXT_PAGE_HEADING ) );
}
}
-
+
/**
* Create a test page using date as part of the name so that it is unique
* @param $pagePrefix The prefix to use for the page name. The current date will be appended to this to make it unique
* @param $watchThis Whether to add the page to my watchlist. Defaults to false.
*/
function createNewTestPage( $pagePrefix, $watchThis = false ) {
- $pageName = $pagePrefix . date("Ymd-His");
- $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, $pageName );
+ $pageName = $pagePrefix . date( "Ymd-His" );
+ $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, $pageName );
$this->click( SeleniumTestConstants::BUTTON_SEARCH );
$this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
$this->click( SeleniumTestConstants::LINK_START . $pageName );
$this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $location = $this->getLocation() . "\n";
- $this->assertContains( '&redlink=1', $location ).
- $this->type( SeleniumTestConstants::TEXT_EDITOR, "Test fixture page. No real content here" );
+ $location = $this->getLocation() . "\n";
+ $this->assertContains( '&redlink=1', $location ) .
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, "Test fixture page. No real content here" );
if ( $watchThis ) {
$this->click( "wpWatchthis" );
}
$this->click( SeleniumTestConstants::BUTTON_SAVE );
$this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
$this->assertTrue( $this->isTextPresent( $pageName ),
- $this->getText( SeleniumTestConstants::TEXT_PAGE_HEADING ) );
+ $this->getText( SeleniumTestConstants::TEXT_PAGE_HEADING ) );
return $pageName;
}
- public function getExistingPage(){
+ public function getExistingPage() {
$this->open( $this->getUrl() .
'/index.php?title=Main_Page&action=edit' );
- $this->type("searchInput", "new" );
- $this->click("searchGoButton");
- $this->waitForPageToLoad("30000");
+ $this->type( "searchInput", "new" );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( "30000" );
}
- public function getNewPage($pageName){
+ public function getNewPage( $pageName ) {
$this->open( $this->getUrl() .
'/index.php?title=Main_Page&action=edit' );
- $this->type("searchInput", $pageName );
- $this->click("searchGoButton");
- $this->waitForPageToLoad("30000");
- $this->click("link=".$pageName);
- $this->waitForPageToLoad("600000");
+ $this->type( "searchInput", $pageName );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( "30000" );
+ $this->click( "link=" . $pageName );
+ $this->waitForPageToLoad( "600000" );
}
+
// Loading the mediawiki editor
- public function loadWikiEditor(){
+ public function loadWikiEditor() {
$this->open( $this->getUrl() .
'/index.php?title=Main_Page&action=edit' );
}
// Clear the content of the mediawiki editor
- public function clearWikiEditor(){
- $this->type("wpTextbox1", "");
+ public function clearWikiEditor() {
+ $this->type( "wpTextbox1", "" );
}
// Click on the 'Show preview' button of the mediawiki editor
- public function clickShowPreviewBtn(){
- $this->click("wpPreview");
+ public function clickShowPreviewBtn() {
+ $this->click( "wpPreview" );
}
// Click on the 'Save Page' button of the mediawiki editor
- public function clickSavePageBtn(){
- $this->click("wpSave");
+ public function clickSavePageBtn() {
+ $this->click( "wpSave" );
}
// Click on the 'Edit' link
- public function clickEditLink(){
- $this->click("link=Edit");
- $this->waitForPageToLoad("30000");
+ public function clickEditLink() {
+ $this->click( "link=Edit" );
+ $this->waitForPageToLoad( "30000" );
}
-
}
$this->tests_failed++;
}
- public function addFailure( PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time )
- {
+ public function addFailure( PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time ) {
$this->logger->write( 'Failed: ' . $e->getMessage() );
$this->tests_failed++;
}
- public function addIncompleteTest( PHPUnit_Framework_Test $test, Exception $e, $time )
- {
+ public function addIncompleteTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
$this->logger->write( 'Incomplete.' );
$this->tests_failed++;
}
- public function addSkippedTest( PHPUnit_Framework_Test $test, Exception $e, $time )
- {
+ public function addSkippedTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
$this->logger->write( 'Skipped.' );
$this->tests_failed++;
}
}
public function endTestSuite( PHPUnit_Framework_TestSuite $suite ) {
- $this->logger->write('Testsuite ' . $suite->getName() . ' ended.' );
+ $this->logger->write( 'Testsuite ' . $suite->getName() . ' ended.' );
if ( $this->tests_ok > 0 || $this->tests_failed > 0 ) {
$this->logger->write( ' OK: ' . $this->tests_ok . ' Failed: ' . $this->tests_failed );
}
const RESULT_OK = 2;
const RESULT_ERROR = 3;
- public abstract function addTests();
+ abstract public function addTests();
public function setUp() {
// Hack because because PHPUnit version 3.0.6 which is on prototype does not
if ( $this->triggerClientTestResources ) {
$this->selenium->open( $this->selenium->getUrl() . '/index.php?setupTestSuite=' . $this->getName() );
//wait a little longer for the db operation
- $this->selenium->waitForPageToLoad( 6000 );
+ $this->selenium->waitForPageToLoad( 6000 );
}
if ( $this->loginBeforeTests ) {
$this->login();
protected function setLoginBeforeTests( $loginBeforeTests = true ) {
$this->loginBeforeTests = $loginBeforeTests;
}
-
+
protected function setTriggerClientTestResources( $triggerClientTestResources = true ) {
$this->triggerClientTestResources = $triggerClientTestResources;
}
LOCK TABLES `mw_msg_resource` WRITE;
/*!40000 ALTER TABLE `mw_msg_resource` DISABLE KEYS */;
-INSERT INTO `mw_msg_resource` VALUES ('ext.vector.collapsibleNav','en','{\"vector-collapsiblenav-more\":\"More languages\"}','20110108005000'),('ext.vector.collapsibleTabs','en','{}','20110108005000'),('ext.vector.simpleSearch','en','{\"vector-simplesearch-search\":\"Search\",\"vector-simplesearch-containing\":\"containing...\"}','20110108005000'),('ext.wikiEditor','en','{}','20110110172914'),('ext.wikiEditor.toolbar','en','{\"wikieditor-toolbar-loading\":\"Loading...\",\"wikieditor-toolbar-tool-bold\":\"Bold\",\"wikieditor-toolbar-tool-bold-example\":\"Bold text\",\"wikieditor-toolbar-tool-italic\":\"Italic\",\"wikieditor-toolbar-tool-italic-example\":\"Italic text\",\"wikieditor-toolbar-tool-ilink\":\"Internal link\",\"wikieditor-toolbar-tool-ilink-example\":\"Link title\",\"wikieditor-toolbar-tool-xlink\":\"External link (remember http:\\/\\/ prefix)\",\"wikieditor-toolbar-tool-xlink-example\":\"http:\\/\\/www.example.com link title\",\"wikieditor-toolbar-tool-link\":\"Link\",\"wikieditor-toolbar-tool-link-title\":\"Insert link\",\"wikieditor-toolbar-tool-link-int\":\"To a wiki page\",\"wikieditor-toolbar-tool-link-int-target\":\"Target page or URL:\",\"wikieditor-toolbar-tool-link-int-target-tooltip\":\"Page title or URL\",\"wikieditor-toolbar-tool-link-int-text\":\"Text to display:\",\"wikieditor-toolbar-tool-link-int-text-tooltip\":\"Text to be displayed\",\"wikieditor-toolbar-tool-link-ext\":\"To an external web page\",\"wikieditor-toolbar-tool-link-ext-target\":\"Link URL:\",\"wikieditor-toolbar-tool-link-ext-text\":\"Link text:\",\"wikieditor-toolbar-tool-link-insert\":\"Insert link\",\"wikieditor-toolbar-tool-link-cancel\":\"Cancel\",\"wikieditor-toolbar-tool-link-int-target-status-exists\":\"Page exists\",\"wikieditor-toolbar-tool-link-int-target-status-notexists\":\"Page does not exist\",\"wikieditor-toolbar-tool-link-int-target-status-invalid\":\"Invalid title\",\"wikieditor-toolbar-tool-link-int-target-status-external\":\"External link\",\"wikieditor-toolbar-tool-link-int-target-status-loading\":\"Checking page existence...\",\"wikieditor-toolbar-tool-link-int-invalid\":\"The title you specified is invalid.\",\"wikieditor-toolbar-tool-link-lookslikeinternal\":\"The URL you specified looks like it was intended as a link to another wiki page.\\nDo you want to make it an internal link?\",\"wikieditor-toolbar-tool-link-lookslikeinternal-int\":\"Internal link\",\"wikieditor-toolbar-tool-link-lookslikeinternal-ext\":\"External link\",\"wikieditor-toolbar-tool-link-empty\":\"You did not enter anything to link to.\",\"wikieditor-toolbar-tool-file\":\"Embedded file\",\"wikieditor-toolbar-tool-file-pre\":\"$1{{ns:file}}:\",\"wikieditor-toolbar-tool-file-example\":\"Example.jpg\",\"wikieditor-toolbar-tool-reference\":\"Reference\",\"wikieditor-toolbar-tool-reference-title\":\"Insert reference\",\"wikieditor-toolbar-tool-reference-cancel\":\"Cancel\",\"wikieditor-toolbar-tool-reference-text\":\"Reference text\",\"wikieditor-toolbar-tool-reference-insert\":\"Insert\",\"wikieditor-toolbar-tool-reference-example\":\"Insert footnote text here\",\"wikieditor-toolbar-tool-signature\":\"Signature and timestamp\",\"wikieditor-toolbar-section-advanced\":\"Advanced\",\"wikieditor-toolbar-tool-heading\":\"Heading\",\"wikieditor-toolbar-tool-heading-1\":\"Level 1\",\"wikieditor-toolbar-tool-heading-2\":\"Level 2\",\"wikieditor-toolbar-tool-heading-3\":\"Level 3\",\"wikieditor-toolbar-tool-heading-4\":\"Level 4\",\"wikieditor-toolbar-tool-heading-5\":\"Level 5\",\"wikieditor-toolbar-tool-heading-example\":\"Heading text\",\"wikieditor-toolbar-group-format\":\"Format\",\"wikieditor-toolbar-tool-ulist\":\"Bulleted list\",\"wikieditor-toolbar-tool-ulist-example\":\"Bulleted list item\",\"wikieditor-toolbar-tool-olist\":\"Numbered list\",\"wikieditor-toolbar-tool-olist-example\":\"Numbered list item\",\"wikieditor-toolbar-tool-indent\":\"Indentation\",\"wikieditor-toolbar-tool-indent-example\":\"Indented line\",\"wikieditor-toolbar-tool-nowiki\":\"No wiki formatting\",\"wikieditor-toolbar-tool-nowiki-example\":\"Insert non-formatted text here\",\"wikieditor-toolbar-tool-redirect\":\"Redirect\",\"wikieditor-toolbar-tool-redirect-example\":\"Target page name\",\"wikieditor-toolbar-tool-big\":\"Big\",\"wikieditor-toolbar-tool-big-example\":\"Big text\",\"wikieditor-toolbar-tool-small\":\"Small\",\"wikieditor-toolbar-tool-small-example\":\"Small text\",\"wikieditor-toolbar-tool-superscript\":\"Superscript\",\"wikieditor-toolbar-tool-superscript-example\":\"Superscript text\",\"wikieditor-toolbar-tool-subscript\":\"Subscript\",\"wikieditor-toolbar-tool-subscript-example\":\"Subscript text\",\"wikieditor-toolbar-group-insert\":\"Insert\",\"wikieditor-toolbar-tool-gallery\":\"Picture gallery\",\"wikieditor-toolbar-tool-gallery-example\":\"{{ns:file}}:Example.jpg|Caption1\\n{{ns:file}}:Example.jpg|Caption2\",\"wikieditor-toolbar-tool-newline\":\"New line\",\"wikieditor-toolbar-tool-table\":\"Table\",\"wikieditor-toolbar-tool-table-example-old\":\"-\\n! header 1\\n! header 2\\n! header 3\\n|-\\n| row 1, cell 1\\n| row 1, cell 2\\n| row 1, cell 3\\n|-\\n| row 2, cell 1\\n| row 2, cell 2\\n| row 2, cell 3\",\"wikieditor-toolbar-tool-table-example-cell-text\":\"Cell text\",\"wikieditor-toolbar-tool-table-example\":\"Example\",\"wikieditor-toolbar-tool-table-example-header\":\"Header text\",\"wikieditor-toolbar-tool-table-title\":\"Insert table\",\"wikieditor-toolbar-tool-table-dimensions-rows\":\"Rows\",\"wikieditor-toolbar-tool-table-dimensions-columns\":\"Columns\",\"wikieditor-toolbar-tool-table-dimensions-header\":\"Add header row\",\"wikieditor-toolbar-tool-table-wikitable\":\"Style with borders\",\"wikieditor-toolbar-tool-table-sortable\":\"Make table sortable\",\"wikieditor-toolbar-tool-table-insert\":\"Insert\",\"wikieditor-toolbar-tool-table-cancel\":\"Cancel\",\"wikieditor-toolbar-tool-table-example-text\":\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut nec purus diam. Sed aliquam imperdiet nunc quis lacinia. Donec rutrum consectetur placerat. Sed volutpat neque non purus faucibus id ultricies enim euismod.\",\"wikieditor-toolbar-tool-table-toomany\":\"Inserting a table with more than $1 cells is not possible with this dialog.\",\"wikieditor-toolbar-tool-table-invalidnumber\":\"You have not entered a valid number of rows or columns.\",\"wikieditor-toolbar-tool-table-zero\":\"You cannot insert a table with zero rows or columns.\",\"wikieditor-toolbar-tool-replace\":\"Search and replace\",\"wikieditor-toolbar-tool-replace-title\":\"Search and replace\",\"wikieditor-toolbar-tool-replace-search\":\"Search for:\",\"wikieditor-toolbar-tool-replace-replace\":\"Replace with:\",\"wikieditor-toolbar-tool-replace-case\":\"Match case\",\"wikieditor-toolbar-tool-replace-regex\":\"Treat search string as a regular expression\",\"wikieditor-toolbar-tool-replace-button-findnext\":\"Find next\",\"wikieditor-toolbar-tool-replace-button-replacenext\":\"Replace next\",\"wikieditor-toolbar-tool-replace-button-replaceall\":\"Replace all\",\"wikieditor-toolbar-tool-replace-close\":\"Close\",\"wikieditor-toolbar-tool-replace-nomatch\":\"Your search did not match anything.\",\"wikieditor-toolbar-tool-replace-success\":\"$1 replacement(s) made.\",\"wikieditor-toolbar-tool-replace-emptysearch\":\"You did not enter anything to search for.\",\"wikieditor-toolbar-tool-replace-invalidregex\":\"The regular expression you entered is invalid: $1\",\"wikieditor-toolbar-section-characters\":\"Special characters\",\"wikieditor-toolbar-characters-page-latin\":\"Latin\",\"wikieditor-toolbar-characters-page-latinextended\":\"Latin extended\",\"wikieditor-toolbar-characters-page-ipa\":\"IPA\",\"wikieditor-toolbar-characters-page-symbols\":\"Symbols\",\"wikieditor-toolbar-characters-page-greek\":\"Greek\",\"wikieditor-toolbar-characters-page-cyrillic\":\"Cyrillic\",\"wikieditor-toolbar-characters-page-arabic\":\"Arabic\",\"wikieditor-toolbar-characters-page-persian\":\"Persian\",\"wikieditor-toolbar-characters-page-hebrew\":\"Hebrew\",\"wikieditor-toolbar-characters-page-bangla\":\"Bangla\",\"wikieditor-toolbar-characters-page-telugu\":\"Telugu\",\"wikieditor-toolbar-characters-page-sinhala\":\"Sinhala\",\"wikieditor-toolbar-characters-page-gujarati\":\"Gujarati\",\"wikieditor-toolbar-characters-page-thai\":\"Thai\",\"wikieditor-toolbar-characters-page-lao\":\"Lao\",\"wikieditor-toolbar-characters-page-khmer\":\"Khmer\",\"wikieditor-toolbar-section-help\":\"Help\",\"wikieditor-toolbar-help-heading-description\":\"Description\",\"wikieditor-toolbar-help-heading-syntax\":\"What you type\",\"wikieditor-toolbar-help-heading-result\":\"What you get\",\"wikieditor-toolbar-help-page-format\":\"Formatting\",\"wikieditor-toolbar-help-page-link\":\"Links\",\"wikieditor-toolbar-help-page-heading\":\"Headings\",\"wikieditor-toolbar-help-page-list\":\"Lists\",\"wikieditor-toolbar-help-page-file\":\"Files\",\"wikieditor-toolbar-help-page-reference\":\"References\",\"wikieditor-toolbar-help-page-discussion\":\"Discussion\",\"wikieditor-toolbar-help-content-bold-description\":\"Bold\",\"wikieditor-toolbar-help-content-bold-syntax\":\"\'\'\'Bold text\'\'\'\",\"wikieditor-toolbar-help-content-bold-result\":\"<strong>Bold text<\\/strong>\",\"wikieditor-toolbar-help-content-italic-description\":\"Italic\",\"wikieditor-toolbar-help-content-italic-syntax\":\"\'\'Italic text\'\'\",\"wikieditor-toolbar-help-content-italic-result\":\"<em>Italic text<\\/em>\",\"wikieditor-toolbar-help-content-bolditalic-description\":\"Bold & italic\",\"wikieditor-toolbar-help-content-bolditalic-syntax\":\"\'\'\'\'\'Bold & italic text\'\'\'\'\'\",\"wikieditor-toolbar-help-content-bolditalic-result\":\"<strong><em>Bold & italic text<\\/em><\\/strong>\",\"wikieditor-toolbar-help-content-ilink-description\":\"Internal link\",\"wikieditor-toolbar-help-content-ilink-syntax\":\"[[Page title|Link label]]<br \\/>[[Page title]]\",\"wikieditor-toolbar-help-content-ilink-result\":\"<a href=\'#\'>Link label<\\/a><br \\/><a href=\'#\'>Page title<\\/a>\",\"wikieditor-toolbar-help-content-xlink-description\":\"External link\",\"wikieditor-toolbar-help-content-xlink-syntax\":\"[http:\\/\\/www.example.org Link label]<br \\/>[http:\\/\\/www.example.org]<br \\/>http:\\/\\/www.example.org\",\"wikieditor-toolbar-help-content-xlink-result\":\"<a href=\'#\' class=\'external\'>Link label<\\/a><br \\/><a href=\'#\' class=\'external autonumber\'>[1]<\\/a><br \\/><a href=\'#\' class=\'external\'>http:\\/\\/www.example.org<\\/a>\",\"wikieditor-toolbar-help-content-heading1-description\":\"<wikieditor-toolbar-help-content-heading1-description>\",\"wikieditor-toolbar-help-content-heading1-syntax\":\"<wikieditor-toolbar-help-content-heading1-syntax>\",\"wikieditor-toolbar-help-content-heading1-result\":\"<wikieditor-toolbar-help-content-heading1-result>\",\"wikieditor-toolbar-help-content-heading2-description\":\"2nd level heading\",\"wikieditor-toolbar-help-content-heading2-syntax\":\"== Heading text ==\",\"wikieditor-toolbar-help-content-heading2-result\":\"<h2>Heading text<\\/h2>\",\"wikieditor-toolbar-help-content-heading3-description\":\"3rd level heading\",\"wikieditor-toolbar-help-content-heading3-syntax\":\"=== Heading text ===\",\"wikieditor-toolbar-help-content-heading3-result\":\"<h3>Heading text<\\/h3>\",\"wikieditor-toolbar-help-content-heading4-description\":\"4th level heading\",\"wikieditor-toolbar-help-content-heading4-syntax\":\"==== Heading text ====\",\"wikieditor-toolbar-help-content-heading4-result\":\"<h4>Heading text<\\/h4>\",\"wikieditor-toolbar-help-content-heading5-description\":\"5th level heading\",\"wikieditor-toolbar-help-content-heading5-syntax\":\"===== Heading text =====\",\"wikieditor-toolbar-help-content-heading5-result\":\"<h5>Heading text<\\/h5>\",\"wikieditor-toolbar-help-content-ulist-description\":\"Bulleted list\",\"wikieditor-toolbar-help-content-ulist-syntax\":\"* List item<br \\/>* List item\",\"wikieditor-toolbar-help-content-ulist-result\":\"<ul><li>List item<\\/li><li>List item<\\/li><\\/ul>\",\"wikieditor-toolbar-help-content-olist-description\":\"Numbered list\",\"wikieditor-toolbar-help-content-olist-syntax\":\"# List item<br \\/># List item\",\"wikieditor-toolbar-help-content-olist-result\":\"<ol><li>List item<\\/li><li>List item<\\/li><\\/ol>\",\"wikieditor-toolbar-help-content-file-description\":\"Embedded file\",\"wikieditor-toolbar-help-content-file-syntax\":\"[[{{ns:file}}:Example.png|thumb|Caption text]]\",\"wikieditor-toolbar-help-content-file-result\":\"<div style=\'width:104px;\' class=\'thumbinner\'><a title=\'Caption text\' class=\'image\' href=\'#\'><img height=\'50\' width=\'100\' border=\'0\' class=\'thumbimage\' src=\'extensions\\/UsabilityInitiative\\/images\\/wikiEditor\\/toolbar\\/example-image.png\' alt=\'\'\\/><\\/a><div class=\'thumbcaption\'><div class=\'magnify\'><a title=\'Enlarge\' class=\'internal\' href=\'#\'><img height=\'11\' width=\'15\' alt=\'\' src=\'$1\\/common\\/images\\/magnify-clip.png\'\\/><\\/a><\\/div>Caption text<\\/div><\\/div>\",\"wikieditor-toolbar-help-content-reference-description\":\"Reference\",\"wikieditor-toolbar-help-content-reference-syntax\":\"Page text.<ref name=\\\"test\\\">[http:\\/\\/www.example.org Link text], additional text.<\\/ref>\",\"wikieditor-toolbar-help-content-reference-result\":\"Page text.<sup><a href=\'#\'>[1]<\\/a><\\/sup>\",\"wikieditor-toolbar-help-content-rereference-description\":\"Additional use of same reference\",\"wikieditor-toolbar-help-content-rereference-syntax\":\"<ref name=\\\"test\\\" \\/>\",\"wikieditor-toolbar-help-content-rereference-result\":\"Page text.<sup><a href=\'#\'>[1]<\\/a><\\/sup>\",\"wikieditor-toolbar-help-content-showreferences-description\":\"Display references\",\"wikieditor-toolbar-help-content-showreferences-syntax\":\"<references \\/>\",\"wikieditor-toolbar-help-content-showreferences-result\":\"<ol class=\'references\'><li id=\'cite_note-test-0\'><b><a title=\'\' href=\'#\'>^<\\/a><\\/b> <a rel=\'nofollow\' title=\'http:\\/\\/www.example.org\' class=\'external text\' href=\'#\'>Link text<\\/a>, additional text.<\\/li><\\/ol>\",\"wikieditor-toolbar-help-content-signaturetimestamp-description\":\"Signature with timestamp\",\"wikieditor-toolbar-help-content-signaturetimestamp-syntax\":\"~~~~\",\"wikieditor-toolbar-help-content-signaturetimestamp-result\":\"<a href=\'#\' title=\'{{#special:mypage}}\'>Username<\\/a> (<a href=\'#\' title=\'{{#special:mytalk}}\'>talk<\\/a>) 15:54, 10 June 2009 (UTC)\",\"wikieditor-toolbar-help-content-signature-description\":\"Signature\",\"wikieditor-toolbar-help-content-signature-syntax\":\"~~~\",\"wikieditor-toolbar-help-content-signature-result\":\"<a href=\'#\' title=\'{{#special:mypage}}\'>Username<\\/a> (<a href=\'#\' title=\'{{#special:mytalk}}\'>talk<\\/a>)\",\"wikieditor-toolbar-help-content-indent-description\":\"Indent\",\"wikieditor-toolbar-help-content-indent-syntax\":\"Normal text<br \\/>:Indented text<br \\/>::Indented text\",\"wikieditor-toolbar-help-content-indent-result\":\"Normal text<dl><dd>Indented text<dl><dd>Indented text<\\/dd><\\/dl><\\/dd><\\/dl>\"}','20110110172914'),('jquery.async','en','{}','20110110172915'),('jquery.autoEllipsis','en','{}','20110110172915'),('jquery.checkboxShiftClick','en','{}','20110110172915'),('jquery.client','en','{}','20110110172915'),('jquery.collapsibleTabs','en','{}','20110110172915'),('jquery.cookie','en','{}','20110110172915'),('jquery.delayedBind','en','{}','20110110172915'),('jquery.highlightText','en','{}','20110110172915'),('jquery.makeCollapsible','en','{\"collapsible-expand\":\"Expand\",\"collapsible-collapse\":\"Collapse\"}','20110110172915'),('jquery.placeholder','en','{}','20110110172915'),('jquery.suggestions','en','{}','20110110172915'),('jquery.tabIndex','en','{}','20110110172915'),('jquery.textSelection','en','{}','20110110172915'),('jquery.wikiEditor','en','{\"wikieditor-wikitext-tab\":\"Wikitext\",\"wikieditor-loading\":\"Loading\"}','20110110172914'),('jquery.wikiEditor.toolbar','en','{}','20110110172914'),('mediawiki.action.watch.ajax','en','{}','20110110172915'),('mediawiki.language','en','{}','20110110172915'),('mediawiki.legacy.ajax','en','{\"watch\":\"Watch\",\"unwatch\":\"Unwatch\",\"watching\":\"Watching...\",\"unwatching\":\"Unwatching...\",\"tooltip-ca-watch\":\"Add this page to your watchlist\",\"tooltip-ca-unwatch\":\"Remove this page from your watchlist\"}','20110110172915'),('mediawiki.legacy.edit','en','{}','20110110172915'),('mediawiki.legacy.wikibits','en','{\"showtoc\":\"show\",\"hidetoc\":\"hide\"}','20110110172915'),('mediawiki.util','en','{}','20110110172915');
+INSERT INTO `mw_msg_resource` VALUES ('ext.vector.collapsibleNav','en','{\"vector-collapsiblenav-more\":\"More languages\"}','20110108005000'),('ext.vector.collapsibleTabs','en','{}','20110108005000'),('ext.vector.simpleSearch','en','{\"vector-simplesearch-search\":\"Search\",\"vector-simplesearch-containing\":\"containing...\"}','20110108005000'),('ext.wikiEditor','en','{}','20110110172914'),('ext.wikiEditor.toolbar','en','{\"wikieditor-toolbar-loading\":\"Loading...\",\"wikieditor-toolbar-tool-bold\":\"Bold\",\"wikieditor-toolbar-tool-bold-example\":\"Bold text\",\"wikieditor-toolbar-tool-italic\":\"Italic\",\"wikieditor-toolbar-tool-italic-example\":\"Italic text\",\"wikieditor-toolbar-tool-ilink\":\"Internal link\",\"wikieditor-toolbar-tool-ilink-example\":\"Link title\",\"wikieditor-toolbar-tool-xlink\":\"External link (remember http:\\/\\/ prefix)\",\"wikieditor-toolbar-tool-xlink-example\":\"http:\\/\\/www.example.com link title\",\"wikieditor-toolbar-tool-link\":\"Link\",\"wikieditor-toolbar-tool-link-title\":\"Insert link\",\"wikieditor-toolbar-tool-link-int\":\"To a wiki page\",\"wikieditor-toolbar-tool-link-int-target\":\"Target page or URL:\",\"wikieditor-toolbar-tool-link-int-target-tooltip\":\"Page title or URL\",\"wikieditor-toolbar-tool-link-int-text\":\"Text to display:\",\"wikieditor-toolbar-tool-link-int-text-tooltip\":\"Text to be displayed\",\"wikieditor-toolbar-tool-link-ext\":\"To an external web page\",\"wikieditor-toolbar-tool-link-ext-target\":\"Link URL:\",\"wikieditor-toolbar-tool-link-ext-text\":\"Link text:\",\"wikieditor-toolbar-tool-link-insert\":\"Insert link\",\"wikieditor-toolbar-tool-link-cancel\":\"Cancel\",\"wikieditor-toolbar-tool-link-int-target-status-exists\":\"Page exists\",\"wikieditor-toolbar-tool-link-int-target-status-notexists\":\"Page does not exist\",\"wikieditor-toolbar-tool-link-int-target-status-invalid\":\"Invalid title\",\"wikieditor-toolbar-tool-link-int-target-status-external\":\"External link\",\"wikieditor-toolbar-tool-link-int-target-status-loading\":\"Checking page existence...\",\"wikieditor-toolbar-tool-link-int-invalid\":\"The title you specified is invalid.\",\"wikieditor-toolbar-tool-link-lookslikeinternal\":\"The URL you specified looks like it was intended as a link to another wiki page.\\nDo you want to make it an internal link?\",\"wikieditor-toolbar-tool-link-lookslikeinternal-int\":\"Internal link\",\"wikieditor-toolbar-tool-link-lookslikeinternal-ext\":\"External link\",\"wikieditor-toolbar-tool-link-empty\":\"You did not enter anything to link to.\",\"wikieditor-toolbar-tool-file\":\"Embedded file\",\"wikieditor-toolbar-tool-file-pre\":\"$1{{ns:file}}:\",\"wikieditor-toolbar-tool-file-example\":\"Example.jpg\",\"wikieditor-toolbar-tool-reference\":\"Reference\",\"wikieditor-toolbar-tool-reference-title\":\"Insert reference\",\"wikieditor-toolbar-tool-reference-cancel\":\"Cancel\",\"wikieditor-toolbar-tool-reference-text\":\"Reference text\",\"wikieditor-toolbar-tool-reference-insert\":\"Insert\",\"wikieditor-toolbar-tool-reference-example\":\"Insert footnote text here\",\"wikieditor-toolbar-tool-signature\":\"Signature and timestamp\",\"wikieditor-toolbar-section-advanced\":\"Advanced\",\"wikieditor-toolbar-tool-heading\":\"Heading\",\"wikieditor-toolbar-tool-heading-1\":\"Level 1\",\"wikieditor-toolbar-tool-heading-2\":\"Level 2\",\"wikieditor-toolbar-tool-heading-3\":\"Level 3\",\"wikieditor-toolbar-tool-heading-4\":\"Level 4\",\"wikieditor-toolbar-tool-heading-5\":\"Level 5\",\"wikieditor-toolbar-tool-heading-example\":\"Heading text\",\"wikieditor-toolbar-group-format\":\"Format\",\"wikieditor-toolbar-tool-ulist\":\"Bulleted list\",\"wikieditor-toolbar-tool-ulist-example\":\"Bulleted list item\",\"wikieditor-toolbar-tool-olist\":\"Numbered list\",\"wikieditor-toolbar-tool-olist-example\":\"Numbered list item\",\"wikieditor-toolbar-tool-indent\":\"Indentation\",\"wikieditor-toolbar-tool-indent-example\":\"Indented line\",\"wikieditor-toolbar-tool-nowiki\":\"No wiki formatting\",\"wikieditor-toolbar-tool-nowiki-example\":\"Insert non-formatted text here\",\"wikieditor-toolbar-tool-redirect\":\"Redirect\",\"wikieditor-toolbar-tool-redirect-example\":\"Target page name\",\"wikieditor-toolbar-tool-big\":\"Big\",\"wikieditor-toolbar-tool-big-example\":\"Big text\",\"wikieditor-toolbar-tool-small\":\"Small\",\"wikieditor-toolbar-tool-small-example\":\"Small text\",\"wikieditor-toolbar-tool-superscript\":\"Superscript\",\"wikieditor-toolbar-tool-superscript-example\":\"Superscript text\",\"wikieditor-toolbar-tool-subscript\":\"Subscript\",\"wikieditor-toolbar-tool-subscript-example\":\"Subscript text\",\"wikieditor-toolbar-group-insert\":\"Insert\",\"wikieditor-toolbar-tool-gallery\":\"Picture gallery\",\"wikieditor-toolbar-tool-gallery-example\":\"{{ns:file}}:Example.jpg|Caption1\\n{{ns:file}}:Example.jpg|Caption2\",\"wikieditor-toolbar-tool-newline\":\"New line\",\"wikieditor-toolbar-tool-table\":\"Table\",\"wikieditor-toolbar-tool-table-example-old\":\"-\\n! header 1\\n! header 2\\n! header 3\\n|-\\n| row 1, cell 1\\n| row 1, cell 2\\n| row 1, cell 3\\n|-\\n| row 2, cell 1\\n| row 2, cell 2\\n| row 2, cell 3\",\"wikieditor-toolbar-tool-table-example-cell-text\":\"Cell text\",\"wikieditor-toolbar-tool-table-example\":\"Example\",\"wikieditor-toolbar-tool-table-example-header\":\"Header text\",\"wikieditor-toolbar-tool-table-title\":\"Insert table\",\"wikieditor-toolbar-tool-table-dimensions-rows\":\"Rows\",\"wikieditor-toolbar-tool-table-dimensions-columns\":\"Columns\",\"wikieditor-toolbar-tool-table-dimensions-header\":\"Add header row\",\"wikieditor-toolbar-tool-table-wikitable\":\"Style with borders\",\"wikieditor-toolbar-tool-table-sortable\":\"Make table sortable\",\"wikieditor-toolbar-tool-table-insert\":\"Insert\",\"wikieditor-toolbar-tool-table-cancel\":\"Cancel\",\"wikieditor-toolbar-tool-table-example-text\":\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut nec purus diam. Sed aliquam imperdiet nunc quis lacinia. Donec rutrum consectetur placerat. Sed volutpat neque non purus faucibus id ultricies enim euismod.\",\"wikieditor-toolbar-tool-table-toomany\":\"Inserting a table with more than $1 cells is not possible with this dialog.\",\"wikieditor-toolbar-tool-table-invalidnumber\":\"You have not entered a valid number of rows or columns.\",\"wikieditor-toolbar-tool-table-zero\":\"You cannot insert a table with zero rows or columns.\",\"wikieditor-toolbar-tool-replace\":\"Search and replace\",\"wikieditor-toolbar-tool-replace-title\":\"Search and replace\",\"wikieditor-toolbar-tool-replace-search\":\"Search for:\",\"wikieditor-toolbar-tool-replace-replace\":\"Replace with:\",\"wikieditor-toolbar-tool-replace-case\":\"Match case\",\"wikieditor-toolbar-tool-replace-regex\":\"Treat search string as a regular expression\",\"wikieditor-toolbar-tool-replace-button-findnext\":\"Find next\",\"wikieditor-toolbar-tool-replace-button-replacenext\":\"Replace next\",\"wikieditor-toolbar-tool-replace-button-replaceall\":\"Replace all\",\"wikieditor-toolbar-tool-replace-close\":\"Close\",\"wikieditor-toolbar-tool-replace-nomatch\":\"Your search did not match anything.\",\"wikieditor-toolbar-tool-replace-success\":\"$1 replacement(s) made.\",\"wikieditor-toolbar-tool-replace-emptysearch\":\"You did not enter anything to search for.\",\"wikieditor-toolbar-tool-replace-invalidregex\":\"The regular expression you entered is invalid: $1\",\"wikieditor-toolbar-section-characters\":\"Special characters\",\"wikieditor-toolbar-characters-page-latin\":\"Latin\",\"wikieditor-toolbar-characters-page-latinextended\":\"Latin extended\",\"wikieditor-toolbar-characters-page-ipa\":\"IPA\",\"wikieditor-toolbar-characters-page-symbols\":\"Symbols\",\"wikieditor-toolbar-characters-page-greek\":\"Greek\",\"wikieditor-toolbar-characters-page-cyrillic\":\"Cyrillic\",\"wikieditor-toolbar-characters-page-arabic\":\"Arabic\",\"wikieditor-toolbar-characters-page-persian\":\"Persian\",\"wikieditor-toolbar-characters-page-hebrew\":\"Hebrew\",\"wikieditor-toolbar-characters-page-bangla\":\"Bangla\",\"wikieditor-toolbar-characters-page-telugu\":\"Telugu\",\"wikieditor-toolbar-characters-page-sinhala\":\"Sinhala\",\"wikieditor-toolbar-characters-page-gujarati\":\"Gujarati\",\"wikieditor-toolbar-characters-page-thai\":\"Thai\",\"wikieditor-toolbar-characters-page-lao\":\"Lao\",\"wikieditor-toolbar-characters-page-khmer\":\"Khmer\",\"wikieditor-toolbar-section-help\":\"Help\",\"wikieditor-toolbar-help-heading-description\":\"Description\",\"wikieditor-toolbar-help-heading-syntax\":\"What you type\",\"wikieditor-toolbar-help-heading-result\":\"What you get\",\"wikieditor-toolbar-help-page-format\":\"Formatting\",\"wikieditor-toolbar-help-page-link\":\"Links\",\"wikieditor-toolbar-help-page-heading\":\"Headings\",\"wikieditor-toolbar-help-page-list\":\"Lists\",\"wikieditor-toolbar-help-page-file\":\"Files\",\"wikieditor-toolbar-help-page-reference\":\"References\",\"wikieditor-toolbar-help-page-discussion\":\"Discussion\",\"wikieditor-toolbar-help-content-bold-description\":\"Bold\",\"wikieditor-toolbar-help-content-bold-syntax\":\"\'\'\'Bold text\'\'\'\",\"wikieditor-toolbar-help-content-bold-result\":\"<strong>Bold text<\\/strong>\",\"wikieditor-toolbar-help-content-italic-description\":\"Italic\",\"wikieditor-toolbar-help-content-italic-syntax\":\"\'\'Italic text\'\'\",\"wikieditor-toolbar-help-content-italic-result\":\"<em>Italic text<\\/em>\",\"wikieditor-toolbar-help-content-bolditalic-description\":\"Bold & italic\",\"wikieditor-toolbar-help-content-bolditalic-syntax\":\"\'\'\'\'\'Bold & italic text\'\'\'\'\'\",\"wikieditor-toolbar-help-content-bolditalic-result\":\"<strong><em>Bold & italic text<\\/em><\\/strong>\",\"wikieditor-toolbar-help-content-ilink-description\":\"Internal link\",\"wikieditor-toolbar-help-content-ilink-syntax\":\"[[Page title|Link label]]<br \\/>[[Page title]]\",\"wikieditor-toolbar-help-content-ilink-result\":\"<a href=\'#\'>Link label<\\/a><br \\/><a href=\'#\'>Page title<\\/a>\",\"wikieditor-toolbar-help-content-xlink-description\":\"External link\",\"wikieditor-toolbar-help-content-xlink-syntax\":\"[http:\\/\\/www.example.org Link label]<br \\/>[http:\\/\\/www.example.org]<br \\/>http:\\/\\/www.example.org\",\"wikieditor-toolbar-help-content-xlink-result\":\"<a href=\'#\' class=\'external\'>Link label<\\/a><br \\/><a href=\'#\' class=\'external autonumber\'>[1]<\\/a><br \\/><a href=\'#\' class=\'external\'>http:\\/\\/www.example.org<\\/a>\",\"wikieditor-toolbar-help-content-heading1-description\":\"<wikieditor-toolbar-help-content-heading1-description>\",\"wikieditor-toolbar-help-content-heading1-syntax\":\"<wikieditor-toolbar-help-content-heading1-syntax>\",\"wikieditor-toolbar-help-content-heading1-result\":\"<wikieditor-toolbar-help-content-heading1-result>\",\"wikieditor-toolbar-help-content-heading2-description\":\"2nd level heading\",\"wikieditor-toolbar-help-content-heading2-syntax\":\"== Heading text ==\",\"wikieditor-toolbar-help-content-heading2-result\":\"<h2>Heading text<\\/h2>\",\"wikieditor-toolbar-help-content-heading3-description\":\"3rd level heading\",\"wikieditor-toolbar-help-content-heading3-syntax\":\"=== Heading text ===\",\"wikieditor-toolbar-help-content-heading3-result\":\"<h3>Heading text<\\/h3>\",\"wikieditor-toolbar-help-content-heading4-description\":\"4th level heading\",\"wikieditor-toolbar-help-content-heading4-syntax\":\"==== Heading text ====\",\"wikieditor-toolbar-help-content-heading4-result\":\"<h4>Heading text<\\/h4>\",\"wikieditor-toolbar-help-content-heading5-description\":\"5th level heading\",\"wikieditor-toolbar-help-content-heading5-syntax\":\"===== Heading text =====\",\"wikieditor-toolbar-help-content-heading5-result\":\"<h5>Heading text<\\/h5>\",\"wikieditor-toolbar-help-content-ulist-description\":\"Bulleted list\",\"wikieditor-toolbar-help-content-ulist-syntax\":\"* List item<br \\/>* List item\",\"wikieditor-toolbar-help-content-ulist-result\":\"<ul><li>List item<\\/li><li>List item<\\/li><\\/ul>\",\"wikieditor-toolbar-help-content-olist-description\":\"Numbered list\",\"wikieditor-toolbar-help-content-olist-syntax\":\"# List item<br \\/># List item\",\"wikieditor-toolbar-help-content-olist-result\":\"<ol><li>List item<\\/li><li>List item<\\/li><\\/ol>\",\"wikieditor-toolbar-help-content-file-description\":\"Embedded file\",\"wikieditor-toolbar-help-content-file-syntax\":\"[[{{ns:file}}:Example.png|thumb|Caption text]]\",\"wikieditor-toolbar-help-content-file-result\":\"<div style=\'width:104px;\' class=\'thumbinner\'><a title=\'Caption text\' class=\'image\' href=\'#\'><img height=\'50\' width=\'100\' border=\'0\' class=\'thumbimage\' src=\'extensions\\/UsabilityInitiative\\/images\\/wikiEditor\\/toolbar\\/example-image.png\' alt=\'\'\\/><\\/a><div class=\'thumbcaption\'><div class=\'magnify\'><a title=\'Enlarge\' class=\'internal\' href=\'#\'><img height=\'11\' width=\'15\' alt=\'\' src=\'$1\\/common\\/images\\/magnify-clip.png\'\\/><\\/a><\\/div>Caption text<\\/div><\\/div>\",\"wikieditor-toolbar-help-content-reference-description\":\"Reference\",\"wikieditor-toolbar-help-content-reference-syntax\":\"Page text.<ref name=\\\"test\\\">[http:\\/\\/www.example.org Link text], additional text.<\\/ref>\",\"wikieditor-toolbar-help-content-reference-result\":\"Page text.<sup><a href=\'#\'>[1]<\\/a><\\/sup>\",\"wikieditor-toolbar-help-content-rereference-description\":\"Additional use of same reference\",\"wikieditor-toolbar-help-content-rereference-syntax\":\"<ref name=\\\"test\\\" \\/>\",\"wikieditor-toolbar-help-content-rereference-result\":\"Page text.<sup><a href=\'#\'>[1]<\\/a><\\/sup>\",\"wikieditor-toolbar-help-content-showreferences-description\":\"Display references\",\"wikieditor-toolbar-help-content-showreferences-syntax\":\"<references \\/>\",\"wikieditor-toolbar-help-content-showreferences-result\":\"<ol class=\'references\'><li id=\'cite_note-test-0\'><b><a title=\'\' href=\'#\'>^<\\/a><\\/b> <a rel=\'nofollow\' title=\'http:\\/\\/www.example.org\' class=\'external text\' href=\'#\'>Link text<\\/a>, additional text.<\\/li><\\/ol>\",\"wikieditor-toolbar-help-content-signaturetimestamp-description\":\"Signature with timestamp\",\"wikieditor-toolbar-help-content-signaturetimestamp-syntax\":\"~~~~\",\"wikieditor-toolbar-help-content-signaturetimestamp-result\":\"<a href=\'#\' title=\'{{#special:mypage}}\'>Username<\\/a> (<a href=\'#\' title=\'{{#special:mytalk}}\'>talk<\\/a>) 15:54, 10 June 2009 (UTC)\",\"wikieditor-toolbar-help-content-signature-description\":\"Signature\",\"wikieditor-toolbar-help-content-signature-syntax\":\"~~~\",\"wikieditor-toolbar-help-content-signature-result\":\"<a href=\'#\' title=\'{{#special:mypage}}\'>Username<\\/a> (<a href=\'#\' title=\'{{#special:mytalk}}\'>talk<\\/a>)\",\"wikieditor-toolbar-help-content-indent-description\":\"Indent\",\"wikieditor-toolbar-help-content-indent-syntax\":\"Normal text<br \\/>:Indented text<br \\/>::Indented text\",\"wikieditor-toolbar-help-content-indent-result\":\"Normal text<dl><dd>Indented text<dl><dd>Indented text<\\/dd><\\/dl><\\/dd><\\/dl>\"}','20110110172914'),('jquery.async','en','{}','20110110172915'),('jquery.autoEllipsis','en','{}','20110110172915'),('jquery.checkboxShiftClick','en','{}','20110110172915'),('jquery.client','en','{}','20110110172915'),('jquery.cookie','en','{}','20110110172915'),('jquery.delayedBind','en','{}','20110110172915'),('jquery.highlightText','en','{}','20110110172915'),('jquery.makeCollapsible','en','{\"collapsible-expand\":\"Expand\",\"collapsible-collapse\":\"Collapse\"}','20110110172915'),('jquery.placeholder','en','{}','20110110172915'),('jquery.suggestions','en','{}','20110110172915'),('jquery.tabIndex','en','{}','20110110172915'),('jquery.textSelection','en','{}','20110110172915'),('jquery.wikiEditor','en','{\"wikieditor-wikitext-tab\":\"Wikitext\",\"wikieditor-loading\":\"Loading\"}','20110110172914'),('jquery.wikiEditor.toolbar','en','{}','20110110172914'),('mediawiki.action.watch.ajax','en','{}','20110110172915'),('mediawiki.language','en','{}','20110110172915'),('mediawiki.legacy.ajax','en','{\"watch\":\"Watch\",\"unwatch\":\"Unwatch\",\"watching\":\"Watching...\",\"unwatching\":\"Unwatching...\",\"tooltip-ca-watch\":\"Add this page to your watchlist\",\"tooltip-ca-unwatch\":\"Remove this page from your watchlist\"}','20110110172915'),('mediawiki.legacy.edit','en','{}','20110110172915'),('mediawiki.legacy.wikibits','en','{\"showtoc\":\"show\",\"hidetoc\":\"hide\"}','20110110172915'),('mediawiki.util','en','{}','20110110172915');
/*!40000 ALTER TABLE `mw_msg_resource` ENABLE KEYS */;
UNLOCK TABLES;
*/
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 30 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name :'Back' and 'Continue' button availability
* Version : MediaWiki 1.18alpha
-*/
-
+ */
class MediaWikiButtonsAvailabilityTestCase extends MediaWikiInstallationCommonFunction {
-
- function setUp() {
- parent::setUp();
- }
-
-
- // Verify only 'Continue' button available on 'Language' page
- public function testOnlyContinueButtonAvailability() {
-
- parent::navigateLanguagePage();
-
- // Verify only 'Continue' button avaialble
- $this->assertTrue( $this->isElementPresent( "submit-continue" ));
-
- // 'Back' button is not avaialble
- $this->assertElementNotPresent( "submit-back" );
- }
-
-
- // Verify 'Continue' and 'Back' buttons availability
- public function testBothButtonsAvailability() {
-
- // Verify buttons availability on 'Welcome to MediaWiki' page
- parent::navigateWelcometoMediaWikiPage();
- $this->assertTrue( $this->isElementPresent( "submit-back" ));
- $this->assertTrue( $this->isElementPresent( "submit-continue" ));
- parent::restartInstallation();
-
- // Verify buttons availability on 'Connect to Database' page
- parent::navigateConnetToDatabasePage();
- $this->assertTrue( $this->isElementPresent( "submit-back" ));
- $this->assertTrue( $this->isElementPresent( "submit-continue" ));
- parent::restartInstallation();
-
- // Verify buttons availability on 'Database settings' page
- $databaseName = DB_NAME_PREFIX."_db_settings";
- parent::navigateDatabaseSettingsPage( $databaseName );
- $this->assertTrue( $this->isElementPresent( "submit-back" ));
- $this->assertTrue( $this->isElementPresent( "submit-continue" ));
- parent::restartInstallation();
-
- // Verify buttons availability on 'Name' page
- $databaseName = DB_NAME_PREFIX."_name";
- parent::navigateNamePage( $databaseName );
- $this->assertTrue( $this->isElementPresent( "submit-back" ));
- $this->assertTrue( $this->isElementPresent( "submit-continue" ));
- parent::restartInstallation();
-
- // Verify buttons availability on 'Options' page
- $databaseName = DB_NAME_PREFIX."_options";
- parent::navigateOptionsPage( $databaseName );
- $this->assertTrue( $this->isElementPresent( "submit-back" ));
- $this->assertTrue( $this->isElementPresent( "submit-continue" ));
- parent::restartInstallation();
-
- // Verify buttons availability on 'Install' page
- $databaseName = DB_NAME_PREFIX."_install";
- parent::navigateInstallPage($databaseName);
- $this->assertTrue( $this->isElementPresent( "submit-back" ));
- $this->assertTrue( $this->isElementPresent( "submit-continue" ));
- }
+ function setUp() {
+ parent::setUp();
+ }
+
+ // Verify only 'Continue' button available on 'Language' page
+ public function testOnlyContinueButtonAvailability() {
+ parent::navigateLanguagePage();
+
+ // Verify only 'Continue' button avaialble
+ $this->assertTrue( $this->isElementPresent( "submit-continue" ) );
+
+ // 'Back' button is not avaialble
+ $this->assertElementNotPresent( "submit-back" );
+ }
+
+ // Verify 'Continue' and 'Back' buttons availability
+ public function testBothButtonsAvailability() {
+ // Verify buttons availability on 'Welcome to MediaWiki' page
+ parent::navigateWelcometoMediaWikiPage();
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-continue" ) );
+ parent::restartInstallation();
+
+ // Verify buttons availability on 'Connect to Database' page
+ parent::navigateConnetToDatabasePage();
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-continue" ) );
+ parent::restartInstallation();
+
+ // Verify buttons availability on 'Database settings' page
+ $databaseName = DB_NAME_PREFIX . "_db_settings";
+ parent::navigateDatabaseSettingsPage( $databaseName );
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-continue" ) );
+ parent::restartInstallation();
+
+ // Verify buttons availability on 'Name' page
+ $databaseName = DB_NAME_PREFIX . "_name";
+ parent::navigateNamePage( $databaseName );
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-continue" ) );
+ parent::restartInstallation();
+
+ // Verify buttons availability on 'Options' page
+ $databaseName = DB_NAME_PREFIX . "_options";
+ parent::navigateOptionsPage( $databaseName );
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-continue" ) );
+ parent::restartInstallation();
+
+ // Verify buttons availability on 'Install' page
+ $databaseName = DB_NAME_PREFIX . "_install";
+ parent::navigateInstallPage( $databaseName );
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-continue" ) );
+ }
}
* Test Case ID : 04 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Install MediaWiki with different Database accounts for web access.
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiDifferentDatabaseAccountTestCase extends MediaWikiInstallationCommonFunction {
+ function setUp() {
+ parent::setUp();
+ }
- function setUp() {
- parent::setUp();
- }
-
-
- // Install Mediawiki using 'MySQL' database type.
- public function testDifferentDatabaseAccount() {
-
- $databaseName = DB_NAME_PREFIX."_dif_accounts";
+ // Install Mediawiki using 'MySQL' database type.
+ public function testDifferentDatabaseAccount() {
+ $databaseName = DB_NAME_PREFIX . "_dif_accounts";
- // Navigate to the 'Database settings' page
- parent::navigateDatabaseSettingsPage( $databaseName );
+ // Navigate to the 'Database settings' page
+ parent::navigateDatabaseSettingsPage( $databaseName );
- // Click on the 'Use the same account as for installation' check box
- $this->click( "mysql__SameAccount" );
+ // Click on the 'Use the same account as for installation' check box
+ $this->click( "mysql__SameAccount" );
- // Change the 'Database username'
- $this->type( "mysql_wgDBuser", DB_WEB_USER );
+ // Change the 'Database username'
+ $this->type( "mysql_wgDBuser", DB_WEB_USER );
- // Enter 'Database password:'
- $this->type( "mysql_wgDBpassword", DB_WEB_USER_PASSWORD );
+ // Enter 'Database password:'
+ $this->type( "mysql_wgDBpassword", DB_WEB_USER_PASSWORD );
- // Select 'Create the account if it does not already exist' check box
- $this->click( "mysql__CreateDBAccount" );
- parent::clickContinueButton();
+ // Select 'Create the account if it does not already exist' check box
+ $this->click( "mysql__CreateDBAccount" );
+ parent::clickContinueButton();
- // 'Name' page
- parent::completeNamePage();
+ // 'Name' page
+ parent::completeNamePage();
- // 'Options' page
- parent::clickContinueButton();
+ // 'Options' page
+ parent::clickContinueButton();
- // 'Install' page
- $this->assertEquals("Creating database user... done",
- $this->getText( LINK_FORM."ul/li[3]"));
- parent::clickContinueButton();
+ // 'Install' page
+ $this->assertEquals( "Creating database user... done",
+ $this->getText( LINK_FORM . "ul/li[3]" ) );
+ parent::clickContinueButton();
- // 'Complete' page
- parent::completePageSuccessfull();
- $this->chooseCancelOnNextConfirmation();
- }
+ // 'Complete' page
+ parent::completePageSuccessfull();
+ $this->chooseCancelOnNextConfirmation();
+ }
}
* Test Case Name : Install MediaWiki with the same database and the different
* database prefixes(Share one database between multiple wikis).
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiDifferntDatabasePrefixTestCase extends MediaWikiInstallationCommonFunction {
+ function setUp() {
+ parent::setUp();
+ }
- function setUp() {
- parent::setUp();
- }
-
- // Install Mediawiki using 'MySQL' database type.
- public function testDifferentDatabasePrefix() {
-
- $databaseName = DB_NAME_PREFIX."_db_prefix";
- parent::navigateInstallPage( $databaseName );
+ // Install Mediawiki using 'MySQL' database type.
+ public function testDifferentDatabasePrefix() {
+ $databaseName = DB_NAME_PREFIX . "_db_prefix";
+ parent::navigateInstallPage( $databaseName );
- // To 'Options' page
- parent::clickBackButton();
+ // To 'Options' page
+ parent::clickBackButton();
- // To 'Name' page
- parent::clickBackButton();
+ // To 'Name' page
+ parent::clickBackButton();
- // To 'Database settings' page
- parent::clickBackButton();
+ // To 'Database settings' page
+ parent::clickBackButton();
- // To 'Connect to database' page
- parent::clickBackButton();
+ // To 'Connect to database' page
+ parent::clickBackButton();
- // From 'Connect to database' page without database prefix
- parent::clickContinueButton();
+ // From 'Connect to database' page without database prefix
+ parent::clickContinueButton();
- // Verify upgrade existing message
- $this->assertEquals( "Upgrade existing installation",
- $this->getText( LINK_DIV."h2" ));
+ // Verify upgrade existing message
+ $this->assertEquals( "Upgrade existing installation",
+ $this->getText( LINK_DIV . "h2" ) );
- // To 'Connect to database' page
- parent::clickBackButton();
+ // To 'Connect to database' page
+ parent::clickBackButton();
- // Input the database prefix
- $this->type( "mysql_wgDBprefix", DATABASE_PREFIX );
+ // Input the database prefix
+ $this->type( "mysql_wgDBprefix", DATABASE_PREFIX );
- // From 'Connect to database' page with database prefix
- parent::clickContinueButton();
+ // From 'Connect to database' page with database prefix
+ parent::clickContinueButton();
- // To 'Complete' page
- parent::clickContinueButton();
- parent::completeNamePage();
- parent::clickContinueButton();
+ // To 'Complete' page
+ parent::clickContinueButton();
+ parent::completeNamePage();
+ parent::clickContinueButton();
- // Verify already installed warning message
- $this->assertEquals( "Install",
- $this->getText( LINK_DIV."h2" ));
- $this->assertEquals( "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
- $this->getText( LINK_FORM."div[1]" ));
+ // Verify already installed warning message
+ $this->assertEquals( "Install",
+ $this->getText( LINK_DIV . "h2" ) );
+ $this->assertEquals( "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
+ $this->getText( LINK_FORM . "div[1]" ) );
- parent::clickContinueButton();
- parent::completePageSuccessfull();
- $this->chooseCancelOnNextConfirmation();
- parent::restartInstallation();
- }
+ parent::clickContinueButton();
+ parent::completePageSuccessfull();
+ $this->chooseCancelOnNextConfirmation();
+ parent::restartInstallation();
+ }
}
* Test Case ID : 09 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Invalid/ blank values for fields in 'Connect to database' page.
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiErrorsConnectToDatabasePageTestCase extends MediaWikiInstallationCommonFunction {
- function setUp() {
- parent::setUp();
- }
-
- // Verify warning messages for the 'Connet to database' page
- public function testErrorsConnectToDatabasePage() {
-
- parent::navigateConnetToDatabasePage();
-
- // Verify warning mesage for invalid database host
- $this->type( "mysql_wgDBserver", INVALID_DB_HOST );
- parent::clickContinueButton();
- $this->assertEquals( "DB connection error: php_network_getaddresses: getaddrinfo failed: No such host is known. (".INVALID_DB_HOST.").",
- $this->getText( LINK_DIV."div[2]/div[2]/p[1]" ));
- $this->assertEquals( "Check the host, username and password below and try again.",
- $this->getText( LINK_DIV."div[2]/div[2]/p[2]" ));
- // Verify warning message for the blank database host
- $this->type( "mysql_wgDBserver", "" );
- parent::clickContinueButton();
- $this->assertEquals( "MySQL 4.0.14 or later is required, you have .",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
- // Valid Database Host
- $this->type( "mysql_wgDBserver", VALID_DB_HOST );
-
- // Verify warning message for the invalid database name
- $this->type( "mysql_wgDBname", INVALID_DB_NAME );
- parent::clickContinueButton();
- $this->assertEquals( "Invalid database name \"".INVALID_DB_NAME."\". Use only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).",
- $this->getText( LINK_DIV."div[2]/div[2]/p" ));
-
- // Verify warning message for the blank database name
- $this->type( "mysql_wgDBname", "");
- parent::clickContinueButton();
- $this->assertEquals( "You must enter a value for \"Database name\"",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
- // valid Database name
- $this->type( "mysql_wgDBname", VALID_DB_NAME);
-
- // Verify warning message for the invalid databaase prefix
- $this->type( "mysql_wgDBprefix", INVALID_DB_PREFIX );
- parent::clickContinueButton();
- $this->assertEquals( "Invalid database prefix \"".INVALID_DB_PREFIX."\". Use only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
- // Valid Database prefix
- $this->type( "mysql_wgDBprefix", VALID_DB_PREFIX );
-
- // Verify warning message for the invalid database user name
- $this->type( "mysql__InstallUser", INVALID_DB_USER_NAME );
- parent::clickContinueButton();
- $this->assertEquals( "DB connection error: Access denied for user '".INVALID_DB_USER_NAME."'@'localhost' (using password: NO) (localhost).",
- $this->getText( LINK_DIV."div[2]/div[2]/p[1]" ));
- $this->assertEquals( "Check the host, username and password below and try again.",
- $this->getText( LINK_DIV."div[2]/div[2]/p[2]"));
-
- // Verify warning message for the blank database user name
- $this->type( "mysql__InstallUser", "" );
- parent::clickContinueButton();
- $this->assertEquals( "DB connection error: Access denied for user 'SYSTEM'@'localhost' (using password: NO) (localhost).",
- $this->getText( LINK_DIV."div[2]/div[2]/p[1]" ));
- $this->assertEquals( "Check the host, username and password below and try again.",
- $this->getText( LINK_DIV."div[2]/div[2]/p[2]" ));
-
- // Valid Database username
- $this->type( "mysql__InstallUser", VALID_DB_USER_NAME );
-
- // Verify warning message for the invalid password
- $this->type( "mysql__InstallPassword", INVALID_DB_PASSWORD );
- parent::clickContinueButton();
-
- $this->assertEquals( "DB connection error: Access denied for user 'root'@'localhost' (using password: YES) (localhost).",
- $this->getText( LINK_DIV."div[2]/div[2]/p[1]" ));
- $this->assertEquals( "Check the host, username and password below and try again.",
- $this->getText( LINK_DIV."div[2]/div[2]/p[2]" ));
-
- // Verify warning message for the invalid username and password
- $this->type( "mysql__InstallUser", INVALID_DB_USER_NAME );
- $this->type( "mysql__InstallPassword", INVALID_DB_PASSWORD );
- parent::clickContinueButton();
- $this->assertEquals( "DB connection error: Access denied for user '".INVALID_DB_USER_NAME."'@'localhost' (using password: YES) (localhost).",
- $this->getText( LINK_DIV."div[2]/div[2]/p[1]" ));
- $this->assertEquals( "Check the host, username and password below and try again.",
- $this->getText( LINK_DIV."div[2]/div[2]/p[2]" ));
-
- // Valid username and valid password
- $this->type( "mysql__InstallUser", VALID_DB_USER_NAME );
- $this->type( "mysql__InstallPassword", "" );
- parent::clickContinueButton();
-
- // successfully completes the 'Connect to database' page
- $this->assertEquals( "Database settings",
- $this->getText( LINK_DIV."h2" ));
- }
+ function setUp() {
+ parent::setUp();
+ }
+
+ // Verify warning messages for the 'Connet to database' page
+ public function testErrorsConnectToDatabasePage() {
+ parent::navigateConnetToDatabasePage();
+
+ // Verify warning mesage for invalid database host
+ $this->type( "mysql_wgDBserver", INVALID_DB_HOST );
+ parent::clickContinueButton();
+ $this->assertEquals( "DB connection error: php_network_getaddresses: getaddrinfo failed: No such host is known. (" . INVALID_DB_HOST . ").",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[1]" ) );
+ $this->assertEquals( "Check the host, username and password below and try again.",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[2]" ) );
+ // Verify warning message for the blank database host
+ $this->type( "mysql_wgDBserver", "" );
+ parent::clickContinueButton();
+ $this->assertEquals( "MySQL 4.0.14 or later is required, you have .",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // Valid Database Host
+ $this->type( "mysql_wgDBserver", VALID_DB_HOST );
+
+ // Verify warning message for the invalid database name
+ $this->type( "mysql_wgDBname", INVALID_DB_NAME );
+ parent::clickContinueButton();
+ $this->assertEquals( "Invalid database name \"" . INVALID_DB_NAME . "\". Use only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p" ) );
+
+ // Verify warning message for the blank database name
+ $this->type( "mysql_wgDBname", "" );
+ parent::clickContinueButton();
+ $this->assertEquals( "You must enter a value for \"Database name\"",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // valid Database name
+ $this->type( "mysql_wgDBname", VALID_DB_NAME );
+
+ // Verify warning message for the invalid databaase prefix
+ $this->type( "mysql_wgDBprefix", INVALID_DB_PREFIX );
+ parent::clickContinueButton();
+ $this->assertEquals( "Invalid database prefix \"" . INVALID_DB_PREFIX . "\". Use only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // Valid Database prefix
+ $this->type( "mysql_wgDBprefix", VALID_DB_PREFIX );
+
+ // Verify warning message for the invalid database user name
+ $this->type( "mysql__InstallUser", INVALID_DB_USER_NAME );
+ parent::clickContinueButton();
+ $this->assertEquals( "DB connection error: Access denied for user '" . INVALID_DB_USER_NAME . "'@'localhost' (using password: NO) (localhost).",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[1]" ) );
+ $this->assertEquals( "Check the host, username and password below and try again.",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[2]" ) );
+
+ // Verify warning message for the blank database user name
+ $this->type( "mysql__InstallUser", "" );
+ parent::clickContinueButton();
+ $this->assertEquals( "DB connection error: Access denied for user 'SYSTEM'@'localhost' (using password: NO) (localhost).",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[1]" ) );
+ $this->assertEquals( "Check the host, username and password below and try again.",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[2]" ) );
+
+ // Valid Database username
+ $this->type( "mysql__InstallUser", VALID_DB_USER_NAME );
+
+ // Verify warning message for the invalid password
+ $this->type( "mysql__InstallPassword", INVALID_DB_PASSWORD );
+ parent::clickContinueButton();
+
+ $this->assertEquals( "DB connection error: Access denied for user 'root'@'localhost' (using password: YES) (localhost).",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[1]" ) );
+ $this->assertEquals( "Check the host, username and password below and try again.",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[2]" ) );
+
+ // Verify warning message for the invalid username and password
+ $this->type( "mysql__InstallUser", INVALID_DB_USER_NAME );
+ $this->type( "mysql__InstallPassword", INVALID_DB_PASSWORD );
+ parent::clickContinueButton();
+ $this->assertEquals( "DB connection error: Access denied for user '" . INVALID_DB_USER_NAME . "'@'localhost' (using password: YES) (localhost).",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[1]" ) );
+ $this->assertEquals( "Check the host, username and password below and try again.",
+ $this->getText( LINK_DIV . "div[2]/div[2]/p[2]" ) );
+
+ // Valid username and valid password
+ $this->type( "mysql__InstallUser", VALID_DB_USER_NAME );
+ $this->type( "mysql__InstallPassword", "" );
+ parent::clickContinueButton();
+
+ // successfully completes the 'Connect to database' page
+ $this->assertEquals( "Database settings",
+ $this->getText( LINK_DIV . "h2" ) );
+ }
}
* Test Case ID : 10 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Invalid/ blank values for fields in 'Name' page.
* Version : MediaWiki 1.18alpha
-*/
+ */
require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
class MediaWikiErrorsNamepageTestCase extends MediaWikiInstallationCommonFunction {
-
- function setUp() {
- parent::setUp();
- }
-
- // Verify warning message for the 'Name' page
- public function testErrorsNamePage() {
-
- $databaseName = DB_NAME_PREFIX."_error_name";
-
- parent::navigateNamePage( $databaseName );
-
- // Verify warning message for all blank fields
- parent::clickContinueButton();
- $this->assertEquals( "Enter a site name.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
- $this->assertEquals( "Enter an administrator username.",
- $this->getText( LINK_DIV."div[3]/div[2]" ));
- $this->assertEquals( "Enter a password for the administrator account.",
- $this->getText( LINK_DIV."div[4]/div[2]" ));
-
- // Verify warning message for the blank 'Site name'
- $this->type( "config__AdminName", VALID_YOUR_NAME );
- $this->type( "config__AdminPassword", VALID_PASSWORD );
- $this->type( "config__AdminPassword2", VALID_PASSWORD_AGAIN );
- parent::clickContinueButton();
- $this->assertEquals( "Enter a site name.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
- // Input valid 'Site name'
- $this->type( "config_wgSitename", VALID_WIKI_NAME );
-
-
- // Verify warning message for the invalid "Project namespace'
- $this->click( "config__NamespaceType_other" );
- $this->type( "config_wgMetaNamespace", INVALID_NAMESPACE );
- parent::clickContinueButton();
- $this->assertEquals( "The specified namespace \"\" is invalid. Specify a different project namespace.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
-
- // Verify warning message for the blank 'Project namespace'
- $this->type( "config_wgSitename", VALID_WIKI_NAME );
- $this->click( "config__NamespaceType_other" );
- $this->type( "config_wgMetaNamespace" , "" );
- parent::clickContinueButton();
- $this->assertEquals( "The specified namespace \"\" is invalid. Specify a different project namespace.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
-
- // Valid 'Project namespace'
- $this->click( "config__NamespaceType_other" );
- $this->type( "config_wgMetaNamespace", VALID_NAMESPACE );
- parent::clickContinueButton();
-
-
- // Valid 'Site name'
- $this->click( "config__NamespaceType_site-name" );
- $this->type( "config_wgSitename", VALID_WIKI_NAME );
-
-
- // Verify warning message for blank 'Your name'
- $this->type( "config__AdminName", " " );
- parent::clickContinueButton();
- $this->assertEquals( "Enter an administrator username.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
- $this->type( "config_wgSitename", VALID_WIKI_NAME );
- // Verify warning message for blank 'Password'
- $this->type( "config__AdminName", VALID_YOUR_NAME );
- $this->type( "config__AdminPassword", " " );
- parent::clickContinueButton();
- $this->assertEquals( "Enter a password for the administrator account.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
-
- // Verify warning message for the blank 'Password again'
- $this->type( "config_wgSitename", VALID_WIKI_NAME );
- $this->type( "config__AdminPassword", VALID_PASSWORD );
- $this->type( "config__AdminPassword2", " " );
- parent::clickContinueButton();
- $this->assertEquals( "The two passwords you entered do not match.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
-
-
- // Verify warning message for the different'Password' and 'Password again'
- $this->type( "config_wgSitename", VALID_WIKI_NAME );
- $this->type( "config__AdminPassword", VALID_PASSWORD );
- $this->type( "config__AdminPassword2", INVALID_PASSWORD_AGAIN );
- parent::clickContinueButton();
- $this->assertEquals( "The two passwords you entered do not match.",
- $this->getText( LINK_DIV."div[2]/div[2]" ));
- }
+ function setUp() {
+ parent::setUp();
+ }
+
+ // Verify warning message for the 'Name' page
+ public function testErrorsNamePage() {
+
+ $databaseName = DB_NAME_PREFIX . "_error_name";
+
+ parent::navigateNamePage( $databaseName );
+
+ // Verify warning message for all blank fields
+ parent::clickContinueButton();
+ $this->assertEquals( "Enter a site name.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+ $this->assertEquals( "Enter an administrator username.",
+ $this->getText( LINK_DIV . "div[3]/div[2]" ) );
+ $this->assertEquals( "Enter a password for the administrator account.",
+ $this->getText( LINK_DIV . "div[4]/div[2]" ) );
+
+ // Verify warning message for the blank 'Site name'
+ $this->type( "config__AdminName", VALID_YOUR_NAME );
+ $this->type( "config__AdminPassword", VALID_PASSWORD );
+ $this->type( "config__AdminPassword2", VALID_PASSWORD_AGAIN );
+ parent::clickContinueButton();
+ $this->assertEquals( "Enter a site name.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // Input valid 'Site name'
+ $this->type( "config_wgSitename", VALID_WIKI_NAME );
+
+ // Verify warning message for the invalid "Project namespace'
+ $this->click( "config__NamespaceType_other" );
+ $this->type( "config_wgMetaNamespace", INVALID_NAMESPACE );
+ parent::clickContinueButton();
+ $this->assertEquals( "The specified namespace \"\" is invalid. Specify a different project namespace.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // Verify warning message for the blank 'Project namespace'
+ $this->type( "config_wgSitename", VALID_WIKI_NAME );
+ $this->click( "config__NamespaceType_other" );
+ $this->type( "config_wgMetaNamespace", "" );
+ parent::clickContinueButton();
+ $this->assertEquals( "The specified namespace \"\" is invalid. Specify a different project namespace.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // Valid 'Project namespace'
+ $this->click( "config__NamespaceType_other" );
+ $this->type( "config_wgMetaNamespace", VALID_NAMESPACE );
+ parent::clickContinueButton();
+
+ // Valid 'Site name'
+ $this->click( "config__NamespaceType_site-name" );
+ $this->type( "config_wgSitename", VALID_WIKI_NAME );
+
+ // Verify warning message for blank 'Your name'
+ $this->type( "config__AdminName", " " );
+ parent::clickContinueButton();
+ $this->assertEquals( "Enter an administrator username.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ $this->type( "config_wgSitename", VALID_WIKI_NAME );
+ // Verify warning message for blank 'Password'
+ $this->type( "config__AdminName", VALID_YOUR_NAME );
+ $this->type( "config__AdminPassword", " " );
+ parent::clickContinueButton();
+ $this->assertEquals( "Enter a password for the administrator account.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // Verify warning message for the blank 'Password again'
+ $this->type( "config_wgSitename", VALID_WIKI_NAME );
+ $this->type( "config__AdminPassword", VALID_PASSWORD );
+ $this->type( "config__AdminPassword2", " " );
+ parent::clickContinueButton();
+ $this->assertEquals( "The two passwords you entered do not match.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+
+ // Verify warning message for the different'Password' and 'Password again'
+ $this->type( "config_wgSitename", VALID_WIKI_NAME );
+ $this->type( "config__AdminPassword", VALID_PASSWORD );
+ $this->type( "config__AdminPassword2", INVALID_PASSWORD_AGAIN );
+ parent::clickContinueButton();
+ $this->assertEquals( "The two passwords you entered do not match.",
+ $this->getText( LINK_DIV . "div[2]/div[2]" ) );
+ }
}
* Test Case ID : 29 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Help field hint availability for the fields.
* Version : MediaWiki 1.18alpha
-*/
+ */
require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
class MediaWikiHelpFieldHintTestCase extends MediaWikiInstallationCommonFunction {
-
- function setUp() {
- parent::setUp();
- }
-
-
- // Verify help field availability for the fields
- public function testMySQLConnectToDatabaseFieldHint() {
-
- parent::navigateConnetToDatabasePage();
-
- // Verify help field for 'Database host'
- $this->click( "//div[@id='DB_wrapper_mysql']/div/div[1]/div/span[1]" );
- $this->assertEquals( MYSQL_DATABASE_HOST_HELP,
- $this->getText( "//div[@id='DB_wrapper_mysql']/div/div[1]/div/span[2]" ) );
-
- // Verify help field for 'Database name'
- $this->click( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/div/span[1]" );
- $this->assertEquals( MYSQL_DATABASE_NAME_HELP,
- $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/div/span[2]" ));
-
-
- // Verify help field for 'Database table prefix'
- $this->click("//div[@id='DB_wrapper_mysql']/fieldset[1]/div[2]/div[1]/div/span[1]" );
- $this->assertEquals(MYSQL_DATABASE_TABLE_PREFIX_HELP,
- $this->getText("//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/div/span[2]/p[1]" ));
-
- // Verify help field for 'Database username'
- $this->click( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[1]/div[1]/div/span[1]" );
- $this->assertEquals( MYSQL_DATBASE_USERNAME_HELP,
- $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[1]/div[1]/div/span[2]" ));
-
- // Verify help field for 'Database password'
- $this->click( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[2]/div[1]/div/span[1]" );
- $this->assertEquals( MYSQL_DATABASE_PASSWORD_HELP,
- $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[2]/div[1]/div/span[2]/p" ));
- }
-
-
- public function testSQLiteConnectToDatabaseFieldHint() {
-
- parent::navigateConnetToDatabasePage();
- $this->click( "DBType_sqlite" );
-
- // Verify help field for 'SQLite data directory'
- $this->click( "//div[@id='DB_wrapper_sqlite']/div[1]/div[1]/div/span[1]" );
- $this->assertEquals( SQLITE_DATA_DIRECTORY_HELP,
- $this->getText( "//div[@id='DB_wrapper_sqlite']/div[1]/div[1]/div/span[2]" ));
-
- // Verify help field for 'Database name'
- $this->click( "//div[@id='DB_wrapper_sqlite']/div[2]/div[1]/div/span[1]" );
- $this->assertEquals( SQLITE_DATABASE_NAME_HELP , $this->getText( "//div[@id='DB_wrapper_sqlite']/div[2]/div[1]/div/span[2]/p" ));
- }
-
-
- public function testDatabaseSettingsFieldHint() {
-
- $databaseName = DB_NAME_PREFIX."_db_field";
- parent::navigateDatabaseSettingsPage($databaseName);
-
- // Verify help field for 'Search engine'
- $this->click( LINK_FORM."div[2]/span[1]" );
- $this->assertEquals( SEARCH_ENGINE_HELP,
- $this->getText( LINK_FORM."div[2]/span[2]" ));
-
- // Verify help field for 'Database character set'
- $this->click( LINK_FORM."div[4]/span[1]" );
- $this->assertEquals( DATABASE_CHARACTER_SET_HELP,
- $this->getText( LINK_FORM."div[4]/span[2]"));
- parent::restartInstallation();
- }
-
-
- public function testNameFieldHint() {
-
- $databaseName = DB_NAME_PREFIX."_name_field";
- parent::navigateNamePage( $databaseName );
-
- // Verify help field for 'Name of Wiki'
- $this->click( LINK_FORM."div[1]/div[1]/div/span[1]" );
- $this->assertEquals( NAME_OF_WIKI_HELP,
- $this->getText( LINK_FORM."div[1]/div[1]/div/span[2]/p" ));
-
- // Verify help field for 'Project namespace'
- $this->click( LINK_FORM."div[2]/div[1]/div/span[1]" );
- $this->assertEquals( PROJECT_NAMESPACE_HELP,
- $this->getText( LINK_FORM."div[2]/div[1]/div/span[2]/p"));
-
- // Verify help field for 'Your Name'
- $this->click( LINK_FORM."fieldset/div[1]/div[1]/div/span[1]" );
- $this->assertEquals( USER_NAME_HELP,
- $this->getText( LINK_FORM."fieldset/div[1]/div[1]/div/span[2]/p" ));
-
- // Verify help field for 'E mail address'
- $this->click( LINK_FORM."fieldset/div[4]/div[1]/div/span[1]" );
- $this->assertEquals( EMAIL_ADDRESS_HELP,
- $this->getText( LINK_FORM."fieldset/div[4]/div[1]/div/span[2]/p" ));
-
- parent::restartInstallation();
- }
+ function setUp() {
+ parent::setUp();
+ }
+
+ // Verify help field availability for the fields
+ public function testMySQLConnectToDatabaseFieldHint() {
+
+ parent::navigateConnetToDatabasePage();
+
+ // Verify help field for 'Database host'
+ $this->click( "//div[@id='DB_wrapper_mysql']/div/div[1]/div/span[1]" );
+ $this->assertEquals( MYSQL_DATABASE_HOST_HELP,
+ $this->getText( "//div[@id='DB_wrapper_mysql']/div/div[1]/div/span[2]" ) );
+
+ // Verify help field for 'Database name'
+ $this->click( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/div/span[1]" );
+ $this->assertEquals( MYSQL_DATABASE_NAME_HELP,
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/div/span[2]" ) );
+
+
+ // Verify help field for 'Database table prefix'
+ $this->click( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[2]/div[1]/div/span[1]" );
+ $this->assertEquals( MYSQL_DATABASE_TABLE_PREFIX_HELP,
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/div/span[2]/p[1]" ) );
+
+ // Verify help field for 'Database username'
+ $this->click( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[1]/div[1]/div/span[1]" );
+ $this->assertEquals( MYSQL_DATBASE_USERNAME_HELP,
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[1]/div[1]/div/span[2]" ) );
+
+ // Verify help field for 'Database password'
+ $this->click( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[2]/div[1]/div/span[1]" );
+ $this->assertEquals( MYSQL_DATABASE_PASSWORD_HELP,
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[2]/div[1]/div/span[2]/p" ) );
+ }
+
+ public function testSQLiteConnectToDatabaseFieldHint() {
+ parent::navigateConnetToDatabasePage();
+ $this->click( "DBType_sqlite" );
+
+ // Verify help field for 'SQLite data directory'
+ $this->click( "//div[@id='DB_wrapper_sqlite']/div[1]/div[1]/div/span[1]" );
+ $this->assertEquals( SQLITE_DATA_DIRECTORY_HELP,
+ $this->getText( "//div[@id='DB_wrapper_sqlite']/div[1]/div[1]/div/span[2]" ) );
+
+ // Verify help field for 'Database name'
+ $this->click( "//div[@id='DB_wrapper_sqlite']/div[2]/div[1]/div/span[1]" );
+ $this->assertEquals( SQLITE_DATABASE_NAME_HELP, $this->getText( "//div[@id='DB_wrapper_sqlite']/div[2]/div[1]/div/span[2]/p" ) );
+ }
+
+ public function testDatabaseSettingsFieldHint() {
+
+ $databaseName = DB_NAME_PREFIX . "_db_field";
+ parent::navigateDatabaseSettingsPage( $databaseName );
+
+ // Verify help field for 'Search engine'
+ $this->click( LINK_FORM . "div[2]/span[1]" );
+ $this->assertEquals( SEARCH_ENGINE_HELP,
+ $this->getText( LINK_FORM . "div[2]/span[2]" ) );
+
+ // Verify help field for 'Database character set'
+ $this->click( LINK_FORM . "div[4]/span[1]" );
+ $this->assertEquals( DATABASE_CHARACTER_SET_HELP,
+ $this->getText( LINK_FORM . "div[4]/span[2]" ) );
+ parent::restartInstallation();
+ }
+
+ public function testNameFieldHint() {
+ $databaseName = DB_NAME_PREFIX . "_name_field";
+ parent::navigateNamePage( $databaseName );
+
+ // Verify help field for 'Name of Wiki'
+ $this->click( LINK_FORM . "div[1]/div[1]/div/span[1]" );
+ $this->assertEquals( NAME_OF_WIKI_HELP,
+ $this->getText( LINK_FORM . "div[1]/div[1]/div/span[2]/p" ) );
+
+ // Verify help field for 'Project namespace'
+ $this->click( LINK_FORM . "div[2]/div[1]/div/span[1]" );
+ $this->assertEquals( PROJECT_NAMESPACE_HELP,
+ $this->getText( LINK_FORM . "div[2]/div[1]/div/span[2]/p" ) );
+
+ // Verify help field for 'Your Name'
+ $this->click( LINK_FORM . "fieldset/div[1]/div[1]/div/span[1]" );
+ $this->assertEquals( USER_NAME_HELP,
+ $this->getText( LINK_FORM . "fieldset/div[1]/div[1]/div/span[2]/p" ) );
+
+ // Verify help field for 'E mail address'
+ $this->click( LINK_FORM . "fieldset/div[4]/div[1]/div/span[1]" );
+ $this->assertEquals( EMAIL_ADDRESS_HELP,
+ $this->getText( LINK_FORM . "fieldset/div[4]/div[1]/div/span[2]/p" ) );
+
+ parent::restartInstallation();
+ }
}
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
require_once ( __DIR__ . '/MediaWikiInstallationConfig.php' );
require_once ( __DIR__ . '/MediaWikiInstallationMessage.php' );
-require_once ( __DIR__ . '/MediaWikiInstallationVariables.php');
-
+require_once ( __DIR__ . '/MediaWikiInstallationVariables.php' );
class MediaWikiInstallationCommonFunction extends PHPUnit_Extensions_SeleniumTestCase {
-
- function setUp() {
- $this->setBrowser( TEST_BROWSER );
- $this->setBrowserUrl("http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/");
- }
-
-
- public function navigateInitialpage() {
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/" );
- }
-
-
- // Navigate to the 'Language' page
- public function navigateLanguagePage() {
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
- }
-
-
- // Navigate to the 'Welcome to MediaWiki' page
- public function navigateWelcometoMediaWikiPage() {
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
- $this->click( "submit-continue ");
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Navigate yo 'Connect to Database' page
- public function navigateConnetToDatabasePage() {
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // 'Welcome to MediaWiki!' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // 'Connect to Database' page
- $this->click("submit-continue");
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Navigate to the 'Database Settings' page
- public function navigateDatabaseSettingsPage( $databaseName ) {
-
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // 'Welcome to MediaWiki!' page
- $this->click("submit-continue");
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // 'Connect to Database' page
- $this->click("submit-continue");
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- $this->type("mysql_wgDBname", $databaseName );
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Navigate to the 'Name' page
- public function navigateNamePage( $databaseName ) {
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // 'Welcome to MediaWiki!' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // 'Connect to Database' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- $this->type( "mysql_wgDBname", $databaseName );
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Database settings
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Navigate 'Options' page
- public function navigateOptionsPage( $databaseName ) {
-
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // 'Welcome to MediaWiki!' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // 'Connect to Database' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- $this->type( "mysql_wgDBname", $databaseName );
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Database settings
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Name
- $this->type( "config_wgSitename", NAME_OF_WIKI );
- $this->type( "config__AdminName", ADMIN_USER_NAME);
- $this->type( "config__AdminPassword", ADMIN_PASSWORD );
- $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
- $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
-
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Navigate 'Install' page
- public function navigateInstallPage( $databaseName ) {
-
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // 'Welcome to MediaWiki!' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // 'Connect to Database' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- $this->type( "mysql_wgDBname", $databaseName );
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Database settings
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Name
- $this->type( "config_wgSitename", NAME_OF_WIKI );
- $this->type( "config__AdminName", ADMIN_USER_NAME);
- $this->type( "config__AdminPassword", ADMIN_PASSWORD );
- $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
- $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
-
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Options page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Navigate to 'Complete' page
- public function navigateCompletePage( $databaseName ) {
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // 'Welcome to MediaWiki!' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // 'Connect to Database' page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- $this->type( "mysql_wgDBname", $databaseName );
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Database settings
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Name
- $this->type( "config_wgSitename", NAME_OF_WIKI );
- $this->type( "config__AdminName", ADMIN_USER_NAME);
- $this->type( "config__AdminPassword", ADMIN_PASSWORD );
- $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
- $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
-
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Options page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Install page
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- $this->chooseCancelOnNextConfirmation();
- }
-
-
- // Complete the Name page fields
- public function completeNamePage() {
- $this->type( "config_wgSitename", NAME_OF_WIKI );
- $this->type( "config__AdminName", ADMIN_USER_NAME);
- $this->type( "config__AdminPassword", ADMIN_PASSWORD );
- $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
- $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME);
- }
-
-
- // Clicking on the 'Continue' button in any MediaWiki page
- public function clickContinueButton() {
- $this->click( "submit-continue" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Clicking on the 'Back' button in any MediaWiki page
- public function clickBackButton() {
- $this->click( "submit-back" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Restarting the installation
- public function restartInstallation() {
- $this->click( "link=Restart installation" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- $this->click( "submit-restart" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- }
-
-
- // Verify 'MediaWiki' logo available in the initial screen
- public function mediaWikiLogoPresentInitialScreen() {
- $this->assertTrue( $this->isElementPresent( "//img[@alt='The MediaWiki logo']" ));
- }
-
-
- // Verify 'MediaWiki' logo available
- public function mediaWikiLogoPresent() {
- $this->assertTrue( $this->isElementPresent( "//div[@id='p-logo']/a" ));
- }
-
-
- public function completePageSuccessfull() {
- $this->assertEquals( "Complete!",
- $this->getText( "//div[@id='bodyContent']/div/div/h2" ));
-
- // 'Congratulations!' text should be available in the 'Complete!' page.
- $this->assertEquals( "Congratulations!",
- $this->getText( "//div[@id='bodyContent']/div/div/div[2]/form/div[1]/div[2]/p[1]/b" ));
- }
+ function setUp() {
+ $this->setBrowser( TEST_BROWSER );
+ $this->setBrowserUrl( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/" );
+ }
+
+ public function navigateInitialpage() {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/" );
+ }
+
+ // Navigate to the 'Language' page
+ public function navigateLanguagePage() {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+ }
+
+ // Navigate to the 'Welcome to MediaWiki' page
+ public function navigateWelcometoMediaWikiPage() {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+ $this->click( "submit-continue " );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Navigate yo 'Connect to Database' page
+ public function navigateConnetToDatabasePage() {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // 'Welcome to MediaWiki!' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // 'Connect to Database' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Navigate to the 'Database Settings' page
+ public function navigateDatabaseSettingsPage( $databaseName ) {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // 'Welcome to MediaWiki!' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // 'Connect to Database' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ $this->type( "mysql_wgDBname", $databaseName );
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Navigate to the 'Name' page
+ public function navigateNamePage( $databaseName ) {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // 'Welcome to MediaWiki!' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // 'Connect to Database' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ $this->type( "mysql_wgDBname", $databaseName );
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Database settings
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Navigate 'Options' page
+ public function navigateOptionsPage( $databaseName ) {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // 'Welcome to MediaWiki!' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // 'Connect to Database' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ $this->type( "mysql_wgDBname", $databaseName );
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Database settings
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Name
+ $this->type( "config_wgSitename", NAME_OF_WIKI );
+ $this->type( "config__AdminName", ADMIN_USER_NAME );
+ $this->type( "config__AdminPassword", ADMIN_PASSWORD );
+ $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
+ $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
+
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Navigate 'Install' page
+ public function navigateInstallPage( $databaseName ) {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // 'Welcome to MediaWiki!' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // 'Connect to Database' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ $this->type( "mysql_wgDBname", $databaseName );
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Database settings
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Name
+ $this->type( "config_wgSitename", NAME_OF_WIKI );
+ $this->type( "config__AdminName", ADMIN_USER_NAME );
+ $this->type( "config__AdminPassword", ADMIN_PASSWORD );
+ $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
+ $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
+
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Options page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Navigate to 'Complete' page
+ public function navigateCompletePage( $databaseName ) {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // 'Welcome to MediaWiki!' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // 'Connect to Database' page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ $this->type( "mysql_wgDBname", $databaseName );
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Database settings
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Name
+ $this->type( "config_wgSitename", NAME_OF_WIKI );
+ $this->type( "config__AdminName", ADMIN_USER_NAME );
+ $this->type( "config__AdminPassword", ADMIN_PASSWORD );
+ $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
+ $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
+
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Options page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Install page
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->chooseCancelOnNextConfirmation();
+ }
+
+ // Complete the Name page fields
+ public function completeNamePage() {
+ $this->type( "config_wgSitename", NAME_OF_WIKI );
+ $this->type( "config__AdminName", ADMIN_USER_NAME );
+ $this->type( "config__AdminPassword", ADMIN_PASSWORD );
+ $this->type( "config__AdminPassword2", ADMIN_RETYPE_PASSWORD );
+ $this->type( "config__AdminEmail", ADMIN_EMAIL_ADDRESS );
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Clicking on the 'Continue' button in any MediaWiki page
+ public function clickContinueButton() {
+ $this->click( "submit-continue" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Clicking on the 'Back' button in any MediaWiki page
+ public function clickBackButton() {
+ $this->click( "submit-back" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Restarting the installation
+ public function restartInstallation() {
+ $this->click( "link=Restart installation" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->click( "submit-restart" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ }
+
+ // Verify 'MediaWiki' logo available in the initial screen
+ public function mediaWikiLogoPresentInitialScreen() {
+ $this->assertTrue( $this->isElementPresent( "//img[@alt='The MediaWiki logo']" ) );
+ }
+
+ // Verify 'MediaWiki' logo available
+ public function mediaWikiLogoPresent() {
+ $this->assertTrue( $this->isElementPresent( "//div[@id='p-logo']/a" ) );
+ }
+
+ public function completePageSuccessfull() {
+ $this->assertEquals( "Complete!",
+ $this->getText( "//div[@id='bodyContent']/div/div/h2" ) );
+
+ // 'Congratulations!' text should be available in the 'Complete!' page.
+ $this->assertEquals( "Congratulations!",
+ $this->getText( "//div[@id='bodyContent']/div/div/div[2]/form/div[1]/div[2]/p[1]/b" ) );
+ }
}
* with current value of the 'DB_NAME_PREFIX'.
* If you wish to run the suite more than one time, you need to change
* the value of the 'DB_NAME_PREFIX'.
-*/
-define('DB_NAME_PREFIX', "database_name" );
-define('DIRECTORY_NAME', "mediawiki" );
+ */
+define( 'DB_NAME_PREFIX', "database_name" );
+define( 'DIRECTORY_NAME', "mediawiki" );
define( 'PORT', "8080" );
define( 'HOST_NAME', "localhost" );
* IE : *iexplore
* Google chrome : *googlechrome
* Opera : *opera
-*/
+ */
define ( 'TEST_BROWSER', "*firefox" );
// 'MySQL' database type help field hint
define( 'MYSQL_DATABASE_HOST_HELP', "If your database server is on different server, enter the host name or IP address here. \nIf you are using shared web hosting, your hosting provider should give you the correct host name in their documentation. \nIf you are installing on a Windows server and using MySQL, using \"localhost\" may not work for the server name. If it does not, try \"127.0.0.1\" for the local IP address." );
define( 'MYSQL_DATABASE_NAME_HELP', "Choose a name that identifies your wiki. It should not contain spaces or hyphens. \nIf you are using shared web hosting, your hosting provider will either give you a specific database name to use or let you create databases via a control panel." );
-define( 'MYSQL_DATABASE_TABLE_PREFIX_HELP', "Choose a name that identifies your wiki. It should not contain spaces or hyphens.");
+define( 'MYSQL_DATABASE_TABLE_PREFIX_HELP', "Choose a name that identifies your wiki. It should not contain spaces or hyphens." );
define( 'MYSQL_DATBASE_USERNAME_HELP', "Enter the username that will be used to connect to the database during the installation process. This is not the username of the MediaWiki account; this is the username for your database." );
define( 'MYSQL_DATABASE_PASSWORD_HELP', "Enter the password that will be used to connect to the database during the installation process. This is not the password for the MediaWiki account; this is the password for your database." );
// 'SQLite' database type help field hint
define( 'SQLITE_DATA_DIRECTORY_HELP', "SQLite stores all data in a single file. \nThe directory you provide must be writable by the webserver during installation. \nIt should not be accessible via the web, this is why we're not putting it where your PHP files are. \nThe installer will write a .htaccess file along with it, but if that fails someone can gain access to your raw database. That includes raw user data (e-mail addresses, hashed passwords) as well as deleted revisions and other restricted data on the wiki. \nConsider putting the database somewhere else altogether, for example in /var/lib/mediawiki/yourwiki." );
-define( 'SQLITE_DATABASE_NAME_HELP', "Choose a name that identifies your wiki. Do not use spaces or hyphens. This will be used for the SQLite data file name.");
+define( 'SQLITE_DATABASE_NAME_HELP', "Choose a name that identifies your wiki. Do not use spaces or hyphens. This will be used for the SQLite data file name." );
// 'Database settings' page hel0p field hint
// 'Name' page help field hint
-define( 'NAME_OF_WIKI_HELP', "This will appear in the title bar of the browser and in various other places.");
+define( 'NAME_OF_WIKI_HELP', "This will appear in the title bar of the browser and in various other places." );
define( 'PROJECT_NAMESPACE_HELP', "Following Wikipedia's example, many wikis keep their policy pages separate from their content pages, in a \"project namespace\". All page titles in this namespace start with a certain prefix, which you can specify here. Traditionally, this prefix is derived from the name of the wiki, but it cannot contain punctuation characters such as \"#\" or \":\"." );
define( 'USER_NAME_HELP', "Enter your preferred username here, for example \"Joe Bloggs\". This is the name you will use to log in to the wiki." );
define( 'EMAIL_ADDRESS_HELP', "Enter an e-mail address here to allow you to receive e-mail from other users on the wiki, reset your password, and be notified of changes to pages on your watchlist." );
// Common variables
-define('PAGE_LOAD_TIME', "80000" );
+define( 'PAGE_LOAD_TIME', "80000" );
// Common links
-define( 'LINK_DIV', "//div[@id='bodyContent']/div/div/");
+define( 'LINK_DIV', "//div[@id='bodyContent']/div/div/" );
define( 'LINK_FORM', "//div[@id='bodyContent']/div/div/div[2]/form/" );
-define( 'LINK_RIGHT_FRAMEWORK', "//div[@id='bodyContent']/div/div/div[1]/ul[1]/");
+define( 'LINK_RIGHT_FRAMEWORK', "//div[@id='bodyContent']/div/div/div[1]/ul[1]/" );
// 'Name' page input values
define( 'NAME_OF_WIKI', "Site Name" );
define( 'VALID_WIKI_NAME', "MyWiki" );
define( 'VALID_YOUR_NAME', "FirstName LastName" );
define( 'VALID_PASSWORD', "12345" );
-define( 'VALID_PASSWORD_AGAIN', "12345" );
+define( 'VALID_PASSWORD_AGAIN', "12345" );
define( 'INVALID_PASSWORD_AGAIN', "123" );
-define( 'VALID_NAMESPACE', "Mynamespace" );
+define( 'VALID_NAMESPACE', "Mynamespace" );
define( 'INVALID_NAMESPACE', "##..##" );
// 'Database settings' page input values
define( 'DB_WEB_USER', "different" );
-define('DB_WEB_USER_PASSWORD', "12345" );
+define( 'DB_WEB_USER_PASSWORD', "12345" );
// 'Connet to database' page input values
-define( 'DATABASE_PREFIX',"databaseprefix" );
+define( 'DATABASE_PREFIX', "databaseprefix" );
// 'Connet to database' page input values for warning messages
define( 'VALID_DB_HOST', "localhost" );
define( 'INVALID_DB_HOST', "local" );
define( 'INVALID_DB_NAME', "my-wiki" );
-define( 'VALID_DB_NAME', "my_wiki1");
+define( 'VALID_DB_NAME', "my_wiki1" );
define( 'INVALID_DB_PREFIX', "database prefix" );
-define( 'VALID_DB_PREFIX', "database_prefix");
+define( 'VALID_DB_PREFIX', "database_prefix" );
define( 'INVALID_DB_USER_NAME', "roots" );
-define( 'VALID_DB_USER_NAME', "root");
+define( 'VALID_DB_USER_NAME', "root" );
define( 'INVALID_DB_PASSWORD', "12345" );
*
*/
-require_once 'PHPUnit/Framework.php';
require_once 'PHPUnit/Framework/TestSuite.php';
require_once ( __DIR__ . '/MediaWikiUserInterfaceTestCase.php' );
require_once ( __DIR__ . '/MediaWikiDifferentDatabaseAccountTestCase.php' );
require_once ( __DIR__ . '/MediaWikiOnAlreadyInstalledTestCase.php' );
-
-
-
-$suite = new PHPUnit_Framework_TestSuite('ArrayTest');
+$suite = new PHPUnit_Framework_TestSuite( 'ArrayTest' );
$result = new PHPUnit_Framework_TestResult;
-$suite->run($result);
+$suite->run( $result );
*
*/
-
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 01 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Install Mediawiki using 'MySQL' database type successfully
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiMySQLDataBaseTestCase extends MediaWikiInstallationCommonFunction {
+ function setUp() {
+ parent::setUp();
+ }
- function setUp() {
- parent::setUp();
- }
-
- // Verify MediaWiki installation using 'MySQL' database type
- public function testMySQLDatabaseSuccess() {
-
- $databaseName = DB_NAME_PREFIX."_sql_db";
+ // Verify MediaWiki installation using 'MySQL' database type
+ public function testMySQLDatabaseSuccess() {
+ $databaseName = DB_NAME_PREFIX . "_sql_db";
- parent::navigateConnetToDatabasePage();
+ parent::navigateConnetToDatabasePage();
- // Verify 'MySQL" is selected as the default database type
- $this->assertEquals( "MySQL settings", $this->getText( "//div[@id='DB_wrapper_mysql']/h3" ));
+ // Verify 'MySQL" is selected as the default database type
+ $this->assertEquals( "MySQL settings", $this->getText( "//div[@id='DB_wrapper_mysql']/h3" ) );
- // Change 'Database name'
- $defaultDbName = $this->getText( "mysql_wgDBname" );
- $this->type( "mysql_wgDBname", " ");
- $this->type( "mysql_wgDBname", $databaseName );
- $this->assertNotEquals( $defaultDbName, $databaseName );
+ // Change 'Database name'
+ $defaultDbName = $this->getText( "mysql_wgDBname" );
+ $this->type( "mysql_wgDBname", " " );
+ $this->type( "mysql_wgDBname", $databaseName );
+ $this->assertNotEquals( $defaultDbName, $databaseName );
- // 'Database settings' page
- parent::clickContinueButton();
+ // 'Database settings' page
+ parent::clickContinueButton();
- // 'Name' page
- parent::clickContinueButton();
- parent::completeNamePage();
+ // 'Name' page
+ parent::clickContinueButton();
+ parent::completeNamePage();
- // 'Options page
- parent::clickContinueButton();
+ // 'Options page
+ parent::clickContinueButton();
- // 'Install' page
- parent::clickContinueButton();
+ // 'Install' page
+ parent::clickContinueButton();
- // 'Complete' page
- parent::completePageSuccessfull();
- parent::restartInstallation();
- }
+ // 'Complete' page
+ parent::completePageSuccessfull();
+ parent::restartInstallation();
+ }
}
*/
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 06 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Install Mediawiki using 'MySQL' database type successfully
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiMySQLiteDataBaseTestCase extends MediaWikiInstallationCommonFunction {
+ function setUp() {
+ parent::setUp();
+ }
- function setUp() {
- parent::setUp();
- }
-
- // Verify MediaWiki installation using 'MySQL' database type
- public function testMySQLDatabaseSuccess() {
-
- $databaseName = DB_NAME_PREFIX."_sqlite_db";
+ // Verify MediaWiki installation using 'MySQL' database type
+ public function testMySQLDatabaseSuccess() {
+ $databaseName = DB_NAME_PREFIX . "_sqlite_db";
- parent::navigateConnetToDatabasePage();
- $this->click( "DBType_sqlite" );
+ parent::navigateConnetToDatabasePage();
+ $this->click( "DBType_sqlite" );
- // Select 'SQLite' database type
- $this->assertEquals( "SQLite settings", $this->getText( "//div[@id='DB_wrapper_sqlite']/h3" ));
+ // Select 'SQLite' database type
+ $this->assertEquals( "SQLite settings", $this->getText( "//div[@id='DB_wrapper_sqlite']/h3" ) );
- // Change database name
- $defaultDbName = $this->getText( "sqlite_wgDBname" );
- $this->type( "sqlite_wgDBname", " ");
- $this->type( "sqlite_wgDBname", $databaseName );
- $this->assertNotEquals( $defaultDbName, $databaseName );
+ // Change database name
+ $defaultDbName = $this->getText( "sqlite_wgDBname" );
+ $this->type( "sqlite_wgDBname", " " );
+ $this->type( "sqlite_wgDBname", $databaseName );
+ $this->assertNotEquals( $defaultDbName, $databaseName );
- // 'Database settings' page
- parent::clickContinueButton();
+ // 'Database settings' page
+ parent::clickContinueButton();
- // 'Name' page
- parent::clickContinueButton();
- parent::completeNamePage();
+ // 'Name' page
+ parent::clickContinueButton();
+ parent::completeNamePage();
- // 'Options page
- parent::clickContinueButton();
+ // 'Options page
+ parent::clickContinueButton();
- // 'Install' page
- parent::clickContinueButton();
+ // 'Install' page
+ parent::clickContinueButton();
- // 'Complete' page
- parent::completePageSuccessfull();
- parent::restartInstallation();
- }
+ // 'Complete' page
+ parent::completePageSuccessfull();
+ parent::restartInstallation();
+ }
}
*/
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 03 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Install mediawiki on a already installed Mediawiki.]
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiOnAlreadyInstalledTestCase extends MediaWikiInstallationCommonFunction {
+ function setUp() {
+ parent::setUp();
+ }
- function setUp() {
- parent::setUp();
- }
-
- // Install Mediawiki using 'MySQL' database type.
- public function testInstallOnAlreadyInstalled() {
-
- $databaseName = DB_NAME_PREFIX."_already_installed";
- parent::navigateInstallPage( $databaseName );
+ // Install Mediawiki using 'MySQL' database type.
+ public function testInstallOnAlreadyInstalled() {
+ $databaseName = DB_NAME_PREFIX . "_already_installed";
+ parent::navigateInstallPage( $databaseName );
- // 'Options' page
- parent::clickBackButton();
+ // 'Options' page
+ parent::clickBackButton();
- // Install page
- parent::clickContinueButton();
+ // Install page
+ parent::clickContinueButton();
- // 'Install' page should display after the 'Option' page
- $this->assertEquals( "Install", $this->getText( LINK_DIV."h2" ));
+ // 'Install' page should display after the 'Option' page
+ $this->assertEquals( "Install", $this->getText( LINK_DIV . "h2" ) );
- // Verify warning text displayed
- $this->assertEquals( "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
- $this->getText( LINK_FORM."div[1]/div[2]" ));
+ // Verify warning text displayed
+ $this->assertEquals( "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
+ $this->getText( LINK_FORM . "div[1]/div[2]" ) );
- // Complete page
- parent::clickContinueButton();
- parent::completePageSuccessfull();
- $this->chooseCancelOnNextConfirmation();
- parent::restartInstallation();
- }
+ // Complete page
+ parent::clickContinueButton();
+ parent::completePageSuccessfull();
+ $this->chooseCancelOnNextConfirmation();
+ parent::restartInstallation();
+ }
}
*/
-
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 11, 12 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Install mediawiki on a already installed Mediawiki.
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiRestartInstallationTestCase extends MediaWikiInstallationCommonFunction {
+ function setUp() {
+ parent::setUp();
+ }
- function setUp() {
- parent::setUp();
- }
-
- // Verify restarting the installation
- public function testSuccessRestartInstallation() {
-
- $dbNameBeforeRestart = DB_NAME_PREFIX."_db_before";
- parent::navigateDatabaseSettingsPage( $dbNameBeforeRestart );
-
- // Verify 'Restart installation' link available
- $this->assertTrue($this->isElementPresent( "link=Restart installation" ));
-
- // Click 'Restart installation'
- $this->click( "link=Restart installation ");
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ // Verify restarting the installation
+ public function testSuccessRestartInstallation() {
+ $dbNameBeforeRestart = DB_NAME_PREFIX . "_db_before";
+ parent::navigateDatabaseSettingsPage( $dbNameBeforeRestart );
- // 'Restart Installation' page displayed
- $this->assertEquals( "Restart installation", $this->getText( LINK_DIV."h2"));
+ // Verify 'Restart installation' link available
+ $this->assertTrue( $this->isElementPresent( "link=Restart installation" ) );
- // Restart warning message displayed
- $this->assertTrue($this->isTextPresent( "exact:Do you want to clear all saved data that you have entered and restart the installation process?" ));
+ // Click 'Restart installation'
+ $this->click( "link=Restart installation " );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
- // Click on the 'Yes, restart' button
- $this->click( "submit-restart" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ // 'Restart Installation' page displayed
+ $this->assertEquals( "Restart installation", $this->getText( LINK_DIV . "h2" ) );
- // Navigate to the initial installation page(Language).
- $this->assertEquals( "Language", $this->getText( LINK_DIV."h2" ));
+ // Restart warning message displayed
+ $this->assertTrue( $this->isTextPresent( "exact:Do you want to clear all saved data that you have entered and restart the installation process?" ) );
- // 'Welcome to MediaWiki!' page
- parent::clickContinueButton();
+ // Click on the 'Yes, restart' button
+ $this->click( "submit-restart" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
- // 'Connect to database' page
- parent::clickContinueButton();
+ // Navigate to the initial installation page(Language).
+ $this->assertEquals( "Language", $this->getText( LINK_DIV . "h2" ) );
- // saved data should be deleted
- $dbNameAfterRestart = $this->getValue("mysql_wgDBname");
- $this->assertNotEquals($dbNameBeforeRestart, $dbNameAfterRestart);
- }
+ // 'Welcome to MediaWiki!' page
+ parent::clickContinueButton();
+ // 'Connect to database' page
+ parent::clickContinueButton();
- // Verify cancelling restart
- public function testCancelRestartInstallation() {
+ // saved data should be deleted
+ $dbNameAfterRestart = $this->getValue( "mysql_wgDBname" );
+ $this->assertNotEquals( $dbNameBeforeRestart, $dbNameAfterRestart );
+ }
- $dbNameBeforeRestart = DB_NAME_PREFIX."_cancel_restart";
+ // Verify cancelling restart
+ public function testCancelRestartInstallation() {
+ $dbNameBeforeRestart = DB_NAME_PREFIX . "_cancel_restart";
- parent::navigateDatabaseSettingsPage( $dbNameBeforeRestart);
- // Verify 'Restart installation' link available
- $this->assertTrue($this->isElementPresent( "link=Restart installation" ));
+ parent::navigateDatabaseSettingsPage( $dbNameBeforeRestart );
+ // Verify 'Restart installation' link available
+ $this->assertTrue( $this->isElementPresent( "link=Restart installation" ) );
- $this->click( "link=Restart installation" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->click( "link=Restart installation" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
- // 'Restart Installation' page displayed
- $this->assertEquals( "Restart installation", $this->getText( LINK_DIV."h2" ));
+ // 'Restart Installation' page displayed
+ $this->assertEquals( "Restart installation", $this->getText( LINK_DIV . "h2" ) );
- // Restart warning message displayed
- $this->assertTrue( $this->isTextPresent( "Do you want to clear all saved data that you have entered and restart the installation process?"));
+ // Restart warning message displayed
+ $this->assertTrue( $this->isTextPresent( "Do you want to clear all saved data that you have entered and restart the installation process?" ) );
- // Click on the 'Back' button
- parent::clickBackButton();
+ // Click on the 'Back' button
+ parent::clickBackButton();
- // Navigates to the previous page
- $this->assertEquals( "Database settings", $this->getText( LINK_DIV."h2" ));
+ // Navigates to the previous page
+ $this->assertEquals( "Database settings", $this->getText( LINK_DIV . "h2" ) );
- // 'Connect to database' page
- parent::clickBackButton();
+ // 'Connect to database' page
+ parent::clickBackButton();
- // Saved data remain on the page.
- $dbNameAfterRestart = $this->getValue( "mysql_wgDBname" );
- $this->assertEquals( $dbNameBeforeRestart, $dbNameAfterRestart );
- }
+ // Saved data remain on the page.
+ $dbNameAfterRestart = $this->getValue( "mysql_wgDBname" );
+ $this->assertEquals( $dbNameBeforeRestart, $dbNameAfterRestart );
+ }
}
*
*/
-
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 14, 15, 16, 17 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* User selects 'Copying' link.
* User selects 'Upgrading' link.
* Version : MediaWiki 1.18alpha
-*/
-
+ */
class MediaWikiRightFrameworkLinksTestCase extends MediaWikiInstallationCommonFunction {
-
- function setUp() {
- parent::setUp();
- }
-
- public function testLinksAvailability() {
-
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // Verify 'Read me' link availability
- $this->assertTrue($this->isElementPresent( "link=Read me" ));
-
- // Verify 'Release notes' link availability
- $this->assertTrue($this->isElementPresent( "link=Release notes" ));
-
- // Verify 'Copying' link availability
- $this->assertTrue($this->isElementPresent( "link=Copying" ));
- }
-
- public function testPageNavigation() {
-
- $this->open( "http://".HOST_NAME.":".PORT."/".DIRECTORY_NAME."/config/index.php" );
-
- // Navigate to the 'Read me' page
- $this->click( "link=Read me" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- $this->assertEquals( "Read me", $this->getText( LINK_DIV."h2[1]" ));
- $this->assertTrue($this->isElementPresent( "submit-back" ));
- parent::clickBackButton();
-
- // Navigate to the 'Release notes' page
- $this->click( "link=Release notes" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME);
- $this->assertEquals( "Release notes", $this->getText( LINK_DIV."h2[1]" ));
- $this->assertTrue( $this->isElementPresent( "submit-back" ));
- parent::clickBackButton();
-
- // Navigate to the 'Copying' page
- $this->click( "link=Copying" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- $this->assertEquals( "Copying", $this->getText( LINK_DIV."h2[1]" ));
- $this->assertTrue($this->isElementPresent( "submit-back" ));
- parent::clickBackButton();
-
- // Navigate to the 'Upgrading' page
- $this->click( "link=Upgrading" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- $this->assertEquals( "Upgrading", $this->getText( LINK_DIV."h2[1]" ));
- }
+ function setUp() {
+ parent::setUp();
+ }
+
+ public function testLinksAvailability() {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // Verify 'Read me' link availability
+ $this->assertTrue( $this->isElementPresent( "link=Read me" ) );
+
+ // Verify 'Release notes' link availability
+ $this->assertTrue( $this->isElementPresent( "link=Release notes" ) );
+
+ // Verify 'Copying' link availability
+ $this->assertTrue( $this->isElementPresent( "link=Copying" ) );
+ }
+
+ public function testPageNavigation() {
+ $this->open( "http://" . HOST_NAME . ":" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+
+ // Navigate to the 'Read me' page
+ $this->click( "link=Read me" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->assertEquals( "Read me", $this->getText( LINK_DIV . "h2[1]" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ parent::clickBackButton();
+
+ // Navigate to the 'Release notes' page
+ $this->click( "link=Release notes" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->assertEquals( "Release notes", $this->getText( LINK_DIV . "h2[1]" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ parent::clickBackButton();
+
+ // Navigate to the 'Copying' page
+ $this->click( "link=Copying" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->assertEquals( "Copying", $this->getText( LINK_DIV . "h2[1]" ) );
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+ parent::clickBackButton();
+
+ // Navigate to the 'Upgrading' page
+ $this->click( "link=Upgrading" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->assertEquals( "Upgrading", $this->getText( LINK_DIV . "h2[1]" ) );
+ }
}
*/
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 05 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : Install Mediawiki by updating the existing database.
* Version : MediaWiki 1.18alpha
-*/
-
+ */
class MediaWikiUpgradeExistingDatabaseTestCase extends MediaWikiInstallationCommonFunction {
-
- function setUp() {
- parent::setUp();
- }
-
- // Install Mediawiki using 'MySQL' database type.
- public function testUpgradeExistingDatabase() {
-
- $databaseName = DB_NAME_PREFIX."_upgrade_existing";
- parent::navigateInstallPage( $databaseName );
-
- $this->open( "http://localhost:".PORT."/".DIRECTORY_NAME."/config/index.php" );
- $this->assertEquals( "Install", $this->getText( LINK_DIV."h2" ));
- $this->assertEquals( "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
- $this->getText( LINK_DIV."div[2]/form/div[1]/div[2]" ));
-
- // 'Optionis' page
- parent::clickBackButton();
-
- // 'Name' page
- parent::clickBackButton();
-
- // 'Database settings' page
- parent::clickBackButton();
-
- // 'Connect to database' page
- parent::clickBackButton();
- $this->type( "mysql_wgDBname", $databaseName );
- parent::clickContinueButton();
-
- // 'Upgrade existing installation' page displayed next to the 'Connect to database' page.
- $this->assertEquals( "Upgrade existing installation", $this->getText( LINK_DIV."h2" ));
-
- // Warning message displayed.
- $this->assertEquals( "There are MediaWiki tables in this database. To upgrade them to MediaWiki 1.18alpha, click Continue.",
- $this->getText( LINK_DIV."div[2]/form/div[1]/div[2]" ));
-
- parent::clickContinueButton();
- $this->assertEquals( "Upgrade existing installation",
- $this->getText( LINK_DIV."h2" ));
-
- // 'Upgrade complete.' text display
- $this->assertEquals("Upgrade complete.",
- $this->getText("//div[@id='bodyContent']/div/div[1]/div[4]/form/div[1]/div[2]/p[1]"));
-
- $this->assertEquals("You can now Folder/index.php start using your wiki.",
- $this->getText("//div[@id='bodyContent']/div/div[1]/div[4]/form/div[1]/div[2]/p[2]" ));
-
- $this->assertEquals( "Folder/index.php start using your wiki",
- $this->getText( "link=Folder/index.php start using your wiki" ));
-
- $this->assertTrue($this->isElementPresent( "submit-regenerate" ));
- $this->click( "submit-regenerate" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
- $this->assertEquals( "Database settings",
- $this->getText( LINK_DIV."h2" ));
-
- // 'Database settings' page
- parent::clickContinueButton();
-
- // Name page
- parent::completeNamePage();
-
- // Options page
- parent::clickContinueButton();
-
- // Install page
- $this->assertEquals( "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
- $this->getText( LINK_FORM."div[1]/div[2]" ));
- parent::clickContinueButton();
-
- // complete
- parent::completePageSuccessfull();
- $this->chooseCancelOnNextConfirmation();
- parent::restartInstallation();
- }
+ function setUp() {
+ parent::setUp();
+ }
+
+ // Install Mediawiki using 'MySQL' database type.
+ public function testUpgradeExistingDatabase() {
+
+ $databaseName = DB_NAME_PREFIX . "_upgrade_existing";
+ parent::navigateInstallPage( $databaseName );
+
+ $this->open( "http://localhost:" . PORT . "/" . DIRECTORY_NAME . "/config/index.php" );
+ $this->assertEquals( "Install", $this->getText( LINK_DIV . "h2" ) );
+ $this->assertEquals(
+ "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
+ $this->getText( LINK_DIV . "div[2]/form/div[1]/div[2]" )
+ );
+
+ // 'Optionis' page
+ parent::clickBackButton();
+
+ // 'Name' page
+ parent::clickBackButton();
+
+ // 'Database settings' page
+ parent::clickBackButton();
+
+ // 'Connect to database' page
+ parent::clickBackButton();
+ $this->type( "mysql_wgDBname", $databaseName );
+ parent::clickContinueButton();
+
+ // 'Upgrade existing installation' page displayed next to the 'Connect to database' page.
+ $this->assertEquals( "Upgrade existing installation", $this->getText( LINK_DIV . "h2" ) );
+
+ // Warning message displayed.
+ $this->assertEquals( "There are MediaWiki tables in this database. To upgrade them to MediaWiki 1.18alpha, click Continue.",
+ $this->getText( LINK_DIV . "div[2]/form/div[1]/div[2]" ) );
+
+ parent::clickContinueButton();
+ $this->assertEquals( "Upgrade existing installation",
+ $this->getText( LINK_DIV . "h2" ) );
+
+ // 'Upgrade complete.' text display
+ $this->assertEquals( "Upgrade complete.",
+ $this->getText( "//div[@id='bodyContent']/div/div[1]/div[4]/form/div[1]/div[2]/p[1]" ) );
+
+ $this->assertEquals( "You can now Folder/index.php start using your wiki.",
+ $this->getText( "//div[@id='bodyContent']/div/div[1]/div[4]/form/div[1]/div[2]/p[2]" ) );
+
+ $this->assertEquals( "Folder/index.php start using your wiki",
+ $this->getText( "link=Folder/index.php start using your wiki" ) );
+
+ $this->assertTrue( $this->isElementPresent( "submit-regenerate" ) );
+ $this->click( "submit-regenerate" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+ $this->assertEquals( "Database settings",
+ $this->getText( LINK_DIV . "h2" ) );
+
+ // 'Database settings' page
+ parent::clickContinueButton();
+
+ // Name page
+ parent::completeNamePage();
+
+ // Options page
+ parent::clickContinueButton();
+
+ // Install page
+ $this->assertEquals( "Warning: You seem to have already installed MediaWiki and are trying to install it again. Please proceed to the next page.",
+ $this->getText( LINK_FORM . "div[1]/div[2]" ) );
+ parent::clickContinueButton();
+
+ // complete
+ parent::completePageSuccessfull();
+ $this->chooseCancelOnNextConfirmation();
+ parent::restartInstallation();
+ }
}
*
*/
-require_once (__DIR__.'/'.'MediaWikiInstallationCommonFunction.php');
+require_once ( __DIR__ . '/MediaWikiInstallationCommonFunction.php' );
/**
* Test Case ID : 18 - 27 (http://www.mediawiki.org/wiki/New_installer/Test_plan)
* Test Case Name : UI of MediaWiki initial/ Language/ Welcome to MediaWiki!/ Connect to database/
* Database settings/ Name/ Options/ Install/ Complete/ Restart Inslation pages
* Version : MediaWiki 1.18alpha
-*/
+ */
class MediaWikiUserInterfaceTestCase extends MediaWikiInstallationCommonFunction {
-
- function setUp() {
- parent::setUp();
- }
-
-
- public function testInitialPageUI() {
-
- parent::navigateInitialpage();
-
- // MediaWiki logo available
- $this->assertTrue( $this->isElementPresent( "//img[@alt='The MediaWiki logo']" ));
-
- // 'MediaWiki 1.18alpha' text available
- $this->assertEquals( "MediaWiki 1.18alpha", $this->getText( "//h1" ));
-
- // 'LocalSettings.php not found.' text available
- $this->assertEquals( "LocalSettings.php not found.", $this->getText( "//p[1]" ));
-
- // 'Please set up the wiki first' text available
- $this->assertEquals( "Please set up the wiki first.", $this->getText( "//p[2]" ));
-
- // 'set up the wiki' link available
- $this->assertTrue($this->isElementPresent( "link=set up the wiki" ));
- }
-
-
- public function testlanguagePageUI() {
-
- parent::navigateLanguagePage();
-
- // Verify 'Language' heading
- $this->assertEquals( "Language", $this->getText( LINK_DIV."h2" ));
-
- // 'Your language' label available
- $this->assertEquals( "Your language:",
- $this->getText( LINK_FORM."div[1]/div[1]/label" ));
-
- // 'Your language' dropdown available
- $this->assertTrue( $this->isElementPresent( "UserLang" ));
-
- // 'Wiki language' label available
- $this->assertEquals( "Wiki language:",
- $this->getText( LINK_FORM."div[2]/div[1]/label" ));
-
- // 'Wiki language' dropdown available
- $this->assertTrue($this->isElementPresent( "ContLang" ));
- }
-
-
- public function testWelcometoMediaWikiUI() {
-
- parent::navigateWelcometoMediaWikiPage();
-
- // Verify 'Welcome to MediaWiki!' heading
- $this->assertEquals( "Welcome to MediaWiki!",
- $this->getText( LINK_DIV."h2" ));
-
- // Verify environment ok text displayed.
- $this->assertEquals( "The environment has been checked.You can install MediaWiki.",
- $this->getText( LINK_DIV."div[6]/span" ));
- }
-
-
- public function testConnectToDatabaseUI() {
-
- parent::navigateConnetToDatabasePage();
-
- // 'MYSQL radio button available
- $this->assertEquals( "MySQL",
- $this->getText( LINK_FORM."div[2]/div[2]/ul/li[1]/label" ));
- $this->assertTrue( $this->isElementPresent( LINK_FORM."div[2]/div[2]/ul/li[1]" ));
-
- // 'SQLite' radio button available
- $this->assertTrue( $this->isElementPresent( LINK_FORM."div[2]/div[2]/ul/li[2]" ));
- $this->assertEquals( "SQLite", $this->getText( LINK_FORM."div[2]/div[2]/ul/li[2]/label "));
-
- // 'Database host' label available
- $this->assertEquals( "Database host:", $this->getText( "//div[@id='DB_wrapper_mysql']/div/div[1]/label" ));
-
- // 'Database host' text box default to 'localhost'
- $this->assertEquals( "localhost", $this->getValue( "mysql_wgDBserver" ));
-
- // 'Identify this wiki' section available
- $this->assertTrue( $this->isElementPresent( "//div[@id='DB_wrapper_mysql']/fieldset[1]/legend" ));
-
- // 'Identify this wiki' label available
- $this->assertEquals( "Identify this wiki", $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/legend" ));
-
- // 'Database name' lable available
- $this->assertEquals( "Database name:",
- $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/label" ));
-
- // Verify 'Database name:' text box is default to 'my_wiki'
- $this->assertEquals( "my_wiki", $this->getValue( "mysql_wgDBname" ));
-
- // Verify 'Database table prefix:' label available
- $this->assertEquals( "Database table prefix:",
- $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[2]/div[1]/label" ));
-
- // 'User account for installation' section available
- $this->assertTrue( $this->isElementPresent( "//div[@id='DB_wrapper_mysql']/fieldset[2]/legend" ));
-
- // 'User account for installation' label available
- $this->assertEquals( "User account for installation", $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/legend" ));
-
- // 'Database username' label available
- $this->assertEquals( "Database username:",
- $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[1]/div[1]/label" ));
-
- // 'Database username' text box defaults to 'root'
- $this->assertEquals("root", $this->getValue( "mysql__InstallUser" ));
-
- // 'Database password' label available
- $this->assertEquals( "Database password:",
- $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[2]/div[1]/label" ));
- }
-
-
-
- public function testDatabaseSettingsUI() {
-
- $databaseName = DB_NAME_PREFIX."_db_settings_UI";
- parent::navigateDatabaseSettingsPage( $databaseName );
-
- // 'Database settings' text available.
- $this->assertEquals( "Database settings", $this->getText( LINK_DIV."h2" ));
-
- // 'Database account for web access' section available
- $this->assertTrue( $this->isElementPresent( LINK_FORM."fieldset" ));
-
- // 'Database account for web access' label available
- $this->assertEquals( "Database account for web access", $this->getText( LINK_FORM."fieldset/legend" ));
-
- // 'Use the same account as for installation' check box available
- $this->assertEquals( "Use the same account as for installation", $this->getText( LINK_FORM."fieldset/div[1]/label" ));
-
- // 'Use the same account as for installation' check box is selected by default
- $this->assertEquals( "on", $this->getValue( "mysql__SameAccount" ));
-
- // 'Use the same account as for installation' check box deselected
- $this->click( "mysql__SameAccount" );
-
- // verify 'Use the same account as for installation' check box is not selected
- $this->assertEquals( "off", $this->getValue( "mysql__SameAccount" ));
-
- // 'Database username' label available
- $this->assertEquals( "Database username:", $this->getText( "//div[@id='dbOtherAccount']/div[1]/div[1]/label" ));
-
- // 'Database username' text box is default to the 'wikiuser'
- $this->assertEquals( "wikiuser", $this->getValue( "mysql_wgDBuser" ));
-
- // 'Database password' label available
- $this->assertEquals( "Database password:", $this->getText( "//div[@id='dbOtherAccount']/div[2]/div[1]/label" ));
-
- // 'Create the account if it does not already exist' label available
- $this->assertEquals( "Create the account if it does not already exist", $this->getText( "//div[@id='dbOtherAccount']/div[4]/label" ));
-
- // 'Create the account if it does not already exist' check box is not selected by default
- $this->assertEquals( "off" , $this->getValue( "mysql__CreateDBAccount" ));
-
- // 'Create the account if it does not already exist' check box selected
- $this->click( "mysql__CreateDBAccount" );
-
- // Verify 'Create the account if it does not already exist' check box is selected
- $this->assertEquals( "on" , $this->getValue( "mysql__CreateDBAccount" ));
- $this->click( "mysql__SameAccount" );
- $this->assertEquals( "on", $this->getValue( "mysql__SameAccount" ));
-
- // 'Storage engine' label available
- $this->assertEquals( "Storage engine:",
- $this->getText( LINK_FORM."div[1]/div[1]/label"));
-
- // 'InnoDB' label available
- $this->assertEquals( "InnoDB",
- $this->getText( LINK_FORM."div[1]/div[2]/ul/li[1]/label" ));
-
- // 'InnoDB' radio button available
- $this->assertTrue( $this->isElementPresent( "mysql__MysqlEngine_InnoDB" ));
-
- // 'MyISAM' label available
- $this->assertEquals( "MyISAM", $this->getText( LINK_FORM."div[1]/div[2]/ul/li[2]/label" ));
-
- // 'MyISAM' radio button available
- $this->assertTrue($this->isElementPresent( "mysql__MysqlEngine_MyISAM" ));
-
- // 'Database character set' label available
- $this->assertEquals( "Database character set:",
- $this->getText( LINK_FORM."div[3]/div[1]/label" ));
-
- // 'Binary' radio button available
- $this->assertTrue( $this->isElementPresent( "mysql__MysqlCharset_binary" ));
-
- // 'Binary' radio button available
- $this->assertEquals( "Binary", $this->getText( LINK_FORM."div[3]/div[2]/ul/li[1]/label" ));
-
- // 'UTF-8' radio button available
- $this->assertTrue( $this->isElementPresent( "mysql__MysqlCharset_utf8" ));
-
- // 'UTF-8' label available
- $this->assertEquals( "UTF-8", $this->getText( LINK_FORM."div[3]/div[2]/ul/li[2]/label" ));
-
- // 'Binary' radio button is selected
- $this->assertEquals( "on", $this->getValue( "mysql__MysqlCharset_binary" ));
- }
-
-
-
- public function testNamePageUI() {
-
- $databaseName = DB_NAME_PREFIX."_name_UI";
- parent::navigateNamePage($databaseName);
-
- // 'Name of wiki' text box available
- $this->assertEquals( "Name of wiki:",
- $this->getText( LINK_FORM."div[1]/div[1]/label" ));
-
- $this->assertTrue( $this->isElementPresent( "config_wgSitename" ));
-
- // 'Project namespace' label available
- $this->assertEquals( "Project namespace:",
- $this->getText( LINK_FORM."div[2]/div[1]/label" ));
-
- // 'Same as the wiki name' radio button available
- $this->assertTrue( $this->isElementPresent( "config__NamespaceType_site-name" ));
-
- // 'Project' radio button available
- $this->assertTrue( $this->isElementPresent( "config__NamespaceType_generic" ));
-
- // 'Project' radio button available
- $this->assertTrue( $this->isElementPresent( "config__NamespaceType_other" ));
-
- // 'Same as the wiki name' label available
- $this->assertEquals( "Same as the wiki name:",
- $this->getText( LINK_FORM."div[2]/div[2]/ul/li[1]/label" ));
-
- // 'Project' label available
- $this->assertEquals("Project",
- $this->getText( LINK_FORM."div[2]/div[2]/ul/li[2]/label" ));
-
- // 'Project' label available
- $this->assertEquals( "Other (specify)",
- $this->getText( LINK_FORM."div[2]/div[2]/ul/li[3]/label" ));
-
- // 'Same as the wiki name' radio button selected by default
- $this->assertEquals( "on", $this->getValue( "config__NamespaceType_site-name" ));
-
- // 'Administrator account' section available
- $this->assertTrue( $this->isElementPresent( LINK_FORM."fieldset" ));
-
- // 'Administrator account' label available
- $this->assertEquals( "Administrator account",
- $this->getText( LINK_FORM."fieldset/legend" ));
-
- // 'Your Name' label available
- $this->assertEquals( "Your name:",
- $this->getText( LINK_FORM."fieldset/div[1]/div[1]/label" ));
-
- // 'Your Name' text box available
- $this->assertTrue( $this->isElementPresent( "config__AdminName" ));
-
- // 'Password' label available
- $this->assertEquals( "Password:",
- $this->getText( LINK_FORM."fieldset/div[2]/div[1]/label" ));
-
- // 'Password' text box available
- $this->assertTrue( $this->isElementPresent( "config__AdminPassword" ));
-
- // 'Password again' label available
- $this->assertEquals( "Password again:",
- $this->getText( LINK_FORM."fieldset/div[3]/div[1]/label" ));
-
- // 'Password again' text box available
- $this->assertTrue( $this->isElementPresent( "config__AdminPassword2" ));
-
- // 'Email address' label avaialble
- $this->assertEquals( "E-mail address:",
- $this->getText( LINK_FORM."fieldset/div[4]/div[1]/label" ));
-
- // 'Email address' text box available
- $this->assertTrue( $this->isElementPresent( "config__AdminEmail" ));
-
- // Message displayed
- $this->assertEquals( "You are almost done! You can now skip the remaining configuration and install the wiki right now.",
- $this->getText( LINK_FORM."/div[4]/div[2]/p" ));
-
- // 'Ask me more questions.' radio button available
- $this->assertTrue( $this->isElementPresent( "config__SkipOptional_continue" ));
-
- // 'Ask me more questions.' label available
- $this->assertEquals( "Ask me more questions.",
- $this->getText( LINK_FORM."div[5]/div[2]/ul/li[1]/label" ));
-
- // 'I'm bored already, just install the wiki' radio button is avaiable
- $this->assertTrue( $this->isElementPresent( "config__SkipOptional_skip" ));
-
- // 'I'm bored already, just install the wiki' label available
- $this->assertEquals( "I'm bored already, just install the wiki.",
- $this->getText( LINK_FORM."div[5]/div[2]/ul/li[2]/label" ));
-
- // 'Ask me more questions.' radio button is default selected
- $this->assertEquals( "on", $this->getValue( "config__SkipOptional_continue" ));
- }
-
-
-
- public function testOptionPageUI() {
-
- $databaseName = DB_NAME_PREFIX."_options_UI";
- parent::navigateOptionsPage($databaseName);
-
- // 'Options' label available
- $this->assertEquals( "Options", $this->getText( LINK_DIV."h2"));
-
- // 'Return e-mail address' label available
- $this->assertEquals( "Return e-mail address:", $this->getText( "//div[@id='emailwrapper']/div[1]/div[1]/label" ));
-
- // 'Return e-mail address' text box available
- $this->assertTrue( $this->isElementPresent( "config_wgPasswordSender" ));
-
- // Text 'apache@localhost' is default value of the 'Return e-mail address' text box
- $this->assertEquals( "apache@localhost", $this->getValue( "config_wgPasswordSender" ));
-
- // 'Logo URL' label available
- $this->assertEquals( "Logo URL:", $this->getText( LINK_FORM."fieldset[2]/div[3]/div[1]/label" ));
-
- // 'Logo URL' text box available
- $this->assertTrue( $this->isElementPresent( "config_wgLogo" ));
-
- // Correct path available in the 'Logo URL' text box
- $this->assertEquals( "/wiki/skins/common/images/wiki.png", $this->getValue( "config_wgLogo" ));
-
- // 'Enable file uploads' radio button available
- $this->assertTrue( $this->isElementPresent( "config_wgEnableUploads" ));
-
- // 'Enable file uploads' label available
- $this->assertEquals( "Enable file uploads",
- $this->getText( LINK_FORM."fieldset[2]/div[1]/label" ));
-
- // 'Enable file uploads' check box is not selected
- $this->assertEquals( "off", $this->getValue( "config_wgEnableUploads" ));
-
- $this->click( "config_wgEnableUploads" );
-
- // 'Directory for deleted files' label available
- $this->assertEquals( "Directory for deleted files:",
- $this->getText( "//div[@id='uploadwrapper']/div/div[1]/label" ));
-
- // 'Directory for deleted files' text box available
- $this->assertTrue( $this->isElementPresent( "config_wgDeletedDirectory" ));
-
- // Correct path available in the 'Directory for deleted files' text box
- $this->assertEquals( "C:\\wamp\\www\\".DIRECTORY_NAME."/images/deleted",
- $this->getValue( "config_wgDeletedDirectory" ));
- }
-
-
-
- public function testInstallPageUI() {
-
- $databaseName = DB_NAME_PREFIX."_install_UI";
- parent::navigateInstallPage( $databaseName );
-
- // Verify installation done messages display
- $this->assertEquals( "Setting up database... done",
- $this->getText( LINK_FORM."ul/li[1]" ));
- $this->assertEquals( "Creating tables... done",
- $this->getText( LINK_FORM."ul/li[2]" ));
- $this->assertEquals( "Creating database user... done",
- $this->getText( LINK_FORM."ul/li[3]" ));
- $this->assertEquals( "Populating default interwiki table... done",
- $this->getText( LINK_FORM."ul/li[4]" ));
- $this->assertEquals( "Generating secret key... done",
- $this->getText( LINK_FORM."ul/li[5]" ));
- $this->assertEquals( "Generating default upgrade key... done",
- $this->getText( LINK_FORM."ul/li[6]" ));
- $this->assertEquals( "Creating administrator user account... done",
- $this->getText( LINK_FORM."ul/li[7]" ));
- $this->assertEquals( "Creating main page with default content... done",
- $this->getText( LINK_FORM."ul/li[8]" ));
- }
-
-
-
- public function testCompletePageUI() {
-
- $databaseName = DB_NAME_PREFIX."_complete_UI";
- parent::navigateCompletePage( $databaseName );
-
- // 'Congratulations!' text display
- $this->assertEquals("Congratulations!",
- $this->getText( LINK_FORM."div[1]/div[2]/p[1]/b"));
- // 'LocalSettings.php' generated message display
- $this->assertEquals( "The installer has generated a LocalSettings.php file. It contains all your configuration.",
- $this->getText( LINK_FORM."div[1]/div[2]/p[2]" ));
-
- // 'Download LocalSettings.php'' link available
- $this->assertTrue( $this->isElementPresent( "link=Download LocalSettings.php" ));
-
- // 'enter your wiki' link available
- $this->assertTrue($this->isElementPresent("link=Folder/index.php enter your wiki"));
- }
-
-
-
- public function testRestartInstallation() {
-
- parent::navigateConnetToDatabasePage();
- $this->click( "link=Restart installation" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // Restart installation' label should be available.
- $this->assertEquals( "Restart installation", $this->getText( LINK_DIV."h2" ));
-
- //'Do you want to clear all saved data that you have entered and restart the installation process?' label available
- $this->assertEquals( "Do you want to clear all saved data that you have entered and restart the installation process?",
- $this->getText( "//*[@id='bodyContent']/div/div/div[2]/form/div[1]/div[2]" ));
- // 'Back' button available
- $this->assertTrue($this->isElementPresent( "submit-back" ));
-
- // 'Restart' button available
- $this->assertTrue($this->isElementPresent( "submit-restart" ));
- }
-
-
-
- public function testMediaWikiLogoAvailability() {
-
- $databaseName = DB_NAME_PREFIX."_mediawiki_logo";
- parent::navigateInitialpage();
- parent::mediaWikiLogoPresentInitialScreen();
- $this->click( "link=set up the wiki" );
- $this->waitForPageToLoad( PAGE_LOAD_TIME );
-
- // 'Language' page
- parent::mediaWikiLogoPresent();
- parent::clickContinueButton();
-
- // 'Welcome to MediaWiki' page
- parent::mediaWikiLogoPresent();
- parent::clickContinueButton();
-
- // 'Connet to database' page
- parent::mediaWikiLogoPresent();
- $this->type("mysql_wgDBname", $databaseName );
- parent::clickContinueButton();
-
- // 'Database setting' page
- parent::mediaWikiLogoPresent();
- parent::clickContinueButton();
-
- // 'Name' page
- parent::mediaWikiLogoPresent();
- parent::completeNamePage();
- parent::clickContinueButton();
-
- // 'Options' page
- parent::mediaWikiLogoPresent();
- parent::clickContinueButton();
-
- // 'Install' page
- parent::mediaWikiLogoPresent();
- }
-
-
- public function testRightFramework() {
-
- parent::navigateLanguagePage();
- // Verfy right framework texts display
- $this->assertEquals( "Language",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[1]" ));
- $this->assertEquals( "Existing wiki",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[2]" ));
- $this->assertEquals( "Welcome to MediaWiki!",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[3]" ));
- $this->assertEquals( "Connect to database",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[4]" ));
- $this->assertEquals( "Upgrade existing installation",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[5]" ));
- $this->assertEquals( "Database settings",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[6]" ));
- $this->assertEquals( "Name",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[7]" ));
- $this->assertEquals( "Options",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[8]" ));
- $this->assertEquals( "Install",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[9]" ));
- $this->assertEquals( "Complete!",
- $this->getText( LINK_RIGHT_FRAMEWORK."li[10]/span" ));
- }
+ function setUp() {
+ parent::setUp();
+ }
+
+ public function testInitialPageUI() {
+
+ parent::navigateInitialpage();
+
+ // MediaWiki logo available
+ $this->assertTrue( $this->isElementPresent( "//img[@alt='The MediaWiki logo']" ) );
+
+ // 'MediaWiki 1.18alpha' text available
+ $this->assertEquals( "MediaWiki 1.18alpha", $this->getText( "//h1" ) );
+
+ // 'LocalSettings.php not found.' text available
+ $this->assertEquals( "LocalSettings.php not found.", $this->getText( "//p[1]" ) );
+
+ // 'Please set up the wiki first' text available
+ $this->assertEquals( "Please set up the wiki first.", $this->getText( "//p[2]" ) );
+
+ // 'set up the wiki' link available
+ $this->assertTrue( $this->isElementPresent( "link=set up the wiki" ) );
+ }
+
+ public function testlanguagePageUI() {
+ parent::navigateLanguagePage();
+
+ // Verify 'Language' heading
+ $this->assertEquals( "Language", $this->getText( LINK_DIV . "h2" ) );
+
+ // 'Your language' label available
+ $this->assertEquals( "Your language:",
+ $this->getText( LINK_FORM . "div[1]/div[1]/label" ) );
+
+ // 'Your language' dropdown available
+ $this->assertTrue( $this->isElementPresent( "UserLang" ) );
+
+ // 'Wiki language' label available
+ $this->assertEquals( "Wiki language:",
+ $this->getText( LINK_FORM . "div[2]/div[1]/label" ) );
+
+ // 'Wiki language' dropdown available
+ $this->assertTrue( $this->isElementPresent( "ContLang" ) );
+ }
+
+ public function testWelcometoMediaWikiUI() {
+ parent::navigateWelcometoMediaWikiPage();
+
+ // Verify 'Welcome to MediaWiki!' heading
+ $this->assertEquals( "Welcome to MediaWiki!",
+ $this->getText( LINK_DIV . "h2" ) );
+
+ // Verify environment ok text displayed.
+ $this->assertEquals( "The environment has been checked.You can install MediaWiki.",
+ $this->getText( LINK_DIV . "div[6]/span" ) );
+ }
+
+ public function testConnectToDatabaseUI() {
+ parent::navigateConnetToDatabasePage();
+
+ // 'MYSQL radio button available
+ $this->assertEquals( "MySQL",
+ $this->getText( LINK_FORM . "div[2]/div[2]/ul/li[1]/label" ) );
+ $this->assertTrue( $this->isElementPresent( LINK_FORM . "div[2]/div[2]/ul/li[1]" ) );
+
+ // 'SQLite' radio button available
+ $this->assertTrue( $this->isElementPresent( LINK_FORM . "div[2]/div[2]/ul/li[2]" ) );
+ $this->assertEquals( "SQLite", $this->getText( LINK_FORM . "div[2]/div[2]/ul/li[2]/label " ) );
+
+ // 'Database host' label available
+ $this->assertEquals( "Database host:", $this->getText( "//div[@id='DB_wrapper_mysql']/div/div[1]/label" ) );
+
+ // 'Database host' text box default to 'localhost'
+ $this->assertEquals( "localhost", $this->getValue( "mysql_wgDBserver" ) );
+
+ // 'Identify this wiki' section available
+ $this->assertTrue( $this->isElementPresent( "//div[@id='DB_wrapper_mysql']/fieldset[1]/legend" ) );
+
+ // 'Identify this wiki' label available
+ $this->assertEquals( "Identify this wiki", $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/legend" ) );
+
+ // 'Database name' lable available
+ $this->assertEquals( "Database name:",
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[1]/div[1]/label" ) );
+
+ // Verify 'Database name:' text box is default to 'my_wiki'
+ $this->assertEquals( "my_wiki", $this->getValue( "mysql_wgDBname" ) );
+
+ // Verify 'Database table prefix:' label available
+ $this->assertEquals( "Database table prefix:",
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[1]/div[2]/div[1]/label" ) );
+
+ // 'User account for installation' section available
+ $this->assertTrue( $this->isElementPresent( "//div[@id='DB_wrapper_mysql']/fieldset[2]/legend" ) );
+
+ // 'User account for installation' label available
+ $this->assertEquals( "User account for installation", $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/legend" ) );
+
+ // 'Database username' label available
+ $this->assertEquals( "Database username:",
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[1]/div[1]/label" ) );
+
+ // 'Database username' text box defaults to 'root'
+ $this->assertEquals( "root", $this->getValue( "mysql__InstallUser" ) );
+
+ // 'Database password' label available
+ $this->assertEquals( "Database password:",
+ $this->getText( "//div[@id='DB_wrapper_mysql']/fieldset[2]/div[2]/div[1]/label" ) );
+ }
+
+ public function testDatabaseSettingsUI() {
+ $databaseName = DB_NAME_PREFIX . "_db_settings_UI";
+ parent::navigateDatabaseSettingsPage( $databaseName );
+
+ // 'Database settings' text available.
+ $this->assertEquals( "Database settings", $this->getText( LINK_DIV . "h2" ) );
+
+ // 'Database account for web access' section available
+ $this->assertTrue( $this->isElementPresent( LINK_FORM . "fieldset" ) );
+
+ // 'Database account for web access' label available
+ $this->assertEquals( "Database account for web access", $this->getText( LINK_FORM . "fieldset/legend" ) );
+
+ // 'Use the same account as for installation' check box available
+ $this->assertEquals( "Use the same account as for installation", $this->getText( LINK_FORM . "fieldset/div[1]/label" ) );
+
+ // 'Use the same account as for installation' check box is selected by default
+ $this->assertEquals( "on", $this->getValue( "mysql__SameAccount" ) );
+
+ // 'Use the same account as for installation' check box deselected
+ $this->click( "mysql__SameAccount" );
+
+ // verify 'Use the same account as for installation' check box is not selected
+ $this->assertEquals( "off", $this->getValue( "mysql__SameAccount" ) );
+
+ // 'Database username' label available
+ $this->assertEquals( "Database username:", $this->getText( "//div[@id='dbOtherAccount']/div[1]/div[1]/label" ) );
+
+ // 'Database username' text box is default to the 'wikiuser'
+ $this->assertEquals( "wikiuser", $this->getValue( "mysql_wgDBuser" ) );
+
+ // 'Database password' label available
+ $this->assertEquals( "Database password:", $this->getText( "//div[@id='dbOtherAccount']/div[2]/div[1]/label" ) );
+
+ // 'Create the account if it does not already exist' label available
+ $this->assertEquals( "Create the account if it does not already exist", $this->getText( "//div[@id='dbOtherAccount']/div[4]/label" ) );
+
+ // 'Create the account if it does not already exist' check box is not selected by default
+ $this->assertEquals( "off", $this->getValue( "mysql__CreateDBAccount" ) );
+
+ // 'Create the account if it does not already exist' check box selected
+ $this->click( "mysql__CreateDBAccount" );
+
+ // Verify 'Create the account if it does not already exist' check box is selected
+ $this->assertEquals( "on", $this->getValue( "mysql__CreateDBAccount" ) );
+ $this->click( "mysql__SameAccount" );
+ $this->assertEquals( "on", $this->getValue( "mysql__SameAccount" ) );
+
+ // 'Storage engine' label available
+ $this->assertEquals( "Storage engine:",
+ $this->getText( LINK_FORM . "div[1]/div[1]/label" ) );
+
+ // 'InnoDB' label available
+ $this->assertEquals( "InnoDB",
+ $this->getText( LINK_FORM . "div[1]/div[2]/ul/li[1]/label" ) );
+
+ // 'InnoDB' radio button available
+ $this->assertTrue( $this->isElementPresent( "mysql__MysqlEngine_InnoDB" ) );
+
+ // 'MyISAM' label available
+ $this->assertEquals( "MyISAM", $this->getText( LINK_FORM . "div[1]/div[2]/ul/li[2]/label" ) );
+
+ // 'MyISAM' radio button available
+ $this->assertTrue( $this->isElementPresent( "mysql__MysqlEngine_MyISAM" ) );
+
+ // 'Database character set' label available
+ $this->assertEquals( "Database character set:",
+ $this->getText( LINK_FORM . "div[3]/div[1]/label" ) );
+
+ // 'Binary' radio button available
+ $this->assertTrue( $this->isElementPresent( "mysql__MysqlCharset_binary" ) );
+
+ // 'Binary' radio button available
+ $this->assertEquals( "Binary", $this->getText( LINK_FORM . "div[3]/div[2]/ul/li[1]/label" ) );
+
+ // 'UTF-8' radio button available
+ $this->assertTrue( $this->isElementPresent( "mysql__MysqlCharset_utf8" ) );
+
+ // 'UTF-8' label available
+ $this->assertEquals( "UTF-8", $this->getText( LINK_FORM . "div[3]/div[2]/ul/li[2]/label" ) );
+
+ // 'Binary' radio button is selected
+ $this->assertEquals( "on", $this->getValue( "mysql__MysqlCharset_binary" ) );
+ }
+
+ public function testNamePageUI() {
+ $databaseName = DB_NAME_PREFIX . "_name_UI";
+ parent::navigateNamePage( $databaseName );
+
+ // 'Name of wiki' text box available
+ $this->assertEquals( "Name of wiki:",
+ $this->getText( LINK_FORM . "div[1]/div[1]/label" ) );
+
+ $this->assertTrue( $this->isElementPresent( "config_wgSitename" ) );
+
+ // 'Project namespace' label available
+ $this->assertEquals( "Project namespace:",
+ $this->getText( LINK_FORM . "div[2]/div[1]/label" ) );
+
+ // 'Same as the wiki name' radio button available
+ $this->assertTrue( $this->isElementPresent( "config__NamespaceType_site-name" ) );
+
+ // 'Project' radio button available
+ $this->assertTrue( $this->isElementPresent( "config__NamespaceType_generic" ) );
+
+ // 'Project' radio button available
+ $this->assertTrue( $this->isElementPresent( "config__NamespaceType_other" ) );
+
+ // 'Same as the wiki name' label available
+ $this->assertEquals( "Same as the wiki name:",
+ $this->getText( LINK_FORM . "div[2]/div[2]/ul/li[1]/label" ) );
+
+ // 'Project' label available
+ $this->assertEquals( "Project",
+ $this->getText( LINK_FORM . "div[2]/div[2]/ul/li[2]/label" ) );
+
+ // 'Project' label available
+ $this->assertEquals( "Other (specify)",
+ $this->getText( LINK_FORM . "div[2]/div[2]/ul/li[3]/label" ) );
+
+ // 'Same as the wiki name' radio button selected by default
+ $this->assertEquals( "on", $this->getValue( "config__NamespaceType_site-name" ) );
+
+ // 'Administrator account' section available
+ $this->assertTrue( $this->isElementPresent( LINK_FORM . "fieldset" ) );
+
+ // 'Administrator account' label available
+ $this->assertEquals( "Administrator account",
+ $this->getText( LINK_FORM . "fieldset/legend" ) );
+
+ // 'Your Name' label available
+ $this->assertEquals( "Your name:",
+ $this->getText( LINK_FORM . "fieldset/div[1]/div[1]/label" ) );
+
+ // 'Your Name' text box available
+ $this->assertTrue( $this->isElementPresent( "config__AdminName" ) );
+
+ // 'Password' label available
+ $this->assertEquals( "Password:",
+ $this->getText( LINK_FORM . "fieldset/div[2]/div[1]/label" ) );
+
+ // 'Password' text box available
+ $this->assertTrue( $this->isElementPresent( "config__AdminPassword" ) );
+
+ // 'Password again' label available
+ $this->assertEquals( "Password again:",
+ $this->getText( LINK_FORM . "fieldset/div[3]/div[1]/label" ) );
+
+ // 'Password again' text box available
+ $this->assertTrue( $this->isElementPresent( "config__AdminPassword2" ) );
+
+ // 'Email address' label avaialble
+ $this->assertEquals( "E-mail address:",
+ $this->getText( LINK_FORM . "fieldset/div[4]/div[1]/label" ) );
+
+ // 'Email address' text box available
+ $this->assertTrue( $this->isElementPresent( "config__AdminEmail" ) );
+
+ // Message displayed
+ $this->assertEquals( "You are almost done! You can now skip the remaining configuration and install the wiki right now.",
+ $this->getText( LINK_FORM . "/div[4]/div[2]/p" ) );
+
+ // 'Ask me more questions.' radio button available
+ $this->assertTrue( $this->isElementPresent( "config__SkipOptional_continue" ) );
+
+ // 'Ask me more questions.' label available
+ $this->assertEquals( "Ask me more questions.",
+ $this->getText( LINK_FORM . "div[5]/div[2]/ul/li[1]/label" ) );
+
+ // 'I'm bored already, just install the wiki' radio button is avaiable
+ $this->assertTrue( $this->isElementPresent( "config__SkipOptional_skip" ) );
+
+ // 'I'm bored already, just install the wiki' label available
+ $this->assertEquals( "I'm bored already, just install the wiki.",
+ $this->getText( LINK_FORM . "div[5]/div[2]/ul/li[2]/label" ) );
+
+ // 'Ask me more questions.' radio button is default selected
+ $this->assertEquals( "on", $this->getValue( "config__SkipOptional_continue" ) );
+ }
+
+ public function testOptionPageUI() {
+ $databaseName = DB_NAME_PREFIX . "_options_UI";
+ parent::navigateOptionsPage( $databaseName );
+
+ // 'Options' label available
+ $this->assertEquals( "Options", $this->getText( LINK_DIV . "h2" ) );
+
+ // 'Return e-mail address' label available
+ $this->assertEquals( "Return e-mail address:", $this->getText( "//div[@id='emailwrapper']/div[1]/div[1]/label" ) );
+
+ // 'Return e-mail address' text box available
+ $this->assertTrue( $this->isElementPresent( "config_wgPasswordSender" ) );
+
+ // Text 'apache@localhost' is default value of the 'Return e-mail address' text box
+ $this->assertEquals( "apache@localhost", $this->getValue( "config_wgPasswordSender" ) );
+
+ // 'Logo URL' label available
+ $this->assertEquals( "Logo URL:", $this->getText( LINK_FORM . "fieldset[2]/div[3]/div[1]/label" ) );
+
+ // 'Logo URL' text box available
+ $this->assertTrue( $this->isElementPresent( "config_wgLogo" ) );
+
+ // Correct path available in the 'Logo URL' text box
+ $this->assertEquals( "/wiki/skins/common/images/wiki.png", $this->getValue( "config_wgLogo" ) );
+
+ // 'Enable file uploads' radio button available
+ $this->assertTrue( $this->isElementPresent( "config_wgEnableUploads" ) );
+
+ // 'Enable file uploads' label available
+ $this->assertEquals( "Enable file uploads",
+ $this->getText( LINK_FORM . "fieldset[2]/div[1]/label" ) );
+
+ // 'Enable file uploads' check box is not selected
+ $this->assertEquals( "off", $this->getValue( "config_wgEnableUploads" ) );
+
+ $this->click( "config_wgEnableUploads" );
+
+ // 'Directory for deleted files' label available
+ $this->assertEquals( "Directory for deleted files:",
+ $this->getText( "//div[@id='uploadwrapper']/div/div[1]/label" ) );
+
+ // 'Directory for deleted files' text box available
+ $this->assertTrue( $this->isElementPresent( "config_wgDeletedDirectory" ) );
+
+ // Correct path available in the 'Directory for deleted files' text box
+ $this->assertEquals( "C:\\wamp\\www\\" . DIRECTORY_NAME . "/images/deleted",
+ $this->getValue( "config_wgDeletedDirectory" ) );
+ }
+
+ public function testInstallPageUI() {
+ $databaseName = DB_NAME_PREFIX . "_install_UI";
+ parent::navigateInstallPage( $databaseName );
+
+ // Verify installation done messages display
+ $this->assertEquals( "Setting up database... done",
+ $this->getText( LINK_FORM . "ul/li[1]" ) );
+ $this->assertEquals( "Creating tables... done",
+ $this->getText( LINK_FORM . "ul/li[2]" ) );
+ $this->assertEquals( "Creating database user... done",
+ $this->getText( LINK_FORM . "ul/li[3]" ) );
+ $this->assertEquals( "Populating default interwiki table... done",
+ $this->getText( LINK_FORM . "ul/li[4]" ) );
+ $this->assertEquals( "Generating secret key... done",
+ $this->getText( LINK_FORM . "ul/li[5]" ) );
+ $this->assertEquals( "Generating default upgrade key... done",
+ $this->getText( LINK_FORM . "ul/li[6]" ) );
+ $this->assertEquals( "Creating administrator user account... done",
+ $this->getText( LINK_FORM . "ul/li[7]" ) );
+ $this->assertEquals( "Creating main page with default content... done",
+ $this->getText( LINK_FORM . "ul/li[8]" ) );
+ }
+
+ public function testCompletePageUI() {
+ $databaseName = DB_NAME_PREFIX . "_complete_UI";
+ parent::navigateCompletePage( $databaseName );
+
+ // 'Congratulations!' text display
+ $this->assertEquals( "Congratulations!",
+ $this->getText( LINK_FORM . "div[1]/div[2]/p[1]/b" ) );
+ // 'LocalSettings.php' generated message display
+ $this->assertEquals( "The installer has generated a LocalSettings.php file. It contains all your configuration.",
+ $this->getText( LINK_FORM . "div[1]/div[2]/p[2]" ) );
+
+ // 'Download LocalSettings.php'' link available
+ $this->assertTrue( $this->isElementPresent( "link=Download LocalSettings.php" ) );
+
+ // 'enter your wiki' link available
+ $this->assertTrue( $this->isElementPresent( "link=Folder/index.php enter your wiki" ) );
+ }
+
+ public function testRestartInstallation() {
+ parent::navigateConnetToDatabasePage();
+ $this->click( "link=Restart installation" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // Restart installation' label should be available.
+ $this->assertEquals( "Restart installation", $this->getText( LINK_DIV . "h2" ) );
+
+ //'Do you want to clear all saved data that you have entered and restart the installation process?' label available
+ $this->assertEquals( "Do you want to clear all saved data that you have entered and restart the installation process?",
+ $this->getText( "//*[@id='bodyContent']/div/div/div[2]/form/div[1]/div[2]" ) );
+ // 'Back' button available
+ $this->assertTrue( $this->isElementPresent( "submit-back" ) );
+
+ // 'Restart' button available
+ $this->assertTrue( $this->isElementPresent( "submit-restart" ) );
+ }
+
+ public function testMediaWikiLogoAvailability() {
+ $databaseName = DB_NAME_PREFIX . "_mediawiki_logo";
+ parent::navigateInitialpage();
+ parent::mediaWikiLogoPresentInitialScreen();
+ $this->click( "link=set up the wiki" );
+ $this->waitForPageToLoad( PAGE_LOAD_TIME );
+
+ // 'Language' page
+ parent::mediaWikiLogoPresent();
+ parent::clickContinueButton();
+
+ // 'Welcome to MediaWiki' page
+ parent::mediaWikiLogoPresent();
+ parent::clickContinueButton();
+
+ // 'Connet to database' page
+ parent::mediaWikiLogoPresent();
+ $this->type( "mysql_wgDBname", $databaseName );
+ parent::clickContinueButton();
+
+ // 'Database setting' page
+ parent::mediaWikiLogoPresent();
+ parent::clickContinueButton();
+
+ // 'Name' page
+ parent::mediaWikiLogoPresent();
+ parent::completeNamePage();
+ parent::clickContinueButton();
+
+ // 'Options' page
+ parent::mediaWikiLogoPresent();
+ parent::clickContinueButton();
+
+ // 'Install' page
+ parent::mediaWikiLogoPresent();
+ }
+
+ public function testRightFramework() {
+ parent::navigateLanguagePage();
+ // Verfy right framework texts display
+ $this->assertEquals( "Language",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[1]" ) );
+ $this->assertEquals( "Existing wiki",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[2]" ) );
+ $this->assertEquals( "Welcome to MediaWiki!",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[3]" ) );
+ $this->assertEquals( "Connect to database",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[4]" ) );
+ $this->assertEquals( "Upgrade existing installation",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[5]" ) );
+ $this->assertEquals( "Database settings",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[6]" ) );
+ $this->assertEquals( "Name",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[7]" ) );
+ $this->assertEquals( "Options",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[8]" ) );
+ $this->assertEquals( "Install",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[9]" ) );
+ $this->assertEquals( "Complete!",
+ $this->getText( LINK_RIGHT_FRAMEWORK . "li[10]/span" ) );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*
*/
-
class AddContentToNewPageTestCase extends SeleniumTestCase {
-
-
- // Add bold text and verify output
- public function testAddBoldText() {
-
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "//*[@id='mw-editbutton-bold']" );
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify bold text displayed on mediawiki preview
- $this->assertTrue($this->isElementPresent( "//div[@id='wikiPreview']/p/b" ));
- $this->assertTrue($this->isTextPresent( "Bold text" ));
- }
-
- // Add italic text and verify output
- public function testAddItalicText() {
-
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "//*[@id='mw-editbutton-italic']" );
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify italic text displayed on mediawiki preview
- $this->assertTrue($this->isElementPresent("//div[@id='wikiPreview']/p/i"));
- $this->assertTrue($this->isTextPresent( "Italic text" ));
- }
-
- // Add internal link for a new page and verify output in the preview
- public function testAddInternalLinkNewPage() {
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "//*[@id='mw-editbutton-link']" );
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify internal link displayed on mediawiki preview
- $source = $this->getText( "//*[@id='wikiPreview']/p/a" );
- $correct = strstr( $source, "Link title" );
- $this->assertEquals( $correct, true );
-
- $this->click( SeleniumTestConstants::LINK_START."Link title" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify internal link open as a new page - editing mode
- $source = $this->getText( "firstHeading" );
- $correct = strstr( $source, "Editing Link title" );
- $this->assertEquals( $correct, true );
- }
-
- // Add external link and verify output in the preview
- public function testAddExternalLink() {
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "//*[@id='mw-editbutton-extlink']" );
- $this->type( SeleniumTestConstants::TEXT_EDITOR, "[http://www.google.com Google]" );
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify external links displayed on mediawiki preview
- $source = $this->getText( "//*[@id='wikiPreview']/p/a" );
- $correct = strstr( $source, "Google" );
- $this->assertEquals( $correct, true );
-
- $this->click( SeleniumTestConstants::LINK_START."Google" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify external link opens
- $source = $this->getTitle();
- $correct = strstr( $source, "Google" );
- $this->assertEquals( $correct, true);
- }
-
- // Add level 2 headline and verify output in the preview
- public function testAddLevel2HeadLine() {
- $blnElementPresent = false;
- $blnTextPresent = false;
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "mw-editbutton-headline" );
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertTrue($this->isElementPresent( "//div[@id='wikiPreview']/h2" ));
-
- // Verify level 2 headline displayed on mediawiki preview
- $source = $this->getText( "//*[@id='Headline_text']" );
- $correct = strstr( $source, "Headline text" );
- $this->assertEquals( $correct, true );
- }
-
- // Add text with ignore wiki format and verify output the preview
- public function testAddNoWikiFormat() {
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "//*[@id='mw-editbutton-nowiki']" );
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify ignore wiki format text displayed on mediawiki preview
- $source = $this->getText( "//div[@id='wikiPreview']/p" );
- $correct = strstr( $source, "Insert non-formatted text here" );
- $this->assertEquals( $correct, true );
- }
-
- // Add signature and verify output in the preview
- public function testAddUserSignature() {
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "mw-editbutton-signature" );
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify signature displayed on mediawiki preview
- $source = $this->getText( "//*[@id='wikiPreview']/p/a" );
- $username = $this->getText( "//*[@id='pt-userpage']/a" );
- $correct = strstr( $source, $username );
- $this->assertEquals( $correct, true );
- }
-
- // Add horizontal line and verify output in the preview
- public function testHorizontalLine() {
- $this->getExistingPage();
- $this->clickEditLink();
- $this->loadWikiEditor();
- $this->clearWikiEditor();
- $this->click( "mw-editbutton-hr" );
-
- $this->clickShowPreviewBtn();
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify horizontal line displayed on mediawiki preview
- $this->assertTrue( $this->isElementPresent( "//div[@id='wikiPreview']/hr" ));
- $this->deletePage( "new" );
- }
+ // Add bold text and verify output
+ public function testAddBoldText() {
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "//*[@id='mw-editbutton-bold']" );
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify bold text displayed on mediawiki preview
+ $this->assertTrue( $this->isElementPresent( "//div[@id='wikiPreview']/p/b" ) );
+ $this->assertTrue( $this->isTextPresent( "Bold text" ) );
+ }
+
+ // Add italic text and verify output
+ public function testAddItalicText() {
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "//*[@id='mw-editbutton-italic']" );
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify italic text displayed on mediawiki preview
+ $this->assertTrue( $this->isElementPresent( "//div[@id='wikiPreview']/p/i" ) );
+ $this->assertTrue( $this->isTextPresent( "Italic text" ) );
+ }
+
+ // Add internal link for a new page and verify output in the preview
+ public function testAddInternalLinkNewPage() {
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "//*[@id='mw-editbutton-link']" );
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify internal link displayed on mediawiki preview
+ $source = $this->getText( "//*[@id='wikiPreview']/p/a" );
+ $correct = strstr( $source, "Link title" );
+ $this->assertEquals( $correct, true );
+
+ $this->click( SeleniumTestConstants::LINK_START . "Link title" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify internal link open as a new page - editing mode
+ $source = $this->getText( "firstHeading" );
+ $correct = strstr( $source, "Editing Link title" );
+ $this->assertEquals( $correct, true );
+ }
+
+ // Add external link and verify output in the preview
+ public function testAddExternalLink() {
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "//*[@id='mw-editbutton-extlink']" );
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, "[http://www.google.com Google]" );
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify external links displayed on mediawiki preview
+ $source = $this->getText( "//*[@id='wikiPreview']/p/a" );
+ $correct = strstr( $source, "Google" );
+ $this->assertEquals( $correct, true );
+
+ $this->click( SeleniumTestConstants::LINK_START . "Google" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify external link opens
+ $source = $this->getTitle();
+ $correct = strstr( $source, "Google" );
+ $this->assertEquals( $correct, true );
+ }
+
+ // Add level 2 headline and verify output in the preview
+ public function testAddLevel2HeadLine() {
+ $blnElementPresent = false;
+ $blnTextPresent = false;
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "mw-editbutton-headline" );
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertTrue( $this->isElementPresent( "//div[@id='wikiPreview']/h2" ) );
+
+ // Verify level 2 headline displayed on mediawiki preview
+ $source = $this->getText( "//*[@id='Headline_text']" );
+ $correct = strstr( $source, "Headline text" );
+ $this->assertEquals( $correct, true );
+ }
+
+ // Add text with ignore wiki format and verify output the preview
+ public function testAddNoWikiFormat() {
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "//*[@id='mw-editbutton-nowiki']" );
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify ignore wiki format text displayed on mediawiki preview
+ $source = $this->getText( "//div[@id='wikiPreview']/p" );
+ $correct = strstr( $source, "Insert non-formatted text here" );
+ $this->assertEquals( $correct, true );
+ }
+
+ // Add signature and verify output in the preview
+ public function testAddUserSignature() {
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "mw-editbutton-signature" );
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify signature displayed on mediawiki preview
+ $source = $this->getText( "//*[@id='wikiPreview']/p/a" );
+ $username = $this->getText( "//*[@id='pt-userpage']/a" );
+ $correct = strstr( $source, $username );
+ $this->assertEquals( $correct, true );
+ }
+
+ // Add horizontal line and verify output in the preview
+ public function testHorizontalLine() {
+ $this->getExistingPage();
+ $this->clickEditLink();
+ $this->loadWikiEditor();
+ $this->clearWikiEditor();
+ $this->click( "mw-editbutton-hr" );
+
+ $this->clickShowPreviewBtn();
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify horizontal line displayed on mediawiki preview
+ $this->assertTrue( $this->isElementPresent( "//div[@id='wikiPreview']/hr" ) );
+ $this->deletePage( "new" );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*
*/
-
class AddNewPageTestCase extends SeleniumTestCase {
-
- // Verify adding a new page
- public function testAddNewPage() {
- $newPage = "new";
- $displayName = "New";
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->type( "searchInput", $newPage );
- $this->click( "searchGoButton" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify 'Search results' text available
- $source = $this->gettext( "firstHeading" );
- $correct = strstr( $source, "Search results" );
- $this->assertEquals( $correct, true);
-
- // Verify 'Create the page "<page name>" on this wiki' text available
- $source = $this->gettext( "//div[@id='bodyContent']/div[4]/p/b" );
- $correct = strstr ( $source, "Create the page \"New\" on this wiki!" );
- $this->assertEquals( $correct, true );
-
- $this->click( SeleniumTestConstants::LINK_START.$displayName );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->assertTrue($this->isElementPresent( SeleniumTestConstants::LINK_START."Create" ));
- $this->type( "wpTextbox1", "add new test page" );
- $this->click( SeleniumTestConstants::BUTTON_SAVE );
-
- // Verify new page added
- $source = $this->gettext( "firstHeading" );
- $correct = strstr ( $source, $displayName );
- $this->assertEquals( $correct, true );
- }
+ // Verify adding a new page
+ public function testAddNewPage() {
+ $newPage = "new";
+ $displayName = "New";
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->type( "searchInput", $newPage );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify 'Search results' text available
+ $source = $this->gettext( "firstHeading" );
+ $correct = strstr( $source, "Search results" );
+ $this->assertEquals( $correct, true );
+
+ // Verify 'Create the page "<page name>" on this wiki' text available
+ $source = $this->gettext( "//div[@id='bodyContent']/div[4]/p/b" );
+ $correct = strstr( $source, "Create the page \"New\" on this wiki!" );
+ $this->assertEquals( $correct, true );
+
+ $this->click( SeleniumTestConstants::LINK_START . $displayName );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->assertTrue( $this->isElementPresent( SeleniumTestConstants::LINK_START . "Create" ) );
+ $this->type( "wpTextbox1", "add new test page" );
+ $this->click( SeleniumTestConstants::BUTTON_SAVE );
+
+ // Verify new page added
+ $source = $this->gettext( "firstHeading" );
+ $correct = strstr( $source, $displayName );
+ $this->assertEquals( $correct, true );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
Class CreateAccountTestCase extends SeleniumTestCase {
-
- // Change these values before run the test
- private $userName = "yourname4000";
- private $password = "yourpass4000";
-
- // Verify 'Log in/create account' link existance in Main page.
- public function testMainPageLink() {
-
- $this->click( "link=Log out" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->open( $this->getUrl().'/index.php?title=Main_Page' );
- $this->assertTrue($this->isElementPresent( "link=Log in / create account" ));
- }
-
- // Verify 'Create an account' link existance in 'Log in / create account' Page.
- public function testCreateAccountPageLink() {
-
- $this->click( "link=Log out" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->open( $this->getUrl().'/index.php?title=Main_Page' );
-
- // click Log in / create account link to open Log in / create account' page
- $this->click( "link=Log in / create account" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertTrue($this->isElementPresent( "link=Create an account" ));
- }
-
- // Verify Create account
- public function testCreateAccount() {
-
- $this->click( "link=Log out" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->open( $this->getUrl().'/index.php?title=Main_Page' );
-
- $this->click( "link=Log in / create account" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->click( "link=Create an account" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify for blank user name
- $this->type( "wpName2", "" );
- $this->click( "wpCreateaccount" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "Login error\n You have not specified a valid user name.",
- $this->getText( "//div[@id='bodyContent']/div[4]" ));
-
- // Verify for invalid user name
- $this->type( "wpName2", "@" );
- $this->click("wpCreateaccount" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "Login error\n You have not specified a valid user name.",
- $this->getText( "//div[@id='bodyContent']/div[4]" ));
-
- // start of test for blank password
- $this->type( "wpName2", $this->userName);
- $this->type( "wpPassword2", "" );
- $this->click( "wpCreateaccount" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "Login error\n Passwords must be at least 1 character.",
- $this->getText("//div[@id='bodyContent']/div[4]" ));
-
- $this->type( "wpName2", $this->userName );
- $this->type( "wpPassword2", $this->password );
- $this->click( "wpCreateaccount" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "Login error\n The passwords you entered do not match.",
- $this->getText( "//div[@id='bodyContent']/div[4]" ));
-
- $this->type( "wpName2", $this->userName );
- $this->type( "wpPassword2", $this->password );
- $this->type( "wpRetype", $this->password );
- $this->click( "wpCreateaccount" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify successful account creation for valid combination of 'Username', 'Password', 'Retype password'
- $this->assertEquals( "Welcome, ".ucfirst( $this->userName )."!",
- $this->getText( "Welcome,_".ucfirst( $this->userName )."!" ));
- }
+ // Change these values before run the test
+ private $userName = "yourname4000";
+ private $password = "yourpass4000";
+
+ // Verify 'Log in/create account' link existance in Main page.
+ public function testMainPageLink() {
+
+ $this->click( "link=Log out" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->open( $this->getUrl() . '/index.php?title=Main_Page' );
+ $this->assertTrue( $this->isElementPresent( "link=Log in / create account" ) );
+ }
+
+ // Verify 'Create an account' link existance in 'Log in / create account' Page.
+ public function testCreateAccountPageLink() {
+
+ $this->click( "link=Log out" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->open( $this->getUrl() . '/index.php?title=Main_Page' );
+
+ // click Log in / create account link to open Log in / create account' page
+ $this->click( "link=Log in / create account" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertTrue( $this->isElementPresent( "link=Create an account" ) );
+ }
+
+ // Verify Create account
+ public function testCreateAccount() {
+
+ $this->click( "link=Log out" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->open( $this->getUrl() . '/index.php?title=Main_Page' );
+
+ $this->click( "link=Log in / create account" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->click( "link=Create an account" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify for blank user name
+ $this->type( "wpName2", "" );
+ $this->click( "wpCreateaccount" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "Login error\n You have not specified a valid user name.",
+ $this->getText( "//div[@id='bodyContent']/div[4]" ) );
+
+ // Verify for invalid user name
+ $this->type( "wpName2", "@" );
+ $this->click( "wpCreateaccount" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "Login error\n You have not specified a valid user name.",
+ $this->getText( "//div[@id='bodyContent']/div[4]" ) );
+
+ // start of test for blank password
+ $this->type( "wpName2", $this->userName );
+ $this->type( "wpPassword2", "" );
+ $this->click( "wpCreateaccount" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "Login error\n Passwords must be at least 1 character.",
+ $this->getText( "//div[@id='bodyContent']/div[4]" ) );
+
+ $this->type( "wpName2", $this->userName );
+ $this->type( "wpPassword2", $this->password );
+ $this->click( "wpCreateaccount" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "Login error\n The passwords you entered do not match.",
+ $this->getText( "//div[@id='bodyContent']/div[4]" ) );
+
+ $this->type( "wpName2", $this->userName );
+ $this->type( "wpPassword2", $this->password );
+ $this->type( "wpRetype", $this->password );
+ $this->click( "wpCreateaccount" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify successful account creation for valid combination of 'Username', 'Password', 'Retype password'
+ $this->assertEquals( "Welcome, " . ucfirst( $this->userName ) . "!",
+ $this->getText( "Welcome,_" . ucfirst( $this->userName ) . "!" ) );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*
*/
-
class DeletePageAdminTestCase extends SeleniumTestCase {
+ // Verify adding a new page
+ public function testDeletePage() {
- // Verify adding a new page
- public function testDeletePage() {
-
-
- $newPage = "new";
- $displayName = "New";
+ $newPage = "new";
+ $displayName = "New";
- $this->open( $this->getUrl().'/index.php?title=Main_Page' );
+ $this->open( $this->getUrl() . '/index.php?title=Main_Page' );
- $this->type( "searchInput", $newPage );
- $this->click( "searchGoButton" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->click( SeleniumTestConstants::LINK_START.$displayName );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->type( SeleniumTestConstants::TEXT_EDITOR, $newPage." text" );
- $this->click( SeleniumTestConstants::BUTTON_SAVE );
+ $this->type( "searchInput", $newPage );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( SeleniumTestConstants::LINK_START . $displayName );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, $newPage . " text" );
+ $this->click( SeleniumTestConstants::BUTTON_SAVE );
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->click( SeleniumTestConstants::LINK_START."Log out" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->click( SeleniumTestConstants::LINK_START."Log in / create account" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->click( SeleniumTestConstants::LINK_START . "Log out" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( SeleniumTestConstants::LINK_START . "Log in / create account" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->type( "wpName1", $this->selenium->getUser() );
- $this->type( "wpPassword1", $this->selenium->getPass() );
- $this->click( "wpLoginAttempt" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->type( "searchInput", "new" );
- $this->click( "searchGoButton");
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->type( "wpName1", $this->selenium->getUser() );
+ $this->type( "wpPassword1", $this->selenium->getPass() );
+ $this->click( "wpLoginAttempt" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->type( "searchInput", "new" );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- // Verify 'Delete' link displayed
- $source = $this->gettext( SeleniumTestConstants::LINK_START."Delete" );
- $correct = strstr ( $source, "Delete" );
- $this->assertEquals($correct, true );
+ // Verify 'Delete' link displayed
+ $source = $this->gettext( SeleniumTestConstants::LINK_START . "Delete" );
+ $correct = strstr( $source, "Delete" );
+ $this->assertEquals( $correct, true );
- $this->click( SeleniumTestConstants::LINK_START."Delete" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( SeleniumTestConstants::LINK_START . "Delete" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- // Verify 'Delete' button available
- $this->assertTrue($this->isElementPresent( "wpConfirmB" ));
+ // Verify 'Delete' button available
+ $this->assertTrue( $this->isElementPresent( "wpConfirmB" ) );
- $this->click( "wpConfirmB" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( "wpConfirmB" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- // Verify 'Action complete' text displayed
- $source = $this->gettext( "firstHeading" );
- $correct = strstr ( $source, "Action complete" );
- $this->assertEquals( $correct, true );
+ // Verify 'Action complete' text displayed
+ $source = $this->gettext( "firstHeading" );
+ $correct = strstr( $source, "Action complete" );
+ $this->assertEquals( $correct, true );
- // Verify '<Page Name> has been deleted. See deletion log for a record of recent deletions.' text displayed
- $source = $this->gettext( "//div[@id='bodyContent']/p[1]" );
- $correct = strstr ( $source, "\"New\" has been deleted. See deletion log for a record of recent deletions." );
- $this->assertEquals( $correct, true );
- }
+ // Verify '<Page Name> has been deleted. See deletion log for a record of recent deletions.' text displayed
+ $source = $this->gettext( "//div[@id='bodyContent']/p[1]" );
+ $correct = strstr( $source, "\"New\" has been deleted. See deletion log for a record of recent deletions." );
+ $this->assertEquals( $correct, true );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
class EmailPasswordTestCase extends SeleniumTestCase {
-
- // change user name for each and every test (with in 24 hours)
- private $userName = "test1";
-
- public function testEmailPasswordButton() {
-
- $this->click( SeleniumTestConstants::LINK_START."Log out" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->open( $this->getUrl().'/index.php?title=Main_Page' );
-
- // click Log in / create account link to open Log in / create account' page
- $this->click( SeleniumTestConstants::LINK_START."Log in / create account" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertTrue($this->isElementPresent( "wpMailmypassword" ));
- }
-
- // Verify Email password functionality
- public function testEmailPasswordMessages() {
-
- $this->click( SeleniumTestConstants::LINK_START."Log out" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->open( $this->getUrl().'/index.php?title=Main_Page' );
-
- // click Log in / create account link to open Log in / create account' page
- $this->click( SeleniumTestConstants::LINK_START."Log in / create account" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( "wpName1", "" );
- $this->click( "wpMailmypassword" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "Login error\n You have not specified a valid user name.",
- $this->getText("//div[@id='bodyContent']/div[4]"));
-
- $this->type( "wpName1", $this->userName );
- $this->click( "wpMailmypassword" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Can not run on localhost
- $this->assertEquals( "A new password has been sent to the e-mail address registered for ".ucfirst($this->userName).". Please log in again after you receive it.",
- $this->getText("//div[@id='bodyContent']/div[4]" ));
-
- $this->type( "wpName1", $this->userName );
- $this->click( "wpMailmypassword" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "Login error\n A password reminder has already been sent, within the last 24 hours. To prevent abuse, only one password reminder will be sent per 24 hours.",
- $this->getText( "//div[@id='bodyContent']/div[4]" ));
- }
+ // change user name for each and every test (with in 24 hours)
+ private $userName = "test1";
+
+ public function testEmailPasswordButton() {
+ $this->click( SeleniumTestConstants::LINK_START . "Log out" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->open( $this->getUrl() . '/index.php?title=Main_Page' );
+
+ // click Log in / create account link to open Log in / create account' page
+ $this->click( SeleniumTestConstants::LINK_START . "Log in / create account" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertTrue( $this->isElementPresent( "wpMailmypassword" ) );
+ }
+
+ // Verify Email password functionality
+ public function testEmailPasswordMessages() {
+ $this->click( SeleniumTestConstants::LINK_START . "Log out" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->open( $this->getUrl() . '/index.php?title=Main_Page' );
+
+ // click Log in / create account link to open Log in / create account' page
+ $this->click( SeleniumTestConstants::LINK_START . "Log in / create account" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( "wpName1", "" );
+ $this->click( "wpMailmypassword" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "Login error\n You have not specified a valid user name.",
+ $this->getText( "//div[@id='bodyContent']/div[4]" ) );
+
+ $this->type( "wpName1", $this->userName );
+ $this->click( "wpMailmypassword" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Can not run on localhost
+ $this->assertEquals( "A new password has been sent to the e-mail address registered for " . ucfirst( $this->userName ) . ". Please log in again after you receive it.",
+ $this->getText( "//div[@id='bodyContent']/div[4]" ) );
+
+ $this->type( "wpName1", $this->userName );
+ $this->click( "wpMailmypassword" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "Login error\n A password reminder has already been sent, within the last 24 hours. To prevent abuse, only one password reminder will be sent per 24 hours.",
+ $this->getText( "//div[@id='bodyContent']/div[4]" ) );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
class MediaWikiEditorConfig {
-
- public static function getSettings(&$includeFiles, &$globalConfigs) {
- $includes = array(
- //files that needed to be included would go here
- //commenting out because this does not exist
- //'tests/selenium/suites/MediaWikiCommonFunction.php'
- );
- $configs = array(
- 'wgPageLoadTime' => "600000"
- );
- $includeFiles = array_merge( $includeFiles, $includes );
- $globalConfigs = array_merge( $globalConfigs, $configs);
- return true;
- }
+ public static function getSettings( &$includeFiles, &$globalConfigs ) {
+ $includes = array(
+ //files that needed to be included would go here
+ //commenting out because this does not exist
+ //'tests/selenium/suites/MediaWikiCommonFunction.php'
+ );
+ $configs = array(
+ 'wgPageLoadTime' => "600000"
+ );
+ $includeFiles = array_merge( $includeFiles, $includes );
+ $globalConfigs = array_merge( $globalConfigs, $configs );
+ return true;
+ }
}
-
-
<?php
class MediaWikiEditorTestSuite extends SeleniumTestSuite {
- public function setUp() {
- $this->setLoginBeforeTests( true );
- parent::setUp();
- }
- public function addTests() {
- $testFiles = array(
- 'tests/selenium/suites/AddNewPageTestCase.php',
- 'tests/selenium/suites/AddContentToNewPageTestCase.php',
- 'tests/selenium/suites/PreviewPageTestCase.php',
- 'tests/selenium/suites/SavePageTestCase.php',
- );
- parent::addTestFiles( $testFiles );
- }
+ public function setUp() {
+ $this->setLoginBeforeTests( true );
+ parent::setUp();
+ }
+
+ public function addTests() {
+ $testFiles = array(
+ 'tests/selenium/suites/AddNewPageTestCase.php',
+ 'tests/selenium/suites/AddContentToNewPageTestCase.php',
+ 'tests/selenium/suites/PreviewPageTestCase.php',
+ 'tests/selenium/suites/SavePageTestCase.php',
+ );
+ parent::addTestFiles( $testFiles );
+ }
}
$this->setLoginBeforeTests( true );
parent::setUp();
}
+
public function addTests() {
$testFiles = array(
'tests/selenium/suites/MyContributionsTestCase.php',
$this->waitForPageToLoad( 30000 );
$this->assertSeleniumHTMLContains(
- '//h1[@class="firstHeading"]', "Wikipedia-logo-v2-de.png" );
+ '//h1[@class="firstHeading"]', "Wikipedia-logo-v2-de.png"
+ );
/*
$this->open( $this->getUrl() . '/index.php?title=Image:'
/**
* Stubs for now. We're going to start populating this test.
*/
-class MediawikiCoreSmokeTestSuite extends SeleniumTestSuite
-{
+class MediawikiCoreSmokeTestSuite extends SeleniumTestSuite {
public function setUp() {
$this->setLoginBeforeTests( false );
parent::setUp();
- }
+ }
+
public function addTests() {
$testFiles = array(
'tests/selenium/suites/MediawikiCoreSmokeTestCase.php'
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
class MovePageTestCase extends SeleniumTestCase {
-
- // Verify move(rename) wiki page
- public function testMovePage() {
-
- $newPage = "mypage99";
- $displayName = "Mypage99";
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->type( "searchInput", $newPage );
- $this->click( "searchGoButton" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->click( "link=".$displayName );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->type( SeleniumTestConstants::TEXT_EDITOR, $newPage." text" );
- $this->click( SeleniumTestConstants::BUTTON_SAVE );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify link 'Move' available
- $this->assertTrue($this->isElementPresent( "link=Move" ));
-
- $this->click( "link=Move" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify correct page name displayed under 'Move Page' field
- $this->assertEquals($displayName,
- $this->getText("//table[@id='mw-movepage-table']/tbody/tr[1]/td[2]/strong/a"));
- $movePageName = $this->getText( "//table[@id='mw-movepage-table']/tbody/tr[1]/td[2]/strong/a" );
-
- // Verify 'To new title' field has current page name as the default name
- $newTitle = $this->getValue( "wpNewTitle" );
- $correct = strstr( $movePageName , $newTitle );
- $this->assertEquals( $correct, true );
-
- $this->type( "wpNewTitle", $displayName );
- $this->click( "wpMove" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify warning message for the same source and destination titles
- $this->assertEquals( "Source and destination titles are the same; cannot move a page over itself.",
- $this->getText("//div[@id='bodyContent']/p[4]/strong" ));
-
- // Verify warning message for the blank title
- $this->type( "wpNewTitle", "" );
- $this->click( "wpMove" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify warning message for the blank title
- $this->assertEquals( "The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title. It may contain one or more characters which cannot be used in titles.",
- $this->getText( "//div[@id='bodyContent']/p[4]/strong" ));
-
- // Verify warning messages for the invalid titles
- $this->type( "wpNewTitle", "# < > [ ] | { }" );
- $this->click( "wpMove" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title. It may contain one or more characters which cannot be used in titles.",
- $this->getText( "//div[@id='bodyContent']/p[4]/strong" ));
-
- $this->type( "wpNewTitle", $displayName."move" );
- $this->click( "wpMove" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify move success message displayed correctly
- $this->assertEquals( "\"".$displayName."\" has been moved to \"".$displayName."move"."\"",
- $this->getText( "//div[@id='bodyContent']/p[1]/b" ));
-
- $this->type( "searchInput", $newPage."move" );
- $this->click( "searchGoButton" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify search using new page name
- $this->assertEquals( $displayName."move", $this->getText( "firstHeading" ));
-
- $this->type( "searchInput", $newPage );
- $this->click( "searchGoButton" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify search using old page name
- $redirectPageName = $this->getText( "//*[@id='contentSub']" );
- $this->assertEquals( "(Redirected from ".$displayName.")" , $redirectPageName );
-
- // newpage delete
- $this->deletePage( $newPage."move" );
- $this->deletePage( $newPage );
- }
+ // Verify move(rename) wiki page
+ public function testMovePage() {
+ $newPage = "mypage99";
+ $displayName = "Mypage99";
+
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->type( "searchInput", $newPage );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( "link=" . $displayName );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, $newPage . " text" );
+ $this->click( SeleniumTestConstants::BUTTON_SAVE );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify link 'Move' available
+ $this->assertTrue( $this->isElementPresent( "link=Move" ) );
+
+ $this->click( "link=Move" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify correct page name displayed under 'Move Page' field
+ $this->assertEquals( $displayName,
+ $this->getText( "//table[@id='mw-movepage-table']/tbody/tr[1]/td[2]/strong/a" ) );
+ $movePageName = $this->getText( "//table[@id='mw-movepage-table']/tbody/tr[1]/td[2]/strong/a" );
+
+ // Verify 'To new title' field has current page name as the default name
+ $newTitle = $this->getValue( "wpNewTitle" );
+ $correct = strstr( $movePageName, $newTitle );
+ $this->assertEquals( $correct, true );
+
+ $this->type( "wpNewTitle", $displayName );
+ $this->click( "wpMove" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify warning message for the same source and destination titles
+ $this->assertEquals( "Source and destination titles are the same; cannot move a page over itself.",
+ $this->getText( "//div[@id='bodyContent']/p[4]/strong" ) );
+
+ // Verify warning message for the blank title
+ $this->type( "wpNewTitle", "" );
+ $this->click( "wpMove" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify warning message for the blank title
+ $this->assertEquals( "The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title. It may contain one or more characters which cannot be used in titles.",
+ $this->getText( "//div[@id='bodyContent']/p[4]/strong" ) );
+
+ // Verify warning messages for the invalid titles
+ $this->type( "wpNewTitle", "# < > [ ] | { }" );
+ $this->click( "wpMove" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title. It may contain one or more characters which cannot be used in titles.",
+ $this->getText( "//div[@id='bodyContent']/p[4]/strong" ) );
+
+ $this->type( "wpNewTitle", $displayName . "move" );
+ $this->click( "wpMove" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify move success message displayed correctly
+ $this->assertEquals( "\"" . $displayName . "\" has been moved to \"" . $displayName . "move" . "\"",
+ $this->getText( "//div[@id='bodyContent']/p[1]/b" ) );
+
+ $this->type( "searchInput", $newPage . "move" );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify search using new page name
+ $this->assertEquals( $displayName . "move", $this->getText( "firstHeading" ) );
+
+ $this->type( "searchInput", $newPage );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify search using old page name
+ $redirectPageName = $this->getText( "//*[@id='contentSub']" );
+ $this->assertEquals( "(Redirected from " . $displayName . ")", $redirectPageName );
+
+ // newpage delete
+ $this->deletePage( $newPage . "move" );
+ $this->deletePage( $newPage );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
require_once dirname( __DIR__ ) . '/SeleniumTestConstants.php';
class MyContributionsTestCase extends SeleniumTestCase {
+ // Verify user contributions
+ public function testRecentChangesAvailability() {
+ $newPage = $this->createNewTestPage( "MyContributionsTest" );
- // Verify user contributions
- public function testRecentChangesAvailability() {
+ // Verify My contributions Link available
+ $this->assertTrue( $this->isElementPresent( "link=Contributions" ) );
- $newPage = $this->createNewTestPage( "MyContributionsTest" );
-
- // Verify My contributions Link available
- $this->assertTrue($this->isElementPresent( "link=Contributions" ));
-
- $this->click( "link=Contributions" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( "link=Contributions" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- // Verify recent page adding available on My Contributions list
- $this->assertEquals( $newPage, $this->getText( "link=".$newPage ));
+ // Verify recent page adding available on My Contributions list
+ $this->assertEquals( $newPage, $this->getText( "link=" . $newPage ) );
- $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, $newPage );
- $this->click( SeleniumTestConstants::BUTTON_SEARCH );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->click( SeleniumTestConstants::LINK_EDIT );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->type( SeleniumTestConstants::TEXT_EDITOR, $newPage . " text changed" );
- $this->click( SeleniumTestConstants::BUTTON_SAVE );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->click( "link=Contributions" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, $newPage );
+ $this->click( SeleniumTestConstants::BUTTON_SEARCH );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- // Verify recent page changes available on My Contributions
- $this->assertTrue( $this->isTextPresent( $newPage ) );
- }
+ $this->click( SeleniumTestConstants::LINK_EDIT );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, $newPage . " text changed" );
+ $this->click( SeleniumTestConstants::BUTTON_SAVE );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( "link=Contributions" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify recent page changes available on My Contributions
+ $this->assertTrue( $this->isTextPresent( $newPage ) );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
require_once dirname( __DIR__ ) . '/SeleniumTestConstants.php';
class MyWatchListTestCase extends SeleniumTestCase {
-
- // Verify user watchlist
- public function testMyWatchlist() {
-
- $pageName = $this->createNewTestPage( "MyWatchListTest", true );
- // Verify link 'My Watchlist' available
- $this->assertTrue( $this->isElementPresent( SeleniumTestConstants::LINK_START."Watchlist" ) );
-
- $this->click( SeleniumTestConstants::LINK_START."Watchlist" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify newly added page to the watchlist is available
- $this->assertEquals( $pageName, $this->getText( SeleniumTestConstants::LINK_START.$pageName ));
-
- $this->click( SeleniumTestConstants::LINK_START.$pageName );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->click( SeleniumTestConstants::LINK_EDIT );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->click( "wpWatchthis" );
- $this->click( SeleniumTestConstants::BUTTON_SAVE );
- $this->assertFalse( $this->isElementPresent( SeleniumTestConstants::LINK_START.$pageName ) );
- //todo watch using the dropdown menu
- }
+ // Verify user watchlist
+ public function testMyWatchlist() {
+ $pageName = $this->createNewTestPage( "MyWatchListTest", true );
+ // Verify link 'My Watchlist' available
+ $this->assertTrue( $this->isElementPresent( SeleniumTestConstants::LINK_START . "Watchlist" ) );
+
+ $this->click( SeleniumTestConstants::LINK_START . "Watchlist" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify newly added page to the watchlist is available
+ $this->assertEquals( $pageName, $this->getText( SeleniumTestConstants::LINK_START . $pageName ) );
+
+ $this->click( SeleniumTestConstants::LINK_START . $pageName );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( SeleniumTestConstants::LINK_EDIT );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( "wpWatchthis" );
+ $this->click( SeleniumTestConstants::BUTTON_SAVE );
+ $this->assertFalse( $this->isElementPresent( SeleniumTestConstants::LINK_START . $pageName ) );
+ //todo watch using the dropdown menu
+ }
}
<?php
class PageDeleteTestSuite extends SeleniumTestSuite {
- public function setUp() {
- $this->setLoginBeforeTests( true );
- parent::setUp();
- }
- public function addTests() {
- $testFiles = array(
- 'tests/selenium/suites/DeletePageAdminTestCase.php'
- );
- parent::addTestFiles( $testFiles );
- }
-
+ public function setUp() {
+ $this->setLoginBeforeTests( true );
+ parent::setUp();
+ }
+ public function addTests() {
+ $testFiles = array(
+ 'tests/selenium/suites/DeletePageAdminTestCase.php'
+ );
+ parent::addTestFiles( $testFiles );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
class PageSearchTestCase extends SeleniumTestCase {
-
- // Verify the functionality of the 'Go' button
- public function testPageSearchBtnGo() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "calcey qa" );
- $this->click( "searchGoButton" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify no page matched with the entered search text
- $source = $this->gettext( "//div[@id='bodyContent']/div[4]/p/b" );
- $correct = strstr ( $source, "Create the page \"Calcey qa\" on this wiki!" );
- $this->assertEquals( $correct, true );
-
- $this->click( "link=Calcey qa" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( SeleniumTestConstants::TEXT_EDITOR , "Calcey QA team" );
- $this->click( "wpSave" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- }
-
- // Verify the functionality of the 'Search' button
- public function testPageSearchBtnSearch() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "Calcey web" );
- $this->click( SeleniumTestConstants::BUTTON_SEARCH );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify no page is available as the search text
- $source = $this->gettext( "//div[@id='bodyContent']/div[4]/p[2]/b" );
- $correct = strstr ( $source, "Create the page \"Calcey web\" on this wiki!" );
- $this->assertEquals( $correct, true );
-
- $this->click( "link=Calcey web" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( SeleniumTestConstants::TEXT_EDITOR, "Calcey web team" );
- $this->click( SeleniumTestConstants::BUTTON_SAVE );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify saved page is opened when the exact page name is given
- $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "Calcey web" );
- $this->click( SeleniumTestConstants::BUTTON_SEARCH );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify exact page matched with the entered search text using 'Search' button
- $source = $this->getText( "//*[@id='bodyContent']/div[4]/p/b" );
- $correct = strstr( $source, "There is a page named \"Calcey web\" on this wiki." );
- $this->assertEquals( $correct, true );
-
- // Verify resutls available when partial page name is entered as the search text
- $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "Calcey" );
- $this->click( SeleniumTestConstants::BUTTON_SEARCH );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify text avaialble in the search result under the page titles
- if($this->isElementPresent( "Page_title_matches" )) {
- $textPageTitle = $this->getText( "//*[@id='bodyContent']/div[4]/ul[1]/li[1]/div[1]/a" );
- $this->assertContains( 'Calcey', $textPageTitle );
- }
-
- // Verify text avaialble in the search result under the page text
- if($this->isElementPresent( "Page_text_matches" )) {
- $textPageText = $this->getText( "//*[@id='bodyContent']/div[4]/ul[2]/li[2]/div[2]/span" );
- $this->assertContains( 'Calcey', $textPageText );
- }
- $this->deletePage("Calcey QA");
- $this->deletePage("Calcey web");
- }
+ // Verify the functionality of the 'Go' button
+ public function testPageSearchBtnGo() {
+
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "calcey qa" );
+ $this->click( "searchGoButton" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify no page matched with the entered search text
+ $source = $this->gettext( "//div[@id='bodyContent']/div[4]/p/b" );
+ $correct = strstr( $source, "Create the page \"Calcey qa\" on this wiki!" );
+ $this->assertEquals( $correct, true );
+
+ $this->click( "link=Calcey qa" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, "Calcey QA team" );
+ $this->click( "wpSave" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ }
+
+ // Verify the functionality of the 'Search' button
+ public function testPageSearchBtnSearch() {
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "Calcey web" );
+ $this->click( SeleniumTestConstants::BUTTON_SEARCH );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify no page is available as the search text
+ $source = $this->gettext( "//div[@id='bodyContent']/div[4]/p[2]/b" );
+ $correct = strstr( $source, "Create the page \"Calcey web\" on this wiki!" );
+ $this->assertEquals( $correct, true );
+
+ $this->click( "link=Calcey web" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, "Calcey web team" );
+ $this->click( SeleniumTestConstants::BUTTON_SAVE );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify saved page is opened when the exact page name is given
+ $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "Calcey web" );
+ $this->click( SeleniumTestConstants::BUTTON_SEARCH );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify exact page matched with the entered search text using 'Search' button
+ $source = $this->getText( "//*[@id='bodyContent']/div[4]/p/b" );
+ $correct = strstr( $source, "There is a page named \"Calcey web\" on this wiki." );
+ $this->assertEquals( $correct, true );
+
+ // Verify resutls available when partial page name is entered as the search text
+ $this->type( SeleniumTestConstants::INPUT_SEARCH_BOX, "Calcey" );
+ $this->click( SeleniumTestConstants::BUTTON_SEARCH );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify text avaialble in the search result under the page titles
+ if ( $this->isElementPresent( "Page_title_matches" ) ) {
+ $textPageTitle = $this->getText( "//*[@id='bodyContent']/div[4]/ul[1]/li[1]/div[1]/a" );
+ $this->assertContains( 'Calcey', $textPageTitle );
+ }
+
+ // Verify text avaialble in the search result under the page text
+ if ( $this->isElementPresent( "Page_text_matches" ) ) {
+ $textPageText = $this->getText( "//*[@id='bodyContent']/div[4]/ul[2]/li[2]/div[2]/span" );
+ $this->assertContains( 'Calcey', $textPageText );
+ }
+ $this->deletePage( "Calcey QA" );
+ $this->deletePage( "Calcey web" );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
class PreviewPageTestCase extends SeleniumTestCase {
+ // Verify adding a new page
+ public function testPreviewPage() {
+ $wikiText = "Adding this page to test the \n Preview button functionality";
+ $newPage = "Test Preview Page";
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->getNewPage( $newPage );
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, $wikiText . "" );
+ $this->assertTrue( $this->isElementPresent( "//*[@id='wpPreview']" ) );
- // Verify adding a new page
- public function testPreviewPage() {
- $wikiText = "Adding this page to test the \n Preview button functionality";
- $newPage = "Test Preview Page";
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->getNewPage( $newPage );
- $this->type( SeleniumTestConstants::TEXT_EDITOR, $wikiText."" );
- $this->assertTrue($this->isElementPresent( "//*[@id='wpPreview']" ));
+ $this->click( "wpPreview" );
- $this->click( "wpPreview" );
+ // Verify saved page available
+ $source = $this->gettext( "firstHeading" );
+ $correct = strstr( $source, "Test Preview Page" );
+ $this->assertEquals( $correct, true );
- // Verify saved page available
- $source = $this->gettext( "firstHeading" );
- $correct = strstr( $source, "Test Preview Page" );
- $this->assertEquals( $correct, true);
-
- // Verify page content previewed succesfully
- $contentOfPreviewPage = $this->getText( "//*[@id='content']" );
- $this->assertContains( $wikiText, $contentOfPreviewPage );
- }
+ // Verify page content previewed succesfully
+ $contentOfPreviewPage = $this->getText( "//*[@id='content']" );
+ $this->assertContains( $wikiText, $contentOfPreviewPage );
+ }
}
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
class SavePageTestCase extends SeleniumTestCase {
-
- // Verify adding a new page
- public function testSavePage() {
- $wikiText = "Adding this page to test the Save button functionality";
- $newPage = "Test Save Page";
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->getNewPage($newPage);
- $this->type( SeleniumTestConstants::TEXT_EDITOR, $wikiText );
-
- // verify 'Save' button available
- $this->assertTrue($this->isElementPresent( SeleniumTestConstants::BUTTON_SAVE ));
- $this->click( SeleniumTestConstants::BUTTON_SAVE );
-
- // Verify saved page available
- $source = $this->gettext( "firstHeading" );
- $correct = strstr( $source, "Test Save Page" );
-
- // Verify Saved page name displayed correctly
- $this->assertEquals( $correct, true );
-
- // Verify page content saved succesfully
- $contentOfSavedPage = $this->getText( "//*[@id='content']" );
- $this->assertContains( $wikiText, $contentOfSavedPage );
- $this->deletePage( $newPage );
- }
+ // Verify adding a new page
+ public function testSavePage() {
+ $wikiText = "Adding this page to test the Save button functionality";
+ $newPage = "Test Save Page";
+
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->getNewPage( $newPage );
+ $this->type( SeleniumTestConstants::TEXT_EDITOR, $wikiText );
+
+ // verify 'Save' button available
+ $this->assertTrue( $this->isElementPresent( SeleniumTestConstants::BUTTON_SAVE ) );
+ $this->click( SeleniumTestConstants::BUTTON_SAVE );
+
+ // Verify saved page available
+ $source = $this->gettext( "firstHeading" );
+ $correct = strstr( $source, "Test Save Page" );
+
+ // Verify Saved page name displayed correctly
+ $this->assertEquals( $correct, true );
+
+ // Verify page content saved succesfully
+ $contentOfSavedPage = $this->getText( "//*[@id='content']" );
+ $this->assertContains( $wikiText, $contentOfSavedPage );
+ $this->deletePage( $newPage );
+ }
}
<?php
class SimpleSeleniumConfig {
-
- public static function getSettings(&$includeFiles, &$globalConfigs, &$resourceFiles) {
+
+ public static function getSettings( &$includeFiles, &$globalConfigs, &$resourceFiles ) {
global $IP;
$includes = array(
//files that needed to be included would go here
);
$configs = array(
- 'wgDBprefix' => 'mw_',
- 'wgDBTableOptions' => 'ENGINE=InnoDB, DEFAULT CHARSET=binary',
- 'wgDBmysql5' => 'false',
- 'wgMainCacheType' => 'CACHE_NONE',
+ 'wgDBprefix' => 'mw_',
+ 'wgDBTableOptions' => 'ENGINE=InnoDB, DEFAULT CHARSET=binary',
+ 'wgDBmysql5' => 'false',
+ 'wgMainCacheType' => 'CACHE_NONE',
'wgParserCacheType' => 'CACHE_NONE',
- 'wgMemCachedServers'=> array(),
- 'wgLanguageCode' => 'en',
- 'wgSitename' => 'test_wiki',
- 'wgDefaultSkin' => 'chick'
+ 'wgMemCachedServers' => array(),
+ 'wgLanguageCode' => 'en',
+ 'wgSitename' => 'test_wiki',
+ 'wgDefaultSkin' => 'chick'
);
$resources = array(
'db' => "$IP/tests/selenium/data/SimpleSeleniumTestDB.sql",
'images' => "$IP/tests/selenium/data/SimpleSeleniumTestImages.zip"
);
-
+
$includeFiles = array_merge( $includeFiles, $includes );
- $globalConfigs = array_merge( $globalConfigs, $configs);
+ $globalConfigs = array_merge( $globalConfigs, $configs );
$resourceFiles = array_merge( $resourceFiles, $resources );
- return true;
+ return true;
}
-}
\ No newline at end of file
+}
public function testGlobalVariableForDefaultSkin() {
$this->open( $this->getUrl() . '/index.php' );
$bodyClass = $this->getAttribute( "//body/@class" );
- $this-> assertContains('skin-chick', $bodyClass, 'Chick skin not set');
+ $this->assertContains( 'skin-chick', $bodyClass, 'Chick skin not set' );
}
/**
public function testDatabaseResourceLoadedCorrectly() {
$this->open( $this->getUrl() . '/index.php/TestResources?action=purge' );
$testString = $this->gettext( "//body//*[@id='firstHeading']" );
- $this-> assertEquals('TestResources', $testString, 'Article that should be present in the test db was not found.');
+ $this->assertEquals( 'TestResources', $testString, 'Article that should be present in the test db was not found.' );
}
}
<?php
/**
- * Sample test suite.
+ * Sample test suite.
* Two ways to configure MW for these tests
* 1) If you are running multiple test suites, add the following in LocalSettings.php
* require_once("tests/selenium/SimpleSeleniumConfig.php");
* 2) Add the following to your Localsettings.php
* $wgDefaultSkin = 'chick';
*/
-class SimpleSeleniumTestSuite extends SeleniumTestSuite
-{
+class SimpleSeleniumTestSuite extends SeleniumTestSuite {
public function setUp() {
$this->setLoginBeforeTests( false );
parent::setUp();
- }
+ }
+
public function addTests() {
$testFiles = array(
'selenium/suites/SimpleSeleniumTestCase.php'
* @file
* @ingroup Testing
* Copyright (C) 2010 Nadeesha Weerasinghe <nadeesha@calcey.com>
- * http://www.calcey.com/
+ * http://www.calcey.com/
*
* 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
*/
class UserPreferencesTestCase extends SeleniumTestCase {
-
- // Verify user information
- public function testUserInfoDisplay() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->click( SeleniumTestConstants::LINK_START."My preferences" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify correct username displayed in User Preferences
- $this->assertEquals( $this->getText( "//li[@id='pt-userpage']/a" ),
- $this->getText( "//table[@id='mw-htmlform-info']/tbody/tr[1]/td[2]" ));
-
- // Verify existing Signature Displayed correctly
- $this->assertEquals( $this->selenium->getUser(),
- $this->getTable( "mw-htmlform-signature.0.1" ) );
- }
-
- // Verify change password
- public function testChangePassword() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->click( SeleniumTestConstants::LINK_START."My preferences" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->click( SeleniumTestConstants::LINK_START."Change password" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( "wpPassword", "12345" );
- $this->type( "wpNewPassword", "54321" );
- $this->type( "wpRetype", "54321" );
- $this->click( "//input[@value='Change password']" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->assertEquals( "Preferences", $this->getText( "firstHeading" ));
-
- $this->click( SeleniumTestConstants::LINK_START."Change password" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( "wpPassword", "54321" );
- $this->type( "wpNewPassword", "12345" );
- $this->type( "wpRetype", "12345" );
- $this->click( "//input[@value='Change password']" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->assertEquals( "Preferences", $this->getText( "firstHeading" ));
-
- $this->click( SeleniumTestConstants::LINK_START."Change password" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( "wpPassword", "54321" );
- $this->type( "wpNewPassword", "12345" );
- $this->type( "wpRetype", "12345" );
- $this->click( "//input[@value='Change password']" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- }
-
- // Verify successful preferences save
- public function testSuccessfullSave() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->click( SeleniumTestConstants::LINK_START."My preferences" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( "mw-input-realname", "Test User" );
- $this->click( "prefcontrol" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify "Your preferences have been saved." message
- $this->assertEquals( "Your preferences have been saved.",
- $this->getText( "//div[@id='bodyContent']/div[4]/strong/p" ));
- $this->type( "mw-input-realname", "" );
- $this->click( "prefcontrol" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- }
-
- // Verify change signature
- public function testChangeSignature() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->click( SeleniumTestConstants::LINK_START."My preferences" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->type( "mw-input-nickname", "TestSignature" );
- $this->click( "prefcontrol" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify change user signature
- $this->assertEquals( "TestSignature", $this->getText( SeleniumTestConstants::LINK_START."TestSignature" ));
- $this->type( "mw-input-nickname", "Test" );
- $this->click( "prefcontrol" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- }
-
- // Verify change date format
- public function testChangeDateFormatTimeZone() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
-
- $this->click( SeleniumTestConstants::LINK_START."My preferences" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
- $this->click( SeleniumTestConstants::LINK_START."Date and time" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- $this->click( "mw-input-date-dmy" );
- $this->select( "mw-input-timecorrection", "label=Asia/Colombo" );
- $this->click( "prefcontrol" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify Date format and time zome saved
- $this->assertEquals( "Your preferences have been saved.",
- $this->getText( "//div[@id='bodyContent']/div[4]/strong/p" ));
- }
-
- // Verify restoring all default settings
- public function testSetAllDefault() {
-
- $this->open( $this->getUrl() .
- '/index.php?title=Main_Page&action=edit' );
- $this->click( SeleniumTestConstants::LINK_START."My preferences" );
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify restoring all default settings
- $this->assertEquals( "Restore all default settings",
- $this->getText( SeleniumTestConstants::LINK_START."Restore all default settings" ));
-
- $this->click("//*[@id='preferences']/div/a");
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify 'This can not be undone' warning message displayed
- $this->assertTrue($this->isElementPresent("//input[@value='Restore all default settings']"));
-
- // Verify 'Restore all default settings' button available
- $this->assertEquals("You can use this page to reset your preferences to the site defaults. This cannot be undone.",
- $this->getText("//div[@id='bodyContent']/p"));
-
- $this->click("//input[@value='Restore all default settings']");
- $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
-
- // Verify preferences saved successfully
- $this->assertEquals("Your preferences have been saved.",
- $this->getText("//div[@id='bodyContent']/div[4]/strong/p"));
- }
+ // Verify user information
+ public function testUserInfoDisplay() {
+
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->click( SeleniumTestConstants::LINK_START . "My preferences" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify correct username displayed in User Preferences
+ $this->assertEquals( $this->getText( "//li[@id='pt-userpage']/a" ),
+ $this->getText( "//table[@id='mw-htmlform-info']/tbody/tr[1]/td[2]" ) );
+
+ // Verify existing Signature Displayed correctly
+ $this->assertEquals( $this->selenium->getUser(),
+ $this->getTable( "mw-htmlform-signature.0.1" ) );
+ }
+
+ // Verify change password
+ public function testChangePassword() {
+
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->click( SeleniumTestConstants::LINK_START . "My preferences" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->click( SeleniumTestConstants::LINK_START . "Change password" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( "wpPassword", "12345" );
+ $this->type( "wpNewPassword", "54321" );
+ $this->type( "wpRetype", "54321" );
+ $this->click( "//input[@value='Change password']" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->assertEquals( "Preferences", $this->getText( "firstHeading" ) );
+
+ $this->click( SeleniumTestConstants::LINK_START . "Change password" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( "wpPassword", "54321" );
+ $this->type( "wpNewPassword", "12345" );
+ $this->type( "wpRetype", "12345" );
+ $this->click( "//input[@value='Change password']" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->assertEquals( "Preferences", $this->getText( "firstHeading" ) );
+
+ $this->click( SeleniumTestConstants::LINK_START . "Change password" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( "wpPassword", "54321" );
+ $this->type( "wpNewPassword", "12345" );
+ $this->type( "wpRetype", "12345" );
+ $this->click( "//input[@value='Change password']" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ }
+
+ // Verify successful preferences save
+ public function testSuccessfullSave() {
+
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->click( SeleniumTestConstants::LINK_START . "My preferences" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( "mw-input-realname", "Test User" );
+ $this->click( "prefcontrol" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify "Your preferences have been saved." message
+ $this->assertEquals( "Your preferences have been saved.",
+ $this->getText( "//div[@id='bodyContent']/div[4]/strong/p" ) );
+ $this->type( "mw-input-realname", "" );
+ $this->click( "prefcontrol" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ }
+
+ // Verify change signature
+ public function testChangeSignature() {
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->click( SeleniumTestConstants::LINK_START . "My preferences" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->type( "mw-input-nickname", "TestSignature" );
+ $this->click( "prefcontrol" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify change user signature
+ $this->assertEquals( "TestSignature", $this->getText( SeleniumTestConstants::LINK_START . "TestSignature" ) );
+ $this->type( "mw-input-nickname", "Test" );
+ $this->click( "prefcontrol" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ }
+
+ // Verify change date format
+ public function testChangeDateFormatTimeZone() {
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+
+ $this->click( SeleniumTestConstants::LINK_START . "My preferences" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+ $this->click( SeleniumTestConstants::LINK_START . "Date and time" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ $this->click( "mw-input-date-dmy" );
+ $this->select( "mw-input-timecorrection", "label=Asia/Colombo" );
+ $this->click( "prefcontrol" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify Date format and time zome saved
+ $this->assertEquals( "Your preferences have been saved.",
+ $this->getText( "//div[@id='bodyContent']/div[4]/strong/p" ) );
+ }
+
+ // Verify restoring all default settings
+ public function testSetAllDefault() {
+ $this->open( $this->getUrl() .
+ '/index.php?title=Main_Page&action=edit' );
+ $this->click( SeleniumTestConstants::LINK_START . "My preferences" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify restoring all default settings
+ $this->assertEquals( "Restore all default settings",
+ $this->getText( SeleniumTestConstants::LINK_START . "Restore all default settings" ) );
+
+ $this->click( "//*[@id='preferences']/div/a" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify 'This can not be undone' warning message displayed
+ $this->assertTrue( $this->isElementPresent( "//input[@value='Restore all default settings']" ) );
+
+ // Verify 'Restore all default settings' button available
+ $this->assertEquals( "You can use this page to reset your preferences to the site defaults. This cannot be undone.",
+ $this->getText( "//div[@id='bodyContent']/p" ) );
+
+ $this->click( "//input[@value='Restore all default settings']" );
+ $this->waitForPageToLoad( SeleniumTestConstants::WIKI_TEST_WAIT_TIME );
+
+ // Verify preferences saved successfully
+ $this->assertEquals( "Your preferences have been saved.",
+ $this->getText( "//div[@id='bodyContent']/div[4]/strong/p" ) );
+ }
}
if ( $success == $total ) {
print $this->term->color( 32 ) . "ALL TESTS PASSED!";
} else {
- $failed = $total - $success ;
+ $failed = $total - $success;
print $this->term->color( 31 ) . "$failed tests failed!";
}
}
}
-class DbTestPreviewer extends TestRecorder {
- protected $lb; // /< Database load balancer
- protected $db; // /< Database connection to the main DB
- protected $curRun; // /< run ID number for the current run
+class DbTestPreviewer extends TestRecorder {
+ protected $lb; // /< Database load balancer
+ protected $db; // /< Database connection to the main DB
+ protected $curRun; // /< run ID number for the current run
protected $prevRun; // /< run ID number for the previous run, if any
protected $results; // /< Result array
function start() {
parent::start();
- if ( ! $this->db->tableExists( 'testrun', __METHOD__ )
- || ! $this->db->tableExists( 'testitem', __METHOD__ ) )
- {
+ if ( !$this->db->tableExists( 'testrun', __METHOD__ )
+ || !$this->db->tableExists( 'testitem', __METHOD__ )
+ ) {
print "WARNING> `testrun` table not found in database.\n";
$this->prevRun = false;
} else {
foreach ( $res as $row ) {
if ( !$this->parent->regex
- || preg_match( "/{$this->parent->regex}/i", $row->ti_name ) )
- {
+ || preg_match( "/{$this->parent->regex}/i", $row->ti_name )
+ ) {
$prevResults[$row->ti_name] = $row->ti_success;
}
}
private function getTestStatusInfo( $testname, $after ) {
// If we're looking at a test that has just been removed, then say when it first appeared.
if ( $after == 'n' ) {
- $changedRun = $this->db->selectField ( 'testitem',
+ $changedRun = $this->db->selectField( 'testitem',
'MIN(ti_run)',
array( 'ti_name' => $testname ),
__METHOD__ );
- $appear = $this->db->selectRow ( 'testrun',
+ $appear = $this->db->selectRow( 'testrun',
array( 'tr_date', 'tr_mw_version' ),
array( 'tr_id' => $changedRun ),
__METHOD__ );
return "First recorded appearance: "
- . date( "d-M-Y H:i:s", strtotime ( $appear->tr_date ) )
- . ", " . $appear->tr_mw_version;
+ . date( "d-M-Y H:i:s", strtotime( $appear->tr_date ) )
+ . ", " . $appear->tr_mw_version;
}
// Otherwise, this test has previous recorded results.
// See when this test last had a different result to what we're seeing now.
$conds = array(
- 'ti_name' => $testname,
+ 'ti_name' => $testname,
'ti_success' => ( $after == 'f' ? "1" : "0" ) );
if ( $this->curRun ) {
- $conds[] = "ti_run != " . $this->db->addQuotes ( $this->curRun );
+ $conds[] = "ti_run != " . $this->db->addQuotes( $this->curRun );
}
- $changedRun = $this->db->selectField ( 'testitem', 'MAX(ti_run)', $conds, __METHOD__ );
+ $changedRun = $this->db->selectField( 'testitem', 'MAX(ti_run)', $conds, __METHOD__ );
// If no record of ever having had a different result.
- if ( is_null ( $changedRun ) ) {
+ if ( is_null( $changedRun ) ) {
if ( $after == "f" ) {
return "Has never passed";
} else {
// Otherwise, we're looking at a test whose status has changed.
// (i.e. it used to work, but now doesn't; or used to fail, but is now fixed.)
// In this situation, give as much info as we can as to when it changed status.
- $pre = $this->db->selectRow ( 'testrun',
+ $pre = $this->db->selectRow( 'testrun',
array( 'tr_date', 'tr_mw_version' ),
array( 'tr_id' => $changedRun ),
__METHOD__ );
- $post = $this->db->selectRow ( 'testrun',
+ $post = $this->db->selectRow( 'testrun',
array( 'tr_date', 'tr_mw_version' ),
- array( "tr_id > " . $this->db->addQuotes ( $changedRun ) ),
+ array( "tr_id > " . $this->db->addQuotes( $changedRun ) ),
__METHOD__,
array( "LIMIT" => 1, "ORDER BY" => 'tr_id' )
);
if ( $post ) {
- $postDate = date( "d-M-Y H:i:s", strtotime ( $post->tr_date ) ) . ", {$post->tr_mw_version}";
+ $postDate = date( "d-M-Y H:i:s", strtotime( $post->tr_date ) ) . ", {$post->tr_mw_version}";
} else {
$postDate = 'now';
}
return ( $after == "f" ? "Introduced" : "Fixed" ) . " between "
- . date( "d-M-Y H:i:s", strtotime ( $pre->tr_date ) ) . ", " . $pre->tr_mw_version
- . " and $postDate";
-
+ . date( "d-M-Y H:i:s", strtotime( $pre->tr_date ) ) . ", " . $pre->tr_mw_version
+ . " and $postDate";
}
/**
$this->lb->closeAll();
parent::end();
}
-
}
-class DbTestRecorder extends DbTestPreviewer {
+class DbTestRecorder extends DbTestPreviewer {
var $version;
/**
function start() {
$this->db->begin( __METHOD__ );
- if ( ! $this->db->tableExists( 'testrun' )
- || ! $this->db->tableExists( 'testitem' ) )
- {
+ if ( !$this->db->tableExists( 'testrun' )
+ || !$this->db->tableExists( 'testitem' )
+ ) {
print "WARNING> `testrun` table not found in database. Trying to create table.\n";
$this->db->sourceFile( $this->db->patchPath( 'patch-testrun.sql' ) );
echo "OK, resuming.\n";
$this->db->insert( 'testrun',
array(
- 'tr_date' => $this->db->timestamp(),
- 'tr_mw_version' => $this->version,
+ 'tr_date' => $this->db->timestamp(),
+ 'tr_mw_version' => $this->version,
'tr_php_version' => phpversion(),
- 'tr_db_version' => $this->db->getServerVersion(),
- 'tr_uname' => php_uname()
+ 'tr_db_version' => $this->db->getServerVersion(),
+ 'tr_uname' => php_uname()
),
__METHOD__ );
- if ( $this->db->getType() === 'postgres' ) {
- $this->curRun = $this->db->currentSequenceValue( 'testrun_id_seq' );
- } else {
- $this->curRun = $this->db->insertId();
- }
+ if ( $this->db->getType() === 'postgres' ) {
+ $this->curRun = $this->db->currentSequenceValue( 'testrun_id_seq' );
+ } else {
+ $this->curRun = $this->db->insertId();
+ }
}
/**
$this->db->insert( 'testitem',
array(
- 'ti_run' => $this->curRun,
- 'ti_name' => $test,
+ 'ti_run' => $this->curRun,
+ 'ti_name' => $test,
'ti_success' => $result ? 1 : 0,
),
__METHOD__ );
private $parserTest; /* An instance of ParserTest (parserTests.php) or MediaWikiParserTest (phpunit) */
private $index = 0;
private $test;
- private $section = null; /** String|null: current test section being analyzed */
+ private $section = null;
+ /** String|null: current test section being analyzed */
private $sectionData = array();
private $lineNum;
private $eof;
$this->section = strtolower( $matches[1] );
if ( $this->section == 'endarticle' ) {
- $this->checkSection( 'text' );
+ $this->checkSection( 'text' );
$this->checkSection( 'article' );
$this->parserTest->addArticle( ParserTest::chomp( $this->sectionData['article'] ), $this->sectionData['text'], $this->lineNum );
}
if ( $this->section == 'end' ) {
- $this->checkSection( 'test' );
- $this->checkSection( 'input' );
+ $this->checkSection( 'test' );
+ $this->checkSection( 'input' );
$this->checkSection( 'result' );
if ( !isset( $this->sectionData['options'] ) ) {
}
if ( ( ( preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) && !$this->parserTest->runDisabled )
- || !preg_match( "/" . $this->parserTest->regex . "/i", $this->sectionData['test'] ) ) ) {
+ || !preg_match( "/" . $this->parserTest->regex . "/i", $this->sectionData['test'] ) )
+ ) {
# disabled test
$this->clearSection();
# We are really going to run the test, run pending hooks and hooks function
wfDebug( __METHOD__ . " unleashing delayed test for: {$this->sectionData['test']}" );
$hooksResult = $delayedParserTest->unleash( $this->parserTest );
- if( !$hooksResult ) {
+ if ( !$hooksResult ) {
# Some hook reported an issue. Abort.
return false;
}
$this->test = array(
- 'test' => ParserTest::chomp( $this->sectionData['test'] ),
- 'input' => ParserTest::chomp( $this->sectionData['input'] ),
- 'result' => ParserTest::chomp( $this->sectionData['result'] ),
+ 'test' => ParserTest::chomp( $this->sectionData['test'] ),
+ 'input' => ParserTest::chomp( $this->sectionData['input'] ),
+ 'result' => ParserTest::chomp( $this->sectionData['result'] ),
'options' => ParserTest::chomp( $this->sectionData['options'] ),
- 'config' => ParserTest::chomp( $this->sectionData['config'] ),
+ 'config' => ParserTest::chomp( $this->sectionData['config'] ),
);
return true;
* @param $token String: expected token that should have been mentionned before closing this section
*/
private function checkSection( $token ) {
- if( is_null( $this->section ) ) {
+ if ( is_null( $this->section ) ) {
throw new MWException( __METHOD__ . " can not verify a null section!\n" );
}
- if( !isset($this->sectionData[$token]) ) {
+ if ( !isset( $this->sectionData[$token] ) ) {
throw new MWException( sprintf(
"'%s' without '%s' at line %s of %s\n",
$this->section,
$token,
$this->lineNum,
$this->file
- ));
+ ) );
}
return true;
}
* Call to this will erase any hooks function that were pending.
*/
public function reset() {
- $this->hooks = array();
+ $this->hooks = array();
$this->fnHooks = array();
}
* Should be the case if we found the parserTest is not disabled
*/
public function unleash( &$parserTest ) {
- if( !($parserTest instanceof ParserTest || $parserTest instanceof NewParserTest
- ) ) {
+ if ( !( $parserTest instanceof ParserTest || $parserTest instanceof NewParserTest ) ) {
throw new MWException( __METHOD__ . " must be passed an instance of ParserTest or NewParserTest classes\n" );
}
# Trigger delayed hooks. Any failure will make us abort
- foreach( $this->hooks as $hook ) {
+ foreach ( $this->hooks as $hook ) {
$ret = $parserTest->requireHook( $hook );
- if( !$ret ) {
+ if ( !$ret ) {
return false;
}
}
# Trigger delayed function hooks. Any failure will make us abort
- foreach( $this->fnHooks as $fnHook ) {
+ foreach ( $this->fnHooks as $fnHook ) {
$ret = $parserTest->requireFunctionHook( $fnHook );
- if( !$ret ) {
+ if ( !$ret ) {
return false;
}
}
public function requireHook( $hook ) {
$this->hooks[] = $hook;
}
+
/**
* Similar to ParserTest object but does not run anything
* Use unleash() to really execute the hook function
$response->header( 'Location: ' .
wfExpandUrl( $img->getThumbUrl( $thumbName ), PROTO_CURRENT ) );
$response->header( 'Expires: ' .
- gmdate( 'D, d M Y H:i:s', time() + 7*86400 ) . ' GMT' );
+ gmdate( 'D, d M Y H:i:s', time() + 7 * 86400 ) . ' GMT' );
if ( $wgVaryOnXFP ) {
$varyHeader[] = 'X-Forwarded-Proto';
}
$hostname = htmlspecialchars( wfHostname() );
$debug = "<!-- $url -->\n<!-- $hostname -->\n";
} else {
- $debug = "";
+ $debug = '';
}
echo <<<EOT
<html><head><title>Error generating thumbnail</title></head>