images/[0-9a-f]
images/archive
images/deleted
+images/lockdir
images/temp
images/thumb
## Extension:EasyTimeline
* (bug 38904) prop=revisions&rvstart=... no longer blows up when continuing.
* (bug 39032) ApiQuery generates help in constructor.
* (bug 11142) Improve file extension blacklist error reporting in API upload.
-* (bug 39665) Cache AllowedGenerator array so it doesn't autoload all query classes
- on every request.
+* (bug 39665) List of query generators is now not built using reflection, instead it is
+ defined in code.
=== Languages updated in 1.20 ===
* (bug 34876) jquery.makeCollapsible has been improved in performance.
* Added ContentHandler facility to allow extensions to support other content than wikitext.
See docs/contenthandler.txt for details.
-* $wgResponsiveImages is added to support images on high-DPI mobile and desktop displays.
+* New feature was developed for showing high-DPI thumbnails for high-DPI mobile
+ and desktop displays (configurable with $wgResponsiveImages).
+* Added new backend to represent and store information about sites and site
+ specific configuration.
+* jQuery UI upgraded from 1.8.23 to 1.8.24.
+* Added separate fa_sha1 field to filearchive table. This allows sha1
+ searches with the api in miser mode for deleted files.
=== Bug fixes in 1.21 ===
* (bug 40353) SpecialDoubleRedirect should support interwiki redirects.
recentchanges table.
* (bug 32951) Do not register internal externals with absolute protocol,
when server has relative protocol.
+* (bug 39005) When purging proxies listed in $wgSquidServers using HTTP PURGE
+ method requests, we now send a Host header by default, for Varnish
+ compatibility. This also works with Squid in reverse-proxy mode. If you wish
+ to support Squid configured in forward-proxy mode, set
+ $wgSquidPurgeUseHostHeader to false.
=== API changes in 1.21 ===
* prop=revisions can now report the contentmodel and contentformat, see docs/contenthandler.txt
* action=edit and action=parse now support contentmodel and contentformat parameters to control the interpretation of
page content; See docs/contenthandler.txt for details.
* (bug 35693) ApiQueryImageInfo now suppresses errors when unserializing metadata.
+* (bug 40111) Disable minor edit for page/section creation by API
=== Languages updated in 1.21 ===
appropriate serialization and deserialization is handled by the Revision class.
Each revision's content model and serialization format is stored in the revision table (resp. in the archive table, if
-the revision was deleted). The page's (current) content model (that is, the conent model of the latest revision) is also
+the revision was deleted). The page's (current) content model (that is, the content model of the latest revision) is also
stored in the page table.
Note however that the content model and format is only stored if it differs from the page's default, as determined by
* @return string Return the text of this revision
*/
public function getContent() {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
$content = $this->getContentObject();
return ContentHandler::getContentText( $content );
}
* @deprecated in 1.21, use WikiPage::getContent() instead
*/
function fetchContent() { #BC cruft!
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
if ( $this->mContentLoaded && $this->mContent ) {
return $this->mContent;
'AbstractContent' => 'includes/content/AbstractContent.php',
'ContentHandler' => 'includes/content/ContentHandler.php',
'Content' => 'includes/content/Content.php',
- 'CssContentHandler' => 'includes/content/ContentHandler.php',
+ 'CssContentHandler' => 'includes/content/CssContentHandler.php',
'CssContent' => 'includes/content/CssContent.php',
- 'JavaScriptContentHandler' => 'includes/content/ContentHandler.php',
+ 'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
'MessageContent' => 'includes/content/MessageContent.php',
- 'TextContentHandler' => 'includes/content/ContentHandler.php',
+ 'TextContentHandler' => 'includes/content/TextContentHandler.php',
'TextContent' => 'includes/content/TextContent.php',
- 'WikitextContentHandler' => 'includes/ContentHandler.php',
+ 'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
'WikitextContent' => 'includes/content/WikitextContent.php',
# includes/actions
'ApiQueryLangLinks' => 'includes/api/ApiQueryLangLinks.php',
'ApiQueryLinks' => 'includes/api/ApiQueryLinks.php',
'ApiQueryLogEvents' => 'includes/api/ApiQueryLogEvents.php',
+ 'ApiQueryORM' => 'includes/api/ApiQueryORM.php',
'ApiQueryPageProps' => 'includes/api/ApiQueryPageProps.php',
'ApiQueryProtectedTitles' => 'includes/api/ApiQueryProtectedTitles.php',
'ApiQueryQueryPage' => 'includes/api/ApiQueryQueryPage.php',
'EmaillingJob' => 'includes/job/EmaillingJob.php',
'EnotifNotifyJob' => 'includes/job/EnotifNotifyJob.php',
'Job' => 'includes/job/Job.php',
+ 'JobQueue' => 'includes/job/JobQueue.php',
+ 'JobQueueDB' => 'includes/job/JobQueueDB.php',
+ 'JobQueueGroup' => 'includes/job/JobQueueGroup.php',
'RefreshLinksJob' => 'includes/job/RefreshLinksJob.php',
'RefreshLinksJob2' => 'includes/job/RefreshLinksJob.php',
'UploadFromUrlJob' => 'includes/job/UploadFromUrlJob.php',
'SqliteSearchResultSet' => 'includes/search/SearchSqlite.php',
'SqlSearchResultSet' => 'includes/search/SearchEngine.php',
+ # includes/site
+ 'MediaWikiSite' => 'includes/site/MediaWikiSite.php',
+ 'Site' => 'includes/site/Site.php',
+ 'SiteArray' => 'includes/site/SiteArray.php',
+ 'SiteList' => 'includes/site/SiteList.php',
+ 'SiteObject' => 'includes/site/SiteObject.php',
+ 'Sites' => 'includes/site/Sites.php',
+ 'SitesTable' => 'includes/site/SitesTable.php',
+
# includes/specials
'ActiveUsersPager' => 'includes/specials/SpecialActiveusers.php',
'AllmessagesTablePager' => 'includes/specials/SpecialAllmessages.php',
'FixExtLinksProtocolRelative' => 'maintenance/fixExtLinksProtocolRelative.php',
'PopulateCategory' => 'maintenance/populateCategory.php',
'PopulateImageSha1' => 'maintenance/populateImageSha1.php',
+ 'PopulateFilearchiveSha1' => 'maintenance/populateFilearchiveSha1.php',
'PopulateLogSearch' => 'maintenance/populateLogSearch.php',
'PopulateLogUsertext' => 'maintenance/populateLogUsertext.php',
'PopulateParentId' => 'maintenance/populateParentId.php',
'DummyContentForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php',
'JavascriptContentTest' => 'tests/phpunit/includes/JavascriptContentTest.php',
'RevisionStorageTest' => 'tests/phpunit/includes/RevisionStorageTest.php',
+ 'TextContentTest' => 'tests/phpunit/includes/TextContentTest.php',
'WikiPageTest' => 'tests/phpunit/includes/WikiPageTest.php',
- 'WikitextContentTest' => 'tests/phpunit/includes/WikitextContentTest.php',
# tests/phpunit/includes
'GenericArrayObjectTest' => 'tests/phpunit/includes/libs/GenericArrayObjectTest.php',
# tests/phpunit/includes/db
'ORMRowTest' => 'tests/phpunit/includes/db/ORMRowTest.php',
+ # tests/phpunit/includes/site
+ 'SiteObjectTest' => 'tests/phpunit/includes/site/SiteObjectTest.php',
+ 'TestSites' => 'tests/phpunit/includes/site/TestSites.php',
+
# tests/parser
'ParserTest' => 'tests/parser/parserTest.inc',
'ParserTestParserHook' => 'tests/parser/parserTestsParserHook.php',
protected function read( $length, $pos ) {
if ( fseek( $this->handle, $pos ) == -1 ) {
// This can easily happen if the internal pointers are incorrect
- throw new MWException(
+ throw new MWException(
'Seek failed, file "' . $this->fileName . '" may be corrupted.' );
}
protected function unpack31( $s ) {
$data = unpack( 'V', $s );
if ( $data[1] > 0x7fffffff ) {
- throw new MWException(
+ throw new MWException(
'Error in CDB file "' . $this->fileName . '", integer too big.' );
}
return $data[1];
/**
* Clean up the temp file and throw an exception
- *
+ *
* @param $msg string
* @throws MWException
*/
/**
* Unified CJK blocks.
*
- * The same definition of a CJK block must be used for both Collation and
- * generateCollationData.php. These blocks are omitted from the first
- * letter data, as an optimisation measure and because the default UCA table
- * is pretty useless for sorting Chinese text anyway. Japanese and Korean
+ * The same definition of a CJK block must be used for both Collation and
+ * generateCollationData.php. These blocks are omitted from the first
+ * letter data, as an optimisation measure and because the default UCA table
+ * is pretty useless for sorting Chinese text anyway. Japanese and Korean
* blocks are not included here, because they are smaller and more useful.
*/
static $cjkBlocks = array(
function __construct( $locale ) {
if ( !extension_loaded( 'intl' ) ) {
- throw new MWException( 'An ICU collation was requested, ' .
+ throw new MWException( 'An ICU collation was requested, ' .
'but the intl extension is not available.' );
}
$this->locale = $locale;
// Check for CJK
$firstChar = mb_substr( $string, 0, 1, 'UTF-8' );
- if ( ord( $firstChar ) > 0x7f
- && self::isCjk( utf8ToCodepoint( $firstChar ) ) )
+ if ( ord( $firstChar ) > 0x7f
+ && self::isCjk( utf8ToCodepoint( $firstChar ) ) )
{
return $firstChar;
}
// Sort the letters.
//
// It's impossible to have the precompiled data file properly sorted,
- // because the sort order changes depending on ICU version. If the
- // array is not properly sorted, the binary search will return random
- // results.
+ // because the sort order changes depending on ICU version. If the
+ // array is not properly sorted, the binary search will return random
+ // results.
//
// We also take this opportunity to remove primary collisions.
$letterMap = array();
}
/**
- * Do a binary search, and return the index of the largest item that sorts
+ * Do a binary search, and return the index of the largest item that sorts
* less than or equal to the target value.
*
* @param $valueCallback array A function to call to get the value with
// We hash the random state with more salt to avoid the state from leaking
// out and being used to predict the /randomness/ that follows.
if ( strlen( $buffer ) < $bytes ) {
- wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
+ wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
}
while ( strlen( $buffer ) < $bytes ) {
wfProfileIn( __METHOD__ . '-fallback' );
CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler', // the usual case
CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler', // dumb version, no syntax highlighting
CONTENT_MODEL_CSS => 'CssContentHandler', // dumb version, no syntax highlighting
+ CONTENT_MODEL_TEXT => 'TextContentHandler', // plain text, for use by extensions etc
);
/**
/** Maximum number of titles to purge in any one client operation */
$wgMaxSquidPurgeTitles = 400;
+/**
+ * Whether to use a Host header in purge requests sent to the proxy servers
+ * configured in $wgSquidServers. Set this to false to support Squid
+ * configured in forward-proxy mode.
+ *
+ * If this is set to true, a Host header will be sent, and only the path
+ * component of the URL will appear on the request line, as if the request
+ * were a non-proxy HTTP 1.1 request. Varnish only supports this style of
+ * request. Squid supports this style of request only if reverse-proxy mode
+ * (http_port ... accel) is enabled.
+ *
+ * If this is set to false, no Host header will be sent, and the absolute URL
+ * will be sent in the request line, as is the standard for an HTTP proxy
+ * request in both HTTP 1.0 and 1.1. This style of request is not supported
+ * by Varnish, but is supported by Squid in either configuration (forward or
+ * reverse).
+ *
+ * @since 1.21
+ */
+$wgSquidPurgeUseHostHeader = true;
+
/**
* Routing configuration for HTCP multicast purging. Add elements here to
* enable HTCP and determine which purges are sent where. If set to an empty
*/
$wgJobTypesExcludedFromDefaultQueue = array();
+/**
+ * Map of job types to configuration arrays.
+ * These settings should be global to all wikis.
+ */
+$wgJobTypeConf = array(
+ 'default' => array( 'class' => 'JobQueueDB' ),
+);
+
/**
* Additional functions to be performed with updateSpecialPages.
* Expensive Querypages are already updated.
$wgAPIMetaModules = array();
$wgAPIPropModules = array();
$wgAPIListModules = array();
+$wgAPIGeneratorModules = array();
/**
* Maximum amount of rows to scan in a DB query in the API
*/
$wgRequirePasswordforEmailChange = true;
+/**
+ * Register handlers for specific types of sites.
+ *
+ * @since 1.20
+ */
+$wgSiteTypes = array();
+$wgSiteTypes['mediawiki'] = 'MediaWikiSite';
+
/**
* For really cool vim folding this needs to be at the end:
* vim: foldmarker=@{,@} foldmethod=marker
/**@{
* RecentChange type identifiers
*/
-define( 'RC_EDIT', 0);
-define( 'RC_NEW', 1);
-define( 'RC_MOVE', 2); // obsolete
-define( 'RC_LOG', 3);
-define( 'RC_MOVE_OVER_REDIRECT', 4); // obsolete
+define( 'RC_EDIT', 0 );
+define( 'RC_NEW', 1 );
+define( 'RC_MOVE', 2 ); // obsolete
+define( 'RC_LOG', 3 );
+define( 'RC_MOVE_OVER_REDIRECT', 4 ); // obsolete
+define( 'RC_EXTERNAL', 5 );
/**@}*/
/**@{
$this->isCssSubpage = $this->mTitle->isCssSubpage();
$this->isJsSubpage = $this->mTitle->isJsSubpage();
$this->isWrongCaseCssJsPage = $this->isWrongCaseCssJsPage();
- $this->isNew = !$this->mTitle->exists() || $this->section == 'new';
# Show applicable editing introductions
if ( $this->formtype == 'initial' || $this->firsttime ) {
* @param $request WebRequest
*/
function importFormData( &$request ) {
- global $wgLang, $wgUser;
+ global $wgContLang, $wgUser;
wfProfileIn( __METHOD__ );
# Section edit can come from either the form or a link
$this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
+ $this->isNew = !$this->mTitle->exists() || $this->section == 'new';
if ( $request->wasPosted() ) {
# These fields need to be checked for encoding.
}
# Truncate for whole multibyte characters
- $this->summary = $wgLang->truncate( $request->getText( 'wpSummary' ), 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
# currently doing double duty as both edit summary and section title. Right now this
# is just to allow API edits to work around this limitation, but this should be
# incorporated into the actual edit form when EditPage is rewritten (Bugs 18654, 26312).
- $this->sectiontitle = $wgLang->truncate( $request->getText( 'wpSectionTitle' ), 255 );
+ $this->sectiontitle = $wgContLang->truncate( $request->getText( 'wpSectionTitle' ), 255 );
$this->sectiontitle = preg_replace( '/^\s*=+\s*(.*?)\s*=+\s*$/', '$1', $this->sectiontitle );
$this->edittime = $request->getVal( 'wpEdittime' );
$this->edittime = $this->mArticle->getTimestamp();
$content = $this->getContentObject( false ); #TODO: track content object?!
+ if ( $content === false ) {
+ return false;
+ }
$this->textbox1 = $this->toEditText( $content );
// activate checkboxes if user wants them to be always active
* @param $def_text string
* @return mixed string on success, $def_text for invalid sections
* @private
- * @deprecated since 1.21
+ * @deprecated since 1.21, get WikiPage::getContent() instead.
*/
function getContent( $def_text = false ) {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
if ( $def_text !== null && $def_text !== false && $def_text !== '' ) {
$def_content = $this->toEditContent( $def_text );
* Use this method before edit() to preload some text into the edit box
*
* @param $text string
- * @deprecated since 1.21
+ * @deprecated since 1.21, use setPreloadedContent() instead.
*/
public function setPreloadedText( $text ) {
- wfDeprecated( __METHOD__, "1.21" );
+ ContentHandler::deprecated( __METHOD__, "1.21" );
$content = $this->toEditContent( $text );
* @deprecated since 1.21, use getPreloadedContent() instead
*/
protected function getPreloadedText( $preload ) {
- wfDeprecated( __METHOD__, "1.21" );
+ ContentHandler::deprecated( __METHOD__, "1.21" );
$content = $this->getPreloadedContent( $preload );
$text = $this->toEditText( $content );
* @deprecated since 1.21, use mergeChangesIntoContent() instead
*/
function mergeChangesInto( &$editText ){
- wfDebug( __METHOD__, "1.21" );
+ ContentHandler::deprecated( __METHOD__, "1.21" );
$editContent = $this->toEditContent( $editText );
'eu_external_id' => $this->getId() ),
__METHOD__ );
}
-
+
/**
* Check whether this external user id is already linked with
* a local user.
? User::newFromId( $row->eu_local_id )
: null;
}
-
+
}
($row->rc_deleted & Revision::DELETED_COMMENT)
? wfMessage('rev-deleted-comment')->escaped()
: $row->rc_comment,
- $actiontext
+ $actiontext
);
}
*
* @file
* @author Niklas Laxström
- * @author Antoine Musso
+ * @author Antoine Musso
*/
/**
if ( isset( $revisionInfo['model'] ) ) {
$revision->setModel( $revisionInfo['model'] );
}
- if ( isset( $revisionInfo['text'] ) ) {
+ if ( isset( $revisionInfo['format'] ) ) {
$revision->setFormat( $revisionInfo['format'] );
}
$revision->setTitle( $pageInfo['_title'] );
* @deprecated Since 1.21, use getContent() instead.
*/
function getText() {
- wfDeprecated( "Use getContent() instead." );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
return $this->text;
}
// Save the old and new blobs for later
$oldBlob = $row->mr_blob;
$newBlob = self::generateMessageBlob( $module, $lang );
-
+
$newRow = array(
'mr_resource' => $name,
'mr_lang' => $lang,
/**
* Standard output handler for use with ob_start
- *
+ *
* @param $s string
- *
+ *
* @return string
*/
function wfOutputHandler( $s ) {
/**
* Handler that compresses data with gzip if allowed by the Accept header.
* Unlike ob_gzhandler, it works for HEAD requests too.
- *
+ *
* @param $s string
*
* @return string
global $wgUseRCPatrol, $wgEnableAPI, $wgRCMaxAge;
$watchlistdaysMax = ceil( $wgRCMaxAge / ( 3600 * 24 ) );
-
+
## Watchlist #####################################
$defaultPreferences['watchlistdays'] = array(
'type' => 'float',
$this->mArticle = $article;
$this->mTitle = $article->getTitle();
$this->mApplicableTypes = $this->mTitle->getRestrictionTypes();
-
+
// Check if the form should be disabled.
// If it is, the form will be available in read-only to show levels.
$this->mPermErrors = $this->mTitle->getUserPermissionsErrors( 'protect', $wgUser );
* @param $flags Integer Bitfield (optional)
* @return Revision or null
*/
- public static function newFromTitle( $title, $id = 0, $flags = null ) {
+ public static function newFromTitle( $title, $id = 0, $flags = 0 ) {
$conds = array(
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey()
} else {
// Use a join to get the latest revision
$conds[] = 'rev_id=page_latest';
- // Callers assume this will be up-to-date
- $flags = is_int( $flags ) ? $flags : self::READ_LATEST; // b/c
}
return self::newFromConds( $conds, (int)$flags );
}
* @return String
*/
public function getText( $audience = self::FOR_PUBLIC, User $user = null ) {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
$content = $this->getContent( $audience, $user );
return ContentHandler::getContentText( $content ); # returns the raw content text, if applicable
* or Revision::getSerializedData() as appropriate.
*/
public function getRawText() {
- wfDeprecated( __METHOD__, "1.21" );
+ ContentHandler::deprecated( __METHOD__, "1.21" );
return $this->getText( self::RAW );
}
*/
/**
- * An HTTP 1.0 client built for the purposes of purging Squid and Varnish.
- * Uses asynchronous I/O, allowing purges to be done in a highly parallel
- * manner.
+ * An HTTP 1.0 client built for the purposes of purging Squid and Varnish.
+ * Uses asynchronous I/O, allowing purges to be done in a highly parallel
+ * manner.
*
* Could be replaced by curl_multi_exec() or some such.
*/
return array( $socket );
}
- /**
+ /**
* Get the host's IP address.
* Does not support IPv6 at present due to the lack of a convenient interface in PHP.
*/
* @param $url string
*/
public function queuePurge( $url ) {
+ global $wgSquidPurgeUseHostHeader;
$url = SquidUpdate::expand( str_replace( "\n", '', $url ) );
- $this->requests[] = "PURGE $url HTTP/1.0\r\n" .
- "Connection: Keep-Alive\r\n" .
- "Proxy-Connection: Keep-Alive\r\n" .
- "User-Agent: " . Http::userAgent() . ' ' . __CLASS__ . "\r\n\r\n";
+ $request = array();
+ if ( $wgSquidPurgeUseHostHeader ) {
+ $url = wfParseUrl( $url );
+ $host = $url['host'];
+ if ( isset( $url['port'] ) && strlen( $url['port'] ) > 0 ) {
+ $host .= ":" . $url['port'];
+ }
+ $path = $url['path'];
+ if ( isset( $url['query'] ) && is_string( $url['query'] ) ) {
+ $path = wfAppendQuery( $path, $url['query'] );
+ }
+ $request[] = "PURGE $path HTTP/1.1";
+ $request[] = "Host: $host";
+ } else {
+ $request[] = "PURGE $url HTTP/1.0";
+ }
+ $request[] = "Connection: Keep-Alive";
+ $request[] = "Proxy-Connection: Keep-Alive";
+ $request[] = "User-Agent: " . Http::userAgent() . ' ' . __CLASS__;
+ // Two ''s to create \r\n\r\n
+ $request[] = '';
+ $request[] = '';
+
+ $this->requests[] = implode( "\r\n", $request );
if ( $this->currentRequestIndex === null ) {
$this->nextRequest();
}
$numReady = socket_select( $readSockets, $writeSockets, $exceptSockets, $timeout );
wfRestoreWarnings();
if ( $numReady === false ) {
- wfDebugLog( 'squid', __METHOD__.': Error in stream_select: ' .
+ wfDebugLog( 'squid', __METHOD__.': Error in stream_select: ' .
socket_strerror( socket_last_error() ) . "\n" );
break;
}
/**
* An iterator which works exactly like:
- *
+ *
* foreach ( explode( $delim, $s ) as $element ) {
* ...
* }
* @deprecated since 1.21, use Content::getRedirectTarget instead.
*/
public static function newFromRedirect( $text ) {
+ ContentHandler::deprecated( __METHOD__, '1.21' );
+
$content = ContentHandler::makeContent( $text, null, CONTENT_MODEL_WIKITEXT );
return $content->getRedirectTarget();
}
* @deprecated since 1.21, use Content::getUltimateRedirectTarget instead.
*/
public static function newFromRedirectRecurse( $text ) {
+ ContentHandler::deprecated( __METHOD__, '1.21' );
+
$content = ContentHandler::makeContent( $text, null, CONTENT_MODEL_WIKITEXT );
return $content->getUltimateRedirectTarget();
}
* @deprecated since 1.21, use Content::getRedirectChain instead.
*/
public static function newFromRedirectArray( $text ) {
+ ContentHandler::deprecated( __METHOD__, '1.21' );
+
$content = ContentHandler::makeContent( $text, null, CONTENT_MODEL_WIKITEXT );
return $content->getRedirectChain();
}
return $ret;
}
-
/**
* Unset an arbitrary value from our get/post data.
*
wfProfileIn( __METHOD__ );
$request = $this->context->getRequest();
- $title = $this->context->getTitle();
+ $requestTitle = $title = $this->context->getTitle();
$output = $this->context->getOutput();
$user = $this->context->getUser();
global $wgArticle;
$wgArticle = new DeprecatedGlobal( 'wgArticle', $article, '1.18' );
- $this->performAction( $article );
+ $this->performAction( $article, $requestTitle );
} elseif ( is_string( $article ) ) {
$output->redirect( $article );
} else {
* Perform one of the "standard" actions
*
* @param $page Page
+ * @param $requestTitle The original title, before any redirects were applied
*/
- private function performAction( Page $page ) {
+ private function performAction( Page $page, Title $requestTitle ) {
global $wgUseSquid, $wgSquidMaxage;
wfProfileIn( __METHOD__ );
if ( $action instanceof Action ) {
# Let Squid cache things if we can purge them.
if ( $wgUseSquid &&
- in_array( $request->getFullRequestURL(), $title->getSquidURLs() )
+ in_array( $request->getFullRequestURL(), $requestTitle->getSquidURLs() )
) {
$output->setSquidMaxage( $wgSquidMaxage );
}
if ( $wgJobRunRate <= 0 || wfReadOnly() ) {
return;
}
+
if ( $wgJobRunRate < 1 ) {
$max = mt_getrandmax();
if ( mt_rand( 0, $max ) > $max * $wgJobRunRate ) {
- return;
+ return; // the higher $wgJobRunRate, the less likely we return here
}
$n = 1;
} else {
$n = intval( $wgJobRunRate );
}
- while ( $n-- && false != ( $job = Job::pop() ) ) {
- $output = $job->toString() . "\n";
- $t = - microtime( true );
- $success = $job->run();
- $t += microtime( true );
- $t = round( $t * 1000 );
- if ( !$success ) {
- $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
- } else {
- $output .= "Success, Time: $t ms\n";
+ $group = JobQueueGroup::singleton();
+ $types = $group->getDefaultQueueTypes();
+ shuffle( $types ); // avoid starvation
+
+ // Scan the queues for a job N times...
+ do {
+ $jobFound = false; // found a job in any queue?
+ // Find a queue with a job on it and run it...
+ foreach ( $types as $i => $type ) {
+ $queue = $group->get( $type );
+ if ( $queue->isEmpty() ) {
+ unset( $types[$i] ); // don't keep checking this queue
+ continue;
+ }
+ $job = $queue->pop();
+ if ( $job ) {
+ $jobFound = true;
+ $output = $job->toString() . "\n";
+ $t = - microtime( true );
+ $success = $job->run();
+ $queue->ack( $job ); // done
+ $t += microtime( true );
+ $t = round( $t * 1000 );
+ if ( !$success ) {
+ $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
+ } else {
+ $output .= "Success, Time: $t ms\n";
+ }
+ wfDebugLog( 'jobqueue', $output );
+ break;
+ } else {
+ unset( $types[$i] ); // don't keep checking this queue
+ }
}
- wfDebugLog( 'jobqueue', $output );
- }
+ } while ( --$n && $jobFound );
}
}
* @deprecated as of 1.21, getContent() should be used instead.
*/
public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) { #@todo: deprecated, replace usage!
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
+
$this->loadLastEdit();
if ( $this->mLastRevision ) {
return $this->mLastRevision->getText( $audience, $user );
* @deprecated as of 1.21, getContent() should be used instead.
*/
public function getRawText() {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
return $this->getText( Revision::RAW );
}
* @deprecated since 1.21: use ContentHandler::getUndoContent() instead.
*/
public function getUndoText( Revision $undo, Revision $undoafter = null ) {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
$this->loadLastEdit();
* @deprecated since 1.21, use replaceSectionContent() instead
*/
public function replaceSection( $section, $text, $sectionTitle = '', $edittime = null ) {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
if ( strval( $section ) == '' ) { //NOTE: keep condition in sync with condition in replaceSectionContent!
// Whole-page edit; let the whole text through
* @deprecated since 1.21: use doEditContent() instead.
*/
public function doEdit( $text, $summary, $flags = 0, $baseRevId = false, $user = null ) {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
$content = ContentHandler::makeContent( $text, $this->getTitle() );
* @deprecated in 1.21: use prepareContentForEdit instead.
*/
public function prepareTextForEdit( $text, $revid = null, User $user = null ) {
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
$content = ContentHandler::makeContent( $text, $this->getTitle() );
return $this->prepareContentForEdit( $content, $revid , $user );
}
* @deprecated since 1.21, use doEditContent() instead.
*/
public function doQuickEdit( $text, User $user, $comment = '', $minor = 0 ) {
- wfDeprecated( __METHOD__, "1.21" );
+ ContentHandler::deprecated( __METHOD__, "1.21" );
$content = ContentHandler::makeContent( $text, $this->getTitle() );
return $this->doQuickEditContent( $content, $user, $comment , $minor );
public static function getAutosummary( $oldtext, $newtext, $flags ) {
# NOTE: stub for backwards-compatibility. assumes the given text is wikitext. will break horribly if it isn't.
- wfDeprecated( __METHOD__, '1.21' );
+ ContentHandler::deprecated( __METHOD__, '1.21' );
$handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT );
$oldContent = is_null( $oldtext ) ? null : $handler->unserializeContent( $oldtext );
} elseif ( $isCurrent ) {
#XXX: why use RAW audience here, and PUBLIC (default) below?
$content = $this->page->getContent( Revision::RAW );
+ if ( $content === null ) {
+ return false;
+ }
+
} else {
$rev = Revision::newFromTitle( $this->page->getTitle(), $this->revid );
if ( $rev === null ) {
/**
* Construct a language selector appropriate for use in a form or preferences
- *
+ *
* @param string $selected The language code of the selected language
* @param boolean $customisedOnly If true only languages which have some content are listed
* @param string $inLanguage The ISO code of the language to display the select list in (optional)
# Sift for real versus user names
foreach ( $contributors as $user ) {
- $cnt--;
+ $cnt--;
if ( $user->isLoggedIn() ) {
$link = $this->link( $user );
if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
} else {
$conds = array();
}
- $checkDeleted = Xml::checkLabel( $this->msg( 'history-show-deleted' )->text(),
+ if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
+ $checkDeleted = Xml::checkLabel( $this->msg( 'history-show-deleted' )->text(),
'deleted', 'mw-show-deleted-only', $request->getBool( 'deleted' ) ) . "\n";
+ } else {
+ $checkDeleted = '';
+ }
// Add the general form
$action = htmlspecialchars( $wgScript );
public function onView() {
$content = '';
+ // Validate revision
+ $oldid = $this->page->getOldID();
+ if ( $oldid ) {
+ $revision = $this->page->getRevisionFetched();
+
+ // Revision is missing
+ if ( $revision === null ) {
+ return $this->msg( 'missing-revision', $oldid )->parse();
+ }
+
+ // Revision is not current
+ if ( !$revision->isCurrent() ) {
+ return $this->msg( 'pageinfo-not-current' )->plain();
+ }
+ }
+
// Page header
if ( !$this->msg( 'pageinfo-header' )->isDisabled() ) {
$content .= $this->msg( 'pageinfo-header' )->parse();
);
}
+ if ( !$this->page->exists() ) {
+ return $pageInfo;
+ }
+
// Edit history
$pageInfo['header-edits'] = array();
$content = $rev->getContent();
if ( !$content instanceof TextContent ) {
- wfHttpError( 406, "Not Acceptable", "The requested page uses the content model `"
- . $content->getModel() . "` which is not supported via this interface." );
+ wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `"
+ . $content->getModel() . "` which is not supported via this interface." );
die();
}
$lang = $this->getLanguage();
$userDate = $lang->userDate( $timestamp, $user );
$userTime = $lang->userTime( $timestamp, $user );
-
+
$this->getOutput()->addWikiMsg( 'filerevert-success', $this->getTitle()->getText(),
$userDate, $userTime,
wfExpandUrl( $this->page->getFile()->getArchiveUrl( $this->getRequest()->getText( 'oldimage' ) ),
protected function getPageTitle() {
return $this->msg( 'filerevert', $this->getTitle()->getText() );
}
-
+
protected function getDescription() {
$this->getOutput()->addBacklinkSubtitle( $this->getTitle() );
return '';
// Need to pass a throwaway variable because generateReason expects
// a reference
$hasHistory = false;
- $reason = $page->getAutoDeleteReason( $hasHistory );
+ $reason = $page->getAutoDeleteReason( $hasHistory );
if ( $reason === false ) {
return array( array( 'cannotdelete', $title->getPrefixedText() ) );
}
{
$content = $pageObj->getContent();
- // @todo: Add support for appending/prepending to the Content interface
-
- if ( !( $content instanceof TextContent ) ) {
- $mode = $contentHandler->getModelID();
- $this->dieUsage( "Can't append to pages using content model $mode", 'appendnotsupported' );
- }
-
if ( !$content ) {
- # If this is a MediaWiki:x message, then load the messages
- # and return the message value for x.
if ( $titleObj->getNamespace() == NS_MEDIAWIKI ) {
+ # If this is a MediaWiki:x message, then load the messages
+ # and return the message value for x.
$text = $titleObj->getDefaultMessageText();
if ( $text === false ) {
$text = '';
$this->dieUsage( $ex->getMessage(), 'parseerror' );
return;
}
+ } else {
+ # Otherwise, make a new empty content.
+ $content = $contentHandler->makeEmptyContent();
}
}
+ // @todo: Add support for appending/prepending to the Content interface
+
+ if ( !( $content instanceof TextContent ) ) {
+ $mode = $contentHandler->getModelID();
+ $this->dieUsage( "Can't append to pages using content model $mode", 'appendnotsupported' );
+ }
+
if ( !is_null( $params['section'] ) ) {
if ( !$contentHandler->supportsSections() ) {
$modelName = $contentHandler->getModelID();
protected function logRequest( $time ) {
$request = $this->getRequest();
$milliseconds = $time === null ? '?' : round( $time * 1000 );
- $s = 'API' .
+ $s = 'API' .
' ' . $request->getMethod() .
' ' . wfUrlencode( str_replace( ' ', '_', $this->getUser()->getName() ) ) .
' ' . $request->getIP() .
*/
public function getCheck( $name ) {
$this->mParamsUsed[$name] = true;
- return $this->getRequest()->getCheck( $name );
+ return $this->getRequest()->getCheck( $name );
}
/**
$popts->enableLimitReport( !$params['disablepp'] );
// Potentially cached
- $p_result = $this->getParsedContent( $pageObj, $popts, $pageid,
+ $p_result = $this->getParsedContent( $pageObj, $popts, $pageid,
isset( $prop['wikitext'] ) ) ;
}
} else { // Not $oldid, $pageid, $page. Hence based on $text
private $params, $redirects, $convertTitles, $iwUrl;
+ /**
+ * List of Api Query prop modules
+ * @var array
+ */
private $mQueryPropModules = array(
'categories' => 'ApiQueryCategories',
'categoryinfo' => 'ApiQueryCategoryInfo',
'templates' => 'ApiQueryLinks',
);
+ /**
+ * List of Api Query list modules
+ * @var array
+ */
private $mQueryListModules = array(
'allcategories' => 'ApiQueryAllCategories',
'allimages' => 'ApiQueryAllImages',
'watchlistraw' => 'ApiQueryWatchlistRaw',
);
+ /**
+ * List of Api Query meta modules
+ * @var array
+ */
private $mQueryMetaModules = array(
'allmessages' => 'ApiQueryAllMessages',
'siteinfo' => 'ApiQuerySiteinfo',
'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',
+ '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',
+ );
+
private $mSlaveDB = null;
private $mNamedDB = array();
- protected $mAllowedGenerators = array();
+ protected $mAllowedGenerators;
/**
* @param $main ApiMain
parent::__construct( $main, $action );
// Allow custom modules to be added in LocalSettings.php
- global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules,
- $wgMemc, $wgAPICacheHelpTimeout;
+ global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules, $wgAPIGeneratorModules;
self::appendUserModules( $this->mQueryPropModules, $wgAPIPropModules );
self::appendUserModules( $this->mQueryListModules, $wgAPIListModules );
self::appendUserModules( $this->mQueryMetaModules, $wgAPIMetaModules );
+ self::appendUserModules( $this->mQueryGenerators, $wgAPIGeneratorModules );
$this->mPropModuleNames = array_keys( $this->mQueryPropModules );
$this->mListModuleNames = array_keys( $this->mQueryListModules );
$this->mMetaModuleNames = array_keys( $this->mQueryMetaModules );
-
- // Get array of query generators from cache if present
- $key = wfMemcKey( 'apiquerygenerators', SpecialVersion::getVersion( 'nodb' ) );
-
- if ( $wgAPICacheHelpTimeout > 0 ) {
- $cached = $wgMemc->get( $key );
- if ( $cached ) {
- $this->mAllowedGenerators = $cached;
- return;
- }
- }
- $this->makeGeneratorList( $this->mQueryPropModules );
- $this->makeGeneratorList( $this->mQueryListModules );
-
- if ( $wgAPICacheHelpTimeout > 0 ) {
- $wgMemc->set( $key, $this->mAllowedGenerators, $wgAPICacheHelpTimeout );
- }
+ $this->mAllowedGenerators = array_keys( $this->mQueryGenerators );
}
/**
* Get the array mapping module names to class names
* @return array array(modulename => classname)
*/
- function getModules() {
+ public function getModules() {
return array_merge( $this->mQueryPropModules, $this->mQueryListModules, $this->mQueryMetaModules );
}
+ /**
+ * Get the generators array mapping module names to class names
+ * @return array array(modulename => classname)
+ */
+ public function getGenerators() {
+ return $this->mQueryGenerators;
+ }
+
/**
* Get whether the specified module is a prop, list or a meta query module
* @param $moduleName string Name of the module to find type for
return implode( "\n", $moduleDescriptions );
}
- /**
- * Adds any classes that are a subclass of ApiQueryGeneratorBase
- * to the allowed generator list
- * @param $moduleList array()
- */
- private function makeGeneratorList( $moduleList ) {
- foreach( $moduleList as $moduleName => $moduleClass ) {
- if ( is_subclass_of( $moduleClass, 'ApiQueryGeneratorBase' ) ) {
- $this->mAllowedGenerators[] = $moduleName;
- }
- }
- }
-
/**
* Override to add extra parameters from PageSet
* @return string
} else {
$this->addWhereRange( 'cat_pages', 'older', $max, $min);
}
-
if ( isset( $params['prefix'] ) ) {
$this->addWhere( 'cat_title' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
$this->addTables( 'filearchive' );
$this->addFields( array( 'fa_name', 'fa_deleted' ) );
- $this->addFieldsIf( 'fa_storage_key', $fld_sha1 );
+ $this->addFieldsIf( 'fa_sha1', $fld_sha1 );
$this->addFieldsIf( 'fa_timestamp', $fld_timestamp );
$this->addFieldsIf( array( 'fa_user', 'fa_user_text' ), $fld_user );
$this->addFieldsIf( array( 'fa_height', 'fa_width', 'fa_size' ), $fld_dimensions || $fld_size );
$sha1Set = isset( $params['sha1'] );
$sha1base36Set = isset( $params['sha1base36'] );
if ( $sha1Set || $sha1base36Set ) {
- global $wgMiserMode;
- if ( $wgMiserMode ) {
- $this->dieUsage( 'Search by hash disabled in Miser Mode', 'hashsearchdisabled' );
- }
-
$sha1 = false;
if ( $sha1Set ) {
if ( !$this->validateSha1Hash( $params['sha1'] ) ) {
$sha1 = $params['sha1base36'];
}
if ( $sha1 ) {
- $this->addWhere( 'fa_storage_key ' . $db->buildLike( "{$sha1}.", $db->anyString() ) );
+ $this->addWhereFld( 'fa_sha1', $sha1 );
}
}
self::addTitleInfo( $file, $title );
if ( $fld_sha1 ) {
- $file['sha1'] = wfBaseConvert( LocalRepo::getHashFromKey( $row->fa_storage_key ), 36, 16, 40 );
+ $file['sha1'] = wfBaseConvert( $row->fa_sha1, 36, 16, 40 );
}
if ( $fld_timestamp ) {
$file['timestamp'] = wfTimestamp( TS_ISO_8601, $row->fa_timestamp );
'prefix' => 'Search for all image titles that begin with this value',
'dir' => 'The direction in which to list',
'limit' => 'How many images to return in total',
- 'sha1' => "SHA1 hash of image. Overrides {$this->getModulePrefix()}sha1base36. Disabled in Miser Mode",
- 'sha1base36' => 'SHA1 hash of image in base 36 (used in MediaWiki). Disabled in Miser Mode',
+ 'sha1' => "SHA1 hash of image. Overrides {$this->getModulePrefix()}sha1base36",
+ 'sha1base36' => 'SHA1 hash of image in base 36 (used in MediaWiki)',
'prop' => array(
'What image information to get:',
' sha1 - Adds SHA-1 hash for the image',
--- /dev/null
+<?php
+
+/**
+ * Base query module for querying results from ORMTables.
+ *
+ * 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 API
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+abstract class ApiQueryORM extends ApiQueryBase {
+
+ /**
+ * Returns an instance of the IORMTable table being queried.
+ *
+ * @since 1.21
+ *
+ * @return IORMTable
+ */
+ protected abstract function getTable();
+
+ /**
+ * Returns the name of the individual rows.
+ * For example: page, user, contest, campaign, etc.
+ * This is used to appropriately name elements in XML.
+ * Deriving classes typically override this method.
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ protected function getRowName() {
+ return 'item';
+ }
+
+ /**
+ * Returns the name of the list of rows.
+ * For example: pages, users, contests, campaigns, etc.
+ * This is used to appropriately name nodes in the output.
+ * Deriving classes typically override this method.
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ protected function getListName() {
+ return 'items';
+ }
+
+ /**
+ * Returns the path to where the items results should be added in the result.
+ *
+ * @since 1.21
+ *
+ * @return null|string|array
+ */
+ protected function getResultPath() {
+ return null;
+ }
+
+ /**
+ * Get the parameters, find out what the conditions for the query are,
+ * run it, and add the results.
+ *
+ * @since 1.21
+ */
+ public function execute() {
+ $params = $this->getParams();
+
+ if ( !in_array( 'id', $params['props'] ) ) {
+ $params['props'][] = 'id';
+ }
+
+ $results = $this->getResults( $params, $this->getConditions( $params ) );
+ $this->addResults( $params, $results );
+ }
+
+ /**
+ * Get the request parameters, handle the * value for the props param
+ * and remove all params set to null (ie those that are not actually provided).
+ *
+ * @since 1.21
+ *
+ * @return array
+ */
+ protected function getParams() {
+ return array_filter(
+ $this->extractRequestParams(),
+ function( $prop ) {
+ return isset( $prop );
+ }
+ );
+ }
+
+ /**
+ * Get the conditions for the query. These will be provided as
+ * regular parameters, together with limit, props, continue,
+ * and possibly others which we need to get rid off.
+ *
+ * @since 1.21
+ *
+ * @param array $params
+ *
+ * @return array
+ */
+ protected function getConditions( array $params ) {
+ $conditions = array();
+ $fields = $this->getTable()->getFields();
+
+ foreach ( $params as $name => $value ) {
+ if ( array_key_exists( $name, $fields ) ) {
+ $conditions[$name] = $value;
+ }
+ }
+
+ return $conditions;
+ }
+
+ /**
+ * Get the actual results.
+ *
+ * @since 1.21
+ *
+ * @param array $params
+ * @param array $conditions
+ *
+ * @return ORMResult
+ */
+ protected function getResults( array $params, array $conditions ) {
+ return $this->getTable()->select(
+ $params['props'],
+ $conditions,
+ array(
+ 'LIMIT' => $params['limit'] + 1,
+ 'ORDER BY' => $this->getTable()->getPrefixedField( 'id' ) . ' ASC',
+ ),
+ __METHOD__
+ );
+ }
+
+ /**
+ * Serialize the results and add them to the result object.
+ *
+ * @since 1.21
+ *
+ * @param array $params
+ * @param ORMResult $results
+ */
+ protected function addResults( array $params, ORMResult $results ) {
+ $serializedResults = array();
+ $count = 0;
+
+ foreach ( $results as /* IORMRow */ $result ) {
+ if ( ++$count > $params['limit'] ) {
+ // We've reached the one extra which shows that
+ // there are additional pages to be had. Stop here...
+ $this->setContinueEnumParameter( 'continue', $result->getId() );
+ break;
+ }
+
+ $serializedResults[] = $this->formatRow( $result, $params );
+ }
+
+ $this->setIndexedTagNames( $serializedResults );
+ $this->addSerializedResults( $serializedResults );
+ }
+
+ /**
+ * Formats a row to it's desired output format.
+ *
+ * @since 1.21
+ *
+ * @param IORMRow $result
+ * @param array $params
+ *
+ * @return mixed
+ */
+ protected function formatRow( IORMRow $result, array $params ) {
+ return $result->toArray( $params['props'] );
+ }
+
+ /**
+ * Set the tag names for formats such as XML.
+ *
+ * @since 1.21
+ *
+ * @param array $serializedResults
+ */
+ protected function setIndexedTagNames( array &$serializedResults ) {
+ $this->getResult()->setIndexedTagName( $serializedResults, $this->getRowName() );
+ }
+
+ /**
+ * Add the serialized results to the result object.
+ *
+ * @since 1.21
+ *
+ * @param array $serializedResults
+ */
+ protected function addSerializedResults( array $serializedResults ) {
+ $this->getResult()->addValue(
+ $this->getResultPath(),
+ $this->getListName(),
+ $serializedResults
+ );
+ }
+
+ /**
+ * @see ApiBase::getAllowedParams()
+ * @return array
+ */
+ public function getAllowedParams() {
+ $params = array (
+ 'props' => array(
+ ApiBase::PARAM_TYPE => $this->getTable()->getFieldNames(),
+ ApiBase::PARAM_ISMULTI => true,
+ ApiBase::PARAM_REQUIRED => true,
+ ),
+ 'limit' => array(
+ ApiBase::PARAM_DFLT => 20,
+ ApiBase::PARAM_TYPE => 'limit',
+ ApiBase::PARAM_MIN => 1,
+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+ ),
+ 'continue' => null,
+ );
+
+ return array_merge( $this->getTable()->getAPIParams(), $params );
+ }
+
+ /**
+ * @see ApiBase::getParamDescription()
+ * @return array
+ */
+ public function getParamDescription() {
+ $descriptions = array (
+ 'props' => 'Fields to query',
+ 'continue' => 'Offset number from where to continue the query',
+ 'limit' => 'Max amount of rows to return',
+ );
+
+ return array_merge( $this->getTable()->getFieldDescriptions(), $descriptions );
+ }
+
+}
public function incrMissesRecent( WebRequest $request ) {
global $wgMemc;
if ( mt_rand( 0, self::MISS_FACTOR - 1 ) == 0 ) {
- # Get a large IP range that should include the user even if that
+ # Get a large IP range that should include the user even if that
# person's IP address changes
$ip = $request->getIP();
if ( !IP::isValid( $ip ) ) {
return;
}
+ wfDebug( "Squid purge: " . implode( ' ', $urlArr ) . "\n" );
+
if ( $wgHTCPMulticastRouting ) {
SquidUpdate::HTCPPurge( $urlArr );
}
static function expand( $url ) {
return wfExpandUrl( $url, PROTO_INTERNAL );
}
-
+
/**
* Find the HTCP routing rule to use for a given URL.
* @param $url string URL to match
}
return false;
}
-
}
*
* @param $name
* @param $value
- *
+ *
* @return bool
*/
protected function writeSetting( $name, $value ) {
* Name of the content model this Content object represents.
* Use with CONTENT_MODEL_XXX constants
*
+ * @since 1.21
+ *
* @var string $model_id
*/
protected $model_id;
/**
- * @param String $model_id
+ * @param string|null $modelId
+ *
+ * @since 1.21
*/
- public function __construct( $model_id = null ) {
- $this->model_id = $model_id;
+ public function __construct( $modelId = null ) {
+ $this->model_id = $modelId;
}
/**
- * @see Content::getModel()
+ * @see Content::getModel
+ *
+ * @since 1.21
*/
public function getModel() {
return $this->model_id;
* Throws an MWException if $model_id is not the id of the content model
* supported by this Content object.
*
- * @param $model_id int the model to check
+ * @since 1.21
+ *
+ * @param string $modelId The model to check
*
* @throws MWException
*/
- protected function checkModelID( $model_id ) {
- if ( $model_id !== $this->model_id ) {
- throw new MWException( "Bad content model: " .
+ protected function checkModelID( $modelId ) {
+ if ( $modelId !== $this->model_id ) {
+ throw new MWException(
+ "Bad content model: " .
"expected {$this->model_id} " .
- "but got $model_id." );
+ "but got $modelId."
+ );
}
}
/**
- * @see Content::getContentHandler()
+ * @see Content::getContentHandler
+ *
+ * @since 1.21
*/
public function getContentHandler() {
return ContentHandler::getForContent( $this );
}
/**
- * @see Content::getDefaultFormat()
+ * @see Content::getDefaultFormat
+ *
+ * @since 1.21
*/
public function getDefaultFormat() {
return $this->getContentHandler()->getDefaultFormat();
}
/**
- * @see Content::getSupportedFormats()
+ * @see Content::getSupportedFormats
+ *
+ * @since 1.21
*/
public function getSupportedFormats() {
return $this->getContentHandler()->getSupportedFormats();
}
/**
- * @see Content::isSupportedFormat()
+ * @see Content::isSupportedFormat
+ *
+ * @param string $format
+ *
+ * @since 1.21
+ *
+ * @return boolean
*/
public function isSupportedFormat( $format ) {
if ( !$format ) {
}
/**
- * Throws an MWException if $this->isSupportedFormat( $format ) doesn't
+ * Throws an MWException if $this->isSupportedFormat( $format ) does not
* return true.
*
- * @param $format
+ * @since 1.21
+ *
+ * @param string $format
* @throws MWException
*/
protected function checkFormat( $format ) {
if ( !$this->isSupportedFormat( $format ) ) {
- throw new MWException( "Format $format is not supported for content model " .
- $this->getModel() );
+ throw new MWException(
+ "Format $format is not supported for content model " .
+ $this->getModel()
+ );
}
}
/**
* @see Content::serialize
+ *
+ * @param string|null $format
+ *
+ * @since 1.21
+ *
+ * @return string
*/
public function serialize( $format = null ) {
return $this->getContentHandler()->serializeContent( $this, $format );
}
/**
- * @see Content::isEmpty()
+ * @see Content::isEmpty
+ *
+ * @since 1.21
+ *
+ * @return boolean
*/
public function isEmpty() {
return $this->getSize() === 0;
}
/**
- * @see Content::isValid()
+ * @see Content::isValid
+ *
+ * @since 1.21
+ *
+ * @return boolean
*/
public function isValid() {
return true;
}
/**
- * @see Content::equals()
+ * @see Content::equals
+ *
+ * @since 1.21
+ *
+ * @param Content|null $that
+ *
+ * @return boolean
*/
public function equals( Content $that = null ) {
if ( is_null( $that ) ) {
/**
- * @see Content::getRedirectChain()
+ * @see Content::getRedirectChain
+ *
+ * @since 1.21
*/
public function getRedirectChain() {
global $wgMaxRedirects;
}
/**
- * @see Content::getRedirectTarget()
+ * @see Content::getRedirectTarget
+ *
+ * @since 1.21
*/
public function getRedirectTarget() {
return null;
}
/**
- * @see Content::getUltimateRedirectTarget()
+ * @see Content::getUltimateRedirectTarget
* @note: migrated here from Title::newFromRedirectRecurse
+ *
+ * @since 1.21
*/
public function getUltimateRedirectTarget() {
$titles = $this->getRedirectChain();
}
/**
- * @see Content::isRedirect()
+ * @see Content::isRedirect
*
* @since 1.21
*
}
/**
- * @see Content::updateRedirect()
+ * @see Content::updateRedirect
*
* This default implementation always returns $this.
*
+ * @param Title $target
+ *
* @since 1.21
*
* @return Content $this
}
/**
- * @see Content::getSection()
+ * @see Content::getSection
+ *
+ * @since 1.21
*/
public function getSection( $sectionId ) {
return null;
}
/**
- * @see Content::replaceSection()
+ * @see Content::replaceSection
+ *
+ * @since 1.21
*/
public function replaceSection( $section, Content $with, $sectionTitle = '' ) {
return null;
}
/**
- * @see Content::preSaveTransform()
+ * @see Content::preSaveTransform
+ *
+ * @since 1.21
*/
public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
return $this;
}
/**
- * @see Content::addSectionHeader()
+ * @see Content::addSectionHeader
+ *
+ * @since 1.21
*/
public function addSectionHeader( $header ) {
return $this;
}
/**
- * @see Content::preloadTransform()
+ * @see Content::preloadTransform
+ *
+ * @since 1.21
*/
public function preloadTransform( Title $title, ParserOptions $popts ) {
return $this;
}
/**
- * @see Content::prepareSave()
+ * @see Content::prepareSave
+ *
+ * @since 1.21
*/
public function prepareSave( WikiPage $page, $flags, $baseRevId, User $user ) {
if ( $this->isValid() ) {
}
/**
- * @see Content::getDeletionUpdates()
+ * @see Content::getDeletionUpdates
*
* @since 1.21
*
}
/**
- * @see Content::matchMagicWord()
- *
* This default implementation always returns false. Subclasses may override this to supply matching logic.
*
+ * @see Content::matchMagicWord
+ *
+ * @since 1.21
+ *
* @param MagicWord $word
*
* @return bool
* @todo: test that this actually works
* @todo: make sure this also works with LuceneSearch / WikiSearch
*/
- public function getTextForSearchIndex( );
+ public function getTextForSearchIndex();
/**
* @since 1.21
* @TODO: used in WikiPage and MessageCache to get message text. Not so
* nice. What should we use instead?!
*/
- public function getWikitextForTransclusion( );
+ public function getWikitextForTransclusion();
/**
* Returns a textual representation of the content suitable for use in edit
*
* @since 1.21
*
- * @param $maxlength int Maximum length of the summary text
- * @return The summary text
+ * @param $maxLength int Maximum length of the summary text
+ * @return string The summary text
*/
- public function getTextForSummary( $maxlength = 250 );
+ public function getTextForSummary( $maxLength = 250 );
/**
* Returns native representation of the data. Interpretation depends on
*
* @NOTE: Caller must be aware of content model!
*/
- public function getNativeData( );
+ public function getNativeData();
/**
* Returns the content's nominal size in bogo-bytes.
*
* @return int
*/
- public function getSize( );
+ public function getSize();
/**
* Returns the ID of the content model used by this Content object.
* Note that this method is called before any update to the page table is performed. This means that
* $page may not yet know a page ID.
*
+ * @since 1.21
+ *
* @param WikiPage $page The page to be saved.
* @param int $flags bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
* @param int $baseRevId the ID of the current revision
/**
* Returns true if this Content object matches the given magic word.
*
+ * @since 1.21
+ *
* @param MagicWord $word the magic word to match
*
* @return bool whether this Content object matches the given magic word.
*/
abstract class ContentHandler {
+ /**
+ * Switch for enabling deprecation warnings. Used by ContentHandler::deprecated()
+ * and ContentHandler::runLegacyHooks().
+ *
+ * Once the ContentHandler code has settled in a bit, this should be set to true to
+ * make extensions etc. show warnings when using deprecated functions and hooks.
+ */
+ protected static $enableDeprecationWarnings = false;
+
/**
* Convenience function for getting flat text from a Content object. This
* should only be used in the context of backwards compatibility with code
* - otherwise, the behaviour is undefined.
*
* @since 1.21
- * @deprecated since 1.21. Always try to use the content object.
*
* @static
* @param $content Content|null
wfRunHooks( 'ContentHandlerForModelID', array( $modelId, &$handler ) );
if ( $handler === null ) {
- throw new MWException( "No handler for model #$modelId registered in \$wgContentHandlers" );
+ throw new MWException( "No handler for model '$modelId'' registered in \$wgContentHandlers" );
}
if ( !( $handler instanceof ContentHandler ) ) {
return false;
}
+ /**
+ * Logs a deprecation warning, visible if $wgDevelopmentWarnings, but only if
+ * self::$enableDeprecationWarnings is set to true.
+ *
+ * @param String $func The name of the deprecated function
+ * @param string $version The version since the method is deprecated. Usually 1.21
+ * for ContentHandler related stuff.
+ * @param String|bool $component: Component to which the function belongs.
+ * If false, it is assumed the function is in MediaWiki core.
+ *
+ * @see ContentHandler::$enableDeprecationWarnings
+ * @see wfDeprecated
+ */
+ public static function deprecated( $func, $version, $component = false ) {
+ if ( self::$enableDeprecationWarnings ) {
+ wfDeprecated( $func, $version, $component, 3 );
+ }
+ }
+
/**
* Call a legacy hook that uses text instead of Content objects.
* Will log a warning when a matching hook function is registered.
*
* @param $event String: event name
* @param $args Array: parameters passed to hook functions
- * @param $warn bool: whether to log a warning (default: true). Should generally be true,
- * may be set to false for testing.
+ * @param $warn bool: whether to log a warning.
+ * Default to self::$enableDeprecationWarnings.
+ * May be set to false for testing.
*
* @return Boolean True if no handler aborted the hook
+ *
+ * @see ContentHandler::$enableDeprecationWarnings
*/
- public static function runLegacyHooks( $event, $args = array(), $warn = true ) {
- global $wgHooks; //@todo: once I39bd5de2 is merged, direct access to $wgHooks is no longer needed.
+ public static function runLegacyHooks( $event, $args = array(),
+ $warn = null ) {
- if ( !Hooks::isRegistered( $event ) && empty( $wgHooks[$event] ) ) {
+ if ( $warn === null ) {
+ $warn = self::$enableDeprecationWarnings;
+ }
+
+ if ( !Hooks::isRegistered( $event ) ) {
return true; // nothing to do here
}
}
}
-/**
- * @since 1.21
- */
-abstract class TextContentHandler extends ContentHandler {
-
- public function __construct( $modelId, $formats ) {
- parent::__construct( $modelId, $formats );
- }
-
- /**
- * Returns the content's text as-is.
- *
- * @param $content Content
- * @param $format string|null
- * @return mixed
- */
- public function serializeContent( Content $content, $format = null ) {
- $this->checkFormat( $format );
- return $content->getNativeData();
- }
-
- /**
- * Attempts to merge differences between three versions. Returns a new
- * Content object for a clean merge and false for failure or a conflict.
- *
- * All three Content objects passed as parameters must have the same
- * content model.
- *
- * This text-based implementation uses wfMerge().
- *
- * @param $oldContent \Content|string String
- * @param $myContent \Content|string String
- * @param $yourContent \Content|string String
- *
- * @return Content|Bool
- */
- public function merge3( Content $oldContent, Content $myContent, Content $yourContent ) {
- $this->checkModelID( $oldContent->getModel() );
- $this->checkModelID( $myContent->getModel() );
- $this->checkModelID( $yourContent->getModel() );
-
- $format = $this->getDefaultFormat();
-
- $old = $this->serializeContent( $oldContent, $format );
- $mine = $this->serializeContent( $myContent, $format );
- $yours = $this->serializeContent( $yourContent, $format );
-
- $ok = wfMerge( $old, $mine, $yours, $result );
-
- if ( !$ok ) {
- return false;
- }
-
- if ( !$result ) {
- return $this->makeEmptyContent();
- }
-
- $mergedContent = $this->unserializeContent( $result, $format );
- return $mergedContent;
- }
-
-}
-
-/**
- * @since 1.21
- */
-class WikitextContentHandler extends TextContentHandler {
-
- public function __construct( $modelId = CONTENT_MODEL_WIKITEXT ) {
- parent::__construct( $modelId, array( CONTENT_FORMAT_WIKITEXT ) );
- }
-
- public function unserializeContent( $text, $format = null ) {
- $this->checkFormat( $format );
-
- return new WikitextContent( $text );
- }
-
- /**
- * @see ContentHandler::makeEmptyContent
- *
- * @return Content
- */
- public function makeEmptyContent() {
- return new WikitextContent( '' );
- }
-
-
- /**
- * Returns a WikitextContent object representing a redirect to the given destination page.
- *
- * @see ContentHandler::makeRedirectContent
- *
- * @param Title $destination the page to redirect to.
- *
- * @return Content
- */
- public function makeRedirectContent( Title $destination ) {
- $mwRedir = MagicWord::get( 'redirect' );
- $redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $destination->getPrefixedText() . "]]\n";
-
- return new WikitextContent( $redirectText );
- }
-
- /**
- * Returns true because wikitext supports sections.
- *
- * @return boolean whether sections are supported.
- */
- public function supportsSections() {
- return true;
- }
-
- /**
- * Returns true, because wikitext supports caching using the
- * ParserCache mechanism.
- *
- * @since 1.21
- * @return bool
- */
- public function isParserCacheSupported() {
- return true;
- }
-}
-
-# XXX: make ScriptContentHandler base class, do highlighting stuff there?
-
-/**
- * @since 1.21
- */
-class JavaScriptContentHandler extends TextContentHandler {
-
- public function __construct( $modelId = CONTENT_MODEL_JAVASCRIPT ) {
- parent::__construct( $modelId, array( CONTENT_FORMAT_JAVASCRIPT ) );
- }
-
- public function unserializeContent( $text, $format = null ) {
- $this->checkFormat( $format );
-
- return new JavaScriptContent( $text );
- }
-
- public function makeEmptyContent() {
- return new JavaScriptContent( '' );
- }
-
- /**
- * Returns the english language, because JS is english, and should be handled as such.
- *
- * @return Language wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageLanguage()
- */
- public function getPageLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-
- /**
- * Returns the english language, because CSS is english, and should be handled as such.
- *
- * @return Language wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageViewLanguage()
- */
- public function getPageViewLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-}
-
-/**
- * @since 1.21
- */
-class CssContentHandler extends TextContentHandler {
-
- public function __construct( $modelId = CONTENT_MODEL_CSS ) {
- parent::__construct( $modelId, array( CONTENT_FORMAT_CSS ) );
- }
-
- public function unserializeContent( $text, $format = null ) {
- $this->checkFormat( $format );
-
- return new CssContent( $text );
- }
-
- public function makeEmptyContent() {
- return new CssContent( '' );
- }
-
- /**
- * Returns the english language, because CSS is english, and should be handled as such.
- *
- * @return Language wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageLanguage()
- */
- public function getPageLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-
- /**
- * Returns the english language, because CSS is english, and should be handled as such.
- *
- * @return Language wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageViewLanguage()
- */
- public function getPageViewLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-}
--- /dev/null
+<?php
+
+/**
+ * @since 1.21
+ */
+class CssContentHandler extends TextContentHandler {
+
+ public function __construct( $modelId = CONTENT_MODEL_CSS ) {
+ parent::__construct( $modelId, array( CONTENT_FORMAT_CSS ) );
+ }
+
+ public function unserializeContent( $text, $format = null ) {
+ $this->checkFormat( $format );
+
+ return new CssContent( $text );
+ }
+
+ public function makeEmptyContent() {
+ return new CssContent( '' );
+ }
+
+ /**
+ * Returns the english language, because CSS is english, and should be handled as such.
+ *
+ * @return Language wfGetLangObj( 'en' )
+ *
+ * @see ContentHandler::getPageLanguage()
+ */
+ public function getPageLanguage( Title $title, Content $content = null ) {
+ return wfGetLangObj( 'en' );
+ }
+
+ /**
+ * Returns the english language, because CSS is english, and should be handled as such.
+ *
+ * @return Language wfGetLangObj( 'en' )
+ *
+ * @see ContentHandler::getPageViewLanguage()
+ */
+ public function getPageViewLanguage( Title $title, Content $content = null ) {
+ return wfGetLangObj( 'en' );
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+# XXX: make ScriptContentHandler base class, do highlighting stuff there?
+
+/**
+ * @since 1.21
+ */
+class JavaScriptContentHandler extends TextContentHandler {
+
+ public function __construct( $modelId = CONTENT_MODEL_JAVASCRIPT ) {
+ parent::__construct( $modelId, array( CONTENT_FORMAT_JAVASCRIPT ) );
+ }
+
+ public function unserializeContent( $text, $format = null ) {
+ $this->checkFormat( $format );
+
+ return new JavaScriptContent( $text );
+ }
+
+ public function makeEmptyContent() {
+ return new JavaScriptContent( '' );
+ }
+
+ /**
+ * Returns the english language, because JS is english, and should be handled as such.
+ *
+ * @return Language wfGetLangObj( 'en' )
+ *
+ * @see ContentHandler::getPageLanguage()
+ */
+ public function getPageLanguage( Title $title, Content $content = null ) {
+ return wfGetLangObj( 'en' );
+ }
+
+ /**
+ * Returns the english language, because CSS is english, and should be handled as such.
+ *
+ * @return Language wfGetLangObj( 'en' )
+ *
+ * @see ContentHandler::getPageViewLanguage()
+ */
+ public function getPageViewLanguage( Title $title, Content $content = null ) {
+ return wfGetLangObj( 'en' );
+ }
+}
\ No newline at end of file
*
* @since 1.21
*/
-abstract class TextContent extends AbstractContent {
+class TextContent extends AbstractContent {
- public function __construct( $text, $model_id = null ) {
+ public function __construct( $text, $model_id = CONTENT_MODEL_TEXT ) {
parent::__construct( $model_id );
if ( !is_string( $text ) ) {
# TODO: make Highlighter interface, use highlighter here, if available
return htmlspecialchars( $this->getNativeData() );
}
-}
\ No newline at end of file
+}
--- /dev/null
+<?php
+
+/**
+ * @since 1.21
+ */
+class TextContentHandler extends ContentHandler {
+
+ public function __construct( $modelId = CONTENT_MODEL_TEXT, $formats = array( CONTENT_FORMAT_TEXT ) ) {
+ parent::__construct( $modelId, $formats );
+ }
+
+ /**
+ * Returns the content's text as-is.
+ *
+ * @param $content Content
+ * @param $format string|null
+ * @return mixed
+ */
+ public function serializeContent( Content $content, $format = null ) {
+ $this->checkFormat( $format );
+ return $content->getNativeData();
+ }
+
+ /**
+ * Attempts to merge differences between three versions. Returns a new
+ * Content object for a clean merge and false for failure or a conflict.
+ *
+ * All three Content objects passed as parameters must have the same
+ * content model.
+ *
+ * This text-based implementation uses wfMerge().
+ *
+ * @param $oldContent \Content|string String
+ * @param $myContent \Content|string String
+ * @param $yourContent \Content|string String
+ *
+ * @return Content|Bool
+ */
+ public function merge3( Content $oldContent, Content $myContent, Content $yourContent ) {
+ $this->checkModelID( $oldContent->getModel() );
+ $this->checkModelID( $myContent->getModel() );
+ $this->checkModelID( $yourContent->getModel() );
+
+ $format = $this->getDefaultFormat();
+
+ $old = $this->serializeContent( $oldContent, $format );
+ $mine = $this->serializeContent( $myContent, $format );
+ $yours = $this->serializeContent( $yourContent, $format );
+
+ $ok = wfMerge( $old, $mine, $yours, $result );
+
+ if ( !$ok ) {
+ return false;
+ }
+
+ if ( !$result ) {
+ return $this->makeEmptyContent();
+ }
+
+ $mergedContent = $this->unserializeContent( $result, $format );
+ return $mergedContent;
+ }
+
+ /**
+ * Unserializes a Content object of the type supported by this ContentHandler.
+ *
+ * @since 1.21
+ *
+ * @param $text string serialized form of the content
+ * @param $format null|String the format used for serialization
+ *
+ * @return Content the TextContent object wrapping $text
+ */
+ public function unserializeContent( $text, $format = null ) {
+ $this->checkFormat( $format );
+
+ return new TextContent( $text );
+ }
+
+ /**
+ * Creates an empty TextContent object.
+ *
+ * @since 1.21
+ *
+ * @return Content
+ */
+ public function makeEmptyContent() {
+ return new TextContent( '' );
+ }
+}
\ No newline at end of file
$text = $this->getNativeData();
$sect = $wgParser->getSection( $text, $section, false );
- return new WikitextContent( $sect );
+ if ( $sect === false ) {
+ return false;
+ } else {
+ return new WikitextContent( $sect );
+ }
}
/**
public function matchMagicWord( MagicWord $word ) {
return $word->match( $this->getNativeData() );
}
-}
\ No newline at end of file
+}
--- /dev/null
+<?php
+
+/**
+ * @since 1.21
+ */
+class WikitextContentHandler extends TextContentHandler {
+
+ public function __construct( $modelId = CONTENT_MODEL_WIKITEXT ) {
+ parent::__construct( $modelId, array( CONTENT_FORMAT_WIKITEXT ) );
+ }
+
+ public function unserializeContent( $text, $format = null ) {
+ $this->checkFormat( $format );
+
+ return new WikitextContent( $text );
+ }
+
+ /**
+ * @see ContentHandler::makeEmptyContent
+ *
+ * @return Content
+ */
+ public function makeEmptyContent() {
+ return new WikitextContent( '' );
+ }
+
+
+ /**
+ * Returns a WikitextContent object representing a redirect to the given destination page.
+ *
+ * @see ContentHandler::makeRedirectContent
+ *
+ * @param Title $destination the page to redirect to.
+ *
+ * @return Content
+ */
+ public function makeRedirectContent( Title $destination ) {
+ $mwRedir = MagicWord::get( 'redirect' );
+ $redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $destination->getPrefixedText() . "]]\n";
+
+ return new WikitextContent( $redirectText );
+ }
+
+ /**
+ * Returns true because wikitext supports sections.
+ *
+ * @return boolean whether sections are supported.
+ */
+ public function supportsSections() {
+ return true;
+ }
+
+ /**
+ * Returns true, because wikitext supports caching using the
+ * ParserCache mechanism.
+ *
+ * @since 1.21
+ * @return bool
+ */
+ public function isParserCacheSupported() {
+ return true;
+ }
+}
\ No newline at end of file
$args = func_get_args();
return call_user_func_array( array( $this->getContext(), 'msg' ), $args );
}
-
}
-
public function getSkin() {
if ( $this->skin === null ) {
wfProfileIn( __METHOD__ . '-createskin' );
-
+
$skin = null;
wfRunHooks( 'RequestContextCreateSkin', array( $this, &$skin ) );
}
}
-
* Clone the table structure
*/
public function cloneTableStructure() {
-
foreach( $this->tablesToClone as $tbl ) {
# Clean up from previous aborted run. So that table escaping
# works correctly across DB engines, we need to change the pre-
# fix back and forth so tableName() works right.
-
+
self::changePrefix( $this->oldTablePrefix );
$oldTableName = $this->db->tableName( $tbl, 'raw' );
-
+
self::changePrefix( $this->newTablePrefix );
$newTableName = $this->db->tableName( $tbl, 'raw' );
-
+
if( $this->dropCurrentTables && !in_array( $this->db->getType(), array( 'postgres', 'oracle' ) ) ) {
$this->db->dropTable( $tbl, __METHOD__ );
wfDebug( __METHOD__." dropping {$newTableName}\n", true);
# Create new table
wfDebug( __METHOD__." duplicating $oldTableName to $newTableName\n", true );
$this->db->duplicateTableStructure( $oldTableName, $newTableName, $this->useTemporaryTables );
-
}
-
}
/**
$this->releaseConnection( $dbw );
return $result;
}
-
+
/**
* Get API parameters for the fields supported by this object.
*
/**
* Generate a diff, no caching.
*
- * Subclasses may override this to provide a
+ * This implementation uses generateTextDiffBody() to generate a diff based on the default
+ * serialization of the given Content objects. This will fail if $old or $new are not
+ * instances of TextContent.
+ *
+ * Subclasses may override this to provide a different rendering for the diff,
+ * perhaps taking advantage of the content's native form. This is required for all content
+ * models that are not text based.
*
* @param $old Content: old content
* @param $new Content: new content
*
* @since 1.21
+ * @throws MWException if $old or $new are not instances of TextContent.
*/
function generateContentDiffBody( Content $old, Content $new ) {
if ( !( $old instanceof TextContent ) ) {
* @deprecated since 1.21, use generateContentDiffBody() instead!
*/
function generateDiffBody( $otext, $ntext ) {
- wfDeprecated( __METHOD__, "1.21" );
+ ContentHandler::deprecated( __METHOD__, "1.21" );
return $this->generateTextDiffBody( $otext, $ntext );
}
* @deprecated since 1.21, use setContent() instead.
*/
function setText( $oldText, $newText ) {
- wfDeprecated( __METHOD__, "1.21" );
+ ContentHandler::deprecated( __METHOD__, "1.21" );
$oldContent = ContentHandler::makeContent( $oldText, $this->getTitle() );
$newContent = ContentHandler::makeContent( $newText, $this->getTitle() );
return "mwstore://{$this->name}";
}
+ /**
+ * Get the storage path for the given container for this backend
+ *
+ * @param $container string Container name
+ * @return string Storage path
+ * @since 1.21
+ */
+ final public function getContainerStoragePath( $container ) {
+ return $this->getRootStoragePath() . "/{$container}";
+ }
+
/**
* Get the file journal object for this backend
*
$timestamp, # time of upload
$dataLoaded, # Whether or not all this has been loaded from the database (loadFromXxx)
$deleted, # Bitfield akin to rev_deleted
+ $sha1, # sha1 hash of file content
$pageCount,
$archive_name;
$this->deleted = 0;
$this->dataLoaded = false;
$this->exists = false;
+ $this->sha1 = '';
if( $title instanceof Title ) {
$this->title = File::normalizeTitle( $title, 'exception' );
'fa_user',
'fa_user_text',
'fa_timestamp',
- 'fa_deleted' ),
+ 'fa_deleted',
+ 'fa_sha1' ),
$conds,
__METHOD__,
array( 'ORDER BY' => 'fa_timestamp DESC' ) );
$row = $ret->fetchObject();
// initialize fields for filestore image object
- $this->id = intval($row->fa_id);
- $this->name = $row->fa_name;
- $this->archive_name = $row->fa_archive_name;
- $this->group = $row->fa_storage_group;
- $this->key = $row->fa_storage_key;
- $this->size = $row->fa_size;
- $this->bits = $row->fa_bits;
- $this->width = $row->fa_width;
- $this->height = $row->fa_height;
- $this->metadata = $row->fa_metadata;
- $this->mime = "$row->fa_major_mime/$row->fa_minor_mime";
- $this->media_type = $row->fa_media_type;
- $this->description = $row->fa_description;
- $this->user = $row->fa_user;
- $this->user_text = $row->fa_user_text;
- $this->timestamp = $row->fa_timestamp;
- $this->deleted = $row->fa_deleted;
+ $this->loadFromRow( $row );
} else {
throw new MWException( 'This title does not correspond to an image page.' );
}
*/
public static function newFromRow( $row ) {
$file = new ArchivedFile( Title::makeTitle( NS_FILE, $row->fa_name ) );
-
- $file->id = intval($row->fa_id);
- $file->name = $row->fa_name;
- $file->archive_name = $row->fa_archive_name;
- $file->group = $row->fa_storage_group;
- $file->key = $row->fa_storage_key;
- $file->size = $row->fa_size;
- $file->bits = $row->fa_bits;
- $file->width = $row->fa_width;
- $file->height = $row->fa_height;
- $file->metadata = $row->fa_metadata;
- $file->mime = "$row->fa_major_mime/$row->fa_minor_mime";
- $file->media_type = $row->fa_media_type;
- $file->description = $row->fa_description;
- $file->user = $row->fa_user;
- $file->user_text = $row->fa_user_text;
- $file->timestamp = $row->fa_timestamp;
- $file->deleted = $row->fa_deleted;
-
+ $file->loadFromRow( $row );
return $file;
}
+ /**
+ * Load ArchivedFile object fields from a DB row.
+ *
+ * @param $row Object database row
+ * @since 1.21
+ */
+ public function loadFromRow( $row ) {
+ $this->id = intval($row->fa_id);
+ $this->name = $row->fa_name;
+ $this->archive_name = $row->fa_archive_name;
+ $this->group = $row->fa_storage_group;
+ $this->key = $row->fa_storage_key;
+ $this->size = $row->fa_size;
+ $this->bits = $row->fa_bits;
+ $this->width = $row->fa_width;
+ $this->height = $row->fa_height;
+ $this->metadata = $row->fa_metadata;
+ $this->mime = "$row->fa_major_mime/$row->fa_minor_mime";
+ $this->media_type = $row->fa_media_type;
+ $this->description = $row->fa_description;
+ $this->user = $row->fa_user;
+ $this->user_text = $row->fa_user_text;
+ $this->timestamp = $row->fa_timestamp;
+ $this->deleted = $row->fa_deleted;
+ if( isset( $row->fa_sha1 ) ) {
+ $this->sha1 = $row->fa_sha1;
+ } else {
+ // old row, populate from key
+ $this->sha1 = LocalRepo::getHashFromKey( $this->key );
+ }
+ }
+
/**
* Return the associated title object
*
return wfTimestamp( TS_MW, $this->timestamp );
}
+ /**
+ * Get the SHA-1 base 36 hash of the file
+ *
+ * @return string
+ * @since 1.21
+ */
+ function getSha1() {
+ $this->load();
+ return $this->sha1;
+ }
+
/**
* Return the user ID of the uploader.
*
'fa_description' => 'img_description',
'fa_user' => 'img_user',
'fa_user_text' => 'img_user_text',
- 'fa_timestamp' => 'img_timestamp'
+ 'fa_timestamp' => 'img_timestamp',
+ 'fa_sha1' => 'img_sha1',
), $where, __METHOD__ );
}
'fa_user' => 'oi_user',
'fa_user_text' => 'oi_user_text',
'fa_timestamp' => 'oi_timestamp',
+ 'fa_sha1' => 'oi_sha1',
), $where, __METHOD__ );
}
}
$deletedRel = $this->file->repo->getDeletedHashPath( $row->fa_storage_key ) . $row->fa_storage_key;
$deletedUrl = $this->file->repo->getVirtualUrl() . '/deleted/' . $deletedRel;
- $sha1 = substr( $row->fa_storage_key, 0, strcspn( $row->fa_storage_key, '.' ) );
+ if( isset( $row->fa_sha1 ) ) {
+ $sha1 = $row->fa_sha1;
+ } else {
+ // old row, populate from key
+ $sha1 = LocalRepo::getHashFromKey( $row->fa_storage_key );
+ }
# Fix leading zero
if ( strlen( $sha1 ) == 32 && $sha1[0] == '0' ) {
protected $shared = false;
+ /**
+ * Scripts to run after database update
+ * Should be a subclass of LoggedUpdateMaintenance
+ */
protected $postDatabaseUpdateMaintenance = array(
'DeleteDefaultMessages',
'PopulateRevisionLength',
'PopulateRevisionSha1',
'PopulateImageSha1',
'FixExtLinksProtocolRelative',
+ 'PopulateFilearchiveSha1',
);
/**
/**
* Add a maintenance script to be run after the database updates are complete.
*
+ * Script should subclass LoggedUpdateMaintenance
+ *
* @since 1.19
*
* @param $class string Name of a Maintenance subclass
array( 'modifyField', 'user_properties', 'up_property', 'patch-up_property.sql' ),
array( 'addTable', 'uploadstash', 'patch-uploadstash.sql' ),
array( 'addTable', 'user_former_groups', 'patch-user_former_groups.sql'),
- array( 'doRebuildLocalisationCache' ),
+ array( 'doRebuildLocalisationCache' ),
// 1.19
array( 'addIndex', 'logging', 'type_action', 'patch-logging-type-action-index.sql'),
array( 'modifyField', 'user_groups', 'ug_group', 'patch-ug_group-length-increase.sql' ),
array( 'addField', 'uploadstash', 'us_chunk_inx', 'patch-uploadstash_chunk.sql' ),
array( 'addfield', 'job', 'job_timestamp', 'patch-jobs-add-timestamp.sql' ),
-
array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ufg_group-length-increase.sql' ),
// 1.20
array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
array( 'dropField', 'site_stats', 'ss_admins', 'patch-drop-ss_admins.sql' ),
array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
+ array( 'addTable', 'sites', 'patch-sites.sql' ),
+ array( 'addField', 'filearchive', 'fa_sha1', 'patch-fa_sha1.sql' ),
+ array( 'addField', 'job', 'job_token', 'patch-job_token.sql' ),
);
}
protected $internalDefaults = array(
'_OracleDefTS' => 'USERS',
'_OracleTempTS' => 'TEMP',
- '_InstallUser' => 'SYSDBA',
+ '_InstallUser' => 'SYSTEM',
);
public $minimumVersion = '9.0.1'; // 9iR1
array( 'addTable', 'config', 'patch-config.sql' ),
array( 'addIndex', 'ipblocks', 'i05', 'patch-ipblocks_i05_index.sql' ),
array( 'addIndex', 'revision', 'i05', 'patch-revision_i05_index.sql' ),
+ array( 'dropField', 'category', 'cat_hidden', 'patch-cat_hidden.sql' ),
//1.21
array( 'addField', 'revision', 'rev_content_format', 'patch-revision-rev_content_format.sql' ),
array( 'addField', 'archive', 'ar_content_format', 'patch-archive-ar_content_format.sql' ),
array( 'addField', 'archive', 'ar_content_model', 'patch-archive-ar_content_model.sql' ),
array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
+ array( 'dropField', 'site_stats', 'ss_admins', 'patch-ss_admins.sql' ),
+ array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
// KEEP THIS AT THE BOTTOM!!
array( 'doRebuildDuplicateFunction' ),
array( 'addPgField', 'archive', 'ar_len', 'INTEGER' ),
array( 'addPgField', 'archive', 'ar_page_id', 'INTEGER' ),
array( 'addPgField', 'archive', 'ar_parent_id', 'INTEGER' ),
+ array( 'addPgField', 'archive', 'ar_content_model', 'TEXT' ),
+ array( 'addPgField', 'archive', 'ar_content_format', 'TEXT' ),
array( 'addPgField', 'categorylinks', 'cl_sortkey_prefix', "TEXT NOT NULL DEFAULT ''"),
array( 'addPgField', 'categorylinks', 'cl_collation', "TEXT NOT NULL DEFAULT 0"),
array( 'addPgField', 'categorylinks', 'cl_type', "TEXT NOT NULL DEFAULT 'page'"),
array( 'addPgField', 'oldimage', 'oi_metadata', "BYTEA NOT NULL DEFAULT ''" ),
array( 'addPgField', 'oldimage', 'oi_minor_mime', "TEXT NOT NULL DEFAULT 'unknown'" ),
array( 'addPgField', 'oldimage', 'oi_sha1', "TEXT NOT NULL DEFAULT ''" ),
+ array( 'addPgField', 'page', 'page_content_model', 'TEXT' ),
array( 'addPgField', 'page_restrictions', 'pr_id', "INTEGER NOT NULL UNIQUE DEFAULT nextval('page_restrictions_pr_id_seq')" ),
array( 'addPgField', 'profiling', 'pf_memory', 'NUMERIC(18,10) NOT NULL DEFAULT 0' ),
array( 'addPgField', 'recentchanges', 'rc_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
array( 'addPgField', 'revision', 'rev_deleted', 'SMALLINT NOT NULL DEFAULT 0' ),
array( 'addPgField', 'revision', 'rev_len', 'INTEGER' ),
array( 'addPgField', 'revision', 'rev_parent_id', 'INTEGER DEFAULT NULL' ),
+ array( 'addPgField', 'revision', 'rev_content_model', 'TEXT' ),
+ array( 'addPgField', 'revision', 'rev_content_format', 'TEXT' ),
array( 'addPgField', 'site_stats', 'ss_active_users', "INTEGER DEFAULT '-1'" ),
array( 'addPgField', 'user_newtalk', 'user_last_timestamp', 'TIMESTAMPTZ' ),
array( 'addPgField', 'logging', 'log_user_text', "TEXT NOT NULL DEFAULT ''" ),
array( 'modifyField', 'user_groups', 'ug_group', 'patch-ug_group-length-increase.sql' ),
array( 'addField', 'uploadstash', 'us_chunk_inx', 'patch-uploadstash_chunk.sql' ),
array( 'addfield', 'job', 'job_timestamp', 'patch-jobs-add-timestamp.sql' ),
-
array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ug_group-length-increase.sql' ),
// 1.20
array( 'dropField', 'site_stats', 'ss_admins', 'patch-drop-ss_admins.sql' ),
array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
+ array( 'addTable', 'sites', 'patch-sites.sql' ),
+ array( 'addField', 'filearchive', 'fa_sha1', 'patch-fa_sha1.sql' ),
+ array( 'addField', 'job', 'job_token', 'patch-job_token.sql' ),
);
}
/**
* Class to both describe a background job and handle jobs.
+ * This queue aspects of this class are now deprecated.
*
* @ingroup JobQueue
*/
abstract class Job {
-
/**
* @var Title
*/
* Run the job
* @return boolean success
*/
- abstract function run();
+ abstract public function run();
/*-------------------------------------------------------------------------
* Static functions
*------------------------------------------------------------------------*/
- /**
- * Pop a job of a certain type. This tries less hard than pop() to
- * actually find a job; it may be adversely affected by concurrent job
- * runners.
- *
- * @param $type string
- *
- * @return Job
- */
- static function pop_type( $type ) {
- wfProfilein( __METHOD__ );
-
- $dbw = wfGetDB( DB_MASTER );
-
- $dbw->begin( __METHOD__ );
-
- $row = $dbw->selectRow(
- 'job',
- '*',
- array( 'job_cmd' => $type ),
- __METHOD__,
- array( 'LIMIT' => 1, 'FOR UPDATE' )
- );
-
- if ( $row === false ) {
- $dbw->commit( __METHOD__ );
- wfProfileOut( __METHOD__ );
- return false;
- }
-
- /* Ensure we "own" this row */
- $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
- $affected = $dbw->affectedRows();
- $dbw->commit( __METHOD__ );
-
- if ( $affected == 0 ) {
- wfProfileOut( __METHOD__ );
- return false;
- }
-
- wfIncrStats( 'job-pop' );
- $namespace = $row->job_namespace;
- $dbkey = $row->job_title;
- $title = Title::makeTitleSafe( $namespace, $dbkey );
- $job = Job::factory( $row->job_cmd, $title, Job::extractBlob( $row->job_params ),
- $row->job_id );
-
- $job->removeDuplicates();
-
- wfProfileOut( __METHOD__ );
- return $job;
- }
-
- /**
- * Pop a job off the front of the queue
- *
- * @param $offset Integer: Number of jobs to skip
- * @return Job or false if there's no jobs
- */
- static function pop( $offset = 0 ) {
- wfProfileIn( __METHOD__ );
-
- $dbr = wfGetDB( DB_SLAVE );
-
- /* Get a job from the slave, start with an offset,
- scan full set afterwards, avoid hitting purged rows
-
- NB: If random fetch previously was used, offset
- will always be ahead of few entries
- */
-
- $conditions = self::defaultQueueConditions();
-
- $offset = intval( $offset );
- $options = array( 'ORDER BY' => 'job_id', 'USE INDEX' => 'PRIMARY' );
-
- $row = $dbr->selectRow( 'job', '*',
- array_merge( $conditions, array( "job_id >= $offset" ) ),
- __METHOD__,
- $options
- );
-
- // Refetching without offset is needed as some of job IDs could have had delayed commits
- // and have lower IDs than jobs already executed, blame concurrency :)
- //
- if ( $row === false ) {
- if ( $offset != 0 ) {
- $row = $dbr->selectRow( 'job', '*', $conditions, __METHOD__, $options );
- }
-
- if ( $row === false ) {
- wfProfileOut( __METHOD__ );
- return false;
- }
- }
-
- // Try to delete it from the master
- $dbw = wfGetDB( DB_MASTER );
- $dbw->begin( __METHOD__ );
- $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
- $affected = $dbw->affectedRows();
- $dbw->commit( __METHOD__ );
-
- if ( !$affected ) {
- $dbw->begin( __METHOD__ );
-
- // Failed, someone else beat us to it
- // Try getting a random row
- $row = $dbw->selectRow( 'job', array( 'minjob' => 'MIN(job_id)',
- 'maxjob' => 'MAX(job_id)' ), '1=1', __METHOD__ );
- if ( $row === false || is_null( $row->minjob ) || is_null( $row->maxjob ) ) {
- // No jobs to get
- $dbw->rollback( __METHOD__ );
- wfProfileOut( __METHOD__ );
- return false;
- }
- // Get the random row
- $row = $dbw->selectRow( 'job', '*',
- 'job_id >= ' . mt_rand( $row->minjob, $row->maxjob ), __METHOD__ );
- if ( $row === false ) {
- // Random job gone before we got the chance to select it
- // Give up
- $dbw->rollback( __METHOD__ );
- wfProfileOut( __METHOD__ );
- return false;
- }
- // Delete the random row
- $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
- $affected = $dbw->affectedRows();
- $dbw->commit( __METHOD__ );
-
- if ( !$affected ) {
- // Random job gone before we exclusively deleted it
- // Give up
- wfProfileOut( __METHOD__ );
- return false;
- }
- }
-
- // If execution got to here, there's a row in $row that has been deleted from the database
- // by this thread. Hence the concurrent pop was successful.
- wfIncrStats( 'job-pop' );
- $namespace = $row->job_namespace;
- $dbkey = $row->job_title;
- $title = Title::makeTitleSafe( $namespace, $dbkey );
-
- if ( is_null( $title ) ) {
- wfProfileOut( __METHOD__ );
- return false;
- }
-
- $job = Job::factory( $row->job_cmd, $title, Job::extractBlob( $row->job_params ), $row->job_id );
-
- // Remove any duplicates it may have later in the queue
- $job->removeDuplicates();
-
- wfProfileOut( __METHOD__ );
- return $job;
- }
-
/**
* Create the appropriate object to handle a specific job
*
* @throws MWException
* @return Job
*/
- static function factory( $command, Title $title, $params = false, $id = 0 ) {
+ public static function factory( $command, Title $title, $params = false, $id = 0 ) {
global $wgJobClasses;
if( isset( $wgJobClasses[$command] ) ) {
$class = $wgJobClasses[$command];
throw new MWException( "Invalid job command `{$command}`" );
}
- /**
- * @param $params
- * @return string
- */
- static function makeBlob( $params ) {
- if ( $params !== false ) {
- return serialize( $params );
- } else {
- return '';
- }
- }
-
- /**
- * @param $blob
- * @return bool|mixed
- */
- static function extractBlob( $blob ) {
- if ( (string)$blob !== '' ) {
- return unserialize( $blob );
- } else {
- return false;
- }
- }
-
/**
* Batch-insert a group of jobs into the queue.
* This will be wrapped in a transaction with a forced commit.
* removed later on, when the first one is popped.
*
* @param $jobs array of Job objects
+ * @deprecated 1.20
*/
- static function batchInsert( $jobs ) {
- if ( !count( $jobs ) ) {
- return;
- }
- $dbw = wfGetDB( DB_MASTER );
- $rows = array();
-
- /**
- * @var $job Job
- */
- foreach ( $jobs as $job ) {
- $rows[] = $job->insertFields();
- if ( count( $rows ) >= 50 ) {
- # Do a small transaction to avoid slave lag
- $dbw->begin( __METHOD__ );
- $dbw->insert( 'job', $rows, __METHOD__, 'IGNORE' );
- $dbw->commit( __METHOD__ );
- $rows = array();
- }
- }
- if ( $rows ) { // last chunk
- $dbw->begin( __METHOD__ );
- $dbw->insert( 'job', $rows, __METHOD__, 'IGNORE' );
- $dbw->commit( __METHOD__ );
- }
- wfIncrStats( 'job-insert', count( $jobs ) );
+ public static function batchInsert( $jobs ) {
+ return JobQueueGroup::singleton()->push( $jobs );
}
/**
* large batches of jobs can cause slave lag.
*
* @param $jobs array of Job objects
+ * @deprecated 1.20
*/
- static function safeBatchInsert( $jobs ) {
- if ( !count( $jobs ) ) {
- return;
- }
- $dbw = wfGetDB( DB_MASTER );
- $rows = array();
- foreach ( $jobs as $job ) {
- $rows[] = $job->insertFields();
- if ( count( $rows ) >= 500 ) {
- $dbw->insert( 'job', $rows, __METHOD__, 'IGNORE' );
- $rows = array();
- }
- }
- if ( $rows ) { // last chunk
- $dbw->insert( 'job', $rows, __METHOD__, 'IGNORE' );
- }
- wfIncrStats( 'job-insert', count( $jobs ) );
- }
-
-
- /**
- * SQL conditions to apply on most JobQueue queries
- *
- * Whenever we exclude jobs types from the default queue, we want to make
- * sure that queries to the job queue actually ignore them.
- *
- * @return array SQL conditions suitable for Database:: methods
- */
- static function defaultQueueConditions( ) {
- global $wgJobTypesExcludedFromDefaultQueue;
- $conditions = array();
- if ( count( $wgJobTypesExcludedFromDefaultQueue ) > 0 ) {
- $dbr = wfGetDB( DB_SLAVE );
- foreach ( $wgJobTypesExcludedFromDefaultQueue as $cmdType ) {
- $conditions[] = "job_cmd != " . $dbr->addQuotes( $cmdType );
- }
- }
- return $conditions;
+ public static function safeBatchInsert( $jobs ) {
+ return JobQueueGroup::singleton()->push( $jobs, JobQueue::QoS_Atomic );
}
/*-------------------------------------------------------------------------
* @param $params array|bool
* @param $id int
*/
- function __construct( $command, $title, $params = false, $id = 0 ) {
+ public function __construct( $command, $title, $params = false, $id = 0 ) {
$this->command = $command;
$this->title = $title;
$this->params = $params;
$this->id = $id;
- // A bit of premature generalisation
- // Oh well, the whole class is premature generalisation really
- $this->removeDuplicates = true;
+ $this->removeDuplicates = false; // expensive jobs may set this to true
}
/**
- * Insert a single job into the queue.
- * @return bool true on success
+ * @return integer May be 0 for jobs stored outside the DB
*/
- function insert() {
- $fields = $this->insertFields();
+ public function getId() {
+ return $this->id;
+ }
- $dbw = wfGetDB( DB_MASTER );
+ /**
+ * @return string
+ */
+ public function getType() {
+ return $this->command;
+ }
- if ( $this->removeDuplicates ) {
- $res = $dbw->select( 'job', array( '1' ), $fields, __METHOD__ );
- if ( $dbw->numRows( $res ) ) {
- return true;
- }
- }
- wfIncrStats( 'job-insert' );
- return $dbw->insert( 'job', $fields, __METHOD__ );
+ /**
+ * @return Title
+ */
+ public function getTitle() {
+ return $this->title;
}
/**
* @return array
*/
- protected function insertFields() {
- $dbw = wfGetDB( DB_MASTER );
- return array(
- 'job_id' => $dbw->nextSequenceValue( 'job_job_id_seq' ),
- 'job_cmd' => $this->command,
- 'job_namespace' => $this->title->getNamespace(),
- 'job_title' => $this->title->getDBkey(),
- 'job_timestamp' => $dbw->timestamp(),
- 'job_params' => Job::makeBlob( $this->params )
- );
+ public function getParams() {
+ return $this->params;
}
/**
- * Remove jobs in the job queue which are duplicates of this job.
- * This is deadlock-prone and so starts its own transaction.
+ * @return bool
*/
- function removeDuplicates() {
- if ( !$this->removeDuplicates ) {
- return;
- }
+ public function ignoreDuplicates() {
+ return $this->removeDuplicates;
+ }
- $fields = $this->insertFields();
- unset( $fields['job_id'] );
- unset( $fields['job_timestamp'] );
- $dbw = wfGetDB( DB_MASTER );
- $dbw->begin( __METHOD__ );
- $dbw->delete( 'job', $fields, __METHOD__ );
- $affected = $dbw->affectedRows();
- $dbw->commit( __METHOD__ );
- if ( $affected ) {
- wfIncrStats( 'job-dup-delete', $affected );
- }
+ /**
+ * Insert a single job into the queue.
+ * @return bool true on success
+ * @deprecated 1.20
+ */
+ public function insert() {
+ return JobQueueGroup::singleton()->push( $this );
}
/**
* @return string
*/
- function toString() {
+ public function toString() {
$paramString = '';
if ( $this->params ) {
foreach ( $this->params as $key => $value ) {
$this->error = $error;
}
- function getLastError() {
+ public function getLastError() {
return $this->error;
}
}
--- /dev/null
+<?php
+/**
+ * Job queue base 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
+ * @defgroup JobQueue JobQueue
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class to handle enqueueing and running of background jobs
+ *
+ * @ingroup JobQueue
+ * @since 1.20
+ */
+abstract class JobQueue {
+ protected $wiki; // string; wiki ID
+ protected $type; // string; job type
+
+ const QoS_Atomic = 1; // integer; "all-or-nothing" job insertions
+
+ /**
+ * @param $params array
+ */
+ protected function __construct( array $params ) {
+ $this->wiki = $params['wiki'];
+ $this->type = $params['type'];
+ }
+
+ /**
+ * Get a job queue object of the specified type.
+ * $params includes:
+ * class : what job class to use (determines job type)
+ * wiki : wiki ID of the wiki the jobs are for (defaults to current wiki)
+ * type : The name of the job types this queue handles
+ *
+ * @param $params array
+ * @return JobQueue
+ * @throws MWException
+ */
+ final public static function factory( array $params ) {
+ $class = $params['class'];
+ if ( !MWInit::classExists( $class ) ) {
+ throw new MWException( "Invalid job queue class '$class'." );
+ }
+ $obj = new $class( $params );
+ if ( !( $obj instanceof self ) ) {
+ throw new MWException( "Class '$class' is not a " . __CLASS__ . " class." );
+ }
+ return $obj;
+ }
+
+ /**
+ * @return string Wiki ID
+ */
+ final public function getWiki() {
+ return $this->wiki;
+ }
+
+ /**
+ * @return string Job type that this queue handles
+ */
+ final public function getType() {
+ return $this->type;
+ }
+
+ /**
+ * @return bool Quickly check if the queue is empty
+ */
+ final public function isEmpty() {
+ wfProfileIn( __METHOD__ );
+ $res = $this->doIsEmpty();
+ wfProfileOut( __METHOD__ );
+ return $res;
+ }
+
+ /**
+ * @see JobQueue::isEmpty()
+ * @return bool
+ */
+ abstract protected function doIsEmpty();
+
+ /**
+ * Push a batch of jobs into the queue
+ *
+ * @param $jobs array List of Jobs
+ * @param $flags integer Bitfield (supports JobQueue::QoS_Atomic)
+ * @return bool
+ */
+ final public function batchPush( array $jobs, $flags = 0 ) {
+ 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 );
+ if ( $ok ) {
+ wfIncrStats( 'job-insert', count( $jobs ) );
+ }
+ wfProfileOut( __METHOD__ );
+ return $ok;
+ }
+
+ /**
+ * @see JobQueue::batchPush()
+ * @return bool
+ */
+ abstract protected function doBatchPush( array $jobs, $flags );
+
+ /**
+ * Pop a job off of the queue
+ *
+ * @return Job|bool Returns false on failure
+ */
+ final public function pop() {
+ wfProfileIn( __METHOD__ );
+ $job = $this->doPop();
+ if ( $job ) {
+ wfIncrStats( 'job-pop' );
+ }
+ wfProfileOut( __METHOD__ );
+ return $job;
+ }
+
+ /**
+ * @see JobQueue::pop()
+ * @return Job
+ */
+ abstract protected function doPop();
+
+ /**
+ * Acknowledge that a job was completed
+ *
+ * @param $job Job
+ * @return bool
+ */
+ final public function ack( Job $job ) {
+ if ( $job->getType() !== $this->type ) {
+ throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
+ }
+ wfProfileIn( __METHOD__ );
+ $ok = $this->doAck( $job );
+ wfProfileOut( __METHOD__ );
+ return $ok;
+ }
+
+ /**
+ * @see JobQueue::ack()
+ * @return bool
+ */
+ abstract protected function doAck( Job $job );
+
+ /**
+ * Wait for any slaves or backup servers to catch up
+ *
+ * @return void
+ */
+ final public function waitForBackups() {
+ wfProfileIn( __METHOD__ );
+ $this->doWaitForBackups();
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * @see JobQueue::waitForBackups()
+ * @return void
+ */
+ protected function doWaitForBackups() {}
+}
--- /dev/null
+<?php
+/**
+ * Database-backed job queue 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 job queues stored in the DB
+ *
+ * @ingroup JobQueue
+ * @since 1.20
+ */
+class JobQueueDB extends JobQueue {
+ const CACHE_TTL = 30; // integer; seconds
+ const MAX_JOB_RANDOM = 2147483647; // 2^31 - 1; used for job_random
+
+ /**
+ * @see JobQueue::doIsEmpty()
+ * @return bool
+ */
+ protected function doIsEmpty() {
+ global $wgMemc;
+
+ $key = $this->getEmptinessCacheKey();
+
+ $isEmpty = $wgMemc->get( $key );
+ if ( $isEmpty === 'true' ) {
+ return true;
+ } elseif ( $isEmpty === 'false' ) {
+ return false;
+ }
+
+ $found = $this->getSlaveDB()->selectField(
+ 'job', '1', array( 'job_cmd' => $this->type ), __METHOD__
+ );
+
+ $wgMemc->add( $key, $found ? 'false' : 'true', self::CACHE_TTL );
+ }
+
+ /**
+ * @see JobQueue::doBatchPush()
+ * @return bool
+ */
+ protected function doBatchPush( array $jobs, $flags ) {
+ if ( count( $jobs ) ) {
+ $dbw = $this->getMasterDB();
+
+ $rows = array();
+ foreach ( $jobs as $job ) {
+ $rows[] = $this->insertFields( $job );
+ }
+ $atomic = ( $flags & self::QoS_Atomic );
+ $key = $this->getEmptinessCacheKey();
+ $ttl = self::CACHE_TTL;
+
+ $dbw->onTransactionIdle( function() use ( $dbw, $rows, $atomic, $key, $ttl ) {
+ global $wgMemc;
+
+ $autoTrx = $dbw->getFlag( DBO_TRX ); // automatic begin() enabled?
+ if ( $atomic ) {
+ $dbw->begin(); // wrap all the job additions in one transaction
+ } else {
+ $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
+ }
+ try {
+ foreach ( array_chunk( $rows, 50 ) as $rowBatch ) { // avoid slave lag
+ $dbw->insert( 'job', $rowBatch, __METHOD__ );
+ }
+ } catch ( DBError $e ) {
+ if ( $atomic ) {
+ $dbw->rollback();
+ } else {
+ $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
+ }
+ throw $e;
+ }
+ if ( $atomic ) {
+ $dbw->commit();
+ } else {
+ $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
+ }
+
+ $wgMemc->set( $key, 'false', $ttl );
+ } );
+ }
+
+ return true;
+ }
+
+ /**
+ * @see JobQueue::doPop()
+ * @return Job|bool
+ */
+ protected function doPop() {
+ global $wgMemc;
+
+ $uuid = wfRandomString( 32 ); // pop attempt
+
+ $dbw = $this->getMasterDB();
+ $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
+
+ $job = false; // job popped off
+ $autoTrx = $dbw->getFlag( DBO_TRX ); // automatic begin() enabled?
+ $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
+ try {
+ do { // retry when our row is invalid or deleted as a duplicate
+ $row = false; // row claimed
+ $rand = mt_rand( 0, self::MAX_JOB_RANDOM ); // encourage concurrent UPDATEs
+ $gte = (bool)mt_rand( 0, 1 ); // find rows with rand before/after $rand
+ // Try to reserve a DB row...
+ if ( $this->claim( $uuid, $rand, $gte ) || $this->claim( $uuid, $rand, !$gte ) ) {
+ // Fetch any row that we just reserved...
+ $row = $dbw->selectRow( 'job', '*',
+ array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__ );
+ // Check if another process deleted it as a duplicate
+ if ( !$row ) {
+ wfDebugLog( 'JobQueueDB', "Row deleted as duplicate by another process." );
+ continue; // try again
+ }
+ // Get the job object from the row...
+ $title = Title::makeTitleSafe( $row->job_namespace, $row->job_title );
+ if ( !$title ) {
+ $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
+ wfDebugLog( 'JobQueueDB', "Row has invalid title '{$row->job_title}'." );
+ continue; // try again
+ }
+ $job = Job::factory( $row->job_cmd, $title,
+ self::extractBlob( $row->job_params ), $row->job_id );
+ // Delete any *other* duplicate jobs in the queue...
+ if ( $job->ignoreDuplicates() && strlen( $row->job_sha1 ) ) {
+ $dbw->delete( 'job',
+ array( 'job_sha1' => $row->job_sha1,
+ "job_id != {$dbw->addQuotes( $row->job_id )}" ),
+ __METHOD__
+ );
+ }
+ } else {
+ $wgMemc->set( $this->getEmptinessCacheKey(), 'true', self::CACHE_TTL );
+ }
+ break; // done
+ } while( true );
+ } catch ( DBError $e ) {
+ $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
+ throw $e;
+ }
+ $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
+
+ return $job;
+ }
+
+ /**
+ * Reserve a row with a single UPDATE without holding row locks over RTTs...
+ * @param $uuid string 32 char hex string
+ * @param $rand integer Random unsigned integer (31 bits)
+ * @param $gte bool Search for job_random >= $random (otherwise job_random <= $random)
+ * @return integer Number of affected rows
+ */
+ protected function claim( $uuid, $rand, $gte ) {
+ $dbw = $this->getMasterDB();
+ $dir = $gte ? 'ASC' : 'DESC';
+ $ineq = $gte ? '>=' : '<=';
+ if ( $dbw->getType() === 'mysql' ) {
+ // Per http://bugs.mysql.com/bug.php?id=6980, we can't use subqueries on the
+ // same table being changed in an UPDATE query in MySQL (gives Error: 1093).
+ // Oracle and Postgre have no such limitation. However, MySQL offers an
+ // alternative here by supporting ORDER BY + LIMIT for UPDATE queries.
+ // The DB wrapper functions do not support this, so it's done manually.
+ $dbw->query( "UPDATE {$dbw->tableName( 'job' )}
+ SET
+ job_token = {$dbw->addQuotes( $uuid ) },
+ job_token_timestamp = {$dbw->addQuotes( $dbw->timestamp() )}
+ WHERE (
+ job_cmd = {$dbw->addQuotes( $this->type )}
+ AND job_token = {$dbw->addQuotes( '' )}
+ AND job_random {$ineq} {$dbw->addQuotes( $rand )}
+ ) ORDER BY job_random {$dir} LIMIT 1",
+ __METHOD__
+ );
+ } else {
+ // Use a subquery to find the job, within an UPDATE to claim it.
+ // This uses as much of the DB wrapper functions as possible.
+ $dbw->update( 'job',
+ array( 'job_token' => $uuid, 'job_token_timestamp' => $dbw->timestamp() ),
+ array( 'job_id = (' .
+ $dbw->selectSQLText( 'job', 'job_id',
+ array(
+ 'job_cmd' => $this->type,
+ 'job_token' => '',
+ "job_random {$ineq} {$dbw->addQuotes( $rand )}" ),
+ __METHOD__,
+ array( 'ORDER BY' => "job_random {$dir}", 'LIMIT' => 1 ) ) .
+ ')'
+ ),
+ __METHOD__
+ );
+ }
+ return $dbw->affectedRows();
+ }
+
+ /**
+ * @see JobQueue::doAck()
+ * @return Job|bool
+ */
+ protected function doAck( Job $job ) {
+ $dbw = $this->getMasterDB();
+ if ( $dbw->trxLevel() ) {
+ wfWarn( "Attempted to ack a job in a transaction; committing first." );
+ $dbw->commit(); // push existing transaction
+ }
+
+ $autoTrx = $dbw->getFlag( DBO_TRX ); // automatic begin() enabled?
+ $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
+ try {
+ // Delete a row with a single DELETE without holding row locks over RTTs...
+ $dbw->delete( 'job', array( 'job_cmd' => $this->type, 'job_id' => $job->getId() ) );
+ } catch ( Exception $e ) {
+ $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
+ throw $e;
+ }
+ $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
+
+ return true;
+ }
+
+ /**
+ * @see JobQueue::doWaitForBackups()
+ * @return void
+ */
+ protected function doWaitForBackups() {
+ wfWaitForSlaves();
+ }
+
+ /**
+ * @return DatabaseBase
+ */
+ protected function getSlaveDB() {
+ return wfGetDB( DB_SLAVE, array(), $this->wiki );
+ }
+
+ /**
+ * @return DatabaseBase
+ */
+ protected function getMasterDB() {
+ return wfGetDB( DB_MASTER, array(), $this->wiki );
+ }
+
+ /**
+ * @param $job Job
+ * @return array
+ */
+ protected function insertFields( Job $job ) {
+ // Rows that describe the nature of the job
+ $descFields = array(
+ 'job_cmd' => $job->getType(),
+ 'job_namespace' => $job->getTitle()->getNamespace(),
+ 'job_title' => $job->getTitle()->getDBkey(),
+ 'job_params' => self::makeBlob( $job->getParams() ),
+ );
+ // Additional job metadata
+ $dbw = $this->getMasterDB();
+ $metaFields = array(
+ 'job_id' => $dbw->nextSequenceValue( 'job_job_id_seq' ),
+ 'job_timestamp' => $dbw->timestamp(),
+ 'job_sha1' => wfBaseConvert( sha1( serialize( $descFields ) ), 16, 36, 32 ),
+ 'job_random' => mt_rand( 0, self::MAX_JOB_RANDOM )
+ );
+ return ( $descFields + $metaFields );
+ }
+
+ /**
+ * @return string
+ */
+ private function getEmptinessCacheKey() {
+ list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+ return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, 'isempty' );
+ }
+
+ /**
+ * @param $params
+ * @return string
+ */
+ protected static function makeBlob( $params ) {
+ if ( $params !== false ) {
+ return serialize( $params );
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * @param $blob
+ * @return bool|mixed
+ */
+ protected static function extractBlob( $blob ) {
+ if ( (string)$blob !== '' ) {
+ return unserialize( $blob );
+ } else {
+ return false;
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * Job queue base 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 enqueueing of background jobs
+ *
+ * @ingroup JobQueue
+ * @since 1.20
+ */
+class JobQueueGroup {
+ /** @var Array */
+ protected static $instances = array();
+
+ protected $wiki; // string; wiki ID
+
+ const TYPE_DEFAULT = 1; // integer; job not in $wgJobTypesExcludedFromDefaultQueue
+ const TYPE_ANY = 2; // integer; any job
+
+ /**
+ * @param $wiki string Wiki ID
+ */
+ protected function __construct( $wiki ) {
+ $this->wiki = $wiki;
+ }
+
+ /**
+ * @param $wiki string Wiki ID
+ * @return JobQueueGroup
+ */
+ public static function singleton( $wiki = false ) {
+ $wiki = ( $wiki === false ) ? wfWikiID() : $wiki;
+ if ( !isset( self::$instances[$wiki] ) ) {
+ self::$instances[$wiki] = new self( $wiki );
+ }
+ return self::$instances[$wiki];
+ }
+
+ /**
+ * @param $type string
+ * @return JobQueue Job queue object for a given queue type
+ */
+ public function get( $type ) {
+ global $wgJobTypeConf;
+
+ $conf = false;
+ if ( isset( $wgJobTypeConf[$type] ) ) {
+ $conf = $wgJobTypeConf[$type];
+ } else {
+ $conf = $wgJobTypeConf['default'];
+ }
+
+ return JobQueue::factory( array(
+ 'class' => $conf['class'],
+ 'wiki' => $this->wiki,
+ 'type' => $type,
+ ) );
+ }
+
+ /**
+ * Insert jobs into the respective queues of with the belong
+ *
+ * @param $jobs Job|array A single Job or a list of Jobs
+ * @return bool
+ */
+ public function push( $jobs ) {
+ $jobs = (array)$jobs;
+
+ $jobsByType = array(); // (job type => list of jobs)
+ foreach ( $jobs as $job ) {
+ $jobsByType[$job->getType()][] = $job;
+ }
+
+ $ok = true;
+ foreach ( $jobsByType as $type => $jobs ) {
+ if ( !$this->get( $type )->batchPush( $jobs ) ) {
+ $ok = false;
+ }
+ }
+
+ return $ok;
+ }
+
+ /**
+ * Pop a job off one of the job queues
+ *
+ * @param $type integer JobQueueGroup::TYPE_* constant
+ * @return Job|bool Returns false on failure
+ */
+ public function pop( $type = self::TYPE_DEFAULT ) {
+ $types = ( $type == self::TYPE_DEFAULT )
+ ? $this->getDefaultQueueTypes()
+ : $this->getQueueTypes();
+ shuffle( $types ); // avoid starvation
+
+ foreach ( $types as $type ) { // for each queue...
+ $job = $this->get( $type )->pop();
+ if ( $job ) {
+ return $job; // found
+ }
+ }
+
+ return false; // no jobs found
+ }
+
+ /**
+ * Acknowledge that a job was completed
+ *
+ * @param $job Job
+ * @return bool
+ */
+ public function ack( Job $job ) {
+ return $this->get( $job->getType() )->ack( $job );
+ }
+
+ /**
+ * Get the list of queue types
+ *
+ * @return array List of strings
+ */
+ public function getQueueTypes() {
+ global $wgJobClasses;
+
+ return array_keys( $wgJobClasses );
+ }
+
+ /**
+ * Get the list of default queue types
+ *
+ * @return array List of strings
+ */
+ public function getDefaultQueueTypes() {
+ global $wgJobTypesExcludedFromDefaultQueue;
+
+ return array_diff( $this->getQueueTypes(), $wgJobTypesExcludedFromDefaultQueue );
+ }
+}
* @ingroup JobQueue
*/
class RefreshLinksJob extends Job {
-
function __construct( $title, $params = '', $id = 0 ) {
parent::__construct( 'refreshLinks', $title, $params, $id );
+ $this->removeDuplicates = true; // job is expensive
}
/**
/**
* Constructor.
- *
+ *
* @since 1.19
- *
+ *
* @param string $type
* @param string $subtype
*/
* '4:color' => 'blue',
* 'animal' => 'dog'
* );
- *
+ *
* @since 1.19
- *
+ *
* @param $parameters array Associative array
*/
public function setParameters( $parameters ) {
/**
* Set the user that performed the action being logged.
- *
+ *
* @since 1.19
- *
+ *
* @param User $performer
*/
public function setPerformer( User $performer ) {
/**
* Set the title of the object changed.
- *
+ *
* @since 1.19
- *
+ *
* @param Title $target
*/
public function setTarget( Title $target ) {
/**
* Set the timestamp of when the logged action took place.
- *
+ *
* @since 1.19
- *
+ *
* @param string $timestamp
*/
public function setTimestamp( $timestamp ) {
/**
* Set a comment associated with the action being logged.
- *
+ *
* @since 1.19
- *
+ *
* @param string $comment
*/
public function setComment( $comment ) {
/**
* TODO: document
- *
+ *
* @since 1.19
- *
+ *
* @param integer $deleted
*/
public function setDeleted( $deleted ) {
}
/**
- * Generate text for a log entry.
+ * Generate text for a log entry.
* Only LogFormatter should call this function.
*
* @param $type String: log type
$linked = true;
if ( isset( $this->mLinked ) )
$linked = $this->mLinked;
-
+
$bits = array();
$key = $this->keys[$this->mSource];
for ( $p=0; $p < strlen($key); $p++ ) {
*/
function formatDate( $bits, $link = true ) {
$format = $this->targets[$this->mTarget];
-
+
if (!$link) {
// strip piped links
$format = preg_replace( '/\[\[[^|]+\|([^\]]+)\]\]/', '$1', $format );
/**
* Don't serialize the parent object, it is big, and not needed when it is
- * a parameter to mergeForeign(), which is the only application of
+ * a parameter to mergeForeign(), which is the only application of
* serializing at present.
*
* Compact the titles, only serialize the text form.
}
/**
- * Merge a LinkHolderArray from another parser instance into this one. The
- * keys will not be preserved. Any text which went with the old
- * LinkHolderArray and needs to work with the new one should be passed in
+ * Merge a LinkHolderArray from another parser instance into this one. The
+ * keys will not be preserved. Any text which went with the old
+ * LinkHolderArray and needs to work with the new one should be passed in
* the $texts array. The strings in this array will have their link holders
* converted for use in the destination link holder. The resulting array of
* strings will be returned.
$maxId = $newKey > $maxId ? $newKey : $maxId;
}
}
- $texts = preg_replace_callback( '/(<!--LINK \d+:)(\d+)(-->)/',
+ $texts = preg_replace_callback( '/(<!--LINK \d+:)(\d+)(-->)/',
array( $this, 'mergeForeignCallback' ), $texts );
# Renumber interwiki links
$this->interwikis[$newKey] = $entry;
$maxId = $newKey > $maxId ? $newKey : $maxId;
}
- $texts = preg_replace_callback( '/(<!--IWLINK )(\d+)(-->)/',
+ $texts = preg_replace_callback( '/(<!--IWLINK )(\d+)(-->)/',
array( $this, 'mergeForeignCallback' ), $texts );
# Set the parent link ID to be beyond the highest used ID
# Internal links
$pos = 0;
while ( $pos < strlen( $text ) ) {
- if ( !preg_match( '/<!--LINK (\d+):(\d+)-->/',
- $text, $m, PREG_OFFSET_CAPTURE, $pos ) )
+ if ( !preg_match( '/<!--LINK (\d+):(\d+)-->/',
+ $text, $m, PREG_OFFSET_CAPTURE, $pos ) )
{
break;
}
wfDebug( "ParserOutput cache found.\n" );
- // The edit section preference may not be the appropiate one in
- // the ParserOutput, as we are not storing it in the parsercache
+ // The edit section preference may not be the appropiate one in
+ // the ParserOutput, as we are not storing it in the parsercache
// key. Force it here. See bug 31445.
$value->setEditSectionTokens( $popts->getEditSection() );
* @ingroup Parser
*/
class ParserOptions {
-
+
/**
* Use DateFormatter to format dates
*/
var $mUseDynamicDates;
-
+
/**
* Interlanguage links are removed and returned in an array
*/
var $mInterwikiMagic;
-
+
/**
* Allow external images inline?
*/
var $mAllowExternalImages;
-
+
/**
* If not, any exception?
*/
var $mAllowExternalImagesFrom;
-
+
/**
* If not or it doesn't match, should we check an on-wiki whitelist?
*/
var $mEnableImageWhitelist;
-
+
/**
* Date format index
*/
var $mDateFormat = null;
-
+
/**
* Create "edit section" links?
*/
var $mEditSection = true;
-
+
/**
* Allow inclusion of special pages?
*/
var $mAllowSpecialInclusion;
-
+
/**
* Use tidy to cleanup output HTML?
*/
var $mTidy = false;
-
+
/**
* Which lang to call for PLURAL and GRAMMAR
*/
var $mInterfaceMessage = false;
-
+
/**
* Overrides $mInterfaceMessage with arbitrary language
*/
var $mTargetLanguage = null;
-
+
/**
* Maximum size of template expansions, in bytes
*/
var $mMaxIncludeSize;
-
+
/**
* Maximum number of nodes touched by PPFrame::expand()
*/
* Maximum number of nodes generated by Preprocessor::preprocessToObj()
*/
var $mMaxGeneratedPPNodeCount;
-
+
/**
* Maximum recursion depth in PPFrame::expand()
*/
var $mMaxPPExpandDepth;
-
+
/**
* Maximum recursion depth for templates within templates
*/
var $mMaxTemplateDepth;
-
+
/**
* Maximum number of calls per parse to expensive parser functions
*/
var $mExpensiveParserFunctionLimit;
-
+
/**
* Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
*/
var $mRemoveComments = true;
-
+
/**
* Callback for template fetching. Used as first argument to call_user_func().
*/
var $mTemplateCallback =
array( 'Parser', 'statelessFetchTemplate' );
-
+
/**
* Enable limit report in an HTML comment on output
*/
var $mEnableLimitReport = false;
-
+
/**
* Timestamp used for {{CURRENTDAY}} etc.
*/
var $mTimestamp;
-
+
/**
* Target attribute for external links
*/
var $mExternalLinkTarget;
-
+
/**
- * Clean up signature texts?
+ * Clean up signature texts?
*
* 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
* 2) Substitute all transclusions
*/
var $mCleanSignatures;
-
+
/**
* Transform wiki markup when saving the page?
*/
* Automatically number headings?
*/
var $mNumberHeadings;
-
+
/**
* User math preference (as integer). Not used (1.19)
*/
var $mMath;
-
+
/**
* Thumb size preferred by the user.
*/
var $mThumbSize;
-
+
/**
* Maximum article size of an article to be marked as "stub"
*/
private $mStubThreshold;
-
+
/**
* Language object of the User language.
*/
var $mUserLang;
/**
- * @var User
+ * @var User
* Stored user object
*/
var $mUser;
-
+
/**
* Parsing the page for a "preview" operation?
*/
var $mIsPreview = false;
-
+
/**
* Parsing the page for a "preview" operation on a single section?
*/
var $mIsSectionPreview = false;
-
+
/**
* Parsing the printable version of the page?
*/
return new ParserOptions( $context->getUser(), $context->getLanguage() );
}
- /**
- * Get user options
+ /**
+ * Get user options
*
* @param $user User object
* @param $lang Language object
* can automatically discard old data.
*/
const VERSION = '1.6.4';
-
+
# Flags for Parser::setLinkHook
# Also available as global constants from Defines.php
const SLH_PATTERN = 1;
$this->mLinkHooks[$ns] = array( $callback, $flags );
return $oldVal;
}
-
+
/**
* Get all registered link hook identifiers
*
}
$holders = new LinkHolderArray( $this );
-
+
if( is_null( $this->mTitle ) ) {
wfProfileOut( __METHOD__ );
wfProfileOut( __METHOD__.'-setup' );
}
wfProfileOut( __METHOD__.'-setup' );
-
+
$offset = 0;
$offsetStack = array();
$markers = new LinkMarkerReplacer( $this, $holders, array( &$this, 'replaceInternalLinksCallback' ) );
$startBracketOffset = array_pop($offsetStack);
# Just to clean up the code, lets place offsets on the outer ends
$endBracketOffset += 2;
-
+
# Only do logic if we actually have a opening bracket for this
if( isset($startBracketOffset) ) {
# Extract text inside the link
# ToDO: Some LinkHooks use patterns rather than namespaces
# these need to be tested at this point here
}
-
}
# Bump our offset to after our current bracket
$offset = $bracketOffset+2;
}
-
-
+
# Now expand our tree
wfProfileIn( __METHOD__.'-expand' );
$s = $markers->expand( $s );
wfProfileOut( __METHOD__.'-expand' );
-
+
wfProfileOut( __METHOD__ );
return $holders;
}
-
+
function replaceInternalLinksCallback( $parser, $holders, $markers, $titleText, $paramText ) {
wfProfileIn( __METHOD__ );
$wt = isset($paramText) ? "[[$titleText|$paramText]]" : "[[$titleText]]";
wfProfileOut( __METHOD__ );
return $wt;
}
-
+
# Make subpage if necessary
if( $this->areSubpagesAllowed() ) {
$titleText = $this->maybeDoSubpageLink( $titleText, $paramText );
}
-
+
# Check for a leading colon and strip it if it is there
$leadingColon = $titleText[0] == ':';
if( $leadingColon ) $titleText = substr( $titleText, 1 );
-
+
wfProfileOut( __METHOD__."-misc" );
# Make title object
wfProfileIn( __METHOD__."-title" );
}
$ns = $title->getNamespace();
wfProfileOut( __METHOD__."-title" );
-
+
# Default for Namespaces is a default link
# ToDo: Default for patterns is plain wikitext
$return = true;
}
if( $return === true ) {
# True (treat as plain link) was returned, call the defaultLinkHook
- $return = CoreLinkFunctions::defaultLinkHook( $parser, $holders, $markers, $title,
+ $return = CoreLinkFunctions::defaultLinkHook( $parser, $holders, $markers, $title,
$titleText, $paramText, $leadingColon );
}
if( $return === false ) {
wfProfileOut( __METHOD__ );
return $return;
}
-
+
}
class LinkMarkerReplacer {
-
+
protected $markers, $nextId, $parser, $holders, $callback;
-
+
function __construct( $parser, $holders, $callback ) {
$this->nextId = 0;
$this->markers = array();
$this->holders = $holders;
$this->callback = $callback;
}
-
+
function addMarker($titleText, $paramText) {
$id = $this->nextId++;
$this->markers[$id] = array( $titleText, $paramText );
return "<!-- LINKMARKER $id -->";
}
-
+
function findMarker( $string ) {
return (bool) preg_match('/<!-- LINKMARKER [0-9]+ -->/', $string );
}
-
+
function expand( $string ) {
return StringUtils::delimiterReplaceCallback( "<!-- LINKMARKER ", " -->", array( &$this, 'callback' ), $string );
}
-
+
function callback( $m ) {
$id = intval($m[1]);
if( !array_key_exists($id, $this->markers) ) return $m[0];
array_unshift( $args, $this->parser );
return call_user_func_array( $this->callback, $args );
}
-
}
}
// Fail if the number of elements exceeds acceptable limits
- // Do not attempt to generate the DOM
+ // Do not attempt to generate the DOM
$this->parser->mGeneratedPPNodeCount += substr_count( $xml, '<' );
$max = $this->parser->mOptions->getMaxGeneratedPPNodeCount();
if ( $this->parser->mGeneratedPPNodeCount > $max ) {
* @return mixed
*/
protected function unstripType( $type, $text ) {
- // Shortcut
+ // Shortcut
if ( !count( $this->data[$type] ) ) {
return $text;
}
. '</span>';
}
if ( $this->recursionLevel >= self::UNSTRIP_RECURSION_LIMIT ) {
- return '<span class="error">' .
+ return '<span class="error">' .
wfMessage( 'parser-unstrip-recursion-limit' )
->numParams( self::UNSTRIP_RECURSION_LIMIT )->inContentLanguage()->text() .
'</span>';
}
/**
- * Get a StripState object which is sufficient to unstrip the given text.
+ * Get a StripState object which is sufficient to unstrip the given text.
* It will contain the minimum subset of strip items necessary.
*
* @param $text string
protected function readStyleFile( $path, $flip ) {
$localPath = $this->getLocalPath( $path );
if ( !file_exists( $localPath ) ) {
- throw new MWException( __METHOD__.": style file not found: \"$localPath\"" );
+ $msg = __METHOD__.": style file not found: \"$localPath\"";
+ wfDebugLog( 'resourceloader', $msg );
+ throw new MWException( $msg );
}
$style = file_get_contents( $localPath );
if ( $flip ) {
--- /dev/null
+<?php
+
+/**
+ * Class representing a MediaWiki site.
+ *
+ * @since 1.21
+ *
+ * @file
+ * @ingroup Site
+ *
+ * @licence GNU GPL v2+
+ * @author John Erling Blad < jeblad@gmail.com >
+ * @author Daniel Kinzler
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class MediaWikiSite extends SiteObject {
+
+ const PATH_FILE = 'file_path';
+ const PATH_PAGE = 'page_path';
+
+ /**
+ * @since 1.21
+ *
+ * @param integer $globalId
+ *
+ * @return MediaWikiSite
+ */
+ public static function newFromGlobalId( $globalId ) {
+ return SitesTable::singleton()->newRow( array(
+ 'type' => Site::TYPE_MEDIAWIKI,
+ 'global_key' => $globalId,
+ ), true );
+ }
+
+ /**
+ * Returns the database form of the given title.
+ *
+ * @since 1.21
+ *
+ * @param String $title the target page's title, in normalized form.
+ *
+ * @return String
+ */
+ public function toDBKey( $title ) {
+ return str_replace( ' ', '_', $title );
+ }
+
+ /**
+ * Returns the normalized form of the given page title, using the normalization rules of the given site.
+ * If the given title is a redirect, the redirect weill be resolved and the redirect target is returned.
+ *
+ * @note : This actually makes an API request to the remote site, so beware that this function is slow and depends
+ * on an external service.
+ *
+ * @note : If MW_PHPUNIT_TEST is defined or $egWBRemoteTitleNormalization is set to false, the call to the
+ * external site is skipped, and the title is normalized using the local normalization rules as
+ * implemented by the Title class.
+ *
+ * @see Site::normalizePageName
+ *
+ * @since 1.21
+ *
+ * @param string $pageName
+ *
+ * @return string
+ * @throws MWException
+ */
+ public function normalizePageName( $pageName ) {
+ global $egWBRemoteTitleNormalization;
+
+ // Check if we have strings as arguments.
+ if ( !is_string( $pageName ) ) {
+ throw new MWException( '$pageName must be a string' );
+ }
+
+ // Go on call the external site
+ if ( defined( 'MW_PHPUNIT_TEST' ) ) {
+ // If the code is under test, don't call out to other sites, just normalize locally.
+ // Note: this may cause results to be inconsistent with the actual normalization used by the respective remote site!
+
+ $t = Title::newFromText( $pageName );
+ return $t->getPrefixedText();
+ } else {
+
+ // Make sure the string is normalized into NFC (due to the bug 40017)
+ // but do nothing to the whitespaces, that should work appropriately.
+ // @see https://bugzilla.wikimedia.org/show_bug.cgi?id=40017
+ $pageName = UtfNormal::cleanUp( $pageName );
+
+ // Build the args for the specific call
+ $args = array(
+ 'action' => 'query',
+ 'prop' => 'info',
+ 'redirects' => true,
+ 'converttitles' => true,
+ 'format' => 'json',
+ 'titles' => $pageName,
+ //@todo: options for maxlag and maxage
+ // Note that maxlag will lead to a long delay before a reply is made,
+ // but that maxage can avoid the extreme delay. On the other hand
+ // maxage could be nice to use anyhow as it stops unnecessary requests.
+ // Also consider smaxage if maxage is used.
+ );
+
+ $url = $this->getFileUrl( 'api.php' ) . '?' . wfArrayToCgi( $args );
+
+ // Go on call the external site
+ //@todo: we need a good way to specify a timeout here.
+ $ret = Http::get( $url );
+ }
+
+ if ( $ret === false ) {
+ wfDebugLog( "MediaWikiSite", "call to external site failed: $url" );
+ return false;
+ }
+
+ $data = FormatJson::decode( $ret, true );
+
+ if ( !is_array( $data ) ) {
+ wfDebugLog( "MediaWikiSite", "call to <$url> returned bad json: " . $ret );
+ return false;
+ }
+
+ $page = static::extractPageRecord( $data, $pageName );
+
+ if ( isset( $page['missing'] ) ) {
+ wfDebugLog( "MediaWikiSite", "call to <$url> returned a marker for a missing page title! " . $ret );
+ return false;
+ }
+
+ if ( isset( $page['invalid'] ) ) {
+ wfDebugLog( "MediaWikiSite", "call to <$url> returned a marker for an invalid page title! " . $ret );
+ return false;
+ }
+
+ if ( !isset( $page['title'] ) ) {
+ wfDebugLog( "MediaWikiSite", "call to <$url> did not return a page title! " . $ret );
+ return false;
+ }
+
+ return $page['title'];
+ }
+
+
+ /**
+ * Get normalization record for a given page title from an API response.
+ *
+ * @since 1.21
+ *
+ * @param array $externalData A reply from the API on a external server.
+ * @param string $pageTitle Identifies the page at the external site, needing normalization.
+ *
+ * @return array|false a 'page' structure representing the page identified by $pageTitle.
+ */
+ private static function extractPageRecord( $externalData, $pageTitle ) {
+ // If there is a special case with only one returned page
+ // we can cheat, and only return
+ // the single page in the "pages" substructure.
+ if ( isset( $externalData['query']['pages'] ) ) {
+ $pages = array_values( $externalData['query']['pages'] );
+ if ( count( $pages) === 1 ) {
+ return $pages[0];
+ }
+ }
+ // This is only used during internal testing, as it is assumed
+ // a more optimal (and lossfree) storage.
+ // Make initial checks and return if prerequisites are not meet.
+ if ( !is_array( $externalData ) || !isset( $externalData['query'] ) ) {
+ return false;
+ }
+ // Loop over the tree different named structures, that otherwise are similar
+ $structs = array(
+ 'normalized' => 'from',
+ 'converted' => 'from',
+ 'redirects' => 'from',
+ 'pages' => 'title'
+ );
+ foreach ( $structs as $listId => $fieldId ) {
+ // Check if the substructure exist at all.
+ if ( !isset( $externalData['query'][$listId] ) ) {
+ continue;
+ }
+ // Filter the substructure down to what we actually are using.
+ $collectedHits = array_filter(
+ array_values( $externalData['query'][$listId] ),
+ function( $a ) use ( $fieldId, $pageTitle ) {
+ return $a[$fieldId] === $pageTitle;
+ }
+ );
+ // If still looping over normalization, conversion or redirects,
+ // then we need to keep the new page title for later rounds.
+ if ( $fieldId === 'from' && is_array( $collectedHits ) ) {
+ switch ( count( $collectedHits ) ) {
+ case 0:
+ break;
+ case 1:
+ $pageTitle = $collectedHits[0]['to'];
+ break;
+ default:
+ return false;
+ }
+ }
+ // If on the pages structure we should prepare for returning.
+ elseif ( $fieldId === 'title' && is_array( $collectedHits ) ) {
+ switch ( count( $collectedHits ) ) {
+ case 0:
+ return false;
+ case 1:
+ return array_shift( $collectedHits );
+ default:
+ return false;
+ }
+ }
+ }
+ // should never be here
+ return false;
+ }
+
+ /**
+ * @see Site::getLinkPathType
+ * Returns Site::PATH_PAGE
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getLinkPathType() {
+ return self::PATH_PAGE;
+ }
+
+ /**
+ * Returns the relative page path.
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getRelativePagePath() {
+ return parse_url( $this->getPath( self::PATH_PAGE ), PHP_URL_PATH );
+ }
+
+ /**
+ * Returns the relative file path.
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getRelativeFilePath() {
+ return parse_url( $this->getPath( self::PATH_FILE ), PHP_URL_PATH );
+ }
+
+ /**
+ * Sets the relative page path.
+ *
+ * @since 1.21
+ *
+ * @param string $path
+ */
+ public function setPagePath( $path ) {
+ $this->setPath( self::PATH_PAGE, $path );
+ }
+
+ /**
+ * Sets the relative file path.
+ *
+ * @since 1.21
+ *
+ * @param string $path
+ */
+ public function setFilePath( $path ) {
+ $this->setPath( self::PATH_FILE, $path );
+ }
+
+ /**
+ * @see Site::getPagePath
+ *
+ * This implementation returns a URL constructed using the path returned by getLinkPath().
+ * In addition to the default behaviour implemented by SiteObject::getPageUrl(), this
+ * method converts the $pageName to DBKey-format by replacing spaces with underscores
+ * before using it in the URL.
+ *
+ * @since 1.21
+ *
+ * @param string|false
+ *
+ * @return string
+ */
+ public function getPageUrl( $pageName = false ) {
+ $url = $this->getLinkPath();
+
+ if ( $url === false ) {
+ return false;
+ }
+
+ if ( $pageName !== false ) {
+ $pageName = $this->toDBKey( trim( $pageName ) );
+ $url = str_replace( '$1', wfUrlencode( $pageName ), $url ) ;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Returns the full file path (ie site url + relative file path).
+ * The path should go at the $1 marker. If the $path
+ * argument is provided, the marker will be replaced by it's value.
+ *
+ * @since 1.21
+ *
+ * @param string|false $path
+ *
+ * @return string
+ */
+ public function getFileUrl( $path = false ) {
+ $filePath = $this->getPath( self::PATH_FILE );
+
+ if ( $filePath !== false ) {
+ $filePath = str_replace( '$1', $path, $filePath );
+ }
+
+ return $filePath;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Interface for site objects.
+ *
+ * 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 Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+interface Site {
+
+ const TYPE_UNKNOWN = 'unknown';
+ const TYPE_MEDIAWIKI = 'mediawiki';
+
+ const GROUP_NONE = 'none';
+
+ const ID_INTERWIKI = 'interwiki';
+ const ID_EQUIVALENT = 'equivalent';
+
+ const SOURCE_LOCAL = 'local';
+
+ /**
+ * Returns the global site identifier (ie enwiktionary).
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getGlobalId();
+
+ /**
+ * Sets the global site identifier (ie enwiktionary).
+ *
+ * @since 1.21
+ *
+ * @param string $globalId
+ */
+ public function setGlobalId( $globalId );
+
+ /**
+ * Returns the type of the site (ie mediawiki).
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getType();
+
+ /**
+ * Sets the type of the site (ie mediawiki).
+ * TODO: remove, we cannot change this after instantiation
+ *
+ * @since 1.21
+ *
+ * @param string $type
+ */
+ public function setType( $type );
+
+ /**
+ * Gets the type of the site (ie wikipedia).
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getGroup();
+
+ /**
+ * Sets the type of the site (ie wikipedia).
+ *
+ * @since 1.21
+ *
+ * @param string $group
+ */
+ public function setGroup( $group );
+
+ /**
+ * Returns the source of the site data (ie 'local', 'wikidata', 'my-magical-repo').
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getSource();
+
+ /**
+ * Sets the source of the site data (ie 'local', 'wikidata', 'my-magical-repo').
+ *
+ * @since 1.21
+ *
+ * @param string $source
+ */
+ public function setSource( $source );
+
+ /**
+ * Returns the protocol of the site, ie 'http://', 'irc://', '//'
+ * Or false if it's not known.
+ *
+ * @since 1.21
+ *
+ * @return string|false
+ */
+ public function getProtocol();
+
+ /**
+ * Returns the domain of the site, ie en.wikipedia.org
+ * Or false if it's not known.
+ *
+ * @since 1.21
+ *
+ * @return string|false
+ */
+ public function getDomain();
+
+ /**
+ * Returns the full URL for the given page on the site.
+ * Or false if the needed information is not known.
+ *
+ * This generated URL is usually based upon the path returned by getLinkPath(),
+ * but this is not a requirement.
+ *
+ * @since 1.21
+ * @see Site::getLinkPath()
+ *
+ * @param bool|String $page
+ *
+ * @return string|false
+ */
+ public function getPageUrl( $page = false );
+
+ /**
+ * Returns language code of the sites primary language.
+ * Or false if it's not known.
+ *
+ * @since 1.21
+ *
+ * @return string|false
+ */
+ public function getLanguageCode();
+
+ /**
+ * Sets language code of the sites primary language.
+ *
+ * @since 1.21
+ *
+ * @param string $languageCode
+ */
+ public function setLanguageCode( $languageCode );
+
+ /**
+ * Returns the normalized, canonical form of the given page name.
+ * How normalization is performed or what the properties of a normalized name are depends on the site.
+ * The general contract of this method is that the normalized form shall refer to the same content
+ * as the original form, and any other page name referring to the same content will have the same normalized form.
+ *
+ * Note that this method may call out to the target site to perform the normalization, so it may be slow
+ * and fail due to IO errors.
+ *
+ * @since 1.21
+ *
+ * @param string $pageName
+ *
+ * @return string the normalized page name
+ */
+ public function normalizePageName( $pageName );
+
+ /**
+ * Returns the interwiki link identifiers that can be used for this site.
+ *
+ * @since 1.21
+ *
+ * @return array of string
+ */
+ public function getInterwikiIds();
+
+ /**
+ * Returns the equivalent link identifiers that can be used to make
+ * the site show up in interfaces such as the "language links" section.
+ *
+ * @since 1.21
+ *
+ * @return array of string
+ */
+ public function getNavigationIds();
+
+ /**
+ * Adds an local identifier to the site.
+ *
+ * @since 1.21
+ *
+ * @param string $type The type of the identifier, element of the Site::ID_ enum
+ * @param string $identifier
+ */
+ public function addLocalId( $type, $identifier );
+
+ /**
+ * Adds an interwiki id to the site.
+ *
+ * @since 1.21
+ *
+ * @param string $identifier
+ */
+ public function addInterwikiId( $identifier );
+
+ /**
+ * Adds a navigation id to the site.
+ *
+ * @since 1.21
+ *
+ * @param string $identifier
+ */
+ public function addNavigationId( $identifier );
+
+ /**
+ * Saves the site.
+ *
+ * @since 1.21
+ *
+ * @param string|null $functionName
+ */
+ public function save( $functionName = null );
+
+ /**
+ * Returns the internal ID of the site.
+ *
+ * @since 1.21
+ *
+ * @return integer
+ */
+ public function getInternalId();
+
+ /**
+ * Sets the provided url as path of the specified type.
+ *
+ * @since 1.21
+ *
+ * @param string $pathType
+ * @param string $fullUrl
+ */
+ public function setPath( $pathType, $fullUrl );
+
+ /**
+ * Returns the path of the provided type or false if there is no such path.
+ *
+ * @since 1.21
+ *
+ * @param string $pathType
+ *
+ * @return string|false
+ */
+ public function getPath( $pathType );
+
+ /**
+ * Sets the path used to construct links with.
+ * Shall be equivalent to setPath( getLinkPathType(), $fullUrl ).
+ *
+ * @param string $fullUrl
+ *
+ * @since 1.21
+ */
+ public function setLinkPath( $fullUrl );
+
+ /**
+ * Returns the path used to construct links with or false if there is no such path.
+ * Shall be equivalent to getPath( getLinkPathType() ).
+ *
+ * @return string|false
+ */
+ public function getLinkPath();
+
+ /**
+ * Returns the path type used to construct links with.
+ *
+ * @return string|false
+ */
+ public function getLinkPathType();
+
+ /**
+ * Returns the paths as associative array.
+ * The keys are path types, the values are the path urls.
+ *
+ * @since 1.21
+ *
+ * @return array of string
+ */
+ public function getAllPaths();
+
+ /**
+ * Removes the path of the provided type if it's set.
+ *
+ * @since 1.21
+ *
+ * @param string $pathType
+ */
+ public function removePath( $pathType );
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Implementation of SiteList using GenericArrayObject.
+ *
+ * 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 Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SiteArray extends GenericArrayObject implements SiteList {
+
+ /**
+ * Internal site identifiers pointing to their sites offset value.
+ *
+ * @since 1.21
+ *
+ * @var array of integer
+ */
+ protected $byInternalId = array();
+
+ /**
+ * Global site identifiers pointing to their sites offset value.
+ *
+ * @since 1.21
+ *
+ * @var array of string
+ */
+ protected $byGlobalId = array();
+
+ /**
+ * @see GenericArrayObject::getObjectType
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getObjectType() {
+ return 'Site';
+ }
+
+ /**
+ * @see GenericArrayObject::preSetElement
+ *
+ * @since 1.21
+ *
+ * @param int|string $index
+ * @param Site $site
+ *
+ * @return boolean
+ */
+ protected function preSetElement( $index, $site ) {
+ if ( $this->hasSite( $site->getGlobalId() ) ) {
+ $this->removeSite( $site->getGlobalId() );
+ }
+
+ $this->byGlobalId[$site->getGlobalId()] = $index;
+ $this->byInternalId[$site->getInternalId()] = $index;
+
+ return true;
+ }
+
+ /**
+ * @see ArrayObject::offsetUnset()
+ *
+ * @since 1.21
+ *
+ * @param mixed $index
+ */
+ public function offsetUnset( $index ) {
+ /**
+ * @var Site $site
+ */
+ $site = $this->offsetGet( $index );
+
+ if ( $site !== false ) {
+ unset( $this->byGlobalId[$site->getGlobalId()] );
+ unset( $this->byInternalId[$site->getInternalId()] );
+ }
+
+ parent::offsetUnset( $index );
+ }
+
+ /**
+ * @see SiteList::getGlobalIdentifiers
+ *
+ * @since 1.21
+ *
+ * @return array
+ */
+ public function getGlobalIdentifiers() {
+ return array_keys( $this->byGlobalId );
+ }
+
+ /**
+ * @see SiteList::hasSite
+ *
+ * @param string $globalSiteId
+ *
+ * @return boolean
+ */
+ public function hasSite( $globalSiteId ) {
+ return array_key_exists( $globalSiteId, $this->byGlobalId );
+ }
+
+ /**
+ * @see SiteList::getSite
+ *
+ * @since 1.21
+ *
+ * @param string $globalSiteId
+ *
+ * @return Site
+ */
+ public function getSite( $globalSiteId ) {
+ return $this->offsetGet( $this->byGlobalId[$globalSiteId] );
+ }
+
+ /**
+ * @see SiteList::removeSite
+ *
+ * @since 1.21
+ *
+ * @param string $globalSiteId
+ */
+ public function removeSite( $globalSiteId ) {
+ $this->offsetUnset( $this->byGlobalId[$globalSiteId] );
+ }
+
+ /**
+ * @see SiteList::isEmpty
+ *
+ * @since 1.21
+ *
+ * @return boolean
+ */
+ public function isEmpty() {
+ return $this->byGlobalId === array();
+ }
+
+ /**
+ * @see SiteList::hasInternalId
+ *
+ * @param integer $id
+ *
+ * @return boolean
+ */
+ public function hasInternalId( $id ) {
+ return array_key_exists( $id, $this->byInternalId );
+ }
+
+ /**
+ * @see SiteList::getSiteByInternalId
+ *
+ * @since 1.21
+ *
+ * @param integer $id
+ *
+ * @return Site
+ */
+ public function getSiteByInternalId( $id ) {
+ return $this->offsetGet( $this->byInternalId[$id] );
+ }
+
+ /**
+ * @see SiteList::removeSiteByInternalId
+ *
+ * @since 1.21
+ *
+ * @param integer $id
+ */
+ public function removeSiteByInternalId( $id ) {
+ $this->offsetUnset( $this->byInternalId[$id] );
+ }
+
+ /**
+ * @see SiteList::setSite
+ *
+ * @since 1.21
+ *
+ * @param Site $site
+ */
+ public function setSite( Site $site ) {
+ $this[] = $site;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Interface for lists of Site objects.
+ *
+ * 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 Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+interface SiteList extends Countable, Traversable, Serializable, ArrayAccess {
+
+ /**
+ * Returns all the global site identifiers.
+ * Optionally only those belonging to the specified group.
+ *
+ * @since 1.21
+ *
+ * @return array
+ */
+ public function getGlobalIdentifiers();
+
+ /**
+ * Returns if the list contains the site with the provided global site identifier.
+ *
+ * @param string $globalSiteId
+ *
+ * @return boolean
+ */
+ public function hasSite( $globalSiteId );
+
+ /**
+ * Returns the Site with the provided global site identifier.
+ * The site needs to exist, so if not sure, call hasGlobalId first.
+ *
+ * @since 1.21
+ *
+ * @param string $globalSiteId
+ *
+ * @return Site
+ */
+ public function getSite( $globalSiteId );
+
+ /**
+ * Removes the site with the specified global site identifier.
+ * The site needs to exist, so if not sure, call hasGlobalId first.
+ *
+ * @since 1.21
+ *
+ * @param string $globalSiteId
+ */
+ public function removeSite( $globalSiteId );
+
+ /**
+ * Returns if the list contains the site with the provided site id.
+ *
+ * @param integer $id
+ *
+ * @return boolean
+ */
+ public function hasInternalId( $id );
+
+ /**
+ * Returns the Site with the provided site id.
+ * The site needs to exist, so if not sure, call has first.
+ *
+ * @since 1.21
+ *
+ * @param integer $id
+ *
+ * @return Site
+ */
+ public function getSiteByInternalId( $id );
+
+ /**
+ * Removes the site with the specified site id.
+ * The site needs to exist, so if not sure, call has first.
+ *
+ * @since 1.21
+ *
+ * @param integer $id
+ */
+ public function removeSiteByInternalId( $id );
+
+ /**
+ * Sets a site in the list. If the site was not there,
+ * it will be added. If it was, it will be updated.
+ *
+ * @since 1.21
+ *
+ * @param Site $site
+ */
+ public function setSite( Site $site );
+
+ /**
+ * Returns if the site list contains no sites.
+ *
+ * @since 1.21
+ *
+ * @return boolean
+ */
+ public function isEmpty();
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Class representing a single site.
+ *
+ * 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 Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author Daniel Werner
+ */
+class SiteObject extends ORMRow implements Site {
+
+ const PATH_LINK = 'link';
+
+ /**
+ * Holds the local ids for this site.
+ * You can obtain them via @see getLocalIds
+ *
+ * @since 1.21
+ *
+ * @var array|false
+ */
+ protected $localIds = false;
+
+ /**
+ * @see Site::getGlobalId
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getGlobalId() {
+ return $this->getField( 'global_key' );
+ }
+
+ /**
+ * @see Site::setGlobalId
+ *
+ * @since 1.21
+ *
+ * @param string $globalId
+ */
+ public function setGlobalId( $globalId ) {
+ $this->setField( 'global_key', $globalId );
+ }
+
+ /**
+ * @see Site::getType
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getType() {
+ return $this->getField( 'type' );
+ }
+
+ /**
+ * @see Site::setType
+ *
+ * @since 1.21
+ *
+ * @param string $type
+ */
+ public function setType( $type ) {
+ $this->setField( 'type', $type );
+ }
+
+ /**
+ * @see Site::getGroup
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getGroup() {
+ return $this->getField( 'group' );
+ }
+
+ /**
+ * @see Site::setGroup
+ *
+ * @since 1.21
+ *
+ * @param string $group
+ */
+ public function setGroup( $group ) {
+ $this->setField( 'group', $group );
+ }
+
+ /**
+ * @see Site::getSource
+ *
+ * @since 1.21
+ *
+ * @return string
+ */
+ public function getSource() {
+ return $this->getField( 'source' );
+ }
+
+ /**
+ * @see Site::setSource
+ *
+ * @since 1.21
+ *
+ * @param string $source
+ */
+ public function setSource( $source ) {
+ $this->setField( 'source', $source );
+ }
+
+ /**
+ * @see Site::getDomain
+ *
+ * @since 1.21
+ *
+ * @return string|false
+ */
+ public function getDomain() {
+ $path = $this->getLinkPath();
+
+ if ( $path === false ) {
+ return false;
+ }
+
+ return parse_url( $path, PHP_URL_HOST );
+ }
+
+ /**
+ * @see Site::getProtocol
+ *
+ * @since 1.21
+ *
+ * @return string|false
+ */
+ public function getProtocol() {
+ $path = $this->getLinkPath();
+
+ if ( $path === false ) {
+ return false;
+ }
+
+ return parse_url( $path, PHP_URL_SCHEME );
+ }
+
+ /**
+ * Sets the path used to construct links with.
+ * @see Site::setLinkPath
+ *
+ * @param string $fullUrl
+ *
+ * @since 1.21
+ *
+ * @throws MWException
+ */
+ public function setLinkPath( $fullUrl ) {
+ $type = $this->getLinkPathType();
+
+ if ( $type === false ) {
+ throw new MWException( "This SiteObject does not support link paths." );
+ }
+
+ $this->setPath( $type, $fullUrl );
+ }
+
+ /**
+ * Returns the path path used to construct links with or false if there is no such path.
+ *
+ * @see Site::getLinkPath
+ *
+ * @return string|false
+ */
+ public function getLinkPath() {
+ $type = $this->getLinkPathType();
+ return $type === false ? false : $this->getPath( $type );
+ }
+
+ /**
+ * @see Site::getLinkPathType
+ *
+ * Returns the main path type, that is the type of the path that should generally be used to construct links
+ * to the target site.
+ *
+ * This default implementation returns SiteObject::PATH_LINK as the default path type. Subclasses can override this
+ * to define a different default path type, or return false to disable site links.
+ *
+ * @since 1.21
+ *
+ * @return string|false
+ */
+ public function getLinkPathType() {
+ return self::PATH_LINK;
+ }
+
+ /**
+ * @see Site::getPageUrl
+ *
+ * This implementation returns a URL constructed using the path returned by getLinkPath().
+ *
+ * @since 1.21
+ *
+ * @param bool|String $pageName
+ *
+ * @return string|false
+ */
+ public function getPageUrl( $pageName = false ) {
+ $url = $this->getLinkPath();
+
+ if ( $url === false ) {
+ return false;
+ }
+
+ if ( $pageName !== false ) {
+ $url = str_replace( '$1', rawurlencode( $pageName ), $url ) ;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Returns $pageName without changes.
+ * Subclasses may override this to apply some kind of normalization.
+ *
+ * @see Site::normalizePageName
+ *
+ * @since 1.21
+ *
+ * @param string $pageName
+ *
+ * @return string
+ */
+ public function normalizePageName( $pageName ) {
+ return $pageName;
+ }
+
+ /**
+ * Returns the value of a type specific field, or the value
+ * of the $default parameter in case it's not set.
+ *
+ * @since 1.21
+ *
+ * @param string $fieldName
+ * @param mixed $default
+ *
+ * @return array
+ */
+ protected function getExtraData( $fieldName, $default = null ) {
+ $data = $this->getField( 'data', array() );
+ return array_key_exists( $fieldName,$data ) ? $data[$fieldName] : $default;
+ }
+
+ /**
+ * Sets the value of a type specific field.
+ * @since 1.21
+ *
+ * @param string $fieldName
+ * @param mixed $value
+ */
+ protected function setExtraData( $fieldName, $value = null ) {
+ $data = $this->getField( 'data', array() );
+ $data[$fieldName] = $value;
+ $this->setField( 'data', $data );
+ }
+
+ /**
+ * @see Site::getLanguageCode
+ *
+ * @since 1.21
+ *
+ * @return string|false
+ */
+ public function getLanguageCode() {
+ return $this->getField( 'language', false );
+ }
+
+ /**
+ * @see Site::setLanguageCode
+ *
+ * @since 1.21
+ *
+ * @param string $languageCode
+ */
+ public function setLanguageCode( $languageCode ) {
+ $this->setField( 'language', $languageCode );
+ }
+
+ /**
+ * Returns the local identifiers of this site.
+ *
+ * @since 1.21
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+ protected function getLocalIds( $type ) {
+ if ( $this->localIds === false ) {
+ $this->loadLocalIds();
+ }
+
+ return array_key_exists( $type, $this->localIds ) ? $this->localIds[$type] : array();
+ }
+
+ /**
+ * Loads the local ids for the site.
+ *
+ * @since 1.21
+ */
+ protected function loadLocalIds() {
+ $dbr = wfGetDB( $this->getTable()->getReadDb() );
+
+ $ids = $dbr->select(
+ 'site_identifiers',
+ array(
+ 'si_type',
+ 'si_key',
+ ),
+ array(
+ 'si_site' => $this->getId(),
+ ),
+ __METHOD__
+ );
+
+ $this->localIds = array();
+
+ foreach ( $ids as $id ) {
+ $this->addLocalId( $id->si_type, $id->si_key );
+ }
+ }
+
+ /**
+ * Adds a local identifier.
+ *
+ * @since 1.21
+ *
+ * @param string $type
+ * @param string $identifier
+ */
+ public function addLocalId( $type, $identifier ) {
+ if ( $this->localIds === false ) {
+ $this->localIds = array();
+ }
+
+ if ( !array_key_exists( $type, $this->localIds ) ) {
+ $this->localIds[$type] = array();
+ }
+
+ if ( !in_array( $identifier, $this->localIds[$type] ) ) {
+ $this->localIds[$type][] = $identifier;
+ }
+ }
+
+ /**
+ * @see Site::addInterwikiId
+ *
+ * @since 1.21
+ *
+ * @param string $identifier
+ */
+ public function addInterwikiId( $identifier ) {
+ $this->addLocalId( 'interwiki', $identifier );
+ }
+
+ /**
+ * @see Site::addNavigationId
+ *
+ * @since 1.21
+ *
+ * @param string $identifier
+ */
+ public function addNavigationId( $identifier ) {
+ $this->addLocalId( 'equivalent', $identifier );
+ }
+
+ /**
+ * @see Site::getInterwikiIds
+ *
+ * @since 1.21
+ *
+ * @return array of string
+ */
+ public function getInterwikiIds() {
+ return $this->getLocalIds( 'interwiki' );
+ }
+
+ /**
+ * @see Site::getNavigationIds
+ *
+ * @since 1.21
+ *
+ * @return array of string
+ */
+ public function getNavigationIds() {
+ return $this->getLocalIds( 'equivalent' );
+ }
+
+ /**
+ * @see Site::getInternalId
+ *
+ * @since 1.21
+ *
+ * @return integer
+ */
+ public function getInternalId() {
+ return $this->getId();
+ }
+
+ /**
+ * @see ORMRow::save
+ * @see Site::save
+ *
+ * @since 1.21
+ *
+ * @param string|null $functionName
+ *
+ * @return boolean Success indicator
+ */
+ public function save( $functionName = null ) {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $trx = $dbw->trxLevel();
+
+ if ( $trx == 0 ) {
+ $dbw->begin( __METHOD__ );
+ }
+
+ $this->setField( 'protocol', $this->getProtocol() );
+ $this->setField( 'domain', strrev( $this->getDomain() ) . '.' );
+
+ $existedAlready = $this->hasIdField();
+
+ $success = parent::save( $functionName );
+
+ if ( $success && $existedAlready ) {
+ $dbw->delete(
+ 'site_identifiers',
+ array( 'si_site' => $this->getId() ),
+ __METHOD__
+ );
+ }
+
+ if ( $success && $this->localIds !== false ) {
+ foreach ( $this->localIds as $type => $ids ) {
+ foreach ( $ids as $id ) {
+ $dbw->insert(
+ 'site_identifiers',
+ array(
+ 'si_site' => $this->getId(),
+ 'si_type' => $type,
+ 'si_key' => $id,
+ ),
+ __METHOD__
+ );
+ }
+ }
+ }
+
+ if ( $trx == 0 ) {
+ $dbw->commit( __METHOD__ );
+ }
+
+ return $success;
+ }
+
+ /**
+ * @see Site::setPath
+ *
+ * @since 1.21
+ *
+ * @param string $pathType
+ * @param string $fullUrl
+ */
+ public function setPath( $pathType, $fullUrl ) {
+ $paths = $this->getExtraData( 'paths', array() );
+ $paths[$pathType] = $fullUrl;
+ $this->setExtraData( 'paths', $paths );
+ }
+
+ /**
+ * @see Sitres::getPath
+ *
+ * @since 1.21
+ *
+ * @param string $pathType
+ *
+ * @return string|false
+ */
+ public function getPath( $pathType ) {
+ $paths = $this->getExtraData( 'paths', array() );
+ return array_key_exists( $pathType, $paths ) ? $paths[$pathType] : false;
+ }
+
+ /**
+ * @see Sitres::getAll
+ *
+ * @since 1.21
+ *
+ * @return array of string
+ */
+ public function getAllPaths() {
+ return $this->getExtraData( 'paths', array() );
+ }
+
+ /**
+ * @see Sitres::removePath
+ *
+ * @since 1.21
+ *
+ * @param string $pathType
+ */
+ public function removePath( $pathType ) {
+ $paths = $this->getExtraData( 'paths', array() );
+ unset( $paths[$pathType] );
+ $this->setExtraData( 'paths', $paths );
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Represents the site configuration of a wiki.
+ * Holds a list of sites (ie SiteList) and takes care
+ * of retrieving and caching site information when appropriate.
+ *
+ * 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 Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class Sites {
+
+ /**
+ * @since 1.21
+ * @var SiteList|false
+ */
+ protected $sites = false;
+
+ /**
+ * Constructor.
+ *
+ * @since 1.21
+ */
+ protected function __construct() {}
+
+ /**
+ * Returns an instance of Sites.
+ *
+ * @since 1.21
+ *
+ * @return Sites
+ */
+ public static function singleton() {
+ static $instance = false;
+
+ if ( $instance === false ) {
+ $instance = new static();
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Factory for creating new site objects.
+ *
+ * @since 1.21
+ *
+ * @param string|false $globalId
+ *
+ * @return Site
+ */
+ public static function newSite( $globalId = false ) {
+ /**
+ * @var Site $site
+ */
+ $site = SitesTable::singleton()->newRow( array(), true );
+
+ if ( $globalId !== false ) {
+ $site->setGlobalId( $globalId );
+ }
+
+ return $site;
+ }
+
+ /**
+ * Returns a list of all sites. By default this site is
+ * fetched from the cache, which can be changed to loading
+ * the list from the database using the $useCache parameter.
+ *
+ * @since 1.21
+ *
+ * @param string $source either 'cache' or 'recache'
+ *
+ * @return SiteList
+ */
+ public function getSites( $source = 'cache' ) {
+ if ( $source === 'cache' ) {
+ if ( $this->sites === false ) {
+ $cache = wfGetMainCache();
+ $sites = $cache->get( 'sites-cache' );
+
+ if ( is_object( $sites ) ) {
+ $this->sites = $sites;
+ }
+ else {
+ $this->loadSites();
+ }
+ }
+ }
+ else {
+ $this->loadSites();
+ }
+
+ return $this->sites;
+ }
+
+ /**
+ * Returns a list of sites in the given group. Calling getGroup() on any of
+ * the sites in the resulting SiteList shall return $group.
+ *
+ * @since 1.21
+ *
+ * @param string $group th group to get.
+ *
+ * @return SiteList
+ */
+ public function getSiteGroup( $group ) {
+ $sites = self::getSites();
+
+ $siteGroup = new SiteArray();
+
+ /* @var Site $site */
+ foreach ( $sites as $site ) {
+ if ( $site->getGroup() == $group ) {
+ $siteGroup->append( $site );
+ }
+ }
+
+ return $siteGroup;
+ }
+
+ /**
+ * Fetches the site from the database and loads them into the sites field.
+ *
+ * @since 1.21
+ */
+ protected function loadSites() {
+ $this->sites = new SiteArray( SitesTable::singleton()->select() );
+
+ // Batch load the local site identifiers.
+ $dbr = wfGetDB( SitesTable::singleton()->getReadDb() );
+
+ $ids = $dbr->select(
+ 'site_identifiers',
+ array(
+ 'si_site',
+ 'si_type',
+ 'si_key',
+ ),
+ array(),
+ __METHOD__
+ );
+
+ foreach ( $ids as $id ) {
+ if ( $this->sites->hasInternalId( $id->si_site ) ) {
+ $site = $this->sites->getSiteByInternalId( $id->si_site );
+ $site->addLocalId( $id->si_type, $id->si_key );
+ $this->sites->setSite( $site );
+ }
+ }
+
+ $cache = wfGetMainCache();
+ $cache->set( 'sites-cache', $this->sites );
+ }
+
+ /**
+ * Returns the site with provided global id, or false if there is no such site.
+ *
+ * @since 1.21
+ *
+ * @param string $globalId
+ * @param string $source
+ *
+ * @return Site|false
+ */
+ public function getSite( $globalId, $source = 'cache' ) {
+ if ( $source === 'cache' && $this->sites !== false ) {
+ return $this->sites->hasSite( $globalId ) ? $this->sites->getSite( $globalId ) : false;
+ }
+
+ return SitesTable::singleton()->selectRow( null, array( 'global_key' => $globalId ) );
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Represents the sites database table.
+ * All access to this table should be done through this class.
+ *
+ * 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 Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SitesTable extends ORMTable {
+
+ /**
+ * @see IORMTable::getName()
+ * @since 1.21
+ * @return string
+ */
+ public function getName() {
+ return 'sites';
+ }
+
+ /**
+ * @see IORMTable::getFieldPrefix()
+ * @since 1.21
+ * @return string
+ */
+ public function getFieldPrefix() {
+ return 'site_';
+ }
+
+ /**
+ * @see IORMTable::getRowClass()
+ * @since 1.21
+ * @return string
+ */
+ public function getRowClass() {
+ return 'SiteObject';
+ }
+
+ /**
+ * @see IORMTable::getFields()
+ * @since 1.21
+ * @return array
+ */
+ public function getFields() {
+ return array(
+ 'id' => 'id',
+
+ // Site data
+ 'global_key' => 'str',
+ 'type' => 'str',
+ 'group' => 'str',
+ 'source' => 'str',
+ 'language' => 'str',
+ 'protocol' => 'str',
+ 'domain' => 'str',
+ 'data' => 'array',
+
+ // Site config
+ 'forward' => 'bool',
+ 'config' => 'array',
+ );
+ }
+
+ /**
+ * @see IORMTable::getDefaults()
+ * @since 1.21
+ * @return array
+ */
+ public function getDefaults() {
+ return array(
+ 'type' => Site::TYPE_UNKNOWN,
+ 'group' => Site::GROUP_NONE,
+ 'source' => Site::SOURCE_LOCAL,
+ 'data' => array(),
+
+ 'forward' => false,
+ 'config' => array(),
+ );
+ }
+
+ /**
+ * Returns the class name for the provided site type.
+ *
+ * @since 1.21
+ *
+ * @param integer $siteType
+ *
+ * @return string
+ */
+ protected static function getClassForType( $siteType ) {
+ global $wgSiteTypes;
+ return array_key_exists( $siteType, $wgSiteTypes ) ? $wgSiteTypes[$siteType] : 'SiteObject';
+ }
+
+ /**
+ * Factory method to construct a new Site instance.
+ *
+ * @since 1.21
+ *
+ * @param array $data
+ * @param boolean $loadDefaults
+ *
+ * @return Site
+ */
+ public function newRow( array $data, $loadDefaults = false ) {
+ if ( !array_key_exists( 'type', $data ) ) {
+ $data['type'] = Site::TYPE_UNKNOWN;
+ }
+
+ $class = static::getClassForType( $data['type'] );
+
+ return new $class( $this, $data, $loadDefaults );
+ }
+
+}
\ No newline at end of file
$name = str_replace( ' ', '_', $user->getName() );
$lb->add( NS_USER, $name );
$lb->add( NS_USER_TALK, $name );
- }
+ }
$lb->execute();
wfProfileOut( __METHOD__ );
)
) ;
- $extraOptions = Xml::tags( 'td', array( 'colspan' => 2 ),
- Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ),
+ if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
+ $deletedOnlyCheck = Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ),
Xml::checkLabel(
$this->msg( 'history-show-deleted' )->text(),
'deletedOnly',
$this->opts['deletedOnly'],
array( 'class' => 'mw-input' )
)
- ) .
+ );
+ } else {
+ $deletedOnlyCheck = '';
+ }
+
+ $extraOptions = Xml::tags( 'td', array( 'colspan' => 2 ),
+ $deletedOnlyCheck .
Html::rawElement( 'span', array( 'style' => 'white-space: nowrap' ),
Xml::checkLabel(
$this->msg( 'sp-contributions-toponly' )->text(),
} else {
$pageSet = array(); // Inverted index of all pages to look up
-
+
// Split up and normalize input
foreach( explode( "\n", $page ) as $pageName ) {
$pageName = trim( $pageName );
* @return ResultWrapper
*/
function listRevisions() {
- global $wgContentHandlerNoDB;
+ global $wgContentHandlerUseDB;
$dbr = wfGetDB( DB_SLAVE );
'ar_comment', 'ar_len', 'ar_deleted', 'ar_rev_id', 'ar_sha1',
);
- if ( !$wgContentHandlerNoDB ) {
+ if ( $wgContentHandlerUseDB ) {
$fields[] = 'ar_content_format';
$fields[] = 'ar_content_model';
}
'fa_user',
'fa_user_text',
'fa_timestamp',
- 'fa_deleted' ),
+ 'fa_deleted',
+ 'fa_sha1' ),
array( 'fa_name' => $this->title->getDBkey() ),
__METHOD__,
array( 'ORDER BY' => 'fa_timestamp DESC' ) );
* @return Revision
*/
function getRevision( $timestamp ) {
- global $wgContentHandlerNoDB;
+ global $wgContentHandlerUseDB;
$dbr = wfGetDB( DB_SLAVE );
'ar_sha1',
);
- if ( !$wgContentHandlerNoDB ) {
+ if ( $wgContentHandlerUseDB ) {
$fields[] = 'ar_content_format';
$fields[] = 'ar_content_model';
}
* @return Status, containing the number of revisions restored on success
*/
private function undeleteRevisions( $timestamps, $unsuppress = false, $comment = '' ) {
- global $wgContentHandlerNoDB;
+ global $wgContentHandlerUseDB;
if ( wfReadOnly() ) {
throw new ReadOnlyError();
'ar_len',
'ar_sha1');
- if ( !$wgContentHandlerNoDB ) {
+ if ( $wgContentHandlerUseDB ) {
$fields[] = 'ar_content_format';
$fields[] = 'ar_content_model';
}
$exists['normalizedFile']->getTitle()->getPrefixedText() )->parse();
} elseif ( $exists['warning'] == 'thumb' ) {
// Swapped argument order compared with other messages for backwards compatibility
- $warning = wfMessage( 'fileexists-thumbnail-yes',
+ $warning = wfMessage( 'fileexists-thumbnail-yes',
$exists['thumbFile']->getTitle()->getPrefixedText(), $filename )->parse();
} elseif ( $exists['warning'] == 'thumb-name' ) {
// Image w/o '180px-' does not exists, but we do not like these filenames
* @return string
*/
function getLabelHtml( $cellAttributes = array() ) {
- $id = "wpSourceType{$this->mParams['upload-type']}";
+ $id = $this->mParams['id'];
$label = Html::rawElement( 'label', array( 'for' => $id ), $this->mLabel );
if ( !empty( $this->mParams['radio'] ) ) {
// now we should construct a File, so we can get mime and other such info in a standard way
// n.b. mimetype may be different from original (ogx original -> jpeg thumb)
- $thumbFile = new UnregisteredLocalFile( false,
+ $thumbFile = new UnregisteredLocalFile( false,
$this->stash->repo, $thumbnailImage->getStoragePath(), false );
if ( !$thumbFile ) {
throw new UploadStashFileNotFoundException( "couldn't create local file object for thumbnail" );
$catMessage = $this->msg( 'broken-file-category' )
->title( Title::newFromText( "Wanted Files", NS_MAIN ) )
->inContentLanguage();
-
+
if ( !$catMessage->isDisabled() ) {
$category = Title::makeTitleSafe( NS_CATEGORY, $catMessage->text() );
} else {
* @ingroup SpecialPage
*/
class WantedPagesPage extends WantedQueryPage {
-
+
function __construct( $name = 'Wantedpages' ) {
parent::__construct( $name );
}
* @return array
*/
public function verifyUpload() {
- # Check for a post_max_size or upload_max_size overflow, so that a
+ # Check for a post_max_size or upload_max_size overflow, so that a
# proper error can be shown to the user
if ( is_null( $this->mTempPath ) || $this->isEmptyFile() ) {
if ( $this->mUpload->isIniSizeOverflow() ) {
- return array(
+ return array(
'status' => UploadBase::FILE_TOO_LARGE,
- 'max' => min(
- self::getMaxUploadSize( $this->getSourceType() ),
- wfShorthandToInteger( ini_get( 'upload_max_filesize' ) ),
+ 'max' => min(
+ self::getMaxUploadSize( $this->getSourceType() ),
+ wfShorthandToInteger( ini_get( 'upload_max_filesize' ) ),
wfShorthandToInteger( ini_get( 'post_max_size' ) )
),
);
}
}
-
+
return parent::verifyUpload();
}
}
'qbbrowse' => 'Snuffel',
'qbedit' => 'Wysig',
'qbpageoptions' => 'Bladsyopsies',
-'qbpageinfo' => 'Bladsyinligting',
'qbmyoptions' => 'My bladsye',
'qbspecialpages' => 'Spesiale bladsye',
'faq' => 'Gewilde vrae',
'qbbrowse' => 'ቃኝ',
'qbedit' => 'አርም',
'qbpageoptions' => 'ይህ ገጽ',
-'qbpageinfo' => 'አግባብ',
'qbmyoptions' => 'የኔ ገጾች',
'qbspecialpages' => 'ልዩ ገጾች',
'faq' => 'ብጊየጥ (ብዙ ጊዜ የሚጠየቁ ጥያቀዎች)',
'qbbrowse' => 'Navegar',
'qbedit' => 'Editar',
'qbpageoptions' => 'Ista pachina',
-'qbpageinfo' => 'Contexto',
'qbmyoptions' => 'Pachinas propias',
'qbspecialpages' => 'Pachinas especials',
'faq' => 'Preguntas freqüents (FAQ)',
'qbbrowse' => 'تصفح',
'qbedit' => 'تعديل',
'qbpageoptions' => 'هذه الصفحة',
-'qbpageinfo' => 'سياق النص',
'qbmyoptions' => 'صفحاتي',
'qbspecialpages' => 'الصفحات الخاصة',
'faq' => 'الأسئلة المتكررة',
'rows' => 'ܨ̈ܦܐ',
'columns' => 'ܥܡܘܕ̈ܐ:',
'searchresultshead' => 'ܒܨܝ',
-'resultsperpage' => 'Ü¡Ü¢Ü\9dÜ¢Ü\90 Ü\95Ü¦Ü Ü\9bÌ\88Ü\90 Ü\92Ü\95ܦܐ:',
+'resultsperpage' => 'Ü¡Ü¢Ü\9dÜ¢Ü\90 Ü\95Ü¦Ü Ü\9bÌ\88Ü\90 Ü\92ܦÜ\90ܬܐ:',
'recentchangesdays' => 'ܝܘܡܬ̈ܐ ܠܚܙܝܐ ܒܫܘܚܠܦ̈ܐ ܚܕ̈ܬܐ:',
'recentchangescount' => 'ܡܢܝܢܐ ܕܫܘܚܠܦ̈ܐ ܠܚܙܝܐ ܪܫܐܝܬ:',
'savedprefs' => 'ܨܒܝܢܝܘܬ̈ܟ ܐܬܠܒܟܘ.',
'action-createaccount' => 'ܒܪܝܬܐ ܕܚܘܫܒܢܐ ܕܗܢܐ ܡܦܠܚܢܐ',
'action-minoredit' => 'ܫܘܕܥܬܐ ܥܠ ܫܘܚܠܦܐ ܗܢܐ ܐܝܟ ܙܥܘܪܐ',
'action-move' => 'ܫܢܝܬܐ ܕܦܐܬܐ ܗܕܐ',
-'action-move-rootuserpages' => 'Ü«Ü¢Ü\9dܬÜ\90 Ü\95Ü\95Ì\88ܦÜ\90 ܫܪÌ\88Ü«Ü\9dܐ ܕܡܦܠܚܢܐ',
+'action-move-rootuserpages' => 'Ü«Ü¢Ü\9dܬÜ\90 Ü\95ܦÜ\90ܬܬÌ\88Ü\90 ܫܪÌ\88Ü«Ü\9dܬܐ ܕܡܦܠܚܢܐ',
'action-movefile' => 'ܫܢܝܬܐ ܕܗܢܐ ܠܦܦܐ',
'action-upload' => 'ܐܣܩܬܐ ܕܗܢܐ ܠܦܦܐ',
'action-delete' => 'ܫܝܦܬܐ ܕܦܐܬܐ ܗܕܐ',
ܗܫܐ ܐܝܬܝܗܝ ܨܘܝܒܐ ܠ [[$2]].',
'brokenredirects' => 'ܨܘܝܒ̈ܐ ܬܒܝܪ̈ܐ',
-'brokenredirectstext' => 'ܨÜ\98Ì\88Ü\9dÜ\92Ü\90 Ü\97Ü Ü\9dÜ¢ Ü¡Ü\9bÜ\9dÜ¢ Ü Ü\95Ì\88ܦÜ\90 Ü\95Ü Ü\9dÜ¬Ü Ü\97Ü\98ܢ ܐܝܬܘܬܐ:',
+'brokenredirectstext' => 'ܨÜ\98Ì\88Ü\9dÜ\92Ü\90 Ü\97Ü Ü\9dÜ¢ Ü¡Ü\9bÜ\9dÜ¢ Ü Ü¦Ü\90ܬܬÌ\88Ü\90 Ü\95Ü Ü\9dÜ¬Ü Ü\97Ü\9dܢ ܐܝܬܘܬܐ:',
'brokenredirects-edit' => 'ܫܚܠܦ',
'brokenredirects-delete' => 'ܫܘܦ',
'tooltip-pt-mytalk' => 'ܦܐܬܐ ܕܡܡܠܘܟ',
'tooltip-pt-preferences' => 'Your preferences',
'tooltip-pt-watchlist' => 'ܡܟܬܒܢܘܬܐ ܕܦܐܬܬ̈ܐ ܕܒܪܗܝܬ ܐܢܬ ܫܘܚܠܦ̈ܐ ܕܬܗܘܐ ܒܗܘܢ',
-'tooltip-pt-mycontris' => 'ܡܟܬܒܢܘܬܐ ܕܫܘܬܦܘܝܬܘ̈ܟ',
+'tooltip-pt-mycontris' => 'ܡܟܬܒܢܘܬܐ ܕܫܘܬܦܘܝܬ̈ܟ',
'tooltip-pt-login' => 'ܢܠܒܒ ܠܟ ܕܣܓܠ ܐܢܬ ܥܠܠܐ ܕܝܠܟ، ܐܠܐ ܗܢܐ ܠܐ ܐܝܬܝܗܝ ܐܠܨܝܐ',
'tooltip-pt-logout' => 'ܦܠܛܐ',
'tooltip-ca-talk' => 'ܡܡܠܠܐ ܥܠ ܚܒܝܫܬܐ ܕܦܐܬܐ',
'tooltip-search' => 'ܒܨܝ ܒܓܘ {{SITENAME}}',
'tooltip-search-fulltext' => 'ܒܨܝ ܒܓܘ ܦܐܬܬ̈ܐ ܥܠ ܗܢܐ ܟܬܝܒܬܐ',
'tooltip-p-logo' => 'ܦܐܬܐ ܪܝܫܝܬܐ',
-'tooltip-n-mainpage' => 'ܬܪÜ\98ܩܬÜ\90 Ü\95ܦܐܬܐ ܪܝܫܝܬܐ',
+'tooltip-n-mainpage' => 'ܣܥܪ ܦܐܬܐ ܪܝܫܝܬܐ',
'tooltip-n-mainpage-description' => 'ܬܪܘܩܬܐ ܕܦܐܬܐ ܪܝܫܝܬܐ',
'tooltip-n-portal' => 'ܚܕܪ ܬܪܡܝܬܐ، ܡܢܐ ܡܫܟܚ ܐܢܬ ܠܥܒܕܐ، ܐܝܟܐ ܬܚܙܝ ܟܠ ܡܐ ܕܣܢܝܩ ܐܢܬ ܠܗ',
'tooltip-n-recentchanges' => 'ܡܟܬܒܢܘܬܐ ܒܫܘܚܠܦ̈ܐ ܚܕ̈ܬܐ ܒܓܘ ܘܝܩܝ.',
'tooltip-ca-nstab-main' => 'ܚܘܝ ܦܐܬܬܐ ܕܚܒ̈ܝܫܬܐ',
'tooltip-ca-nstab-user' => 'ܚܘܝ ܦܐܬܐ ܕܡܦܠܚܢܐ',
'tooltip-ca-nstab-image' => 'ܚܘܝ ܦܐܬܐ ܕܠܦܦܐ',
-'tooltip-ca-nstab-category' => 'ܚܘܝ ܦܐܬܐ ܕܣܕܪ̈ܐ',
+'tooltip-ca-nstab-category' => 'ܚܘܝ ܦܐܬܐ ܕܣܕܪܐ',
'tooltip-save' => 'ܠܒܘܟ ܫܘܚܠܦܟ',
-'tooltip-watch' => 'Ü\90Ü\98ܣܦ Ü\97Ü¢Ü\90 ܦÜ\90ܬÜ\90 Ü Ü¡Ü\9fܬÜ\92Ü¢Ü\98ܬÜ\90 Ü\95ܪÜ\97Ü\9dܬÜ\98ܟ',
+'tooltip-watch' => 'Ü\90Ü\98ܣܦ ܦÜ\90ܬÜ\90 Ü\97Ü\95Ü\90 Ü Ü¡Ü\9fܬÜ\92Ü¢Ü\98ܬÜ\90 Ü\95ܪÌ\88Ü\97Ü\9dܬܟ',
# Attribution
'anonymous' => '{{PLURAL:$1|ܡܦܠܚܢܐ ܠܐ ܝܕܝܥܐ|ܡܦܠܚܢ̈ܐ ܠܐ ܝܕ̈ܝܥܐ}} ܕ {{SITENAME}}',
'qbbrowse' => 'تصفح',
'qbedit' => 'عدل',
'qbpageoptions' => ' الصفحه دى',
-'qbpageinfo' => 'السياق',
'qbmyoptions' => 'صفحاتى',
'qbspecialpages' => 'الصفحات الخاصة',
'faq' => 'اسئله بتتسئل كتير',
'qbbrowse' => 'ব্ৰাওজ',
'qbedit' => 'সম্পাদনা',
'qbpageoptions' => 'এই পৃষ্ঠা',
-'qbpageinfo' => 'প্ৰসংগ',
'qbmyoptions' => 'মোৰ পৃষ্ঠাসমূহ',
'qbspecialpages' => 'বিশেষ পৃষ্ঠাসমূহ',
'faq' => 'সততে উদিত প্ৰশ্নসমূহ (FAQ)',
'qbbrowse' => 'Restolar',
'qbedit' => 'Editar',
'qbpageoptions' => 'Esta páxina',
-'qbpageinfo' => 'Contestu',
'qbmyoptions' => 'Les mios páxines',
'qbspecialpages' => 'Páxines especiales',
'faq' => 'EMF (entrugues más frecuentes)',
'vector-action-protect' => 'Protexer',
'vector-action-undelete' => 'Restaurar',
'vector-action-unprotect' => 'Camudar la proteición',
-'vector-simplesearch-preference' => 'Activar suxerencies meyoraes de gueta (namái apariencia Vector)',
+'vector-simplesearch-preference' => 'Activar la barra de gueta simplificada (namái apariencia Vector)',
'vector-view-create' => 'Crear',
'vector-view-edit' => 'Editar',
'vector-view-history' => 'Ver historial',
'protectedpagetext' => 'Esta páxina ta candada pa torgar la so edición.',
'viewsourcetext' => "Pues ver y copiar la fonte d'esta páxina:",
'viewyourtext' => "Pues ver y copiar la fonte de '''les tos ediciones''' d'esta páxina:",
-'protectedinterface' => "Esta páxina proporciona testu d'interfaz de l'aplicación, y ta candada pa torgar abusos.",
-'editinginterface' => "'''Avisu:''' Tas editando una páxina que s'usa pa proporcionar el testu d'interfaz de l'aplicación.
-Los cambeos nesta páxina van afeutar l'apariencia de la interfaz pa otros usuarios.
-Si quies facer traducciones, por favor usa [//translatewiki.net/wiki/Main_Page?setlang=ast translatewiki.net], el proyeutu de traducción de MediaWiki.",
+'protectedinterface' => "Esta páxina proporciona'l testu de la interfaz del software d'esta wiki, y ta candada pa torgar abusos.
+P'amestar o cambiar les traducciones de toles wikis, por favor usa [//translatewiki.net/translatewiki.net], el proyeutu de llocalización de MediaWiki.",
+'editinginterface' => "'''Avisu:''' Tas editando una páxina que s'usa pa proporcionar el testu d'interfaz del programa.
+Los cambeos nesta páxina van afeutar l'apariencia de la interfaz pa otros usuarios d'esta wiki.
+P'amestar o camudar traducciones pa toles wikis, por favor, usa [//translatewiki.net/ translatewiki.net], el proyeutu de traducción de MediaWiki.",
'sqlhidden' => '(consulta SQL anubrida)',
'cascadeprotected' => "Esta páxina ta protexida d'ediciones porque ta enxerta {{PLURAL:$1|na siguiente páxina|nes siguientes páxines}}, que {{PLURAL:$1|ta protexida|tán protexíes}} cola opción «en cascada» activada:
$2",
<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} guetar los rexistros rellacionaos],
o [{{fullurl:{{FULLPAGENAME}}|action=edit}} editar esta páxina equí]</span>.',
'noarticletext-nopermission' => 'Nestos momentos nun hai testu nesta páxina.
-Pues [[Special:Search/{{PAGENAME}}|guetar esti títulu de páxina]] n\'otres páxines,
-o <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} guetar los rexistros rellacionaos]</span>.',
+Pues [[Special:Search/{{PAGENAME}}|guetar esti títulu de páxina]] n\'otres páxines o <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} guetar los rexistros rellacionaos]</span>, pero nun tienes permisu pa crear esta páxina.',
'missing-revision' => 'La revisión #$1 de la páxina llamada "{{PAGENAME}}" nun esiste.
De vezu la causa d\'esto ye siguir un enllaz antiguu del historial a una páxina que se desanició.
'edit-already-exists' => 'Nun se pudo crear una páxina nueva.
Yá esiste.',
'defaultmessagetext' => 'Testu predetermináu',
+'content-failed-to-parse' => 'Fallu al analizar el conteníu $2 pal modelu $1: $3',
+'invalid-content-data' => 'Datos del conteníu inválidos',
+'content-not-allowed-here' => 'El conteníu «$1» nun se permite na páxina [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'testu wiki',
+'content-model-text' => 'testu simple',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => "'''Avisu:''' Esta páxina contién demasiaes llamaes costoses a funciones d'análisis sintáuticu.
'timezoneregion-indian' => 'Océanu Índicu',
'timezoneregion-pacific' => 'Océanu Pacíficu',
'allowemail' => 'Dexar a los otros usuarios mandate correos',
-'prefs-searchoptions' => 'Opciones de busca',
+'prefs-searchoptions' => 'Guetar',
'prefs-namespaces' => 'Espacios de nome',
'defaultns' => "D'otra miente, guetar nestos espacios de nome:",
'default' => 'predetermináu',
'backend-fail-internal' => 'Hebo un fallu desconocíu nel motor d\'almacenamientu "$1".',
'backend-fail-contenttype' => 'Non se pudo determinar la triba de conteníu de ficheru a guardar en "$1".',
'backend-fail-batchsize' => "El motor d'almacenamientu dio un llote de $1 {{PLURAL:$1|operación|operaciones}} en ficheros; el llímite ye de $2 {{PLURAL:$2|operación|operaciones}}.",
-'backend-fail-usable' => 'Nun se pudo escribir el ficheru $1 porque nun hai permisos bastantes o falten los direutorios/contenedores.',
+'backend-fail-usable' => 'Nun se pudo llee o escribir el ficheru «$1» porque nun hai permisos bastantes o falten los direutorios/contenedores.',
# File journal errors
'filejournal-fail-dbconnect' => 'Nun se pudo coneutar cola base de datos del diariu pal sofitu d\'almacenamientu "$1".',
'undeletedrevisions' => '{{PLURAL:$1|1 revisión restaurada|$1 revisiones restauraes}}',
'undeletedrevisions-files' => '{{PLURAL:$1|1 revisión|$1 revisiones}} y {{PLURAL:$2|1 archivu|$2 archivos}} restauraos',
'undeletedfiles' => '{{PLURAL:$1|1 archivu restauráu|$1 archivos restauraos}}',
-'cannotundelete' => 'Falló la restauración; seique daquién yá restaurara la páxina enantes.',
+'cannotundelete' => 'Falló la restauración:
+$1',
'undeletedpage' => "'''Restauróse $1'''
Consulta'l [[Special:Log/delete|rexistru d'esborraos]] pa ver los esborraos y restauraciones de recién.",
'immobile-target-namespace-iw' => "Nun puedes mover una páxina a un enllaz d'Interwiki.",
'immobile-source-page' => 'Esta páxina nun ye treslladable.',
'immobile-target-page' => 'Nun se pue treslladar a esi títulu de destín.',
+'bad-target-model' => 'El destín deseáu utiliza un modelu de conteníu diferente. Nun se pue convertir de $1 a $2.',
'imagenocrossnamespace' => "Nun se pue treslladar una imaxe a nun espaciu de nomes que nun ye d'imáxenes",
'nonfile-cannot-move-to-file' => 'Nun se pue treslladar más que ficheros al espaciu de nomes de ficheros',
'imagetypemismatch' => 'La estensión nueva del archivu nun concueya cola so mena',
'pageinfo-magic-words' => '{{PLURAL:$1|Pallabra máxica|Pallabres máxiques}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Categoría anubrida|Categoríes anubríes}} ($1)',
'pageinfo-templates' => '{{PLURAL:$1|Plantía incluída|Plantíes incluíes}} ($1)',
+'pageinfo-toolboxlink' => 'Información de la páxina',
# Skin names
'skinname-standard' => 'Clásicu',
# Scary transclusion
'scarytranscludedisabled' => '[La tresclusión interwiki ta desactivada]',
-'scarytranscludefailed' => '[La obtención de la plantía falló pa $1]',
+'scarytranscludefailed' => '[Falló la recuperación de la plantía pa $1]',
+'scarytranscludefailed-httpstatus' => '[Falló la recuperación de la plantía pa $1: HTTP $2]',
'scarytranscludetoolong' => '[La URL ye demasiao llarga]',
# Delete conflict
'qbbrowse' => 'Farura',
'qbedit' => 'Betara',
'qbpageoptions' => 'Ikatcuksbu',
-'qbpageinfo' => 'Givabu',
'qbmyoptions' => 'Jinaf ikatcukseem',
'qbspecialpages' => 'Aptaf bueem',
'faq' => 'NEB',
'qbbrowse' => 'Gözdən keçir',
'qbedit' => 'Redaktə',
'qbpageoptions' => 'Bu səhifə',
-'qbpageinfo' => 'Məzmun',
'qbmyoptions' => 'Mənim səhifələrim',
'qbspecialpages' => 'Xüsusi səhifələr',
'faq' => 'TSS',
'qbbrowse' => 'Байҡарға',
'qbedit' => 'Үҙгәртергә',
'qbpageoptions' => 'Был бит',
-'qbpageinfo' => 'Бит тураһында мәғлүмәттәр',
'qbmyoptions' => 'Биттәрем',
'qbspecialpages' => 'Махсус биттәр',
'faq' => 'ЙБҺ',
'currentrev' => 'Ағымдағы версия',
'currentrev-asof' => '$1, ағымдағы версия',
'revisionasof' => '$1 версияһы',
-'revision-info' => 'Версия: $1; $2',
+'revision-info' => '<div id="viewingold-warning" style="background: #FFBDBD; border: 1px solid #BB7979; color: #000000; margin: 1em 0 .5em; padding: .5em 1em; vertical-align: middle; font-weight: bold; font-family: Palatino Linotype, Microsoft Sans Serif, Arial Unicode MS, Droid Sans; clear: both;">Хәҙер һеҙ был биттең иҫке, <span id="mw-revision-name">$2</span> тарафынан <span id="mw-revision-date">$1</span> һаҡланған версияһын ҡарайһығыҙ. Уның <span class="plainlinks">[{{fullurl:{{FULLPAGENAME}}}} ағымдағы версиянан] айырмаһы булыуы мөмкин</span>.</div>',
'previousrevision' => '← Алдағы',
'nextrevision' => 'Киләһе →',
'currentrevisionlink' => 'Ағымдағы версия',
'qbbrowse' => 'بروز',
'qbedit' => 'اصلاح',
'qbpageoptions' => 'صفحه',
-'qbpageinfo' => 'متن',
'qbmyoptions' => 'منی صفحات',
'qbspecialpages' => 'حاصین صفحات',
'faq' => 'ب.ج.س',
'qbbrowse' => 'Halungkáta',
'qbedit' => 'Liwata',
'qbpageoptions' => 'Ining pahina',
-'qbpageinfo' => 'Konteksto',
'qbmyoptions' => 'Sakong mga pahina',
'qbspecialpages' => 'Espesyal na mga pahina',
'faq' => 'PPK (Pirmihang Pighahapot na mga kahaputan)',
'qbbrowse' => 'Выбраць',
'qbedit' => 'Правіць',
'qbpageoptions' => 'Гэтая старонка',
-'qbpageinfo' => 'Кантэкст',
'qbmyoptions' => 'Свае старонкі',
'qbspecialpages' => 'Адмысловыя старонкі',
'faq' => 'ЧАПЫ',
'qbbrowse' => 'Праглядзець',
'qbedit' => 'Рэдагаваць',
'qbpageoptions' => 'Гэтая старонка',
-'qbpageinfo' => 'Інфармацыя пра старонку',
'qbmyoptions' => 'Мае старонкі',
'qbspecialpages' => 'Спэцыяльныя старонкі',
'faq' => 'Частыя пытаньні',
'qbbrowse' => 'Избор',
'qbedit' => 'Редактиране',
'qbpageoptions' => 'Тази страница',
-'qbpageinfo' => 'Информация за страницата',
'qbmyoptions' => 'Моите страници',
'qbspecialpages' => 'Специални страници',
'faq' => 'ЧЗВ',
'qbbrowse' => 'Tangadahi',
'qbedit' => 'Babak',
'qbpageoptions' => 'Tungkaran ini',
-'qbpageinfo' => 'Naskah aluran',
'qbmyoptions' => 'Tungkaran ulun',
'qbspecialpages' => 'Tungkaran istimiwa',
'faq' => 'FAQ',
'qbbrowse' => 'ব্রাউজ',
'qbedit' => 'সম্পাদনা',
'qbpageoptions' => 'এ পাতার বিকল্পসমূহ',
-'qbpageinfo' => 'পাতা-সংক্রান্ত তথ্য',
'qbmyoptions' => 'আমার পছন্দ',
'qbspecialpages' => 'বিশেষ পাতাসমূহ',
'faq' => 'সম্ভাব্য প্রশ্নসমূহ',
'vector-action-protect' => 'সুরক্ষা',
'vector-action-undelete' => 'পুনরুদ্ধার',
'vector-action-unprotect' => 'সুরক্ষা পরিবর্তন',
-'vector-simplesearch-preference' => 'à¦\86রà¦\93 সমà§\83দà§\8dধ à¦\85নà§\81সনà§\8dধান পরামরà§\8dশ সক্রিয় করুন (শুধুমাত্র ভেক্টর স্কিনের জন্য)',
+'vector-simplesearch-preference' => 'সরল à¦\85নà§\81সনà§\8dধান সক্রিয় করুন (শুধুমাত্র ভেক্টর স্কিনের জন্য)',
'vector-view-create' => 'তৈরি করুন',
'vector-view-edit' => 'সম্পাদনা',
'vector-view-history' => 'ইতিহাস',
'edit-already-exists' => 'নতুন পাতা সৃষ্টি করা যায়নি।
পাতাটি ইতিমধ্যেই বিদ্যমান।',
'defaultmessagetext' => 'আদি টেক্সট',
+'content-failed-to-parse' => '$1 মডেলের জন্য $2 কন্টেন্ট পার্স করা যাচ্ছে না: $3',
+'invalid-content-data' => 'ভুল কন্টেন্ট ডাটা',
+'content-not-allowed-here' => '"$1" কন্টেন্টটি [[$2]] পাতায় অনুমোদিত নয়',
+
+# Content models
+'content-model-wikitext' => 'উইকিটেক্সট',
+'content-model-text' => 'সাধারণ লেখা',
+'content-model-javascript' => 'জাভাস্ক্রিপ্ট',
+'content-model-css' => 'সিএসএস',
# Parser/template warnings
'expensive-parserfunction-warning' => "'''সতর্ক হোন:''' এই পাতাটি অনেক বেশি পরিমাণে এক্সপেনসিভ পার্সার ফাংশন কল রয়েছে।
'uploadnewversion-linktext' => 'এই ফাইলটির একটি নতুন সংস্করণ আপলোড করুন',
'shared-repo-from' => '$1 থেকে',
'shared-repo' => 'শেয়ার্ড রিপোজিটরী',
-'upload-disallowed-here' => 'দà§\81à¦\83à¦\96িত à¦\86পনি à¦\8fà¦\87 à¦\9bবিটি প্রতিস্থাপন করতে পারবেন না।',
+'upload-disallowed-here' => 'à¦\86পনি à¦\8fà¦\87 ফাà¦\87লটি প্রতিস্থাপন করতে পারবেন না।',
# File reversion
'filerevert' => '$1 পূর্বাবস্থায় ফেরত নিন',
'qbbrowse' => 'Furchal',
'qbedit' => 'Kemmañ',
'qbpageoptions' => 'Pajenn an dibaboù',
-'qbpageinfo' => 'Pajenn gelaouiñ',
'qbmyoptions' => 'Ma dibaboù',
'qbspecialpages' => 'Pajennoù dibar',
'faq' => 'FAG',
'tog-nocache' => 'Onemogući keširanje stranica u pregledniku',
'tog-enotifwatchlistpages' => 'Pošalji mi e-poštu kad se promijene stranice',
'tog-enotifusertalkpages' => 'Pošalji mi e-poštu kad se promijeni moja korisnička stranica za razgovor',
-'tog-enotifminoredits' => 'Pošalji mi e-poštu takođe za male izmjene stranica',
+'tog-enotifminoredits' => 'Pošalji mi e-poštu također za male izmjene u stranicama i datotekama',
'tog-enotifrevealaddr' => 'Otkrij adresu moje e-pošte u porukama obaviještenja',
'tog-shownumberswatching' => 'Prikaži broj korisnika koji prate',
'tog-oldsig' => 'Postojeći potpis:',
'qbbrowse' => 'Prelistajte',
'qbedit' => 'Uredi',
'qbpageoptions' => 'Opcije stranice',
-'qbpageinfo' => 'Informacije o stranici',
'qbmyoptions' => 'Moje opcije',
'qbspecialpages' => 'Posebne stranice',
'faq' => 'ČPP',
'youhavenewmessages' => 'Imate $1 ($2).',
'newmessageslink' => 'novih poruka',
'newmessagesdifflink' => 'posljednja promjena',
+'youhavenewmessagesfromusers' => 'Imate $1 od {{PLURAL:$3|drugog korisnika|$3 korisnika}} ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|novu poruku|nove poruke}}',
'youhavenewmessagesmulti' => 'Imate nove poruke na $1',
'editsection' => 'uredi',
'editsection-brackets' => '[$1]',
'protectedpagetext' => 'Ova stranica je zaključana da bi se spriječile izmjene.',
'viewsourcetext' => 'Možete vidjeti i kopirati izvorni tekst ove stranice:',
'viewyourtext' => "Možete da pogledate i kopirate izvor '''vaših izmjena''' na ovoj stranici:",
-'protectedinterface' => 'Ova stranica je zaštićena jer sadrži tekst MediaWiki programa.',
+'protectedinterface' => 'Ova stranica sadrži tekst korisničkog okruženja za softver na ovom wikiju i zaštićena je radi sprečavanja zloupotrebe.
+Da biste dodali ili izmjenili prijevode svih wikija, posjetite [//translatewiki.net/ translatewiki.net], projekat za lokalizaciju Mediawikija.',
'editinginterface' => "'''Upozorenje:''' Mijenjate stranicu koja sadrži aktivan tekst programa.
Promjene na ovoj stranici dovode i do promjena za druge korisnike.
Za prijevode, molimo Vas koristite [//translatewiki.net/wiki/Main_Page?setlang=bs translatewiki.net], projekt prijevoda za MediaWiki.",
'titleprotected' => 'Naslov stranice je zaštićen od postavljanja od strane korisnika [[User:$1|$1]].
Iz razloga "\'\'$2\'\'".',
'exception-nologin' => 'Niste prijavljeni',
+'exception-nologin-text' => 'Ova stranica ili aktivnost zahtijeva da budete prijavljeni na ovom wikiju.',
# Virus scanner
'virus-badscanner' => "Loša konfiguracija: nepoznati anti-virus program: ''$1''",
'remembermypassword' => 'Zapamti moju šifru na ovom računaru (najviše $1 {{PLURAL:$1|dan|dana|dana}})',
'securelogin-stick-https' => 'Ostani povezan na HTTPS nakon prijave',
'yourdomainname' => 'Vaš domen:',
+'password-change-forbidden' => 'Ne možete da promjenite lozinku na ovom wikiju.',
'externaldberror' => 'Došlo je do greške pri vanjskoj autorizaciji baze podataka ili vam nije dopušteno osvježavanje Vašeg vanjskog korisničkog računa.',
'login' => 'Prijavi se',
'nav-login-createaccount' => 'Prijavi se / Registruj se',
Možete [[Special:Search/{{PAGENAME}}|tražiti naslov ove stranice]] na drugim stranicama.
<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tražiti u povezanim zapisima] ili [{{fullurl:{{FULLPAGENAME}}|action=edit}} urediti ovu stranicu]</span>.',
'noarticletext-nopermission' => 'Trenutno nema teksta na ovoj stranici.
-Možete [[Special:Search/{{PAGENAME}}|tražiti ovaj naslov stranice]] na drugim stranicama ili <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pretražiti povezane zapisnike]</span>.',
+Možete [[Special:Search/{{PAGENAME}}|tražiti ovaj naslov stranice]] na drugim stranicama ili <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pretražiti povezane zapisnike]</span>, ali nemate dozvolu da napravite ovu stranicu.',
'userpage-userdoesnotexist' => 'Korisnički račun "<nowiki>$1</nowiki>" nije registrovan.
Molimo provjerite da li želite napraviti/izmijeniti ovu stranicu.',
'userpage-userdoesnotexist-view' => 'Korisnički račun "$1" nije registrovan.',
*'''Firefox / Safari:''' držite ''Shift'' tipku i kliknite na ''Reload'' dugme ili pritisnite ''Ctrl-F5'' ili ''Ctrl-R'' (''⌘-R'' na Macu)
*'''Google Chrome:''' pritisnite ''Ctrl-Shift-R'' (''⌘-Shift-R'' na Macu)
*'''Internet Explorer:''' držite tipku ''Ctrl'' i kliknite na ''Refresh'' ili pritisnite ''Ctrl-F5''
-*'''Konqueror:''' klikni na ''Reload'' ili pritisnite dugme ''F5''
*'''Opera:''' očistite \"keš\" preko izbornika ''Tools → Preferences''",
'usercssyoucanpreview' => "'''Pažnja:''' Koristite dugme \"{{int:showpreview}}\" da testirate svoj novi CSS prije nego što sačuvate.",
'userjsyoucanpreview' => "'''Pažnja:''' Koristite dugme \"{{int:showpreview}}\" da testirate svoj novi JavaScript prije nego što sačuvate.",
Izgleda da već postoji.',
'defaultmessagetext' => 'Uobičajeni tekst poruke',
+# Content models
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
+
# Parser/template warnings
'expensive-parserfunction-warning' => 'Upozorenje: Ova stranica sadrži previše poziva opterećujućih parserskih funkcija.
'timezoneregion-indian' => 'Indijski okean',
'timezoneregion-pacific' => 'Tihi okean',
'allowemail' => 'Dozvoli e-poštu od ostalih korisnika',
-'prefs-searchoptions' => 'Opcije pretrage',
+'prefs-searchoptions' => 'Traži',
'prefs-namespaces' => 'Imenski prostori',
'defaultns' => 'Inače tražite u ovim imenskim prostorima:',
'default' => 'standardno',
'allpages-bad-ns' => '{{SITENAME}} nema imenski prostor "$1".',
'allpages-hide-redirects' => 'Sakrij preusmjerenja',
+# SpecialCachedPage
+'cachedspecial-refresh-now' => 'Pogledaj najnoviju.',
+
# Special:Categories
'categories' => 'Kategorije',
'categoriespagetext' => '{{PLURAL:$1|Slijedeća kategorija sadrži|Slijedeće kategorije sadrže}} stranice ili multimedijalne datoteke.
i imati ispravnu adresu e-pošte u vašim [[Special:Preferences|podešavanjima]]
da biste slali e-poštu drugim korisnicima.',
'emailuser' => 'Pošalji e-poštu ovom korisniku',
+'emailuser-title-notarget' => 'Pošalji e-mail korisniku',
'emailpage' => 'Pošalji e-mail korisniku',
'emailpagetext' => 'Možete korisiti formu ispod za slanje e-mail poruka ovom korisniku.
E-mail adresa koju ste unijeli u [[Special:Preferences|Vašim korisničkim postavkama]] će biti prikazana kao adresa pošiljaoca, tako da će primaoc poruke moći da Vam odgovori.',
# Durations
'duration-seconds' => '$1 {{PLURAL:$1|sekunda|sekunde}}',
+'duration-minutes' => '$1 {{PLURAL:$1|minut|minuta|minuta}}',
+'duration-hours' => '$1 {{PLURAL:$1|sat|sata|sati}}',
'duration-days' => '$1 {{PLURAL:$1|dan|dana}}',
+'duration-weeks' => '$1 {{PLURAL:$1|sedmica|sedmice|sedmica}}',
+'duration-years' => '$1 {{PLURAL:$1|godina|godine|godina}}',
+'duration-decades' => '$1 {{PLURAL:$1|decenija|decenije|decenija}}',
+'duration-centuries' => '$1 {{PLURAL:$1|vijek|vijeka|vijekova}}',
);
'qbbrowse' => 'Navega',
'qbedit' => 'Modifica',
'qbpageoptions' => 'Opcions de pàgina',
-'qbpageinfo' => 'Informació de pàgina',
'qbmyoptions' => 'Pàgines pròpies',
'qbspecialpages' => 'Pàgines especials',
'faq' => 'PMF',
'vector-action-protect' => 'Protegeix',
'vector-action-undelete' => 'Restaura',
'vector-action-unprotect' => 'Desprotegeix',
-'vector-simplesearch-preference' => 'Habilitar suggeriments de recerca millorats (només aparença Vector)',
+'vector-simplesearch-preference' => 'Activar la barra de cerca simplificada (només aparença Vector)',
'vector-view-create' => 'Inicia',
'vector-view-edit' => 'Modifica',
'vector-view-history' => "Mostra l'historial",
'protectedpagetext' => 'Aquesta pàgina està protegida per evitar modificacions.',
'viewsourcetext' => "Podeu visualitzar i copiar la font d'aquesta pàgina:",
'viewyourtext' => "Vostè pot veure i copiar la font de ' ' les modificacions ' ' d'aquesta pàgina:",
-'protectedinterface' => "Aquesta pàgina conté cadenes de text per a la interfície del programari, i és protegida per a previndre'n abusos.",
+'protectedinterface' => "Aquesta pàgina proporciona el text de la interfície del software d'aquest wiki i està protegida per evitar els abusos.
+Per agregar o canviar les traduccions per a tots els wikis, si us plau fes servir [//translatewiki.net/ translatewiki.net], el projecte de localització de MediaWiki.",
'editinginterface' => "'''Avís:''' Esteu editant una pàgina que conté cadenes de text per a la interfície d'aquest programari. Tingueu en compte que els canvis que es fan a aquesta pàgina afecten a l'aparença de la interfície d'altres usuaris. Pel que fa a les traduccions, plantegeu-vos utilitzar la [//translatewiki.net/wiki/Main_Page?setlang=ca translatewiki.net], el projecte de traducció de MediaWiki.",
'sqlhidden' => '(consulta SQL oculta)',
'cascadeprotected' => "Aquesta pàgina està protegida i no es pot modificar perquè està inclosa en {{PLURAL:$1|la següent pàgina, que té|les següents pàgines, que tenen}} activada l'opció de «protecció en cascada»:
'userpage-userdoesnotexist-view' => 'El compte d\'usuari "$1" no està registrat.',
'blocked-notice-logextract' => "En aquests moments aquest compte d'usuari es troba blocat.
Per més detalls, la darrera entrada del registre es mostra a continuació:",
-'clearyourcache' => "'''Nota:''' Després de desar, podeu haver d'ometre la memòria cau del vostre navegador per a veure'n els canvis.
-* '''Firefox / Safari:''' Premeu ''Maj'' mentre cliqueu a ''Actualitza'' (Reload), o premeu ''Ctrl+F5'' o ''Ctrl+R'' (''⌘+R'' en un Mac)
-* '''Google Chrome:''' Premeu ''Ctrl+Maj+R'' (''⌘+Maj+R'' en un Mac)
-* '''Internet Explorer:''' Premeu ''Ctrl'' mentre cliqueu a ''Actualitza'' (Refresh), o premeu ''Ctrl+F5''
-* '''Konqueror:''' Cliqueu al botó ''Recarrega'' (Reload), o premeu ''F5''
-* '''Opera:''' Netegeu la vostra memòria cau a ''Tools → Preferences''",
+'clearyourcache' => "'''Nota:''' després de guardar possiblement necessites refrescar el teu cache per poder veure els canvis.
+* '''Firefox / Safari:''' pressiona ''Shift'' mentre cliques el botó ''Actualitzar'', o pressiona ''Ctrl+F5'' o ''Ctrl+R'' (''⌘+R'' a Mac)
+* '''Google Chrome:''' pressiona ''Ctrl+Shift+R'' (''⌘+Shift+R'' a Mac)
+* '''Internet Explorer:''' pressiona la tecla ''Ctrl'' mentre cliques a ''Actualitzar'' o pressiona ''Ctrl+F5''
+* '''Opera:''' buida la memòria cau (cache) ''Eines → Preferències''",
'usercssyoucanpreview' => "'''Consell:''' Utilitzeu el botó \"{{int:showpreview}}\" per provar el vostre nou CSS abans de desar-lo.",
'userjsyoucanpreview' => "'''Consell:''' Utilitzeu el botó \"{{int:showpreview}}\" per provar el vostre nou JavaScript abans de desar-lo.",
'usercsspreview' => "'''Recordeu que esteu previsualitzant el vostre CSS d'usuari.'''
'revdelete-only-restricted' => 'Error amagant els ítems $2, $1: no pots suprimir elements a la vista dels administradors sense seleccionar alhora una de les altres opcions de supressió.',
'revdelete-reason-dropdown' => "*Raons d'esborrament comunes
** Violació del copyright
-** Informació personal inapropiada
+** Comentari o informació personal inapropiada
+** Nom d'usuari inapropiat
** Informació potencialment calumniosa",
'revdelete-otherreason' => 'Altre motiu / motiu suplementari:',
'revdelete-reasonotherlist' => 'Altres raons',
i tenir una direcció electrònica vàlida en les vostres [[Special:Preferences|preferències]]
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",
'emailpage' => 'Correu electrònic a usuari',
'emailpagetext' => "Podeu usar el següent formulari per a enviar un missatge de correu electrònic a aquest usuari.
L'adreça electrònica que heu entrat en [[Special:Preferences|les vostres preferències d'usuari]] apareixerà com a remitent del correu electrònic, de manera que el destinatari us podrà respondre directament.",
'undeletedrevisions' => '{{PLURAL:$1|Una revisió restaurada|$1 revisions restaurades}}',
'undeletedrevisions-files' => '{{PLURAL:$1|Una revisió|$1 revisions}} i {{PLURAL:$2|un fitxer|$2 fitxers}} restaurats',
'undeletedfiles' => '$1 {{PLURAL:$1|fitxer restaurat|fitxers restaurats}}',
-'cannotundelete' => "No s'ha pogut restaurar; algú altre pot estar restaurant la mateixa pàgina.",
+'cannotundelete' => 'Hi ha hagut un error en el procés de restauració:
+$1',
'undeletedpage' => "'''S'ha restaurat «$1»'''
Consulteu el [[Special:Log/delete|registre d'esborraments]] per a veure els esborraments i els restauraments més recents.",
# Info page
'pageinfo-title' => 'Informació de «$1»',
-'pageinfo-header-edits' => 'Modificacions',
+'pageinfo-header-basic' => 'Informació bàsica',
+'pageinfo-header-edits' => "Historial d'edicions",
+'pageinfo-header-restrictions' => 'Protecció de pàgina',
'pageinfo-views' => 'Número de visites',
-'pageinfo-watchers' => "Número d'usuaris que l'estan vigilant",
-'pageinfo-edits' => "Número d'edicions",
-'pageinfo-authors' => "Número d'autors diferents",
+'pageinfo-watchers' => "Número d'usuaris que vigilen la pàgina",
+'pageinfo-firstuser' => 'Creador de la pàgina',
+'pageinfo-firsttime' => 'Data de la creació de la pàgina',
+'pageinfo-lastuser' => 'Últim editor',
+'pageinfo-lasttime' => "Data de l'última edició",
+'pageinfo-edits' => "Número total d'edicions",
+'pageinfo-authors' => "Número total d'autors diferents",
# Skin names
'skinname-standard' => 'Clàssic',
'qbbrowse' => 'بگهڕێ',
'qbedit' => 'دەستکاری',
'qbpageoptions' => 'ئەم پەڕەیە',
-'qbpageinfo' => 'زانیاریی پهڕه',
'qbmyoptions' => 'پەڕەکانم',
'qbspecialpages' => 'پەڕە تایبەتەکان',
'faq' => 'پرسیار و وەڵام (FAQ)',
'import-logentry-interwiki-detail' => '$1 {{PLURAL:$1|پێداچوونەوە|پێداچوونەوە}} لە $2',
# Tooltip help for the actions
-'tooltip-pt-userpage' => 'پەڕە بەکارھێنەریی تۆ',
+'tooltip-pt-userpage' => 'پەڕەی بەکارھێنەرییەکەت',
'tooltip-pt-anonuserpage' => 'پەڕەی بەکارھێنەری بۆ ئایپی یەکە کە بەناویەوە خەریکی دەستکاری کردنی',
-'tooltip-pt-mytalk' => 'Ù¾Û\95Ú\95Û\95Û\8c Ù\88تÙ\88بÛ\8eÚ\98Û\8c تÛ\86',
+'tooltip-pt-mytalk' => 'Ù¾Û\95Ú\95Û\95Û\8c Ù\84Û\8eدÙ\88اÙ\86Û\95Ú©Û\95ت',
'tooltip-pt-anontalk' => 'لێدوان لەسەر دەستکارییەکان لەم ئایپی ئەدرەسەوە',
-'tooltip-pt-preferences' => 'بژاردەکانت',
+'tooltip-pt-preferences' => 'هەڵبژاردەکانت',
'tooltip-pt-watchlist' => 'پێرستی ئەو پەڕانە کە چاودێریی گۆڕانکارییەکانیانی دەکەی',
-'tooltip-pt-mycontris' => 'Ù\84Û\8cستی بەشدارییەکانت',
+'tooltip-pt-mycontris' => 'Ù¾Û\8eرستی بەشدارییەکانت',
'tooltip-pt-login' => 'پێشنیارت پێدەکرێ بچیتە ژوورەوە؛ ھەرچەندە زۆرت لێناکرێ',
'tooltip-pt-anonlogin' => 'پێشنیار دەکەین بڕۆیتەژوورەوە، ئەگەرچی ئەوە زۆرەملیی نیە',
'tooltip-pt-logout' => 'دەرچوون',
'qbbrowse' => 'Listování',
'qbedit' => 'Editování',
'qbpageoptions' => 'Tato stránka',
-'qbpageinfo' => 'Kontext',
'qbmyoptions' => 'Moje volby',
'qbspecialpages' => 'Speciální stránky',
'faq' => 'Často kladené otázky',
'shared-repo-from' => 'z {{grammar:2sg|$1}}',
'shared-repo' => 'sdíleného úložiště',
'filepage.css' => '/* Zde uvedené CSS se vkládá na stránky s popisem souboru, včetně cizích klientských wiki */',
-'upload-disallowed-here' => 'Tento soubor bohužel nemůžete přepsat.',
+'upload-disallowed-here' => 'Tento soubor nemůžete přepsat.',
# File reversion
'filerevert' => 'Vrátit zpět $1',
# Info page
'pageinfo-title' => 'Informace o stránce „$1“',
+'pageinfo-not-current' => 'Informace lze zobrazit jen pro aktuální verzi.',
'pageinfo-header-basic' => 'Základní údaje',
'pageinfo-header-edits' => 'Historie editací',
'pageinfo-header-restrictions' => 'Zámek stránky',
'qbbrowse' => 'Pori',
'qbedit' => 'Golygu',
'qbpageoptions' => 'Y dudalen hon',
-'qbpageinfo' => 'Cyd-destun',
'qbmyoptions' => 'Fy nhudalennau',
'qbspecialpages' => 'Tudalennau arbennig',
'faq' => 'Cwestiynau cyffredin',
'qbbrowse' => 'Gennemse',
'qbedit' => 'Redigér',
'qbpageoptions' => 'Indstillinger for side',
-'qbpageinfo' => 'Information om side',
'qbmyoptions' => 'Mine indstillinger',
'qbspecialpages' => 'Specielle sider',
'faq' => 'OSS',
'edit-no-change' => 'Din ændring ignoreredes, fordi der ikke var ændring af teksten.',
'edit-already-exists' => 'En ny side kunne ikke oprettes, fordi den allerede findes.',
'defaultmessagetext' => 'Standardtekst',
+'content-failed-to-parse' => 'Kunne ikke parse $2 indhold for $1 model: $3',
+'invalid-content-data' => 'Ugyldig indholdsdata',
+'content-not-allowed-here' => '"$1" indhold er ikke tilladt på siden [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'wikitekst',
+'content-model-text' => 'almindelig tekst',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Advarsel: Der er for mange beregningstunge oversætter-funktionskald på denne side.
'undeletedrevisions' => '$1 {{PLURAL:$1|version|versioner}} gendannet',
'undeletedrevisions-files' => '$1 {{plural:$1|version|versioner}} og $2 {{plural:$2|fil|filer}} gendannet',
'undeletedfiles' => '$1 {{plural:$1|fil|filer}} gendannet',
-'cannotundelete' => 'Gendannelse mislykkedes; en anden har allerede gendannet siden.',
+'cannotundelete' => 'Gendannelse mislykkedes:
+$1',
'undeletedpage' => "'''$1''' blev gendannet.
I [[Special:Log/delete|slette-loggen]] findes en oversigt over de nyligt slettede og gendannede sider.",
'immobile-target-namespace-iw' => 'En side kan ikke flyttes til en interwiki-henvisning.',
'immobile-source-page' => 'Denne side kan ikke flyttes.',
'immobile-target-page' => 'Kan ikke flytte til det navn.',
+'bad-target-model' => 'Den ønskede destination bruger en anden indholdsmodel. Kan ikke konvertere fra $1 til $2.',
'imagenocrossnamespace' => 'Filer kan ikke flyttes til et navnerum der ikke indeholder filer',
'nonfile-cannot-move-to-file' => 'Kan ikke flytte ikke-filer til fil-navnerummet',
'imagetypemismatch' => 'Den nye filendelse passer ikke til filtypen',
# Info page
'pageinfo-title' => 'Information om "$1"',
+'pageinfo-not-current' => 'Oplysninger vises kun for den aktuelle version.',
'pageinfo-header-basic' => 'Grundlæggende oplysninger',
'pageinfo-header-edits' => 'Redigeringshistorik',
'pageinfo-header-restrictions' => 'Sidebeskyttelse',
'qbbrowse' => 'Durchsuchen',
'qbedit' => 'Bearbeiten',
'qbpageoptions' => 'Seitenoptionen',
-'qbpageinfo' => 'Kontext',
'qbmyoptions' => 'Meine Seiten',
'qbspecialpages' => 'Spezialseiten',
'faq' => 'Häufig gestellte Fragen',
'shared-repo-from' => 'aus $1',
'shared-repo' => 'einem gemeinsam genutzten Medienarchiv',
'filepage.css' => '/* Das folgende CSS wird auf Dateibeschreibungsseiten, auch auf fremden Client-Wikis, geladen. */',
-'upload-disallowed-here' => 'Leider kannst du dieses Bild nicht überschreiben.',
+'upload-disallowed-here' => 'Du kannst diese Datei nicht überschreiben.',
# File reversion
'filerevert' => 'Zurücksetzen von „$1“',
# Info page
'pageinfo-title' => 'Informationen zu „$1“',
+'pageinfo-not-current' => 'Diese Informationen können nur für die aktuelle Version angezeigt werden.',
'pageinfo-header-basic' => 'Basisinformationen',
'pageinfo-header-edits' => 'Bearbeitungsgeschichte',
'pageinfo-header-restrictions' => 'Seitenschutz',
# Font style option in Special:Preferences
'editfont-style' => 'Cayê vurnayışi de tipê nuştışi:',
-'editfont-default' => 'Hesıbyayiya rovıteri',
-'editfont-monospace' => 'Tipê nustey sabıtcagırewtoği',
-'editfont-sansserif' => 'Tipê nustey Sans-serifi',
-'editfont-serif' => 'Tipê nustey Serifi',
+'editfont-default' => 'Qerar cıgeyraoği dest dero',
+'editfont-monospace' => 'Tipê nusteyê sabıtcagırewtoği',
+'editfont-sansserif' => 'Babetê Sans-serifi',
+'editfont-serif' => 'Tipê nusteyê serifi',
# Dates
'sunday' => 'Bazar',
'thursday' => 'Pancşeme',
'friday' => 'Êne',
'saturday' => 'Bahdê êni',
-'sun' => 'Baz',
-'mon' => 'Ber',
+'sun' => 'Bzr',
+'mon' => 'Brr',
'tue' => 'Tlt',
'wed' => 'Çrş',
-'thu' => 'Pnş',
+'thu' => 'Pşm',
'fri' => 'Êne',
'sat' => 'Bah',
'january' => 'Çele',
'february' => 'Zemherı',
'march' => 'Mert',
-'april' => 'Lisane',
-'may_long' => 'Gulan',
+'april' => 'Lizan',
+'may_long' => 'Vılıkan',
'june' => 'Heziran',
'july' => 'Paliyan',
'august' => 'Tebaxe',
'january-gen' => 'Çele',
'february-gen' => 'Zemherı',
'march-gen' => 'Mert',
-'april-gen' => 'Lisan',
-'may-gen' => 'Gulan',
+'april-gen' => 'Lizan',
+'may-gen' => 'Vılıkan',
'june-gen' => 'Heziran',
'july-gen' => 'Paliyan',
'august-gen' => 'Tebaxe',
'about' => 'Heqa',
'article' => 'Wesiqe',
-'newwindow' => '(zerreyê teqeyê newey de beno a)',
+'newwindow' => '(teqa da newi de abena)',
'cancel' => 'Bıtexelne',
'moredotdotdot' => 'Vêşêri...',
'mypage' => 'Pela mı',
-'mytalk' => 'Verênayışê mı',
+'mytalk' => 'Behsê mı',
'anontalk' => 'Pela werênayışê nê IPy',
'navigation' => 'Geyrayış',
'and' => ' u',
'qbbrowse' => 'Rovete',
'qbedit' => 'Bıvurne',
'qbpageoptions' => 'Ena pele',
-'qbpageinfo' => 'Gıre',
'qbmyoptions' => 'Pelê mı',
'qbspecialpages' => 'Peley xısusi',
'faq' => 'PZP (Persê ke zehf persiyenê)',
# Edit pages
'summary' => 'Xelese:',
'subject' => 'Mewzu/serrêze:',
-'minoredit' => 'Vurnayışo qıcek',
+'minoredit' => 'Eno vurnayışo de qıckeko',
'watchthis' => 'Ena perer teqib ke',
'savearticle' => 'Pele qeyd ke',
'preview' => 'Verqayt',
'showpreview' => 'Verqayti bımocne',
'showlivepreview' => 'Verqayto cıwın',
-'showdiff' => 'Vurnayışa bıvin',
+'showdiff' => 'Vurnayışan bımocne',
'anoneditwarning' => 'Teme!: Şıma bı hesabê xo nıkewtê cı. Hurêndiya namey şıma dı IP-adresa şıma qeyd bena u asena.',
'anonpreviewwarning' => "''Ti hama nicikewte. Qeyd kerdiş zerre tarixê pele de adresê IP yê tu keyd keno.''",
'missingsummary' => "'''DİQET:''' Şıma kılmnuşte nıkerd.
'shared-repo' => 'yew embarê repositoryî',
'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
'filepage.css' => '/* CSS placed here is included on the file description page, also included on foreign client wikis */',
-'upload-disallowed-here' => 'Nê asengi sero theba nênusneyêno.',
+'upload-disallowed-here' => 'Şıma na dosya de teba nênusnayo.',
# File reversion
'filerevert' => '$1 reyna biyere',
'usermessage-template' => 'MediaWiki:UserMessage',
# Watchlist
-'watchlist' => 'lista mına seyr-kerdışi',
-'mywatchlist' => 'Listey taqiban',
+'watchlist' => 'Listey teqiban',
+'mywatchlist' => 'Listey teqiban',
'watchlistfor2' => 'Qandê $1 ($2)',
'nowatchlist' => 'listeya temaşa kerdıişê şıma de yew madde zi çina.',
'watchlistanontext' => 'qey vurnayişê maddeya listeya temaşakerdişi $1.',
# Contributions
'contributions' => 'İştiraqê karberi',
'contributions-title' => 'Dekerdenê karber de $1',
-'mycontris' => 'Dekerdeni',
+'mycontris' => 'Dekerdenê mı',
'contribsub2' => 'Qandê $1 ($2)',
'nocontribs' => 'Ena kriteriya de vurnayîş çini yo.',
'uctop' => '(top)',
# Info page
'pageinfo-title' => 'Heq tê "$1"\'i',
+'pageinfo-not-current' => 'Malumat tenya qande rocane rewizyoni mocneyêno.',
'pageinfo-header-basic' => 'Seron zanayış',
'pageinfo-header-edits' => 'Vurnayışi verêni',
'pageinfo-header-restrictions' => 'Xısusiyetê pela',
# Watchlist editing tools
'watchlisttools-view' => 'vurnayışanê eleqadari bıvin',
-'watchlisttools-edit' => 'listey taqiban bıvinê u bıvurnê',
+'watchlisttools-edit' => 'Lista seyrkerdışi bıvênên u bıvurnên',
'watchlisttools-raw' => 'Listeyê seyr-kerdışi bıvin',
# Iranian month names
'qbbrowse' => 'Pśeběraś',
'qbedit' => 'Pśeměniś',
'qbpageoptions' => 'Toś ten bok',
-'qbpageinfo' => 'Kontekst',
'qbmyoptions' => 'Móje boki',
'qbspecialpages' => 'Specialne boki',
'faq' => 'FAQ (pšašanja a wótegrona)',
'qbbrowse' => 'Περιήγηση',
'qbedit' => 'Επεξεργασία',
'qbpageoptions' => 'Αυτή η σελίδα',
-'qbpageinfo' => 'Συμφραζόμενα',
'qbmyoptions' => 'Οι σελίδες μου',
'qbspecialpages' => 'Σελίδες λειτουργιών',
'faq' => 'Συχνές ερωτήσεις (FAQ)',
'qbbrowse' => 'Browse',
'qbedit' => 'Edit',
'qbpageoptions' => 'This page',
-'qbpageinfo' => 'Context',
'qbmyoptions' => 'My pages',
'qbspecialpages' => 'Special pages',
'faq' => 'FAQ',
'portal-url' => 'Project:Community portal',
'privacy' => 'Privacy policy',
'privacypage' => 'Project:Privacy policy',
-'content-failed-to-parse' => "Failed to parse $2 content for $1 model: $3",
'badaccess' => 'Permission error',
'badaccess-group0' => 'You are not allowed to execute the action you have requested.',
'addsection-preload' => '', # do not translate or duplicate this message to other languages
'addsection-editintro' => '', # do not translate or duplicate this message to other languages
'defaultmessagetext' => 'Default message text',
+'content-failed-to-parse' => 'Failed to parse $2 content for $1 model: $3',
'invalid-content-data' => 'Invalid content data',
'content-not-allowed-here' => '"$1" content is not allowed on page [[$2]]',
+# Content models
+'content-model-wikitext' => 'wikitext',
+'content-model-text' => 'plain text',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
+
# Parser/template warnings
'expensive-parserfunction-warning' => "'''Warning:''' This page contains too many expensive parser function calls.
'shared-repo' => 'a shared repository',
'shared-repo-name-wikimediacommons' => 'Wikimedia Commons', # only translate this message to other languages if you have to change it
'filepage.css' => '/* CSS placed here is included on the file description page, also included on foreign client wikis */', # only translate this message to other languages if you have to change it
-'upload-disallowed-here' => 'Unfortunately you cannot overwrite this image.',
+'upload-disallowed-here' => 'You cannot overwrite this file.',
# File reversion
'filerevert' => 'Revert $1',
# Info page
'pageinfo-header' => '-', # do not translate or duplicate this message to other languages
'pageinfo-title' => 'Information for "$1"',
+'pageinfo-not-current' => 'Information may only be displayed for the current revision.',
'pageinfo-header-basic' => 'Basic information',
'pageinfo-header-edits' => 'Edit history',
'pageinfo-header-restrictions' => 'Page protection',
'duration-centuries' => '$1 {{PLURAL:$1|century|centuries}}',
'duration-millennia' => '$1 {{PLURAL:$1|millennium|millennia}}',
-# Content model IDs for the ContentHandler facility; used by ContentHandler::getContentModel()
-'content-model-wikitext' => 'wikitext',
-'content-model-javascript' => 'JavaScript',
-'content-model-css' => 'CSS',
-'content-model-text' => 'plain text',
-
);
'qbbrowse' => 'Foliumi',
'qbedit' => 'Redakti',
'qbpageoptions' => 'Paĝagado',
-'qbpageinfo' => 'Paĝinformoj',
'qbmyoptions' => 'Personaĵoj',
'qbspecialpages' => 'Specialaj paĝoj',
'faq' => 'Oftaj demandoj',
* @author Locos epraix
* @author Mahadeva
* @author Manuelt15
+ * @author Maor X
* @author McDutchie
* @author Muro de Aguas
* @author Omnipaedista
'qbbrowse' => 'Navegar',
'qbedit' => 'Editar',
'qbpageoptions' => 'Opciones de página',
-'qbpageinfo' => 'Información de página',
'qbmyoptions' => 'Mis páginas',
'qbspecialpages' => 'Páginas especiales',
'faq' => 'Preguntas más frecuentes',
'faqpage' => 'Project:FAQ',
# Vector skin
-'vector-action-addsection' => 'Añadir tema',
+'vector-action-addsection' => 'Nueva sección',
'vector-action-delete' => 'Borrar',
'vector-action-move' => 'Mover',
'vector-action-protect' => 'Proteger',
'edit-already-exists' => 'No se pudo crear una página nueva.
Ya existe.',
'defaultmessagetext' => 'Texto de mensaje predeterminado',
+'content-failed-to-parse' => 'No se pudo analizar el contenido $2 del modelo $1: $3',
+'invalid-content-data' => 'Datos de contenido inválidos',
+'content-not-allowed-here' => 'El contenido "$1" no está permitido en la página [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'texto wiki',
+'content-model-text' => 'Texto sin formato',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Aviso: Esta página contiene demasiadas llamadas a funciones sintácticas costosas (#ifexist: y similares)
Leyenda: (act) = diferencias con la versión actual,
(prev) = diferencias con la versión previa, M = edición menor",
'history-fieldset-title' => 'Buscar en el historial',
-'history-show-deleted' => 'Solamente borrado',
+'history-show-deleted' => 'Solo ediciones ocultadas',
'histfirst' => 'Primeras',
'histlast' => 'Últimas',
'historysize' => '({{PLURAL:$1|1 byte|$1 bytes}})',
'shared-repo-from' => 'de $1',
'shared-repo' => 'un repositorio compartido',
'filepage.css' => '/* Los estilos CSS colocados aquí se incluirán en las páginas de descripción de archivos, incluso en los wikis externos que incluyan estas páginas */',
-'upload-disallowed-here' => 'Lamentablemente no puedes sobrescribir esta imagen.',
+'upload-disallowed-here' => 'No puedes sobrescribir este archivo.',
# File reversion
'filerevert' => 'Revertir $1',
Puedes filtrar la vista seleccionando un tipo de registro, el nombre del usuario o la página afectada. Se distinguen mayúsculas de minúsculas.',
'logempty' => 'No hay elementos en el registro con esas condiciones.',
'log-title-wildcard' => 'Buscar títulos que empiecen con este texto',
-'showhideselectedlogentries' => 'Mostrar u ocultar las entradas del registro seleccionado',
+'showhideselectedlogentries' => 'Mostrar u ocultar las entradas seleccionadas del registro',
# Special:AllPages
'allpages' => 'Todas las páginas',
'undeletedrevisions' => '{{PLURAL:$1|Una edición restaurada|$1 ediciones restauradas}}',
'undeletedrevisions-files' => '$1 {{PLURAL:$1|ediciones restauradas y $2 archivo restaurado|ediciones y $2 archivos restaurados}}',
'undeletedfiles' => '$1 {{PLURAL:$1|archivo restaurado|archivos restaurados}}',
-'cannotundelete' => 'Ha fallado el deshacer el borrado;
-alguien más puede haber deshecho el borrado antes.',
+'cannotundelete' => 'Hubo un error durante la restauración:
+$1',
'undeletedpage' => "'''Se ha restaurado $1'''
Consulta el [[Special:Log/delete|registro de borrados]] para ver una lista de los últimos borrados y restauraciones.",
A continuación se muestra la última entrada del registro de bloqueos para mayor referencia.',
'sp-contributions-search' => 'Buscar contribuciones',
'sp-contributions-username' => 'Dirección IP o nombre de usuario:',
-'sp-contributions-toponly' => 'Mostrar solamente revisiones top',
+'sp-contributions-toponly' => 'Solo mostrar últimas ediciones de página',
'sp-contributions-submit' => 'Buscar',
# What links here
'immobile-target-namespace-iw' => 'Un enlace interwiki no es un destino válido para trasladar una página.',
'immobile-source-page' => 'Esta página no se puede renombrar.',
'immobile-target-page' => 'No se puede trasladar a tal título.',
+'bad-target-model' => 'El destino deseado utiliza un modelo diferente de contenido. No se puede realizar la conversión de $1 a $2.',
'imagenocrossnamespace' => 'No se puede trasladar el fichero a otro espacio de nombres',
'nonfile-cannot-move-to-file' => 'No es posible mover un no-archivo al espacio de nombres de archivo',
'imagetypemismatch' => 'La nueva extensión de archivo no corresponde con su tipo',
# Info page
'pageinfo-title' => 'Información para «$1»',
+'pageinfo-not-current' => 'Únicamente se puede mostrar la información para la revisión actual.',
'pageinfo-header-basic' => 'Información básica',
'pageinfo-header-edits' => 'Historial de ediciones',
'pageinfo-header-restrictions' => 'Protección de página',
'sqlite-no-fts' => '$1 sin soporte para búsqueda de texto completo',
# New logging system
-'logentry-delete-delete' => '$1 borró la página $3',
-'logentry-delete-restore' => '$1 restauró la página $3',
+'logentry-delete-delete' => '$1 borró la página «$3»',
+'logentry-delete-restore' => '$1 restauró la página «$3»',
'logentry-delete-event' => '$1 modificó la visibilidad de {{PLURAL:$5|un evento del registro|$5 eventos del registro}} en $3: $4',
'logentry-delete-revision' => '$1 modificó la visibilidad de {{PLURAL:$5|una edición|$5 ediciones}} en la página $3: $4',
'logentry-delete-event-legacy' => '$1 modificó la visibilidad de los eventos del registro en $3',
'qbbrowse' => 'Sirvi',
'qbedit' => 'Redigeeri',
'qbpageoptions' => 'Lehekülje suvandid',
-'qbpageinfo' => 'Lehekülje andmed',
'qbmyoptions' => 'Minu suvandid',
'qbspecialpages' => 'Erileheküljed',
'faq' => 'KKK',
'qbbrowse' => 'Arakatu',
'qbedit' => 'Aldatu',
'qbpageoptions' => 'Orrialde hau',
-'qbpageinfo' => 'Testuingurua',
'qbmyoptions' => 'Nire orrialdeak',
'qbspecialpages' => 'Aparteko orrialdeak',
'faq' => 'Maiz egindako galderak',
'qbbrowse' => 'Escrucal',
'qbedit' => 'Eital',
'qbpageoptions' => 'Esta páhina',
-'qbpageinfo' => 'Contestu',
'qbmyoptions' => 'Las mis páhinas',
'qbspecialpages' => 'Páhinas especialis',
'faq' => 'FAQ',
'qbbrowse' => 'مرور',
'qbedit' => 'ویرایش',
'qbpageoptions' => 'این صفحه',
-'qbpageinfo' => 'محتوا',
'qbmyoptions' => 'صفحههای من',
'qbspecialpages' => 'صفحههای ویژه',
'faq' => 'پرسشهای متداول',
'shared-repo-from' => 'از $1',
'shared-repo' => 'یک مخزن مشترک',
'shared-repo-name-wikimediacommons' => 'ویکیانبار',
-'upload-disallowed-here' => 'Ù\85تاسÙ\81اÙ\86Ù\87 Ø´Ù\85ا Ù\86Ù\85Û\8c تÙ\88اÙ\86Û\8cد اÛ\8cÙ\86 Ù\86گاره را بازنویس کنید.',
+'upload-disallowed-here' => 'Ù\85تاسÙ\81اÙ\86Ù\87 Ø´Ù\85ا Ù\86Ù\85Û\8c تÙ\88اÙ\86Û\8cد اÛ\8cÙ\86 پرÙ\88Ù\86ده را بازنویس کنید.',
# File reversion
'filerevert' => 'واگردانی $1',
'undeletedrevisions-files' => '$1 نسخه و $2 پرونده احیا {{PLURAL:$1|شد|شدند}}.',
'undeletedfiles' => '$1 پرونده احیا {{PLURAL:$1|شد|شدند}}.',
'cannotundelete' => 'احیا ناموفق بود؛
-ممکن است کس دیگری پیشتر این صفحه را احیا کرده باشد.',
+$1',
'undeletedpage' => "'''$1 احیا شد'''
برای دیدن سیاههٔ حذفها و احیاهای اخیر به [[Special:Log/delete|سیاههٔ حذف]] رجوع کنید.",
'qbbrowse' => 'Selaa',
'qbedit' => 'Muokkaa',
'qbpageoptions' => 'Sivuasetukset',
-'qbpageinfo' => 'Sivun tiedot',
'qbmyoptions' => 'Asetukset',
'qbspecialpages' => 'Toimintosivut',
'faq' => 'Usein kysytyt kysymykset',
'delete-hook-aborted' => 'Laajennuskoohdi esti muokkauksen antamatta syytä.',
'badtitle' => 'Virheellinen otsikko',
'badtitletext' => 'Pyytämäsi sivuotsikko oli virheellinen, tyhjä tai väärin linkitetty kieltenvälinen tai wikienvälinen linkki.',
-'perfcached' => 'Tiedot ovat välimuistista eivätkä välttämättä ole ajan tasalla. Välimuistissa on enintään {{PLURAL:$1|yksi tulos|$1 tulosta}}.',
-'perfcachedts' => 'Tiedot ovat välimuistista ja se päivitettiin viimeksi $1. Välimuistissa on enintään {{PLURAL:$4|yksi tulos|$4 tulosta}}.',
+'perfcached' => 'Tiedot ovat välimuistista eivätkä välttämättä ole ajan tasalla. Välimuistissa on saatavilla enintään {{PLURAL:$1|yksi tulos|$1 tulosta}}.',
+'perfcachedts' => 'Tiedot ovat välimuistista ja se päivitettiin viimeksi $1. Välimuistissa on saatavilla enintään {{PLURAL:$4|yksi tulos|$4 tulosta}}.',
'querypage-no-updates' => 'Tämän sivun tietoja ei toistaiseksi päivitetä.',
'wrong_wfQuery_params' => 'Virheelliset parametrit wfQuery()<br />Funktio: $1<br />Tiedustelu: $2',
'viewsource' => 'Lähdekoodi',
'token_suffix_mismatch' => "'''Muokkauksesi on hylätty, koska asiakasohjelmasi ei osaa käsitellä välimerkkejä muokkaustarkisteessa. Syynä voi olla viallinen välityspalvelin.'''",
'edit_form_incomplete' => "'''Osa muokkauslomakkeesta ei saavuttanut palvelinta. Tarkista, että muokkauksesi ovat vahingoittumattomia ja yritä uudelleen.'''",
'editing' => 'Muokataan sivua $1',
-'creating' => 'Luodaan sivu $1',
+'creating' => 'Luodaan sivua $1',
'editingsection' => 'Muokataan osiota sivusta $1',
'editingcomment' => 'Muokataan uutta osiota sivulla $1',
'editconflict' => 'Päällekkäinen muokkaus: $1',
'tog-shownumberswatching' => 'Näytä kuinka moni käyttäjä valvoo sivua',
'tog-oldsig' => 'Nykynen allekirjotus',
'tog-fancysig' => 'Mookkaamaton allekirjotus ilman auttomaattista linkkiä',
-'tog-externaleditor' => 'Käytä ekterniä tekstiedituuria stantartina. Vain kokenheile käyttäjile, vaatii taattorin asetuksitten muuttamista. Käytä eksterniä tekstiedituuria oletuksena. Vain kokeneille käyttäjille, vaatii selaimen asetusten muuttamista. (<span class="plainlinks">[[//www.mediawiki.org/wiki/Manual:External_editors Ohje]</span>)',
+'tog-externaleditor' => 'Käytä ekterniä tekstiedituuria stantartina. Vain kokenheile käyttäjile, vaatii taattorin asetuksitten muuttamista. Käytä eksterniä tekstiedituuria oletuksena. Vain kokeneille käyttäjille, vaatii selaimen asetusten muuttamista. ([//www.mediawiki.org/wiki/Manual:External_editors Ohje])',
# Dates
'sunday' => 'pyhä',
# Cologne Blue skin
'qbedit' => 'Mookkaa',
'qbpageoptions' => 'Tämä sivu',
-'qbpageinfo' => 'Sisältö',
'qbmyoptions' => 'Minun inställninkit',
'qbspecialpages' => 'Spesiaali sivut',
'faq' => 'Useasti kysytyt kysymykset',
'qbbrowse' => 'Parcourir',
'qbedit' => 'Modifier',
'qbpageoptions' => 'Cette page',
-'qbpageinfo' => 'Contexte',
'qbmyoptions' => 'Mes pages',
'qbspecialpages' => 'Pages spéciales',
'faq' => 'FAQ',
'vector-simplesearch-preference' => "Activer la barre de recherche simplifiée (seulement pour l'habillage Vector)",
'vector-view-create' => 'Créer',
'vector-view-edit' => 'Modifier',
-'vector-view-history' => 'Afficher l’historique',
+'vector-view-history' => "Afficher l'historique",
'vector-view-view' => 'Lire',
'vector-view-viewsource' => 'Voir la source',
'actions' => 'Actions',
Votre compte a été créé.
N’oubliez pas de personnaliser vos [[Special:Preferences|préférences sur {{SITENAME}}]].',
-'yourname' => 'Nom d’utilisateur :',
+'yourname' => 'Nom d’utilisateur :',
'yourpassword' => 'Mot de passe :',
'yourpasswordagain' => 'Confirmez le mot de passe :',
'remembermypassword' => 'Me reconnecter automatiquement aux prochaines visites avec ce navigateur (au maximum $1 {{PLURAL:$1|jour|jours}})',
pouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.',
'noemail' => "Aucune adresse de courriel n’a été enregistrée pour l'utilisateur « $1 ».",
'noemailcreate' => 'Vous devez fournir une adresse de courriel valide',
-'passwordsent' => 'Un nouveau mot de passe a été envoyé à l’adresse de courriel de l’utilisateur « $1 ». Veuillez vous reconnecter après l’avoir reçu.',
+'passwordsent' => "Un nouveau mot de passe a été envoyé à l'adresse de courriel de l'utilisateur « $1 ». Veuillez vous reconnecter après l'avoir reçu.",
'blocked-mailpassword' => 'Votre adresse IP est bloquée en écriture, la fonction de rappel du mot de passe est donc désactivée pour éviter les abus.',
'eauthentsent' => 'Un courriel de confirmation a été envoyé à l’adresse indiquée.
Avant qu’un autre courriel ne soit envoyé à ce compte, vous devrez suivre les instructions du courriel et confirmer que le compte est bien le vôtre.',
Si vous cliquez de nouveau sur « {{int:Savearticle}} », votre modification sera enregistrée sans titre.",
'summary-preview' => 'Aperçu du résumé :',
'subject-preview' => 'Prévisualisation du sujet/titre :',
-'blockedtitle' => 'L’utilisateur est bloqué.',
+'blockedtitle' => "L'utilisateur est bloqué.",
'blockedtext' => "'''Votre compte utilisateur ou votre adresse IP a été bloqué.'''
Le blocage a été effectué par $1.
'page_first' => 'première',
'page_last' => 'dernière',
'histlegend' => 'Légende : ({{int:cur}}) = différence avec la version actuelle, ({{int:last}}) = différence avec la version précédente, <b>{{int:minoreditletter}}</b> = modification mineure',
-'history-fieldset-title' => 'Naviguer dans l’historique',
+'history-fieldset-title' => "Naviguer dans l'historique",
'history-show-deleted' => 'Masqués seulement',
'histfirst' => 'première page',
'histlast' => 'dernière page',
'userrights-user-editname' => 'Entrez un nom d’utilisateur :',
'editusergroup' => 'Modification des groupes d’utilisateurs',
'editinguser' => "Modification des droits de l’{{GENDER:$1|utilisateur|utilisatrice}} '''[[User:$1|$1]]''' $2",
-'userrights-editusergroup' => 'Modifier les groupes de l’utilisateur',
+'userrights-editusergroup' => "Modifier les groupes de l'utilisateur",
'saveusergroups' => 'Enregistrer les groupes de l’utilisateur',
'userrights-groupsmember' => 'Membre de :',
'userrights-groupsmember-auto' => 'Membre implicite de :',
# User rights log
'rightslog' => 'Journal des modifications de droits d’utilisateurs',
'rightslogtext' => 'Voici l’historique des modifications des droits des utilisateurs.',
-'rightslogentry' => 'a modifié les droits de l’utilisateur « $1 » de $2 à $3',
+'rightslogentry' => "a modifié les droits de l'utilisateur « $1 » de $2 à $3",
'rightslogentry-autopromote' => 'a été automatiquement promu de $2 à $3',
'rightsnone' => '(aucun)',
'shared-repo' => 'un dépôt partagé',
'shared-repo-name-wikimediacommons' => 'Wikimédia Commons',
'filepage.css' => '/* Les styles CSS placés ici sont inclus dans la page de description du fichier, également incluse sur les clients wikis étrangers */',
-'upload-disallowed-here' => 'Malheureusement, vous ne peut pas remplacer cette image.',
+'upload-disallowed-here' => 'Vous ne pouvez pas remplacer ce fichier.',
# File reversion
'filerevert' => 'Rétablir $1',
'mailnologintext' => 'Vous devez être [[Special:UserLogin|identifié]] et avoir indiqué une adresse électronique valide dans vos [[Special:Preferences|préférences]] pour pouvoir envoyer des courriels à d’autres utilisateurs.',
'emailuser' => 'Lui envoyer un courriel',
'emailuser-title-target' => 'Envoyer un courriel à {{GENDER:$1|cet utilisateur|cette utilisatrice}}',
-'emailuser-title-notarget' => 'Envoyer un courriel à l’utilisateur',
-'emailpage' => 'Envoyer un courriel à l’utilisateur',
+'emailuser-title-notarget' => "Envoyer un courriel à l'utilisateur",
+'emailpage' => "Envoyer un courriel à l'utilisateur",
'emailpagetext' => 'Vous pouvez utiliser le formulaire ci-dessous pour envoyer un courriel à cet utilisateur.
L’adresse électronique que vous avez indiquée dans [[Special:Preferences|vos préférences]] apparaîtra dans le champ « Expéditeur » de votre message ; ainsi, le destinataire pourra vous répondre directement.',
'usermailererror' => 'Erreur dans l’objet du courriel :',
-'defemailsubject' => '{{SITENAME}} Courriel de l’utilisateur « $1 »',
+'defemailsubject' => "{{SITENAME}} Courriel de l'utilisateur « $1 »",
'usermaildisabled' => 'L’envoi de courriels entre utilisateurs est désactivé',
'usermaildisabledtext' => 'Vous ne pouvez pas envoyer de courriels à d’autres utilisateurs sur ce wiki',
'noemailtitle' => 'Aucune adresse de courriel',
'nowikiemailtext' => 'Cet utilisateur a choisi de ne pas recevoir de courriel de la part d’autres utilisateurs.',
'emailnotarget' => "Nom d'utilisateur du destinataire inexistant ou invalide.",
'emailtarget' => "Entrez le nom d'utilisateur du destinataire",
-'emailusername' => "Nom de l'utilisateur :",
+'emailusername' => 'Nom d’utilisateur :',
'emailusernamesubmit' => 'Soumettre',
'email-legend' => 'Envoyer un courriel à un autre utilisateur de {{SITENAME}}',
'emailfrom' => 'De :',
'emailccsubject' => 'Copie de votre message à $1 : $2',
'emailsent' => 'Courriel envoyé',
'emailsenttext' => 'Votre message a été envoyé par courriel.',
-'emailuserfooter' => 'Ce courriel a été envoyé par « $1 » à « $2 » par la fonction « Envoyer un courriel à l’utilisateur » de {{SITENAME}}.',
+'emailuserfooter' => "Ce courriel a été envoyé par « $1 » à « $2 » par la fonction « Envoyer un courriel à l'utilisateur » de {{SITENAME}}.",
# User Messenger
'usermessage-summary' => 'A laissé un message système.',
'blanknamespace' => '(Principal)',
# Contributions
-'contributions' => 'Contributions de l’utilisateur',
+'contributions' => "Contributions de l'utilisateur",
'contributions-title' => 'Liste des contributions de l’utilisateur $1',
'mycontris' => 'Contributions',
'contribsub2' => 'Pour $1 ($2)',
'nocontribs' => 'Aucune modification correspondant à ces critères n’a été trouvée.',
'uctop' => '(dernière)',
'month' => 'À partir du mois (et précédents) :',
-'year' => 'À partir de l’année (et précédentes) :',
+'year' => "À partir de l'année (et précédentes) :",
'sp-contributions-newbies' => 'Ne montrer que les contributions des nouveaux utilisateurs',
'sp-contributions-newbies-sub' => 'Parmi les nouveaux comptes',
La dernière entrée du journal des blocages est indiquée ci-dessous à titre d’information :',
'sp-contributions-search' => 'Rechercher les contributions',
'sp-contributions-username' => 'Adresse IP ou nom d’utilisateur :',
-'sp-contributions-toponly' => 'Ne montrer que les articles dont je suis le dernier contributeur',
+'sp-contributions-toponly' => 'Ne montrer que les contributions qui sont les dernières des articles',
'sp-contributions-submit' => 'Rechercher',
# What links here
# Block/unblock
'autoblockid' => 'Blocage automatique #$1',
-'block' => 'Bloquer l’utilisateur',
-'unblock' => 'Débloquer l’utilisateur',
-'blockip' => 'Bloquer l’utilisateur',
-'blockip-title' => 'Bloquer l’utilisateur',
-'blockip-legend' => 'Bloquer l’utilisateur',
+'block' => "Bloquer l'utilisateur",
+'unblock' => "Débloquer l'utilisateur",
+'blockip' => "Bloquer l'utilisateur",
+'blockip-title' => "Bloquer l'utilisateur",
+'blockip-legend' => "Bloquer l'utilisateur",
'blockiptext' => 'Utilisez le formulaire ci-dessous pour bloquer l’accès aux modifications faites à partir d’une adresse IP spécifique ou d’un nom d’utilisateur.
Une telle mesure ne devrait être prise que pour prévenir le vandalisme et en accord avec les [[{{MediaWiki:Policy-url}}|règles internes]].
Donnez ci-dessous un motif précis (par exemple en citant les pages qui ont été vandalisées).',
-'ipadressorusername' => 'Adresse IP ou nom d’utilisateur :',
+'ipadressorusername' => "Adresse IP ou nom d'utilisateur :",
'ipbexpiry' => 'Durée avant expiration :',
'ipbreason' => 'Motif :',
'ipbreasonotherlist' => 'Autre motif',
'emailblock' => 'courriel bloqué',
'blocklist-nousertalk' => 'ne peut modifier sa propre page de discussion',
'ipblocklist-empty' => 'La liste des adresses IP bloquées est actuellement vide.',
-'ipblocklist-no-results' => 'L’adresse IP ou l’utilisateur demandé n’est pas bloqué.',
+'ipblocklist-no-results' => "L'adresse IP ou l'utilisateur demandé n'est pas bloqué.",
'blocklink' => 'bloquer',
'unblocklink' => 'débloquer',
'change-blocklink' => 'modifier le blocage',
# Attribution
'anonymous' => '{{PLURAL:$1|Utilisateur non enregistré|Utilisateurs non enregistrés}} sur {{SITENAME}}',
-'siteuser' => '{{GENDER:$2|l’utilisateur|l’utilisatrice|l’utilisateur}} $1 de {{SITENAME}}',
-'anonuser' => 'l’utilisateur anonyme $1 de {{SITENAME}}',
+'siteuser' => "{{GENDER:$2|l'utilisateur|l'utilisatrice|l'utilisateur}} $1 de {{SITENAME}}",
+'anonuser' => "l'utilisateur anonyme $1 de {{SITENAME}}",
'lastmodifiedatby' => 'Cette page a été modifiée pour la dernière fois le $1 à $2 par $3.',
'othercontribs' => 'Basé sur le travail de $1.',
'others' => 'autres',
# Info page
'pageinfo-title' => 'Informations pour « $1 »',
+'pageinfo-not-current' => 'Les informations peuvent uniquement être affichées pour la révision en cours.',
'pageinfo-header-basic' => 'Informations de base',
'pageinfo-header-edits' => 'Historique des modifications',
'pageinfo-header-restrictions' => 'Protection de la page',
* <span class="mw-specialpagecached">Pages spéciales seulement en cache (pourraient être désuètes).</span>',
'specialpages-group-maintenance' => 'Rapports de maintenance',
'specialpages-group-other' => 'Autres pages spéciales',
-'specialpages-group-login' => 'S’identifier / s’inscrire',
+'specialpages-group-login' => "S'identifier / s'inscrire",
'specialpages-group-changes' => 'Modifications récentes et journaux',
'specialpages-group-media' => 'Rapports et import de fichiers médias',
'specialpages-group-users' => 'Utilisateurs et droits rattachés',
'qbbrowse' => 'Fâre dèfelar',
'qbedit' => 'Changiér',
'qbpageoptions' => 'Ceta pâge',
-'qbpageinfo' => 'Contèxto',
'qbmyoptions' => 'Mes pâges',
'qbspecialpages' => 'Pâges spèciâles',
'faq' => 'Quèstions sovent posâyes',
'qbbrowse' => 'Bleese',
'qbedit' => 'Änre',
'qbpageoptions' => 'Jüdeer sid',
-'qbpageinfo' => 'Sidedoote',
'qbmyoptions' => 'Min side',
'qbspecialpages' => 'Spetsjåålside',
'faq' => 'FAQ',
'qbbrowse' => '查看',
'qbedit' => '编写',
'qbpageoptions' => '个页',
-'qbpageinfo' => '个页信息',
'qbmyoptions' => '偶𠮶选项',
'qbspecialpages' => '特殊页',
'faq' => 'FAQ',
'qbbrowse' => '查看',
'qbedit' => '編寫',
'qbpageoptions' => '箇頁',
-'qbpageinfo' => '箇頁信息',
'qbmyoptions' => '我嗰頁面',
'qbspecialpages' => '特殊頁',
'faq' => 'FAQ',
* @author Lameiro
* @author Prevert
* @author Toliño
+ * @author Vivaelcelta
* @author Xosé
* @author לערי ריינהארט
*/
'qbbrowse' => 'Navegar',
'qbedit' => 'Editar',
'qbpageoptions' => 'Esta páxina',
-'qbpageinfo' => 'Contexto',
'qbmyoptions' => 'As miñas páxinas',
'qbspecialpages' => 'Páxinas especiais',
'faq' => 'Preguntas máis frecuentes',
'faqpage' => 'Project:FAQ',
# Vector skin
-'vector-action-addsection' => 'Engadir un comentario',
+'vector-action-addsection' => 'Nova sección',
'vector-action-delete' => 'Borrar',
'vector-action-move' => 'Mover',
'vector-action-protect' => 'Protexer',
Pode contactar con $1 ou con calquera outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir este bloqueo.
-Teña en conta que non pode empregar "enviarlle un correo electrónico a este usuario" a non ser que dispoña dun enderezo electrónico válido rexistrado nas súas [[Special:Preferences|preferencias de usuario]] e e que o seu uso non fose bloqueado.
+Teña en conta que non pode empregar a característica "Enviar un correo electrónico a este usuario" a non ser que dispoña dun enderezo electrónico válido rexistrado nas súas [[Special:Preferences|preferencias de usuario]] e e que o seu uso non fose bloqueado.
O seu enderezo IP actual é $3 e o ID do bloqueo é #$5.
Por favor, inclúa eses datos nas consultas que faga.',
'shared-repo-from' => 'de $1',
'shared-repo' => 'repositorio compartido',
'filepage.css' => '/** O CSS que se coloque aquí será incluído na páxina de descrición do ficheiro, así como nos wikis de clientes estranxeiros */',
-'upload-disallowed-here' => 'Por desgraza, non pode sobrescribir esta imaxe.',
+'upload-disallowed-here' => 'Non pode sobrescribir este ficheiro.',
# File reversion
'filerevert' => 'Reverter $1',
'blocklogpage' => 'Rexistro de bloqueos',
'blocklog-showlog' => 'Este usuario xa foi bloqueado con anterioridade. Velaquí está o rexistro de bloqueos por se quere consultalo:',
'blocklog-showsuppresslog' => 'Este usuario xa foi bloqueado e agochado con anterioridade. Velaquí está o rexistro de supresións por se quere consultalo:',
-'blocklogentry' => 'bloqueou a [[$1]] $3 cun tempo de duración de $2',
+'blocklogentry' => 'bloqueou a [[$1]] cun tempo de duración de $2 $3',
'reblock-logentry' => 'cambiou as configuracións do bloqueo de "[[$1]]" cunha caducidade de $2 $3',
'blocklogtext' => 'Este é o rexistro das accións de bloqueo e desbloqueo de usuarios.
Non se listan os enderezos IP bloqueados automaticamente.
# Info page
'pageinfo-title' => 'Información sobre "$1"',
+'pageinfo-not-current' => 'Unicamente se pode mostrar a información sobre a revisión actual.',
'pageinfo-header-basic' => 'Información básica',
'pageinfo-header-edits' => 'Historial de edicións',
'pageinfo-header-restrictions' => 'Protección da páxina',
'qbbrowse' => 'Ἀλάου',
'qbedit' => 'Μεταγράφειν',
'qbpageoptions' => 'Ἥδε ἡ δέλτος',
-'qbpageinfo' => 'Συγκείμενον',
'qbmyoptions' => 'Οἱ δέλτοι μου',
'qbspecialpages' => 'Εἰδικαὶ δέλτοι',
'faq' => 'Τὰ πολλάκις αἰτηθέντα',
'qbbrowse' => 'Blättre',
'qbedit' => 'Ändere',
'qbpageoptions' => 'Sytenoptione',
-'qbpageinfo' => 'Sytedate',
'qbmyoptions' => 'Ystellige',
'qbspecialpages' => 'Spezialsytene',
'faq' => 'Froge, wo vilmol gstellt wäre',
'edit-no-change' => 'Dyyni Bearbeitig isch ignoriert wore, wel kei Änderig am Täxt gmacht woren isch.',
'edit-already-exists' => 'Di nej Syte het nid chenne aaglait wäre, wel s si scho git.',
'defaultmessagetext' => 'Standardtext',
+'content-failed-to-parse' => 'Parse vum Inhalt $2 fir Modell $1 fählgschlaa: $3',
+'invalid-content-data' => 'Uugiltigi Inhaltsdate',
+'content-not-allowed-here' => 'Dr Inhalt „$1“ isch uf dr Syte [[$2]] nit erlaubt',
+
+# Content models
+'content-model-wikitext' => 'Wikitext',
+'content-model-text' => 'Klartext',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Achtig: In däre Syte het s z vyyl Ufruef vu ufwändige Parserfunktione.
'undeletedrevisions' => '{{PLURAL:$1|ei Revision|$1 Revisione}} wider zruckgholt.',
'undeletedrevisions-files' => '{{PLURAL:$1|1 Version|$1 Versione}} un {{PLURAL:$2|1 Datei|$2 Dateie}} sin widerhärgstellt wore',
'undeletedfiles' => '{{PLURAL:$1|1 Datei isch|$1 Dateie sin}} widerhärgstellt wore',
-'cannotundelete' => 'Widerhärstellig isch nit gange; eber ander het villicht d Syte scho widerhärgstellt.',
+'cannotundelete' => 'D Widerhärstellig isch nit gange:
+
+$1',
'undeletedpage' => "'''„$1“''' isch widerhärgstellt wore.
Im [[Special:Log/delete|Lesch-Logbuech]] findsch e Ibersicht vu dr gleschte un widerhärgstellte Syte.",
'immobile-target-namespace-iw' => 'E Interwiki-Link isch kei gültigs Ziil für e Syteverschiebig.',
'immobile-source-page' => 'Die Syte cha nüt verschobe werde.',
'immobile-target-page' => 'Uf die Ziilsyte cha nüt verschobe werde.',
+'bad-target-model' => 'Di gwinsche Ziilsyte brucht e ander Inhaltsmodell. S Inhaltsmodell $1 cha nit in s Inhaltsmodell $2 umgwandlet wäre.',
'imagenocrossnamespace' => 'Dateie chönne nüt ussem {{ns:file}}-Namensruum use verschobe werde',
'nonfile-cannot-move-to-file' => 'Nit-Dateie chenne nit in dr Datei-Namensruum verschobe wäre',
'imagetypemismatch' => 'D nöii Dateierwiiterig passt nüt zu sym Typ',
'qbbrowse' => 'બ્રાઉઝ',
'qbedit' => 'ફેરફાર કરો',
'qbpageoptions' => 'આ પાનું',
-'qbpageinfo' => 'સંદર્ભ',
'qbmyoptions' => 'મારાં પાનાં',
'qbspecialpages' => 'ખાસ પાનાં',
'faq' => 'FAQ
તમે [[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}}}} સંલગ્ન માહિતિ પત્રકોમાં શોધી શકો છો],
-અથવા [{{fullurl:{{FULLPAGENAME}}|action=edit}} આ પાનામાં ફેરફાર કરી] માહિતિ ઉમેરવાનું શરૂ કરી શકો છો</span>.',
+તમે [[Special:Search/{{PAGENAME}}|આ શબ્દ]] ધરાવતાં અન્ય લેખો શોધી શકો છો, અથવા <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} સંલગ્ન માહિતિ પત્રકોમાં શોધી શકો છો], પરંતુ તમને આ પાનું બનાવવાની મંજૂરી નથી.',
'userpage-userdoesnotexist' => 'સભ્ય ખાતું "<nowiki>$1</nowiki>"ની નોંધણીનથી થઈ.
શું તમે ખરેખર આ પાનાની રચના કે ફેરફાર કરવા માંગો છો',
'userpage-userdoesnotexist-view' => 'સભ્યના ખાતા $1 ની નોંધણી નથી થઈ',
'sp-deletedcontributions-contribs' => 'યોગદાન',
# Special:LinkSearch
-'linksearch' => 'બાહ્ય કડીઓ શોધ',
-'linksearch-pat' => 'શોધા આલેખ',
+'linksearch' => 'બાહ્ય કડીઓ શોધો',
+'linksearch-pat' => 'શોધ આલેખ',
'linksearch-ns' => 'નામાવકાશ:',
'linksearch-ok' => 'શોધ',
'linksearch-text' => '"*.wikipedia.org" જેવા વાઈલ્ડાકાર્ડ અહીં વાપર્યા હોઈ શકે છે.
'qbbrowse' => 'Chhà-khon',
'qbedit' => 'Phiên-siá',
'qbpageoptions' => 'Vùn-chông sién-hong',
-'qbpageinfo' => 'Vùn-chông chṳ̂-liau',
'qbmyoptions' => 'Ngô-ke sién-hong',
'qbspecialpages' => 'Thi̍t-sû hong-mien',
'faq' => 'Sòng-kien mun-thì kié-tap',
'qbbrowse' => 'דפדוף',
'qbedit' => 'עריכה',
'qbpageoptions' => 'אפשרויות דף',
-'qbpageinfo' => 'מידע על הדף',
'qbmyoptions' => 'האפשרויות שלי',
'qbspecialpages' => 'דפים מיוחדים',
'faq' => 'שאלות ותשובות',
'shared-repo' => 'מקום איחסון משותף',
'shared-repo-name-wikimediacommons' => 'ויקישיתוף',
'filepage.css' => '/* הסגנונות הנכתבים כאן יוכללו בדף תיאור הקובץ, כולל באתרי ויקי זרים */',
-'upload-disallowed-here' => '×\9c×\9eר×\91×\94 ×\94צער, ×\90×\99×\9f ×\9c×\9a ×\94רש×\90×\94 ×\9c×\94×¢×\9c×\95ת ×\92רס×\94 ×\90×\97רת ש×\9c ×\94ת×\9e×\95× ×\94 ×\94×\96×\90ת.',
+'upload-disallowed-here' => '×\90×\99×\9f ×\91×\90פשר×\95ת×\9b×\9d ×\9c×\93ר×\95ס ×\90ת ×\94ק×\95×\91×¥ ×\94×\96×\94.',
# File reversion
'filerevert' => 'שחזור $1',
# Info page
'pageinfo-title' => 'מידע על "$1"',
+'pageinfo-not-current' => 'המידע יכול להיות מוצג רק עבור הגרסה הנוכחית.',
'pageinfo-header-basic' => 'מידע בסיסי',
'pageinfo-header-edits' => 'היסטוריית עריכות',
'pageinfo-header-restrictions' => 'הגנה על הדף',
'qbbrowse' => 'ब्राउज़',
'qbedit' => 'बदलें',
'qbpageoptions' => 'यह पृष्ठ',
-'qbpageinfo' => 'पृष्ठ जानकारी',
'qbmyoptions' => 'मेरे पृष्ठ',
'qbspecialpages' => 'विशेष पृष्ठ',
'faq' => 'बहुधा पूछित प्रश्न',
'qbbrowse' => 'Browse karo',
'qbedit' => 'Badlo',
'qbpageoptions' => 'Ii panna',
-'qbpageinfo' => 'Vishay',
'qbmyoptions' => 'Hamar panna',
'qbspecialpages' => 'Khaas panna',
'faq' => 'Sab time puchhe waala sawal',
'vector-action-protect' => 'Bachao',
'vector-action-undelete' => 'Pahile jaise karo',
'vector-action-unprotect' => 'Surakchha ke badlo',
-'vector-simplesearch-preference' => 'Aur achchhaa se khoje salah do (Khaali vector skin)',
+'vector-simplesearch-preference' => 'Aur achchhaa se khoje ke salah do (Khaali vector skin)',
'vector-view-create' => 'Banao',
'vector-view-edit' => 'Badlo',
'vector-view-history' => 'Itihaas dekho',
'youhavenewmessages' => 'Aapke pass hai $1 ($2).',
'newmessageslink' => 'nawaa khabar',
'newmessagesdifflink' => 'pahile waala badlao',
+'youhavenewmessagesfromusers' => 'Aap ke lage {{PLURAL:$3|duusra sadasya|$3 sadasya}} ke lage se $1 hae ($2).',
+'youhavenewmessagesmanyusers' => 'Aap ke lage dher sadasya se $1 hae ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|ek nawaa sandes|nawaa sandes}}',
+'newmessagesdifflinkplural' => 'pichhla {{PLURAL:$1|badlao}}',
'youhavenewmessagesmulti' => 'Aap ke khatir $1 pe sandes hai',
'editsection' => 'badlo',
'editold' => 'badlao',
'error' => 'Galti',
'databaseerror' => 'Database me galti hai',
'dberrortext' => 'Database ke khoj me syntax error hoe gais hae.
-Saait software me bug hoi.
+Iske matlab ii hoe sake hae ki saait software me bug hoi.
Pahile waala database ke khoj ke kosis rahaa:
-<blockquote><tt>$1</tt></blockquote>
-"<tt>$2</tt>" function ke bhitar se.
-Database ke galti sandes rahaa "<tt>$3: $4</tt>".',
+<blockquote><code>$1</code></blockquote>
+"<code>$2</code>" function ke bhitar se.
+Database ke galti sandes rahaa "<samp>$3: $4</samp>".',
'dberrortextcl' => 'Database ke khoj me syntax error hoe gais hae.
Pahile waala database ke khoj ke kosis rahaa:
"$1"
'protectedpagetext' => 'Ii panna ke badlao ke roke ke khatir band kar dewa gais hai.',
'viewsourcetext' => 'Aap ii panna ke source ke dekhe aur nakal utare kare sakta hai:',
'viewyourtext' => "Aap '''aapan badlao''' ke source ke dekhe aur copy kare saktaa hae",
-'protectedinterface' => 'Ii panna software ke interface text dewe hai, aur iske barbaadi se roke ke khatir band kar dewa gais hai.',
+'protectedinterface' => 'Ii panna, ii wiki ke khatir, software ke interface text dewe hai, aur iske barbaadi se roke ke khatir band kar dewa gais hai.
+Sab wiki me anuwaad ke jorre nai to badle ke khatir, meharbaani kar ke [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project ke kaam me laao.',
'editinginterface' => "'''Chetawani:''' Aap ek panna ke badaltaa hai jon ki software ke interface text dewe hae.
-Ii panna me badlao ke asar duusra sadasya ke interface ke bhi hoi.
-Translation khatir [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net], the MediaWiki localisation project, ke kaam me lao.",
+Ii panna me badlao ke asar duusra sadasya ke interface pe bhi hoi.
+Translation khatir [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project, ke kaam me lao.",
'sqlhidden' => '(SQL query lukawal hai)',
'cascadeprotected' => 'Ii panna ke badlao se bachawa gais hai, kahe ki iske {{PLURAL:$1|panna, jon ki|panna, jon ki}} surakchhit hae "cascading" option turned on ke saathe me rakkhaa gais hai:
$2',
'remembermypassword' => 'Ii computer pe hamaar login yaad rakho (jaada se jaada $1 {{PLURAL:$1|din|din}} talak)',
'securelogin-stick-https' => 'Login kare ke baad HTTPS se connected raho',
'yourdomainname' => 'Aap ke domain:',
+'password-change-forbidden' => 'Aap ii wiki me password nai badle saktaa hae.',
'externaldberror' => 'Koi bahaari database authentication error hai, nai to aap ke bahaari account badle ke adhikar nai hai.',
'login' => 'Log in karo',
'nav-login-createaccount' => 'Log in karo/ nawaa account banao',
Aap saktaa hai [[Special:Search/{{PAGENAME}}|ii panna ke title khoje]] duusra panna me,
<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],
nai to [{{fullurl:{{FULLPAGENAME}}|action=edit}} ii panna ke badlo]</span>.',
-'noarticletext-nopermission' => 'Abhi ii panna pe koi chij likha nai hae.
+'noarticletext-nopermission' => 'Abhi ii panna me koi chij likha nai hae.
Aap sakta hae [[Special:Search/{{PAGENAME}}|ii panna ke title ke khoje]] duusra panna me,
-nai to <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>.',
+nai to <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>, lekin aap ke ii panna ke banae ke ijaaja tnai hae.',
+'missing-revision' => 'Panna "{{PAGENAME}}" me #$1 badlao nai hae.
+Iske kaaran ii hoe sake hae ki ek mitawa gais panna se link karaa jaawe hae.
+Iske baare me aur jaankari [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log] me paawa jaae sake hae.',
'userpage-userdoesnotexist' => 'User account "<nowiki>$1</nowiki>" abi registered nai hai.
Check karo ki Ii panna ke aap banae/badle mangta hai.',
'userpage-userdoesnotexist-view' => 'User account "$1" abhi register nai karaa gais hae',
'blocked-notice-logextract' => 'Ii sadasya ke abhi rok dewa gais hae.
Sab se nawaa block log entry, aap ke reference ke khatir, niche dewa gais hae:',
'clearyourcache' => "'''Note:''' - Save kare ke baad, aap ke sait browser ke cache ke bypass kare ke parri badlao ke dekhe khatir.
-* '''Mozilla / Firefox / Safari:''' ''Shift'' ke dabae ke ''Reload,'' pe click karo, nai to chaahe ''Ctrl-F5'' nai to ''Ctrl-R'' (''Command-R'' Mac pe)
-* '''Google Chrome:''' ''Ctrl-Shift-R'' dabao (''Command-Shift-R'' Mac pe)
-* '''Internet Explorer:''' ''Ctrl'' dabae ke ''Refresh'' pe click karo, nai to ''Ctrl-F5'' dabao
-* '''Konqueror: ''' ''Reload'' click karo nai to ''F5 dabao;''
-* '''Opera:''' ''Tools → Preferences'' me se cache ke safaa karo",
+* '''Firefox / Safari:''' me ''Shift'' ke dabae ke ''Reload,'' pe click karo, nai to chaahe ''Ctrl-F5'' nai to ''Ctrl-R'' (''⌘-R'' Mac pe)
+* '''Google Chrome:''' me ''Ctrl-Shift-R'' dabao (''⌘-Shift-R'' Mac pe)
+* '''Internet Explorer:''' me ''Ctrl'' dabae ke ''Refresh'' pe click karo, nai to ''Ctrl-F5'' dabao",
'usercssyoucanpreview' => "'''Salah:''' Bachae se pahile \"{{int:showpreview}}\" button ke kaam me laae ke aapan nawaa CSS ke test karo.",
'userjsyoucanpreview' => "'''Salah:''' Bachae se pahile \"{{int:showpreview}}\" button ke kaam me laae ke aapan nawaa JavaScript ke test karo.",
'usercsspreview' => "'''Yaad rakhna ki aap khali aapan CSS ke jhalak dekhta hai.
'edit-already-exists' => 'Nawaa panna nai banae sakaa hai.
Ii naam ke panna abhi hai.',
'defaultmessagetext' => 'Default message text',
+'content-failed-to-parse' => '$1 model ke khatir $2 ke parse nai kare sakaa hae: $3',
+'invalid-content-data' => 'Panna me likha gais chij right nai hae',
+'content-not-allowed-here' => 'Panna [[$2]] me "$1" likhe ke ijaajat nai hae',
# Parser/template warnings
'expensive-parserfunction-warning' => "'''Chetauni''': Ii panna me bahut jaada expensive parser function calls hai.
'expansion-depth-exceeded-warning' => 'Panna expansion depth ke exceed karis hae',
'parser-unstrip-loop-warning' => 'Unstrip loop ke pawa gai shae',
'parser-unstrip-recursion-limit' => 'Unstrip recursion limit ke exceed karaa gais hae ($1)',
+'converter-manual-rule-error' => 'Bhasa ke anuwaad kare waala niyam me galti hae',
# "Undo" feature
'undo-success' => 'Ii badlao ke pahile jaise karaa jaae sake hai.
Meharbani ka ke logs ke check karo.',
'revdelete-only-restricted' => 'Jon chij aap $2, $1 ke lukae mangta rahaa me galti hoe gais hae: aap administrator log se koi chij lukae nai saktaa hae bina duursa dekhe waala option ke chune.',
'revdelete-reason-dropdown' => '*Mitae ke jaada kar ke kaaran
-** Bina chhape ke adikar se
+** Bina chhape ke adikar nai
** Aapan baare me fajuul jankari
+** Kharaab sadasya ke naam
** Ninda kare waala jankari',
'revdelete-otherreason' => 'Duusra/aur kaaran:',
'revdelete-reasonotherlist' => 'Duusra kaaran',
'timezoneregion-indian' => 'Indian Ocean',
'timezoneregion-pacific' => 'Pacific Ocean',
'allowemail' => 'Aur sadasya se e-mail enable karo',
-'prefs-searchoptions' => 'Khoje ke option',
+'prefs-searchoptions' => 'Khojo',
'prefs-namespaces' => 'Naam:',
'defaultns' => 'Default se ii namespaces me khojo:',
'default' => 'baaki',
'right-writeapi' => 'Likhe waala API ke kaam me lawa jaawe hae',
'right-delete' => 'Panna ke mitao',
'right-bigdelete' => 'Barraa itihaas waala panna ke mitao',
+'right-deletelogentry' => 'Mitawa aur khola gais panna ke baare me log entires',
'right-deleterevision' => 'Panna ke khaas badlao ke mitao nai to bachao',
'right-deletedhistory' => 'Mitawa gais itihass ke entry ke binaa saathe waala text ke dekho',
'right-deletedtext' => 'Mitawa gais text aur mitawa gais badlao ke biich waala badlao ke dekho',
'backend-fail-internal' => 'Storage backend "$1" me ek unknown error hoe gais hae.',
'backend-fail-contenttype' => 'Ii nai pataa lagae sakaa hae ki "$1" me bachae ke khaatir file kon rakam ke hae.',
'backend-fail-batchsize' => 'Storage backend ke $1 file {{PLURAL:$1|operation|operations}} ke ek batch ke dewa gais hae ; limit $2 {{PLURAL:$2|operation|operation}} hae.',
-'backend-fail-usable' => 'File $1 ke nai likhe sakaa hae kaahe ki iske khatir jaruri ijajat nai hae, nai to directories/containers nai hae.',
+'backend-fail-usable' => 'File $1 me nai likhe, nai to nai parrhe, sakaa hae kaahe ki iske khatir jaruri ijajat nai hae, nai to directories/containers nai hae.',
# File journal errors
'filejournal-fail-dbconnect' => 'Storage backend "$1" ke khatir journal database se nai jorre sakaa hae.',
'disambiguations' => 'Garrbarri ke sudhare waala panna',
'disambiguationspage' => 'Template:disambig',
'disambiguations-text' => "Niche ke panna '''disambiguation panna''' se link hoe hai.
-They should link to the appropriate topic instead.<br />
-A page is treated as disambiguation page if it uses a template which is linked from [[MediaWiki:Disambiguationspage]]",
+Saait isse aur achchha panna se link hoi. <br />
+Ek panna ke disambiguation panna maana jaae hae jab ki ii ek template ke kaam me laae hae jon ki [[MediaWiki:Disambiguationspage]] se link hoe hae.",
'doubleredirects' => 'Dugna redirects',
'doubleredirectstext' => 'Ii panna uu panna ke suchi de hai jon ki duusra redirect panna pe redirect kare hai.
'qbbrowse' => 'Pregledaj',
'qbedit' => 'Uredi',
'qbpageoptions' => 'Postavke stranice',
-'qbpageinfo' => 'O stranici',
'qbmyoptions' => 'Moje stranice',
'qbspecialpages' => 'Posebne stranice',
'faq' => 'Najčešća pitanja',
'qbbrowse' => 'Přepytować',
'qbedit' => 'Wobdźěłać',
'qbpageoptions' => 'Tuta strona',
-'qbpageinfo' => 'Kontekst',
'qbmyoptions' => 'Moje strony',
'qbspecialpages' => 'Specialne strony',
'faq' => 'Husto stajene prašenja (FAQ)',
'qbbrowse' => 'Böngészés',
'qbedit' => 'Szerkesztés',
'qbpageoptions' => 'Lapbeállítások',
-'qbpageinfo' => 'Lapinformáció',
'qbmyoptions' => 'Lapjaim',
'qbspecialpages' => 'Speciális lapok',
'faq' => 'GyIK',
'vector-action-protect' => 'Lapvédelem',
'vector-action-undelete' => 'Visszaállítás',
'vector-action-unprotect' => 'Védelem módosítása',
-'vector-simplesearch-preference' => 'Továbbfejlesztett keresési javaslatok engedélyezése (csak Vector felületen)',
+'vector-simplesearch-preference' => 'Egyszerűsített keresési sáv engedélyezése (csak Vector felületen)',
'vector-view-create' => 'Létrehozás',
'vector-view-edit' => 'Szerkesztés',
'vector-view-history' => 'Laptörténet',
'youhavenewmessages' => '$1 a vitalapodon! ($2 külön is megtekintheted.)',
'newmessageslink' => 'új üzenet vár',
'newmessagesdifflink' => 'az utolsó üzenetet',
+'youhavenewmessagesfromusers' => '$1 a vitalapodon {{PLURAL:$3|egy|$3}} szerkesztőtől! ($2 külön is megtekintheted.)',
'youhavenewmessagesmanyusers' => '$1ed van több szerkesztőtől ($2).',
'newmessageslinkplural' => '{{PLURAL:$1|Új üzenet vár|Új üzenetek várnak}}',
'newmessagesdifflinkplural' => 'Az utolsó {{PLURAL:$1|változtatást|változtatásokat}}',
'cannotdelete' => 'A(z) $1 lapot vagy fájlt nem lehet törölni.
Talán már valaki más törölte.',
'cannotdelete-title' => 'Nem lehet törölni a(z) „$1” lapot',
+'delete-hook-aborted' => 'A törlés meg lett szakítva egy hook által.
+Nem lett magyarázat csatolva.',
'badtitle' => 'Hibás cím',
'badtitletext' => 'A kért oldal címe érvénytelen, üres, vagy rosszul hivatkozott nyelvközi vagy wikiközi cím volt. Olyan karaktereket is tartalmazhatott, melyek a címekben nem használhatóak.',
'perfcached' => "Az alábbi adatok gyorsítótárból (''cache''-ből) származnak, és ezért lehetséges, hogy nem a legfrissebb változatot mutatják. Legfeljebb {{PLURAL:$1|egy|$1 }} eredmény áll rendelkezésre a gyorsítótárban.",
'timezoneregion-indian' => 'Indiai-óceán',
'timezoneregion-pacific' => 'Csendes-óceán',
'allowemail' => 'E-mail engedélyezése más szerkesztőktől',
-'prefs-searchoptions' => 'A keresés beállításai',
+'prefs-searchoptions' => 'Keresés',
'prefs-namespaces' => 'Névterek',
'defaultns' => 'Egyébként a következő névterekben keressen:',
'default' => 'alapértelmezett',
'right-writeapi' => 'a szerkesztő-API használata',
'right-delete' => 'lapok törlése',
'right-bigdelete' => 'nagy történettel rendelkező fájlok törlése',
+'right-deletelogentry' => 'bizonyos napló bejegyzések törlése és visszaállítása',
'right-deleterevision' => 'lapok adott változatainak törlése és helyreállítása',
'right-deletedhistory' => 'törölt lapváltozatok megtekintése, a szövegük nélkül',
'right-deletedtext' => 'törölt változatok szövegének és a változatok közötti eltérés megtekintése',
# Recent changes
'nchanges' => '{{PLURAL:$1|egy|$1}} változtatás',
'recentchanges' => 'Friss változtatások',
-'recentchanges-legend' => 'A friss változások beállításai',
+'recentchanges-legend' => 'A friss változtatások beállításai',
'recentchanges-summary' => 'Ezen a lapon a wikiben történt legutóbbi fejleményeket lehet nyomon követni.',
'recentchanges-feed-description' => 'Kövesd a wiki friss változtatásait ezzel a hírcsatornával.',
'recentchanges-label-newpage' => 'Ezzel a szerkesztéssel egy új lap jött létre',
'recentchanges-label-bot' => 'Ezt a szerkesztést egy bot hajtotta végre',
'recentchanges-label-unpatrolled' => 'Ezt a szerkesztést még nem ellenőrizték',
'rcnote' => "Alább az utolsó '''{{PLURAL:$2|egy|$2}}''' nap utolsó '''{{PLURAL:$1|egy|$1}}''' változtatása látható. A lap generálásának időpontja $4, $5.",
-'rcnotefrom' => 'Alább a <b>$2</b> óta történt változások láthatóak (<b>$1</b> db).',
-'rclistfrom' => '$1 után történt változások megtekintése',
+'rcnotefrom' => 'Alább a <b>$2</b> óta történt változtatások láthatóak (<b>$1</b> db).',
+'rclistfrom' => '$1 után történt változtatások megtekintése',
'rcshowhideminor' => 'apró szerkesztések $1',
'rcshowhidebots' => 'botok szerkesztéseinek $1',
'rcshowhideliu' => 'bejelentkezett felhasználók szerkesztéseinek $1',
'recentchangeslinked-feed' => 'Kapcsolódó változtatások',
'recentchangeslinked-toolbox' => 'Kapcsolódó változtatások',
'recentchangeslinked-title' => 'A(z) $1 laphoz kapcsolódó változtatások',
-'recentchangeslinked-noresult' => 'A megadott időtartam alatt nem történt változás a kapcsolódó lapokon.',
+'recentchangeslinked-noresult' => 'A megadott időtartam alatt nem történt változtatás a kapcsolódó lapokon.',
'recentchangeslinked-summary' => "Alább azon lapoknak a legutóbbi változtatásai láthatóak, amelyekre hivatkozik egy megadott lap (vagy tagjai a megadott kategóriának).
A [[Special:Watchlist|figyelőlistádon]] szereplő lapok '''félkövérrel''' vannak jelölve.",
'recentchangeslinked-page' => 'Lap neve:',
# Miscellaneous special pages
'nbytes' => '{{PLURAL:$1|egy|$1}} bájt',
'ncategories' => '{{PLURAL:$1|egy|$1}} kategória',
+'ninterwikis' => '{{PLURAL:$1|egy|$1}} interwiki',
'nlinks' => '{{PLURAL:$1|egy|$1}} hivatkozás',
'nmembers' => '{{PLURAL:$1|egy|$1}} elem',
'nrevisions' => '{{PLURAL:$1|egy|$1}} változat',
'mostlinkedtemplates' => 'Legtöbbet hivatkozott sablonok',
'mostcategories' => 'Legtöbb kategóriába tartozó lapok',
'mostimages' => 'Legtöbbet hivatkozott fájlok',
+'mostinterwikis' => 'Legtöbb interwikit tartalmazó lapok',
'mostrevisions' => 'Legtöbbet szerkesztett lapok',
'prefixindex' => 'Keresés előtag szerint',
'prefixindex-namespace' => 'Összes lap adott előtaggal ($1 névtér)',
'undeletedrevisions' => '{{PLURAL:$1|egy|$1}} változat helyreállítva',
'undeletedrevisions-files' => '{{PLURAL:$1|egy|$1}} változat és {{PLURAL:$2|egy|$2}} fájl visszaállítva',
'undeletedfiles' => '{{PLURAL:$1|egy|$1}} fájl visszaállítva',
-'cannotundelete' => 'Nem lehet a lapot visszaállítani; lehet, hogy azt már valaki visszaállította.',
+'cannotundelete' => 'Lap visszaállítása sikertelen: $1',
'undeletedpage' => "'''$1 helyreállítva'''
Lásd a [[Special:Log/delete|törlési naplót]] a legutóbbi törlések és helyreállítások listájához.",
'import-interwiki-templates' => 'Az összes sablon hozzáadása',
'import-interwiki-submit' => 'Importálás',
'import-interwiki-namespace' => 'Célnévtér:',
+'import-interwiki-rootpage' => 'Cél gyökér lap (opcionális):',
'import-upload-filename' => 'Fájlnév:',
'import-comment' => 'Megjegyzés:',
'importtext' => 'Exportáld a fájlt a forráswikiből az [[Special:Export|exportáló eszköz]] segítségével.
'import-error-interwiki' => '„$1” lap nem került importálásra, mert a név külső hivatkozásokra van fenntartva (interwiki).',
'import-error-special' => '„$1” lap nem került importálásra, mert olyan speciális névtérbe tartozik, amelyen nem engedélyezettek a lapok.',
'import-error-invalid' => '„$1” lap nem került importálásra, mert a neve nem érvényes.',
+'import-options-wrong' => 'Rossz {{PLURAL:$2|opció|opciók}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'A megadott gyökér oldal címe érvénytelen.',
# Import log
'importlogpage' => 'Importnapló',
# Info page
'pageinfo-title' => 'Információk a(z) „$1” lapról',
+'pageinfo-header-basic' => 'Alapinformációk',
'pageinfo-header-edits' => 'Szerkesztések története',
+'pageinfo-header-restrictions' => 'Lapvédelem',
+'pageinfo-header-properties' => 'Lap tulajdonságok',
+'pageinfo-display-title' => 'Megjelenített cím',
+'pageinfo-default-sort' => 'Alapértelmezett rendezési kulcs',
+'pageinfo-length' => 'Lap hossza (bájtokban)',
+'pageinfo-article-id' => 'Lapazonosító',
+'pageinfo-robot-policy' => 'Kereső motor státusz',
+'pageinfo-robot-index' => 'Indexelhető',
+'pageinfo-robot-noindex' => 'Nem indexelhető',
'pageinfo-views' => 'Megtekintések száma',
'pageinfo-watchers' => 'Figyelők száma',
+'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-firstuser' => 'Lap létrehozója',
+'pageinfo-firsttime' => 'A lap létrehozás ideje',
+'pageinfo-lastuser' => 'Utolsó szerkesztő',
+'pageinfo-lasttime' => 'Az utolsó szerkesztés ideje',
'pageinfo-edits' => 'Szerkesztések teljes száma',
'pageinfo-authors' => 'Egyedi szerkesztők teljes száma',
+'pageinfo-recent-edits' => 'Friss változtatások száma (elmúlt $1 alatt)',
+'pageinfo-recent-authors' => 'Friss változtatások szerkesztőinek száma',
+'pageinfo-magic-words' => 'Varázs{{PLURAL:$1|szó|szavak}} ($1)',
+'pageinfo-hidden-categories' => 'Rejtett {{PLURAL:$1|kategória|kategóriák}} ($1)',
+'pageinfo-templates' => 'Felhasznált {{PLURAL:$1|sablon|sablonok}} ($1)',
# Skin names
'skinname-standard' => 'Klasszikus',
'file-info-size-pages' => '$1 × $2 képpont, fájlméret: $3, MIME típus: $4, $5 oldal',
'file-nohires' => 'Nem érhető el nagyobb felbontású változat.',
'svg-long-desc' => 'SVG fájl, névlegesen $1 × $2 képpont, fájlméret: $3',
+'svg-long-desc-animated' => 'Animált SVG fájl, névlegesen $1 × $2 képpont, fájlméret: $3',
'show-big-image' => 'A kép nagyfelbontású változata',
'show-big-image-preview' => 'Az előnézet mérete: $1',
'show-big-image-other' => 'További {{PLURAL:$2|felbontás|felbontások}}: $1.',
'file-info-png-looped' => 'ismétlődik',
'file-info-png-repeat' => 'lejátszva {{PLURAL:$1|egy|$1}} alkalommal',
'file-info-png-frames' => '{{PLURAL:$1|egy|$1}} képkocka',
+'file-no-thumb-animation' => "'''Megjegyzés: technikai korlátok miatt a fájl bélyegképe nem lesz animált.'''",
+'file-no-thumb-animation-gif' => "'''Megjegyzés: technikai korlátok miatt a nagy felbontású GIF képekből készített bélyegkép nem lesz animált.'''",
# Special:NewFiles
'newimages' => 'Új fájlok galériája',
'qbbrowse' => 'Թերթել',
'qbedit' => 'Խմբագրել',
'qbpageoptions' => 'Այս էջը',
-'qbpageinfo' => 'Հոդվածի մասին',
'qbmyoptions' => 'Իմ էջերը',
'qbspecialpages' => 'Սպասարկող էջեր',
'faq' => 'ՀՏՀ',
'qbbrowse' => 'Foliar',
'qbedit' => 'Modificar',
'qbpageoptions' => 'Iste pagina',
-'qbpageinfo' => 'Contexto',
'qbmyoptions' => 'Mi paginas',
'qbspecialpages' => 'Paginas special',
'faq' => 'FAQ',
'vector-action-protect' => 'Proteger',
'vector-action-undelete' => 'Restaurar',
'vector-action-unprotect' => 'Cambiar protection',
-'vector-simplesearch-preference' => 'Activar le suggestiones de recerca meliorate (solmente in apparentia Vector)',
+'vector-simplesearch-preference' => 'Activar le barra de recerca simplificate (solmente in apparentia Vector)',
'vector-view-create' => 'Crear',
'vector-view-edit' => 'Modificar',
'vector-view-history' => 'Vider historia',
'edit-already-exists' => 'Non poteva crear un nove pagina.
Illo existe ja.',
'defaultmessagetext' => 'Texto predefinite del message',
+'content-failed-to-parse' => 'Impossibile processar le contento $2 pro le modello $1: $3',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Attention: Iste pagina contine troppo de appellos costose al functiones del analysator syntactic.
'qbbrowse' => 'Navigasi',
'qbedit' => 'Sunting',
'qbpageoptions' => 'Halaman ini',
-'qbpageinfo' => 'Konteks halaman',
'qbmyoptions' => 'Halaman saya',
'qbspecialpages' => 'Halaman istimewa',
'faq' => 'FAQ',
'qbbrowse' => 'Agbasabasa',
'qbedit' => 'Urnosen',
'qbpageoptions' => 'Daytoy a panid',
-'qbpageinfo' => 'Linaon',
'qbmyoptions' => 'Pampanidko',
'qbspecialpages' => 'Espesial a pampanid',
'faq' => 'FAQ',
'qbbrowse' => 'Flakka',
'qbedit' => 'Breyta',
'qbpageoptions' => 'Þessi síða',
-'qbpageinfo' => 'Samhengi',
'qbmyoptions' => 'Mínar síður',
'qbspecialpages' => 'Kerfissíður',
'faq' => 'Algengar spurningar',
'qbbrowse' => 'Sfoglia',
'qbedit' => 'Modifica',
'qbpageoptions' => 'Opzioni pagina',
-'qbpageinfo' => 'Informazioni sulla pagina',
'qbmyoptions' => 'Le mie pagine',
'qbspecialpages' => 'Pagine speciali',
'faq' => 'Domande frequenti',
'shared-repo-from' => 'da $1',
'shared-repo' => 'un archivio condiviso',
'filepage.css' => '/* Il CSS messo qui viene incluso nella pagina di descrizione del file, inclusa anche su wiki client esterni */',
-'upload-disallowed-here' => 'Impossibile sovrascrivere questa immagine.',
+'upload-disallowed-here' => 'Impossibile sovrascrivere questo file.',
# File reversion
'filerevert' => 'Ripristina $1',
# Info page
'pageinfo-title' => 'Informazioni per "$1"',
+'pageinfo-not-current' => 'Le informazioni possono essere visualizzate solo per la versione corrente.',
'pageinfo-header-basic' => 'Informazioni di base',
'pageinfo-header-edits' => 'Cronologia delle modifiche',
'pageinfo-header-restrictions' => 'Protezione della pagina',
'qbbrowse' => '閲覧',
'qbedit' => '編集',
'qbpageoptions' => 'このページについて',
-'qbpageinfo' => '関連情報',
'qbmyoptions' => '自分のページ',
'qbspecialpages' => '特別ページ',
'faq' => 'よくある質問と回答',
'viewyourtext' => "このページへの'''あなたの編集'''のソースの閲覧やコピーができます:",
'protectedinterface' => 'このページにはこのウィキのソフトウェアのインターフェイスに使用されるテキストが保存されており、いたずらなどの防止のために保護されています。
すべてのウィキに対して翻訳を追加/変更する場合は、MediaWiki の地域化プロジェクト [//translatewiki.net/ translatewiki.net] を使用してください。',
-'editinginterface' => "'''è¦å\91\8a:''' ã\82½ã\83\95ã\83\88ã\82¦ã\82§ã\82¢ã\81®ã\82¤ã\83³ã\82¿ã\83¼ã\83\95ã\82§ã\82¤ã\82¹ã\81«ä½¿ç\94¨ã\81\95ã\82\8cã\82\8bã\81®ã\83\86ã\82ã\82¹ã\83\88ã\81®ã\83\9aã\83¼ã\82¸ã\82\92ç·¨é\9b\86ã\81\97ã\81¦ã\81\84ã\81¾ã\81\99ã\80\82
+'editinginterface' => "'''警告:''' ソフトウェアのインターフェイスに使用されるテキストのページを編集しています。
このページを変更すると、このウィキの他の利用者のユーザーインターフェイスの外観に影響します。
すべてのウィキに対して翻訳を追加/変更する場合は、MediaWiki の地域化プロジェクト [//translatewiki.net/wiki/Main_Page?setlang=ja translatewiki.net] を使用してください。",
'sqlhidden' => '(SQL クエリ非表示)',
'loginreqtitle' => 'ログインが必要',
'loginreqlink' => 'ログイン',
'loginreqpagetext' => '他のページを閲覧するには$1する必要があります。',
-'accmailtitle' => 'パスワードを送信しました。',
+'accmailtitle' => 'パスワードをお送りしました。',
'accmailtext' => "[[User talk:$1|$1]]のために無作為に生成したパスワードを、$2に送信しました。
この新アカウントのパスワードは、ログインした際に''[[Special:ChangePassword|パスワード変更]]''ページで変更できます。",
'edit-already-exists' => '新しいページを作成できませんでした。
そのページは既に存在しています。',
'defaultmessagetext' => '既定のメッセージ文',
-'content-failed-to-parse' => '$2 の本文を$1モデルとして構文解析できませんでした。',
+'content-failed-to-parse' => '$2 の本文を$1モデルとして構文解析できませんでした: $3',
'invalid-content-data' => '本文データが無効です',
'content-not-allowed-here' => 'ページ [[$2]] では、「$1」コンテンツは許可されていません',
'revdelete-hide-comment' => '編集の要約を隠す',
'revdelete-hide-user' => '投稿者の利用者名またはIPを隠す',
'revdelete-hide-restricted' => '他の利用者と同様に管理者からもデータを隠す',
-'revdelete-radio-same' => '(変更しない)',
+'revdelete-radio-same' => '(変更しない)',
'revdelete-radio-set' => 'はい',
'revdelete-radio-unset' => 'いいえ',
'revdelete-suppress' => '他の利用者と同様に管理者からもデータを隠す',
'search-suggest' => 'もしかして:$1',
'search-interwiki-caption' => '姉妹プロジェクト',
'search-interwiki-default' => '$1の結果:',
-'search-interwiki-more' => '(続き)',
+'search-interwiki-more' => '(続き)',
'search-relatedarticle' => '関連',
'mwsuggest-disable' => 'Ajaxによる検索候補の提示を無効にする',
'searcheverything-enable' => 'すべての名前空間を検索',
'prefs-watchlist-edits-max' => '最大数:1000',
'prefs-watchlist-token' => 'ウォッチリストのトークン:',
'prefs-misc' => 'その他',
-'prefs-resetpass' => 'ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\81®変更',
+'prefs-resetpass' => 'ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\82\92変更',
'prefs-changeemail' => 'メールアドレスを変更',
'prefs-setemail' => 'メールアドレスを設定',
'prefs-email' => 'メールの設定',
'right-suppressredirect' => '転送ページを作成せずにページを移動',
'right-upload' => 'ファイルをアップロード',
'right-reupload' => '既存のファイルに上書き',
-'right-reupload-own' => '自分自身がアップロードした既存のファイルに上書き',
+'right-reupload-own' => '自身がアップロードした既存のファイルに上書き',
'right-reupload-shared' => '共有メディアリポジトリ上のファイルにローカルで上書き',
'right-upload_by_url' => 'URL からファイルをアップロード',
'right-purge' => '確認なしでサイトのキャッシュを破棄',
'right-hideuser' => '利用者名をブロックして公開記録から隠す',
'right-ipblock-exempt' => 'IPブロック、自動ブロック、広域ブロックを回避',
'right-proxyunbannable' => 'プロキシの自動ブロックを回避',
-'right-unblockself' => '自分自身に対するブロックを解除',
+'right-unblockself' => '自身に対するブロックを解除',
'right-protect' => '保護レベルを変更し、保護されたページを編集',
'right-editprotected' => '保護ページ(カスケード保護を除く)を編集',
'right-editinterface' => 'ユーザーインターフェイスを編集',
'right-import' => '他のウィキからページを取り込み',
'right-importupload' => 'ファイルアップロードでページを取り込み',
'right-patrol' => '他人の編集を巡回済みにする',
-'right-autopatrol' => '自分の編集を自動的に巡回済みにする',
+'right-autopatrol' => '自身の編集を自動で巡回済みにする',
'right-patrolmarks' => '最近の更新で巡回済み印を閲覧',
'right-unwatchedpages' => 'ウォッチされていないページ一覧を閲覧',
'right-mergehistory' => 'ページの履歴を統合',
'shared-repo' => '共有リポジトリ',
'shared-repo-name-wikimediacommons' => 'ウィキメディア・コモンズ',
'filepage.css' => '/* ここに記述したCSSはファイル解説ページにて読み込まれます。また外部のクライアントウィキにも影響します */',
-'upload-disallowed-here' => '残念ながらこの画像には上書きできません。',
+'upload-disallowed-here' => 'このファイルには上書きできません。',
# File reversion
'filerevert' => '$1を差し戻す',
'booksources-isbn' => 'ISBN:',
'booksources-go' => '検索',
'booksources-text' => 'お探しの書籍の新品/中古品を販売している外部サイトへのリンクを以下に列挙します。この書籍についてさらに詳しい情報があるかもしれません:',
-'booksources-invalid-isbn' => '指定したISBN番号は有効ではないようです。情報源から写し間違えていないか確認してください。',
+'booksources-invalid-isbn' => '指定した ISBN は有効ではないようです。情報源から写し間違えていないか確認してください。',
# Special:Log
'specialloguserlabel' => '実行者:',
# Namespace form on various pages
'namespace' => '名前空間:',
-'invert' => '名前空間の選択を反転',
+'invert' => '選択したものを除く',
'tooltip-invert' => '選択した名前空間 (チェックを入れている場合は、関連付けられた名前空間も含む) のページの変更を非表示にするには、このボックスにチェックを入れる',
'namespace_association' => '関連付けられた名前空間も含める',
'tooltip-namespace_association' => '選択した名前空間に関連付けられたトークページ (逆にトークページの名前空間を選択した場合も同様) の名前空間も含めるには、このボックスにチェックを入れる',
'ipb-blocklist' => '現在有効なブロックを表示',
'ipb-blocklist-contribs' => '$1の投稿の一覧',
'unblockip' => 'ブロックを解除',
-'unblockiptext' => '以ä¸\8bã\81®ã\83\95ã\82©ã\83¼ã\83 ã\82\92使ç\94¨ã\81\97ã\81¦ã\80\81以å\89\8dã\83\96ã\83ã\83\83ã\82¯ã\81\97ã\81\9fIPã\82¢ã\83\89ã\83¬ã\82¹ã\81¾ã\81\9fã\81¯å\88©ç\94¨è\80\85ã\81\8bã\82\89ã\81®æ\9b¸ã\81\8dè¾¼ã\81¿ã\82¢ã\82¯ã\82»ã\82¹ã\82\92ã\83\96ã\83ã\83\83ã\82¯解除できます。',
+'unblockiptext' => '以ä¸\8bã\81®ã\83\95ã\82©ã\83¼ã\83 ã\81§å\88©ç\94¨è\80\85ã\81¾ã\81\9fã\81¯IPã\82¢ã\83\89ã\83¬ã\82¹ã\81®ã\83\96ã\83ã\83\83ã\82¯ã\82\92解除できます。',
'ipusubmit' => 'このブロックを解除',
'unblocked' => '[[User:$1|$1]]のブロックを解除しました',
'unblocked-range' => '$1のブロックは解除されています',
# Info page
'pageinfo-title' => '「$1」の情報',
+'pageinfo-not-current' => '現在のバージョンの情報のみが表示される可能性があります。',
'pageinfo-header-basic' => '基本情報',
'pageinfo-header-edits' => '編集履歴',
'pageinfo-header-restrictions' => 'ページの保護',
'exif-flash-mode-1' => '強制発光モード',
'exif-flash-mode-2' => '強制非発光モード',
'exif-flash-mode-3' => '自動発光モード',
-'exif-flash-function-1' => 'ストロボ機能無し',
+'exif-flash-function-1' => 'ストロボ機能なし',
'exif-flash-redeye-1' => '赤目軽減有り',
'exif-focalplaneresolutionunit-2' => 'インチ',
'qbbrowse' => 'Navigasi',
'qbedit' => 'Sunting',
'qbpageoptions' => 'Kaca iki',
-'qbpageinfo' => 'Kontèks kaca',
'qbmyoptions' => 'Opsiku',
'qbspecialpages' => 'Kaca-kaca astaméwa',
'faq' => 'FAQ (Pitakonan sing kerep diajokaké)',
'qbbrowse' => 'გადახედე',
'qbedit' => 'რედაქტირება',
'qbpageoptions' => 'ეს გვერდი',
-'qbpageinfo' => 'კონტექსტი',
'qbmyoptions' => 'ჩემი გვერდები',
'qbspecialpages' => 'სპეციალური გვერდები',
'faq' => 'ხშირი შეკითხვები',
'vector-action-protect' => 'დაცვა',
'vector-action-undelete' => 'აღდგენა',
'vector-action-unprotect' => 'დაცვის დონის შეცვლა',
-'vector-simplesearch-preference' => 'á\83«á\83\94á\83\91á\83\9cá\83\98á\83¡ á\83\92á\83\90á\83¤á\83\90á\83 á\83\97á\83\9dá\83\94á\83\91á\83£á\83\9aá\83\98 á\83\9bá\83\98á\83\9cá\83\98á\83¨á\83\9cá\83\94á\83\91á\83\94á\83\91ის ჩართვა (მხოლოდ ვექტორული იერსახისთვის)',
+'vector-simplesearch-preference' => 'á\83«á\83\94á\83\91á\83\9cá\83\98á\83¡ á\83\92á\83\90á\83¤á\83\90á\83 á\83\97á\83\9dá\83\94á\83\91á\83£á\83\9aá\83\98 á\83\95á\83\94á\83\9aის ჩართვა (მხოლოდ ვექტორული იერსახისთვის)',
'vector-view-create' => 'შექმნა',
'vector-view-edit' => 'რედაქტირება',
'vector-view-history' => 'ისტორია',
'edit-already-exists' => 'ახალი გვერდის შექმნა არ მოხერხდა.
ის უკვე არსებობს.',
'defaultmessagetext' => 'შეტყობინების სტანდარტული ტექსტი',
+'content-failed-to-parse' => '$2-ის შინაარსი არ შეესაბამება $1-ის ტიპს: $3.',
+'invalid-content-data' => 'დაუშვებელი მონაცემები',
+'content-not-allowed-here' => '„$1“-ის შინაარსი დაუშვებელია [[$2]] გვერდზე',
+
+# Content models
+'content-model-wikitext' => 'ვიკიტექსტი',
+'content-model-text' => 'უბრალო ტექსტი',
+'content-model-javascript' => 'ჯავასკრიპტი',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'ყურადღება. მოცემული გვერდი შეიცავს ძალიან ბევრ მძიმე ფუნქციას.
'shared-repo-from' => ' $1-დან',
'shared-repo' => 'საერთო საცავიდან',
'shared-repo-name-wikimediacommons' => 'ვიკისაწყობი',
-'upload-disallowed-here' => 'á\83¡á\83\90á\83\9bá\83¬á\83£á\83®á\83\90á\83 á\83\9dá\83\93, á\83\97á\83¥á\83\95á\83\94á\83\9c á\83\90á\83 á\83¨á\83\94á\83\92á\83\98á\83«á\83\9aá\83\98á\83\90á\83\97 á\83\90á\83\9b á\83¡á\83£á\83 á\83\90á\83\97ზე გადაწერა.',
+'upload-disallowed-here' => 'á\83\97á\83¥á\83\95á\83\94á\83\9c á\83\90á\83 á\83¨á\83\94á\83\92á\83\98á\83«á\83\9aá\83\98á\83\90á\83\97 á\83\90á\83\9b á\83¤á\83\90á\83\98á\83\9aზე გადაწერა.',
# File reversion
'filerevert' => 'დააბრუნე $1',
'undeletedrevisions' => '$1 ვერსია აღდგენილია',
'undeletedrevisions-files' => '$1 ვერსია და $2 ფაილი აღდგენილია',
'undeletedfiles' => '$1 ფაილი აღდგენილია',
-'cannotundelete' => 'წაშლის გაუქმება ვერ განხორციელდა; შესაძლოა თქვენამდე სხვამ უკვე გააუქმა წაშლა.',
+'cannotundelete' => 'წაშლის გაუქმება ვერ განხორციელდა:
+$1',
'undeletedpage' => "'''$1 აღდგენილია'''
უკანასკნელი წაშლილთა და აღდგენის სია შეგიძლიათ ნახოთ [[Special:Log/delete|წაშლილთა სიაში]].",
'immobile-target-namespace-iw' => 'ინტერვიკის ბმული შეუძლებელია გამოყენებული იქნას გადარქმევისთვის.',
'immobile-source-page' => 'ამ გვეერდის გადატანა შეუძლებელია.',
'immobile-target-page' => 'შეუძლებელია მოცემულ სახელზე გადატანა.',
+'bad-target-model' => 'შეუძლებელია $1-ის გარდაქმნა $2-ზე: მონაცემების შეუსაბამო მოდელი.',
'imagenocrossnamespace' => 'შეუძლებელია ფაილს მიეცეს სახელი სახელთა სხვა სივრციდან',
'nonfile-cannot-move-to-file' => 'შეუძლებელია არაფაილების გადატანა ფაილის სახელთა სივრცეში',
'imagetypemismatch' => 'ფაილს ახალი გაფართოება არ შეესაბამება მის ტიპს',
# Info page
'pageinfo-title' => 'ინფორმაცია „$1“-თვის',
+'pageinfo-not-current' => 'მონაცემები წარმოდგენილია მხოლოდ მიმდინარე რედაქტირებისათვის.',
'pageinfo-header-basic' => 'საბაზისო ინფორმაცია',
'pageinfo-header-edits' => 'რედაქტირების ისტორია',
'pageinfo-header-restrictions' => 'გვერდის დაცვა',
'pageinfo-magic-words' => 'ჯადოსნური {{PLURAL:$1|სიტყვა|სიტყვა}} ($1)',
'pageinfo-hidden-categories' => 'დამალული {{PLURAL:$1|კატეგორია|კატეგორია}} ($1)',
'pageinfo-templates' => 'ინტეგრირებულია {{PLURAL:$1|თარგი|თარგი}} ($1)',
+'pageinfo-toolboxlink' => 'გვერდის ინფორმაცია',
# Skin names
'skinname-standard' => 'კლასიკური',
# Scary transclusion
'scarytranscludedisabled' => '[«Interwiki transcluding» გათიშულია]',
'scarytranscludefailed' => '[$1-თან დაკავშირების შეცდომა]',
+'scarytranscludefailed-httpstatus' => '[ვერ მოხერხდა თარგის ჩატვირთვა $1-თვის: HTTP $2]',
'scarytranscludetoolong' => '[URL ძალიან გრძელია]',
# Delete conflict
* @author Azwaw
* @author Mmistmurt
* @author MoubarikBelkasim
+ * @author Salem333
* @author Teak
* @author Urhixidur
*/
'qbbrowse' => 'Ẓer isebtar',
'qbedit' => 'Beddel',
'qbpageoptions' => 'Asebter-agi',
-'qbpageinfo' => 'Asatal',
'qbmyoptions' => 'isebtar inu',
'qbspecialpages' => 'isebtar usligen',
'faq' => 'Isteqsiyen',
'yourrealname' => 'Isem n ṣṣeḥ *:',
'yourlanguage' => 'Tutlayt:',
'yourvariant' => 'Lqem nniḍen n tutlayt n ugbur :',
+'prefs-help-variant' => 'Lqem naɣ inun inek/inem iwakken an beqqeḍ agbur n wiki agi.',
'yournick' => 'Azmul amaynut :',
'prefs-help-signature' => 'Iwenniten ɣef isebtar n umeslay ilaq ad illin zmelen s « <nowiki>~~~~</nowiki> », sakin ad i sɛu aselkat ɣer azmul inek/inem dɣa azmez d usrag.',
'badsig' => 'Azmul mačči d ṣaḥiḥ; Ssenqed tags n HTML.',
'saveusergroups' => 'Smekti iderman n yimseqdacen',
'userrights-groupsmember' => 'Amaslad deg:',
'userrights-groupsmember-auto' => 'Aεeggal udrig n :',
+'userrights-groups-help' => 'Tzemreḍ ad beddeleḍ igrawen anda yella aseqdac agi :
+* Taxxamt i tekkin : aseqdac yella deg ugraw agi.
+* Taxxamt ur tekkin ara : aseqdac ur yella ara deg ugraw agi
+* Titrit (*) : ur tzemreḍ ara ad ekkeseḍ agraw agi sakin i tid ernuḍ, naɣ bis-bersa.',
'userrights-reason' => 'Ayɣer',
+'userrights-no-interwiki' => 'Ur tesɛiḍ ara turagt iwakken ad beddeleḍ izerfan n iseqdacen ɣef wiki nniḍen.',
'userrights-nodatabase' => 'Taffa n isefka « $1 » ulac itt naɣ mačči d tadigant.',
'userrights-nologin' => 'Ilaq ad [[Special:UserLogin|qqeneḍ]] s yiwen umiḍan anedbal iwakken ad beddeleḍ izerfan n useqdac.',
'userrights-notallowed' => 'Amiḍan inek/inem ur yesɛa ara turagt iwakken ad beddeleḍ izerfan n useqdac.',
'right-upload' => 'Azen ifuyla',
'right-reupload' => 'Sefxes afaylu yellan',
'right-reupload-own' => 'Sefxes afaylu id n-azen.',
+'right-reupload-shared' => 'Ɛefes deg udigan afaylu yellan ɣef azadur azduklan',
'right-upload_by_url' => 'Kter afaylu seg tansa URL',
'right-purge' => 'Senger tazarkatut n isebtar war asuter n uragag',
'right-autoconfirmed' => 'Beddel isebtar azinsegdelen',
+'right-bot' => 'Ad yilli yesniret am ukala yeswurmen',
+'right-nominornewtalk' => 'Ur ndeḥ ara tazmilt n inzan imaynuten ma neseqdac abeddel amectuḥ ɣef usebtar n umeslay n yiwen useqdac',
'right-apihighlimits' => 'Seqdec tilisa tid ɛlayen deg tuttriwin API',
'right-writeapi' => 'Seqdec API n ubeddel',
'right-delete' => 'Mḥu isebtar',
'right-bigdelete' => 'Mḥu isebtar yesɛan amezruy affuyan',
+'right-deletelogentry' => 'Ekkes ḍɣa erred yiwen asekcem n uɣmis',
+'right-deleterevision' => 'Ekkes dɣa erred yiwen lqem n usebter',
+'right-deletedhistory' => 'Ẓeṛ isekcam n imezruyen yekksen, maca war aḍris nsen',
'right-deletedtext' => 'Ẓeṛ aḍris yemḥan d timeẓliwin gar ileqman yemḥan',
'right-browsearchive' => 'Nadi ɣef isebtar yettumḥan',
'right-undelete' => 'Erred asebter yemḥan',
+'right-suppressrevision' => 'Ssekyed dɣa erred ileqman yefren i inedbalen',
'right-suppressionlog' => 'Ẓeṛ iɣmisen usligen',
'right-block' => 'Kyef deg tira iseqdacen nniḍen',
'right-blockemail' => 'Sḍiqqef aceggaɛ n tira (e-mail) i yiwen useqdac',
'right-hideuser' => 'Kyef aseqdac s tuffra n isem-is ar udem n uzayez',
+'right-ipblock-exempt' => 'Zizdew tansiwin IP yekyefen, ikyafen iwurmanen d ikyafen n tagrummiwin IP',
+'right-proxyunbannable' => 'Zizdew ikyafen iwurmanen n iqeddacen proxy',
+'right-unblockself' => 'Ad ekkesen akyaf imanen nsen',
'right-protect' => 'Beddel aswir n umesten n isebtar dɣa beddel isebtar i gdelen',
'right-editprotected' => 'Beddel isebtar i gdelen (war asegdel s uceṛcuṛ)',
'right-editinterface' => 'Beddel agrudem n useqdac',
'right-editusercssjs' => 'Beddel ifuyla CSS d JavaScript n iseqdacen nniḍen',
'right-editusercss' => 'Beddel ifuyla CSS n iseqdacen nniḍen',
'right-edituserjs' => 'Beddel ifuyla JavaScript n iseqdacen nniḍen',
+'right-rollback' => 'Ekkes s urured ibeddilen n umedraw aneggaru deg yiwen asebter',
+'right-markbotedits' => 'Creḍ ibeddilen yetwekkesen am aken d aṛubut i tni beddelen.',
+'right-noratelimit' => 'Ur i tilli ara yeswaɣ sɣur tilisa n utug',
'right-import' => 'Kter ifuyla seg iWikiyen nniḍen',
'right-importupload' => 'Azen isebtar seg ufaylu',
+'right-patrol' => 'Creḍ ibeddilen n wiyaḍ nniḍen am aken selkenen',
+'right-autopatrol' => 'Ad i sɛu ibeddilen is creḍen s uwurman am aken ɛessan',
+'right-patrolmarks' => 'Ẓeṛ ticraḍ n uɛassi deg ibeddilen imaynuten',
'right-unwatchedpages' => 'Ẓeṛ umuɣ n isebtar ur sɛan ara iɛssasen',
'right-mergehistory' => 'Sdukel amezruy n isebtar',
'right-userrights' => 'Beddel akkw izerfan n yiwen aseqdac',
'right-userrights-interwiki' => 'Beddel izerfan n iseqdacen yellan deg awiki nniḍen',
'right-siteadmin' => 'Sekkweṛ naɣ kkes aseḍru i taffa n isefka',
+'right-override-export-depth' => 'Sifeḍ isebtar akkw d isebtar iqqenen alama tadrut n 5 iswiren',
'right-sendemail' => 'Ceggaɛ tirawt i iseqdacen nniḍen',
+'right-passwordreset' => 'Ẓeṛ tira n uwennez n awalen uɛaddi',
# User rights log
'rightslog' => 'Aɣmis n yizerfan n wemseqdac',
'rightslogtext' => 'Wagi d aɣmis n yibeddlen n yizerfan n wemseqdac',
'rightslogentry' => 'Yettubeddel izerfan n wemseqdac $1 seg $2 ar $3',
+'rightslogentry-autopromote' => 'yesnerna s uwurman seg $2 ar $3',
'rightsnone' => '(ulaḥedd)',
# Associated actions - in the sentence "You do not have permission to X"
'action-movefile' => 'beddel isem n ufaylu agi',
'action-upload' => 'Azen afaylu agi',
'action-reupload' => 'Sefxes afaylu yellan',
+'action-reupload-shared' => 'fel deg udigan afaylu agi yellan ɣef azadur azduklan',
'action-upload_by_url' => 'Azen afaylu agi seg tansa URL',
'action-writeapi' => 'seqdec API n tira',
'action-delete' => 'mḥu asebter-agi',
'action-deletedhistory' => 'ẓeṛ amezruy yemḥan n usebter agi',
'action-browsearchive' => 'nadi ɣef isebtar yettumḥan',
'action-undelete' => 'erred asebter agi',
+'action-suppressrevision' => 'sekyed dɣa uɣaled ar lqem agi yetwekkesen',
'action-suppressionlog' => 'ẓeṛ aɣmis agi uslig',
'action-block' => 'Kyef deg tira aseqdac agi',
'action-protect' => 'beddel iswiren n umesten i usebter agi',
+'action-rollback' => 'ekkes s urured ibeddilen n umedraw aneggaru yebeddelen yiwen usebter',
'action-import' => 'Kter asebter agi seg wiki nniḍen',
'action-importupload' => 'Kter asebter agi seg ufaylu n wezdam (upload)',
+'action-patrol' => 'Creḍ abeddel n wiyaḍ nniḍen am aken tesɛa tacaggart',
+'action-autopatrol' => 'ad sɛuḍ tacaggart i ubeddil ik',
'action-unwatchedpages' => 'Sken-d tabdart n isebtaren ur yettwalan ara.',
'action-mergehistory' => 'Sdukel amezruy n usebtar agi',
'action-userrights' => 'Ẓreg izerfan n imseqdacen yark',
'upload_directory_missing' => 'Akaram n taktert n ufaylu ($1) ulac-it dɣa ur d-yesnulfa ara sɣur aqeddac web.',
'upload_directory_read_only' => 'Weserver/serveur Web ur yezmir ara ad yaru deg ($1).',
'uploaderror' => 'Agul deg usekcam',
+'upload-recreate-warning' => "'''Ɣur-wet : Afaylu s isem agi yetwekkes naɣ yetembiwel.'''
+Aɣmis n tukksiwin d win n ittembiwilen n usebter agi beqqeḍen d-agi i tilɣa :",
'uploadtext' => "Sseqdec tiferkit agi iwakken ad ktereḍ ifuyla ɣef uqeddac.
Iwakken ad ẓṛeḍ naɣ ad nadiḍ tugniwin i ktren uqbel, ẓeṛ [[Special:FileList|umuɣ n tugniwin]]. Taktert tella daɣen deg [[Special:Log/upload|aɣmis n taktert n ifuyla]], dɣa inuzal deg [[Special:Log/delete|aɣmis n inuzal]].
'filetype-mime-mismatch' => 'Asiɣzef n ufaylu « .$1 » ur yesɛa ara tuqqna s tawsit MIME id n-ufa deg ufaylu ($2).',
'filetype-badmime' => 'Ur tettalaseḍ ara ad tazneḍ ufayluwen n anaw n MIME "$1".',
'filetype-bad-ie-mime' => 'Afaylu ur yezmer ara ad yetwekter acku yetwaf am « $1 » sɣur Internet Explorer. Tawsit agi d tazanbagt acku d tamihawt.',
+'filetype-unwanted-type' => "'''« .$1 »''' d amasal n ufaylu azanbag.
+Ilaq ad seqdeceḍ {{PLURAL:$3|amasal|imusal}} $2.",
+'filetype-banned-type' => "''' « .$1 » '''mačči d {{PLURAL:$4|amasal yesɛan turagt|imusal yesɛan turagt}}.
+{{PLURAL:$3|Amasal yesɛan turagt d-wagi :|Imusal yesɛan turagt d-wigi :}} $2.",
'filetype-missing' => 'Afaylu ur yesɛi ara taseggiwit (am ".jpg").',
'empty-file' => 'Afaylu id cegɛeḍ d-ilem.',
'file-too-large' => 'Afaylu id cegɛed d-ameqqṛan aṭas.',
'windows-nonascii-filename' => 'Wiki agi ur yebra ara isemawen n ifuyla s isekkilen usligen.',
'fileexists' => 'Afaylu s yisem-agi yewǧed yagi, ssenqed <strong>[[:$1]]</strong> ma telliḍ mačči meḍmun akken a t-tbeddleḍ.
[[$1|thumb]]',
+'filepageexists' => 'Asebter n uglam i ufaylu agi yesnulfad yakan d-agi <strong>[[:$1]]</strong>, maca ulac asebter s isem agi.
+Agzul ad efkeḍ tura ur d yettban ara ɣef asebter n uglam.
+Ma tebɣiḍ ad yeban, ilaq ad beddeleḍ s awfus asebter. [[$1|thumb]]',
'fileexists-extension' => 'Afaylu s yisem yecban wagi yella : [[$2|thumb]]
* Isem n ufaylu i tezneḍ: <strong>[[:$1]]</strong>
* Isem n ufaylu i yellan: <strong>[[:$2]]</strong>
Ma tebɣiḍ ad azeneḍ afaylu inek/inem, ilaq ad uɣaleḍ ar deffir dɣa ad as efkeḍ isem amaynut.
[[File:$1|thumb|center|$1]]',
'file-exists-duplicate' => 'Afaylu agi d-asleg n {{PLURAL:$1|ufaylu agi|ifuyla agi}} :',
+'file-deleted-duplicate' => 'Afaylu am wagi ([[:$1]]) yetwekkes yakan. Ilaq ad selkeneḍ aɣmis n tukksiwin n ufaylu agi uqbel atid ktereḍ tikkelt nniḍen.',
'uploadwarning' => 'Aɣtal deg wazan n ufayluwen',
'uploadwarning-text' => 'Beddel aglam n ufaylu dɣa ɛreḍ tikkelt nniḍen',
'savefile' => 'Smekti afaylu',
'upload-options' => 'Tixtiṛiyin n taktert ifuyla',
'watchthisupload' => 'Ɛass asebter agi',
'filewasdeleted' => 'Afaylu s yisem-agi yettwazen umbeɛd yettumḥa. Ssenqed $1 qbel ad tazniḍ tikelt nniḍen.',
+'filename-bad-prefix' => "Isem n ufaylu yezwer s '''« $1 »''', wagi d isem i sedgeren s uwurman sɣur timsakenwin tumḍinin.
+Xteṛ isem n ufaylu agelmaw.",
'upload-success-subj' => 'Azen yekfa',
'upload-success-msg' => 'Taktert inek/inem seg [$2] yesmures. Af-it d-agi : [[:{{ns:file}}:$1]]',
'upload-failure-subj' => 'Ugur n taktert',
'lockmanager-fail-svr-release' => 'Ulamek an bru izekṛunen ɣef uqeddac $1.',
# ZipDirectoryReader
+'zip-file-open-error' => 'Yella agul mi d neldi afaylu i senqeden ifuyla zip.',
'zip-wrong-format' => 'Afaylu agi mačči d afaylu n weɣbaṛ ZIP.',
+'zip-bad' => 'Afaylu agi d afaylu n weɣbaṛ ameggafsu naɣ ur nezmer ara an ɣaṛ deg-es.
+Ur nezmer ara aten selken i taɣellist.',
+'zip-unsupported' => 'Afaylu agi d afaylu n weɣbaṛ i seqdacen tiɣariwin ur yeḥemmel ara MediaWiki.
+Taɣellist ines ur tezmer ara at illi teseklen.',
# Special:UploadStash
'uploadstash' => 'Tazarkatut n taktert',
+'uploadstash-summary' => 'Asebter agi yetefk addaf i ifuyla yekteren (naɣ yesɛan taktert tanazzalt), maca mazal i beqqeḍen deg wiki. Ifuyla agi mazal id banen, ḥaca i useqdac i tni kteren.',
'uploadstash-clear' => 'Sfeḍ ifuyla deg tazarkatut',
'uploadstash-nofiles' => 'Ur tesɛiḍ ara ifuyla deg tazarkatut n taktert',
+'uploadstash-badtoken' => 'Aselkem n tigawt agi yexseṛ, ahat acku tilɣa inek/inem n usulu gweḍent ar tasewti nsent. Ɛreḍ tikkelt nniḍen.',
'uploadstash-errclear' => 'Asfeḍ n ifuyla yefkad taruẓi',
'uploadstash-refresh' => 'Mucceḍ umuɣ n ifuyla',
'invalid-chunk-offset' => 'Tiggit n iɣil ur teɣbel ara',
# img_auth script messages
'img-auth-accessdenied' => 'Addaf yugwi',
+'img-auth-nopathinfo' => 'Yexus BATH_INFU.
+Aqeddac inek/inem ur yeseɣwer ara iwakken ad i ɛeddi talɣut agi.
+Ahat i lḥu s CGI dɣa ur s-yezmer ara i img_auth.
+Ẓeṛ https://www.mediawiki.org/wiki/Manual:Image_Authorization.',
'img-auth-notindir' => 'Abrid yesuteren mačči d akaram n taktert yellan deg tawila.',
'img-auth-badtitle' => 'Ulamek an ssali azwel i ɣbelen seg « $1 ».',
'img-auth-nologinnWL' => 'Ur teqqneḍ ara dɣa « $1 » ur yella ara deg umuɣ amellal.',
'img-auth-isdir' => 'Tɛerdeḍ ad ldiḍ akaram « $1 ».
Tzemreḍ kan ad ldiḍ ifuyla.',
'img-auth-streaming' => 'Taɣuri tamaɣlalt n « $1 ».',
+'img-auth-public' => 'Tasɣent n img_auth.php tella i ubeqqeḍ n ifuyla n yiwen wiki uslig.
+Wiki agi yesɣwer am wiki azayez.
+I taɣellist tameqqṛant, img_auth.php yensa.',
'img-auth-noread' => 'Aseqdac ur yesɛa ara azref deg taɣuri ɣef « $1 ».',
'img-auth-bad-query-string' => 'URL tesɛa azrar n tuttra ur i ɣbelen ara.',
'upload_source_file' => ' (afaylu deg uselkim inek)',
# Special:ListFiles
+'listfiles-summary' => 'Asebter agi uslig i εemmed ad yefk umu n akkw ifuyla i kteren.
+Ma aseqdac as yernu tastayt, ala ifuyla s lqem taneggarut id yekter aseqdac nni ad beqqeḍen.',
'listfiles_search_for' => 'Nadi ɣef yisem n tugna:',
'imgfile' => 'afaylu',
'listfiles' => 'Umuɣ n tugniwin',
'uploadnewversion-linktext' => 'tazneḍ tasiwelt tamaynut n ufaylu-yagi',
'shared-repo-from' => 'seg : $1',
'shared-repo' => 'azadur azduklan',
-'upload-disallowed-here' => 'Ur tzemreḍ ara ad semselsiḍ tugna agi.',
+'upload-disallowed-here' => 'Ur tzemreḍ ara ad semselsiḍ afaylu agi.',
# File reversion
'filerevert' => 'Erred $1',
# Random redirect
'randomredirect' => 'Asemmimeḍ menwala',
+'randomredirect-nopages' => 'Ulac asebter n alsanamad deg tallunt n isemawen « $1 ».',
# Statistics
'statistics' => 'Tisnaddanin',
'exif-originaltransmissionref' => 'Tangalt n usideg n tuzzna tamezwarut',
'exif-identifier' => 'Asulay',
+'exif-copyrighted-true' => 'Ddaw azref n umeskar',
+'exif-copyrighted-false' => 'Taɣuly tazayezt',
+
+'exif-unknowndate' => 'Azmez warisem',
+
+'exif-orientation-1' => 'Amagnu',
+'exif-orientation-2' => 'Tetti s udem aglawan',
+'exif-orientation-3' => 'Tezzi s 180°',
+'exif-orientation-4' => 'Tetti s udem aratak',
+'exif-orientation-5' => 'Tezzi s 90° deg unamek imitti n usrag dɣa tetti s udem aratak',
+'exif-orientation-6' => 'Tezzi s 90° deg unamek imitti n usrag',
+'exif-orientation-7' => 'Tezzi s 90° deg unamek n usrag dɣa tetti s udem aratak',
+'exif-orientation-8' => 'Tezzi s 90° deg unamek n usrag',
+
+'exif-planarconfiguration-1' => 'Isefka iqriben',
+'exif-planarconfiguration-2' => 'Isefka ibrarazen',
+
+'exif-colorspace-65535' => 'Ur yezize ara',
+
+'exif-componentsconfiguration-0' => 'Ulac it',
+
+'exif-exposureprogram-0' => 'Ur yersen ara',
+'exif-exposureprogram-1' => 'Awfus',
+'exif-exposureprogram-2' => 'Ahil alugan',
+'exif-exposureprogram-3' => 'Tazwart i ulday',
+'exif-exposureprogram-4' => 'Tazwart i uqfel',
+'exif-exposureprogram-5' => 'Ahil n usnulfu (azullen i tadrut n urti)',
+'exif-exposureprogram-6' => 'Ahil n tigawt (azullen i urured n yqfel)',
+'exif-exposureprogram-7' => 'Askar tafrist (i tugniwin s tama dɣa s ugilal iluɣen)',
+'exif-exposureprogram-8' => 'Askar agama (i tugniwin n igmaten i llulcen)',
+
'exif-subjectdistance-value' => '$1 lmitra',
'exif-meteringmode-0' => 'Warisem',
'exif-gpsdestdistance-m' => 'igimen',
'exif-gpsdestdistance-n' => 'Miles iwlalen',
+'exif-gpsdop-excellent' => 'Yufrar ($1)',
'exif-gpsdop-good' => 'Tamellayt ($1)',
'exif-gpsdop-moderate' => 'Tallalt ($1)',
+'exif-gpsdop-fair' => 'Attwadag ($1)',
+'exif-gpsdop-poor' => 'Yecmet ($1)',
'exif-objectcycle-a' => 'Tanzayt kan',
'exif-objectcycle-p' => 'Tameddit kan',
'exif-iimcategory-hth' => 'Tadawsa',
'exif-iimcategory-hum' => 'Aramsu alsi',
'exif-iimcategory-lab' => 'Amahil',
+'exif-iimcategory-lif' => 'Askar n tudert dɣa n imezlan',
+'exif-iimcategory-pol' => 'Tasertit',
+'exif-iimcategory-rel' => 'Ddin d tifelsin',
+'exif-iimcategory-sci' => 'Tussna d tatiknulujit',
+'exif-iimcategory-soi' => 'Tuttriwin timettiyin',
+'exif-iimcategory-spo' => 'Addalen',
+'exif-iimcategory-war' => 'Ṭrad, taẓit d tasmessit',
+'exif-iimcategory-wea' => 'Tasnignewt',
+
+'exif-urgency-normal' => 'Alugen ($1)',
+'exif-urgency-low' => 'Anammum ($1)',
+'exif-urgency-high' => 'Afella ($1)',
# External editor support
'edit-externally' => 'Beddel afaylu-yagi s usnas aberrani.',
'watchlistall2' => 'akk',
'namespacesall' => 'akk',
'monthsall' => 'akk',
+'limitall' => 'Akkw',
# E-mail address confirmation
'confirmemail' => 'Sentem tansa n e-mail',
# Special:Tags
'tag-filter' => 'Astay n [[Special:Tags|ticraḍ]] :',
+# Feedback
+'feedback-subject' => 'Asentel :',
+'feedback-message' => 'Izen :',
+'feedback-cancel' => 'Semmewet',
+'feedback-submit' => 'Ceggaɛ iwenniten',
+'feedback-adding' => 'Rnud iwenniten inek/inem ar usebter...',
+
# Durations
'duration-seconds' => '$1 {{PLURAL:$1|tasint|tisinin}}',
'duration-minutes' => '$1 {{PLURAL:$1|tamrect|timercin}}',
'qbbrowse' => 'شولۋ',
'qbedit' => 'وڭدەۋ',
'qbpageoptions' => 'بۇل بەت',
-'qbpageinfo' => 'اينالا',
'qbmyoptions' => 'بەتتەرىم',
'qbspecialpages' => 'ارنايى بەتتەر',
'faq' => 'ٴجىيى قويىلعان ساۋالدار',
'qbbrowse' => 'Шолу',
'qbedit' => 'Өңдеу',
'qbpageoptions' => 'Бұл бет',
-'qbpageinfo' => 'Айнала',
'qbmyoptions' => 'Беттерім',
'qbspecialpages' => 'Арнайы беттер',
'faq' => 'Жиі қойылған сауалдар',
'qbbrowse' => 'Şolw',
'qbedit' => 'Öñdew',
'qbpageoptions' => 'Bul bet',
-'qbpageinfo' => 'Aýnala',
'qbmyoptions' => 'Betterim',
'qbspecialpages' => 'Arnaýı better',
'faq' => 'Jïi qoýılğan sawaldar',
'qbbrowse' => 'រាវរក',
'qbedit' => 'កែប្រែ',
'qbpageoptions' => 'ទំព័រនេះ',
-'qbpageinfo' => 'ព័ត៌មានទំព័រ',
'qbmyoptions' => 'ទំព័ររបស់ខ្ញុំ',
'qbspecialpages' => 'ទំព័រពិសេសៗ',
'faq' => 'សំណួរដែលសួរញឹកញាប់',
'qbbrowse' => '탐색',
'qbedit' => '편집',
'qbpageoptions' => '문서 기능',
-'qbpageinfo' => '문서 정보',
'qbmyoptions' => '내 사용자 문서',
'qbspecialpages' => '특수 문서',
'faq' => '자주 묻는 질문',
'searcharticle' => '가기',
'history' => '문서 역사',
'history_short' => '역사',
-'updatedmarker' => '마지막으로 읽은 뒤 바뀌었음',
+'updatedmarker' => '마지막으로 방문한 뒤 바뀜',
'printableversion' => '인쇄용 문서',
'permalink' => '고유링크',
'print' => '인쇄',
'shared-repo' => '공용 저장소',
'shared-repo-name-wikimediacommons' => '위키미디어 공용',
'filepage.css' => '/* 이 CSS 설정은 파일 설명 문서에 포함되며, 또한 해외 클라이언트 위키에 포함됩니다 */',
-'upload-disallowed-here' => 'ì£\84ì\86¡í\95\98ì§\80ë§\8c ì\9d´ 그림ì\9d\84 ë\8d®ì\96´ 쓸 수 없습니다.',
+'upload-disallowed-here' => 'ì\9d´ í\8c\8cì\9d¼ì\9d\84 ë\8d®ì\96´쓸 수 없습니다.',
# File reversion
'filerevert' => '$1 되돌리기',
# Info page
'pageinfo-title' => '"$1" 문서에 대한 정보',
+'pageinfo-not-current' => '정보는 현재 판만을 보여줄 수 있습니다.',
'pageinfo-header-basic' => '기본 정보',
'pageinfo-header-edits' => '편집 역사',
'pageinfo-header-restrictions' => '문서 보호',
'qbbrowse' => 'Къарау',
'qbedit' => 'Тюрлендир',
'qbpageoptions' => 'Бу бет',
-'qbpageinfo' => 'Бетни юсюнден',
'qbmyoptions' => 'Бетлерим',
'qbspecialpages' => 'Къуллукъчу бетле',
'faq' => 'FAQ',
'qbbrowse' => 'Aanluure',
'qbedit' => 'Ändere',
'qbpageoptions' => 'Sigge Enstellunge',
-'qbpageinfo' => 'Üvver de Sigg',
'qbmyoptions' => 'Ming Sigge',
'qbspecialpages' => 'Spezial Sigge',
'faq' => 'FAQ',
'qbbrowse' => 'Perspicere',
'qbedit' => 'Recensere',
'qbpageoptions' => 'Optiones paginae',
-'qbpageinfo' => 'Contextus',
'qbmyoptions' => 'Paginae meae',
'qbspecialpages' => 'Paginae speciales',
'faq' => 'Quaestiones frequentes',
'qbbrowse' => 'Duerchsichen',
'qbedit' => 'Änneren',
'qbpageoptions' => 'Säitenoptiounen',
-'qbpageinfo' => 'Kontext',
'qbmyoptions' => 'Meng Säiten',
'qbspecialpages' => 'Spezialsäiten',
'faq' => 'FAQ',
'edit-no-change' => 'Är ännerung gouf ignoréiert, well Dir näischt um Text geännert hutt.',
'edit-already-exists' => 'Déi nei Säit konnt net ugeluecht ginn, well et se scho gëtt.',
'defaultmessagetext' => 'Standardtext',
+'content-not-allowed-here' => '"$1"-Inhalt ass op der Säit [[$2]] net erlaabt',
+
+# Content models
+'content-model-wikitext' => 'Wikitext',
+'content-model-text' => 'Kloertext',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => "'''Opgepasst:'' Dës Säit huet ze vill Ufroe vu komplexe Parserfunktiounen.
'undeletedrevisions' => '$1 {{PLURAL:$1|Versioun gouf|$1 Versioune goufe}} restauréiert',
'undeletedrevisions-files' => '{{PLURAL:$1|1 Versioun|$1 Versiounen}} a(n) {{PLURAL:$2|1 Fichier|$2 Fichiere}} goufe restauréiert',
'undeletedfiles' => '$1 {{PLURAL:$1|Fichier gouf|Fichiere goufe}} restauréiert',
-'cannotundelete' => "D'Restauratioun huet net fonktionéiert. Een anere Benotzer huet déi Säit warscheinlech scho virun iech restauréiert.",
+'cannotundelete' => "D'Restauratioun huet net fonctionnéiert:
+$1",
'undeletedpage' => "'''$1''' gouf restauréiert.
Am [[Special:Log/delete|Läsch-Logbuch]] fannt Dir déi geläscht a restauréiert Säiten.",
'qbbrowse' => 'Bladere',
'qbedit' => 'Bewirke',
'qbpageoptions' => 'Pagina-opties',
-'qbpageinfo' => 'Pagina-informatie',
'qbmyoptions' => 'mien opties',
'qbspecialpages' => "Speciaal pagina's",
'faq' => 'FAQ (väölgesjtèlde vraoge)',
'qbfind' => 'Attrêuva',
'qbedit' => 'Cangia',
'qbpageoptions' => "Opsioîn de 'sta paggina",
-'qbpageinfo' => 'Informassion inscia paggina',
'qbmyoptions' => 'E mæ paggine',
'qbspecialpages' => 'Pagine speçiä',
'faq' => 'Domande frequenti',
'qbbrowse' => 'Naršymas',
'qbedit' => 'Taisyti',
'qbpageoptions' => 'Šis puslapis',
-'qbpageinfo' => 'Kontekstas',
'qbmyoptions' => 'Mano puslapiai',
'qbspecialpages' => 'Specialieji puslapiai',
'faq' => 'DUK',
'qbbrowse' => 'Fangvêl rawh',
'qbedit' => 'Siamţhatna',
'qbpageoptions' => 'He phêk hi',
-'qbpageinfo' => 'Thukhawchang',
'qbmyoptions' => 'Ka phêkte',
'qbspecialpages' => 'Phêk vohbîkte',
'faq' => 'Zawhzin',
Ahnuaih hian {{PLURAL:$1|zawmtu hmasa ber|zawmtu hmasa $1-te}} kan rawn tlar chhuak e.
Zawmtu zawng zawng [[Special:WhatLinksHere/$2|tlarchhuahna hetah hian a awm]] e.',
'nolinkstoimage' => 'He taksa zawmtu/hmanna phêk pakhat mah a awm lo.',
-'morelinkstoimage' => 'Hemi taksa zawmpui dang [[Special:WhatLinksHere/$1|enna}}.',
+'morelinkstoimage' => 'Hemi taksa zawmpui dang [[Special:WhatLinksHere/$1|enna]].',
'linkstoimage-redirect' => '$1 (taksa hruailuhna) $2',
'duplicatesoffile' => 'A hnuaia taksa{{PLURAL:$1||te}} khu hë taksa nihpui{{PLURAL:$1||te}} a{{PLURAL:$1||n}} ni ([[Special:FileDuplicateSearch/$2|chanchin kimchang]]):',
'sharedupload' => 'Hë taksa hi $1-a mi a ni a, hna-hmachhawp dangin a hmang vè mai thei.',
'qbbrowse' => 'Navigācija',
'qbedit' => 'Izmainīšana',
'qbpageoptions' => 'Šī lapa',
-'qbpageinfo' => 'Konteksts',
'qbmyoptions' => 'Manas lapas',
'qbspecialpages' => 'Īpašās lapas',
'faq' => 'BUJ',
'qbbrowse' => '覽',
'qbedit' => '纂',
'qbpageoptions' => '此頁',
-'qbpageinfo' => '內文',
'qbmyoptions' => '吾好',
'qbspecialpages' => '非凡',
'faq' => '頻答問',
'qbbrowse' => 'गवेषण करू',
'qbedit' => 'सम्पादन करू',
'qbpageoptions' => 'ई पन्ना',
-'qbpageinfo' => 'विषय',
'qbmyoptions' => 'हमर पन्ना सभ',
'qbspecialpages' => 'विशेष पन्ना सभ',
'faq' => 'त्वरित प्रश्नोत्तरी',
'tog-shownumberswatching' => 'Няфтемс мъзяра сувсида конат арафтозь лопать эсь мельгеваномазост',
'tog-oldsig' => 'Афкуксонь кядьтяшкс',
'tog-fancysig' => 'Кядьтяшкст улихть викитекстокс (эслек тиеви сюлмафксфтома)',
-'tog-externaleditor' => 'Нолдамс тевс ушеширень петнить мъзярс илякс изь мярьгов (аньцек тевонь содайхненди, сяс мес эрявихть башка кядьёнкст-арафнемат содама машинаса)',
-'tog-externaldiff' => 'Нолдамс тевс ушеширень програм верзиень ваксс путоманкса мъзярс илякс изь мярьгов (аньцек тевонь содайхненди, сяс мес эрявихть башка кядьёнкст-арафнемат содама машинаса)',
+'tog-externaleditor' => 'Нолдамс тевс ушеширень петнить мъзярс илякс изь мярьгов (аньцек тевонь содайхненди, сяс мес эрявихть башка кядьёнкст-арафнемат содама машинаса [//www.mediawiki.org/wiki/Manual:External_editors сяда тов.])',
+'tog-externaldiff' => 'Нолдамс тевс ушеширень програм верзиень ваксс путоманкса мъзярс илякс изь мярьгов (аньцек тевонь содайхненди, сяс мес эрявихть башка кядьёнкст-арафнемат содама машинаса[//www.mediawiki.org/wiki/Manual:External_editors сяда тов.])',
'tog-showjumplinks' => 'Мярьгомс "юпадемс" сатовома сюлмафкстненди',
'tog-uselivepreview' => 'Максомс эряй васень няфтемась (JavaScript) (Варжамань)',
'tog-forceeditsummary' => 'Няфтемс мондине мезе сёрмадомс шава петнема вальмас сувамста',
'tog-watchlisthideminor' => 'Кяшемс петнема анцяйнятне ванома лопаста',
'tog-watchlisthideliu' => 'Кяшемс сёрматфтф тиихнень петнемаснон мельгеваномаса',
'tog-watchlisthideanons' => 'Кяшемс лемфтома тиихнень петнемаснон мельгеваномаса',
+'tog-watchlisthidepatrolled' => 'Кяшемс лувонь кирдихнень видептемаснон мельгеваномаса',
'tog-ccmeonemails' => 'Кучт тейне копия электрононь сермане конатнень кучсайне иля тиихненди.',
'tog-diffonly' => 'Тят няфте лопань потмоц кафта верзиятнень ваксс путомать ала',
'tog-showhiddencats' => 'Няфтемс кяшф категориет',
'underline-never' => 'Мъзярдонга',
'underline-default' => 'Интернет полатксть кадомс апак полафтт',
+# Font style option in Special:Preferences
+'editfont-style' => 'Полафтомс тя паксянь сёрмадома стиленц',
+'editfont-default' => 'Интернетс вятись апак полафтт',
+'editfont-monospace' => 'Фкя келеса сёрмадома',
+'editfont-sansserif' => 'Сёрмадома Sans-serif',
+'editfont-serif' => 'Serif сёрмадома',
+
# Dates
'sunday' => 'Таргоши (Недляши)',
'monday' => 'Одговши (Панедельник)',
'category-file-count' => '{{PLURAL:$2|Тя категориеса аньцек фкя файл.|Вага {{PLURAL:$1|файл|$1 файлхт}} тя категориеса $2-нь эста.}}',
'category-file-count-limited' => 'Вага {{PLURAL:$1|файл|$1 файлхт}} тя категориеса.',
'listingcontinuesabbrev' => 'полатксоц',
+'index-category' => 'Индексыяф лопат',
'noindex-category' => '↓Индексфтома лопатне',
+'broken-file-category' => 'Лопат колаф сюлмафкснень мархта',
'about' => 'Колганза',
'article' => 'Сёрматфть потмонц лопац',
'qbbrowse' => 'Ванондома',
'qbedit' => 'Петнема',
'qbpageoptions' => 'Тя лопась',
-'qbpageinfo' => 'Контекстсь',
'qbmyoptions' => 'Монь лопане',
'qbspecialpages' => 'Башка тевонь лопат',
'faq' => 'Сидеста Кеподеви Кизефксне',
'vector-action-move' => 'Шашфтомс',
'vector-action-protect' => 'Араламс',
'vector-action-undelete' => 'Мърдафтомс',
-'vector-action-unprotect' => 'Аралама лоткамс',
+'vector-action-unprotect' => 'Араламать полафтомс',
+'vector-simplesearch-preference' => 'Нодамс тевс тёждялгтотф кядьёнксонь седяфксть (аньцек векторонь лангакс)',
'vector-view-create' => 'Тиемс',
'vector-view-edit' => 'Петнемс',
'vector-view-history' => 'История няфтемс',
'printableversion' => 'Лихтеви верзие',
'permalink' => 'Ялань сюлмафкс',
'print' => 'Нолдамс',
+'view' => 'Ваномс',
'edit' => 'Петнеме',
'create' => 'Тиемс',
'editthispage' => 'Петнемс тя лопать',
'delete' => 'Нардамс',
'deletethispage' => 'Нардамс тя лопать',
'undelete_short' => 'Мърдафтомс {{PLURAL:$1|петнема|$1 петнемат}}',
+'viewdeleted_short' => 'Ваномс {{PLURAL:$1|фкя нардаф видептема|$1 нардаф видептемат}}',
'protect' => 'Араламс',
'protect_change' => 'полафтомс прянь араламать',
'protectthispage' => 'Араламс тя лопать',
-'unprotect' => 'Ð\92алÑ\85Ñ\82омÑ\81 аÑ\80аламаÑ\82Ñ\8c',
-'unprotectthispage' => 'Ð\92алÑ\85Ñ\82омÑ\81 Ñ\82Ñ\8f лопаÑ\82Ñ\8c аÑ\80аламац',
+'unprotect' => 'Ð\90Ñ\80аламаÑ\82Ñ\8c полаÑ\84Ñ\82омÑ\81',
+'unprotectthispage' => 'Ð\9fолаÑ\84Ñ\82омÑ\81 Ñ\82Ñ\8f лопаÑ\82Ñ\8c аÑ\80аламанц',
'newpage' => 'Од лопа',
'talkpage' => 'Корхтамс тя лопать колга',
'talkpagelinktext' => 'Корхтама',
'jumpto' => 'Юпадемс тязк:',
'jumptonavigation' => 'навигацие',
'jumptosearch' => 'вешендема',
+'view-pool-error' => 'Ужяль, тя пингть серверхнень вийсна аф сатовихть.
+Вельф лама тиихть тяряфнихть ваномс тя лопать.
+Эняльттяма учт аф ламос тя лопанди одукс сама инголе.
+$1',
+'pool-timeout' => 'Пигонь кирдемась учи пякстаманц',
+'pool-queuefull' => 'Тяряфнемада вельф лама',
+'pool-errorunknown' => 'Аф содаф эльбятькс',
# 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}} колга',
'youhavenewmessages' => 'Тонь ули $1 ($2).',
'newmessageslink' => 'Од сёрмат',
'newmessagesdifflink' => 'мекольце полафтома',
+'youhavenewmessagesfromusers' => 'Тонь $1 {{PLURAL:$3|тага фкя тиить эзда|$3 тиихнень эзда}} ($2).',
+'youhavenewmessagesmanyusers' => 'Тонь $1 лама тиихнень эзда ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|од сёрма|од сёрмат}}',
+'newmessagesdifflinkplural' => 'мекольце {{PLURAL:$1|полафнема|полафнемат}}',
'youhavenewmessagesmulti' => 'Тонь улихть од сёрмат $1-са',
'editsection' => 'петнемс',
'editold' => 'петнемс',
'toc' => 'Лопань потмоц',
'showtoc' => 'няфтемс',
'hidetoc' => 'кяшемс',
+'collapsible-collapse' => 'Ёмлалгофтомс',
+'collapsible-expand' => 'Келептемс',
'thisisdeleted' => 'Ваномс эли мърдафтомс $1?',
'viewdeleted' => 'Ваномс $1?',
'restorelink' => '{{PLURAL:$1|нардаф петнема|$1 нардаф петнемат}}',
'page-rss-feed' => '"$1" RSS линия',
'page-atom-feed' => '"$1" Atom линия',
'red-link-title' => '$1 (стама лопась аш)',
+'sort-descending' => 'Арафтомс алу',
+'sort-ascending' => 'Арафтомс вяри',
# Short words for each namespace, by default used in the namespace tab in monobook
'nstab-main' => 'Лопа',
# General errors
'error' => 'Эльбятькс',
'databaseerror' => 'Датабаза эльбятькс',
-'dberrortext' => 'Ð\94аÑ\82абазанÑ\8c веÑ\88ендембаÑ\87к лиÑ\81Ñ\81Ñ\8c Ñ\81инÑ\82акÑ\81 эльбятькс.
-ТÑ\8f, Ñ\83лема, пÑ\80огÑ\80амонÑ\8c Ñ\8dлÑ\8cбÑ\8fÑ\82Ñ\8cкÑ\81.
-Мекольце датабазонь вешендема ульсь:
-<blockquote><tt>$1</tt></blockquote>
-функциеста "<tt>$2</tt>".
-Ð\94аÑ\82абазаÑ\81Ñ\8c мÑ\8aÑ\80даÑ\84Ñ\82озе Ñ\8dлÑ\8cбÑ\8fÑ\82Ñ\8cкÑ\81Ñ\82Ñ\8c "<tt>$3: $4</tt>".',
+'dberrortext' => 'СодамоÑ\88инÑ\8c паÑ\80ганÑ\8c веÑ\88ендембаÑ\87к лиÑ\81Ñ\81Ñ\8c Ñ\81инÑ\82акÑ\81онÑ\8c эльбятькс.
+ТÑ\8f, Ñ\83лема, пÑ\80огÑ\80амгÑ\8fÑ\80Ñ\8cкÑ\81онÑ\8c Ñ\81и.
+Мекольце содамошинь паргань вешема:
+<blockquote><code>$1</code></blockquote>
+функциеста "<code>$2</code>".
+СодамоÑ\88инÑ\8c паÑ\80гаÑ\81Ñ\8c паÑ\87Ñ\84Ñ\82еÑ\81Ñ\8c Ñ\8dлÑ\8cбÑ\8fÑ\82Ñ\8cкÑ\81 "<samp>$3: $4</samp>".',
'dberrortextcl' => 'Датабазонь вешендембачк лиссь синтакс эльбятькс.
Мекольце датабазонь вешендема ульсь:
"$1"
'readonly_lag' => 'Датабазась эслек пякстась мъзярс кядяла датабаза серверхт сотни прясерверть мархта',
'internalerror' => 'Потмонь эльбятькс',
'internalerror_info' => 'Потмонь эльбятькс: $1',
+'fileappenderrorread' => '"$1" файлась аф лувови поладома пингста.',
+'fileappenderror' => '"$1" файлась изь поладов "$2" файлти.',
'filecopyerror' => 'Аш кода копиямс файл "$1" файл "$2"с.',
'filerenameerror' => 'Аш кода "$1" файлти максомс од лем "$2".',
'filedeleteerror' => 'Файл "$1" аф нардави.',
'badarticleerror' => 'Тя лопаса тя аф тиеви.',
'cannotdelete' => 'Лопась эли кочкаф "$1" файлсь аф нардави.
Сонь, улема, кинге нардазе ни.',
+'cannotdelete-title' => '"$1" лопась аф нардави',
+'delete-hook-aborted' => 'Туворкс програм петнемать лоткафтозе.
+Пачфтемат тянь коряс аш.',
'badtitle' => 'Аф кондясти лем',
'badtitletext' => 'Вешф лопань лемоц аф тяфтама эли шава, шятьта кялень-ётка эли викинь-ётка лемсна аф лац сюлмафт. Сонь эса, улема ащи фкя эли сяда лама башка тяштькстт конат коняксонди аф кондястихть.',
-'perfcached' => 'Вешф програмонь информациесь сёрматфоль эслек ванфневи файлхнень эса ди, улема, сирелгодсь. A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.',
-'perfcachedts' => 'Тя програмонь информациесь сёрматфоль эслек ванфневи файлхнень эса ди мекольцеда одонзаф $1. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.',
+'perfcached' => 'Вешф програмонь информациесь сёрматфоль эслек ванфневи файлхнень эса ди, улема, сирелгодсь. Сяда {{PLURAL:$1|фкя муфкс|$1 муфкст}} эслек ванфневи файлань кярьксса.',
+'perfcachedts' => 'Тя програмонь информациесь сёрматфоль эслек ванфневи файлхнень эса ди мекольцеда одонзаф $1. Сяда {{PLURAL:$4|фкя муфкс|$4 муфкст}} эслек ванфневи файлонь кярьксса.',
'querypage-no-updates' => 'Тя лопать одонзапне тяни аф тиевихть. Информациесь тяса тяни аф одонзави.',
'wrong_wfQuery_params' => 'Аф кондясти параметратне функцияса wfQuery()<br />
Функцие: $1<br />
Вешфкс: $2',
'viewsource' => 'Ваномс лисьмоть',
+'viewsource-title' => 'Ванк $1 лисьмаста',
'actionthrottled' => 'Куроксшись кирьфтаф',
'actionthrottledtext' => 'Лудна мархта тюрема туфталонкса тя тевть ламоксть тиемась нюрьхконя ётка пингста кардаф. Эняльттяма мърдамс тя тевти мъзярошка минутода меле.',
'protectedpagetext' => 'Тя лопас сувама пякстаф лопань петнема кардамать сюнеда.',
'viewsourcetext' => 'Тейть ули кода ваномс эди копиямс тя лопать лисьмоц:',
-'protectedinterface' => 'Тя лопаса ащи лопать ванфонц програмонь текстоц, сон пякстаф кальдяв тевда араламать сюнеда.',
-'editinginterface' => "'''Инголе кардама:''' Тон петнесак лопать конань эса ащи лопать ванфонц програмонь текстоц. Петнематне полафтсазь сонь ванфоц кода сон няеви иля тиихненди. Ётафтома тиеманкса эняльттяма ваномс [//translatewiki.net/wiki/Main_Page?setlang=mdf translatewiki.net] МедиаВикить локализациеть проектть.",
+'viewyourtext' => "Тондейть ули кода тя лопань '''петнематнень''' ваномс ди тиемс копиянснон:",
+'protectedinterface' => 'Тя лопать эса интерфейс текстсь тя викить програмгярксти, сон аралаф кальдяв тиемада.
+Вики ётафтоматнень поладоманди полафнемандивок сувак [//translatewiki.net/ translatewiki.net], MediaWiki локализациень проектти.',
+'editinginterface' => "'''Инголи кардама:''' Тон петнесак лопать конань эса ащи интерфейс текст програмкярьксонди. Петнематне полафтсазь сонь ванфоц, кода сон няеви иля тиихненди. Вики ётафтоматнень поладоманди, полафтомандивок сувак [//translatewiki.net/ translatewiki.net] MediaWiki локализациень проектти.",
'sqlhidden' => '(SQL вешфкс кяшф)',
'cascadeprotected' => 'Тя лопать аралазь петнемада сяс мес сон сувафни {{PLURAL:$1|сай лопас, кона путфоль|сай лопас, конат путфольхть}} каскад араламас:
$2',
'namespaceprotected' => "Тондейть аф мярьгови петнемс лопатне '''$1''' лепнень мархта.",
+'customcssprotected' => 'Тейть аф мярьгови петнемс CSS лопать, сяс мес потмосонза иля тиить латцеманза.',
+'customjsprotected' => 'Тейть аф мярьгови петнемс JavaScript лопать, сяс мес потмосонза иля тиить латцеманза.',
'ns-specialprotected' => '{{ns:special}} лепнень мархта лопатне аф петневихть.',
'titleprotected' => "[[User:$1|$1]] кардазь тя лемсь мархта лопа тиемать.
Туфталсь ''$2''.",
+'filereadonlyerror' => '"$1" файлась аф полафтови сяс мес "$2" файлонь пърдафкссь аньцек морафтови форматса.
+
+Админць конась сёлгозе кадсь пачфтема: "$3".',
+'invalidtitle-knownnamespace' => 'Аф кондясти лем "$2" лемботмоса ди "$3" текстть эса',
+'invalidtitle-unknownnamespace' => 'Аф кондясти лем $1 лемботмоса ди "$2" текстть эса',
+'exception-nologin' => 'Апак сувак',
+'exception-nologin-text' => 'Тя лопать эли тиемать сатоманди васенда эряви сувамс викис.',
# Virus scanner
'virus-badscanner' => "Аф кондясти конфигурациесь: аф содаф вирусонь вешендема програмсь: ''$1''",
'yourpassword' => 'Сувама валце:',
'yourpasswordagain' => 'Сёрматк сувама валце омбоцекс:',
'remembermypassword' => 'Ванфтомс монь сувама лемозе тя содам машинаса (максимум $1 {{PLURAL:$1|шис|шис}})',
+'securelogin-stick-https' => 'Кадовомс сотфокс HTTPS вельде сувамада меле',
'yourdomainname' => 'Тонь доменце:',
+'password-change-forbidden' => 'Сувама валхне тя викить эса аф полафтовихть',
'externaldberror' => 'Лиссь эльбятькс ушеширень датабазонь вельде кемокстакшнембачк эли тондейть аф мярьгови полафнемс тонь ушеширень сёрматфтомацень.',
'login' => 'Сувама',
'nav-login-createaccount' => 'Сувама / сёрматфтома',
'loginprompt' => 'Тондейть эряви нолдамс тевс cookies {{SITENAME}}с суваманди.',
'userlogin' => 'Сувама / сёрматфтома',
+'userloginnocreate' => 'Сувамс',
'logout' => 'Лисема',
'userlogout' => 'Лисема',
'notloggedin' => 'Апак сувак',
'gotaccountlink' => 'Сувамс',
'userlogin-resetlink' => 'Сувама эрявикснень юкстайть?',
'createaccountmail' => 'электрононь сёрма вельде',
+'createaccountreason' => 'Туфтал:',
'badretype' => 'Сувама валхне тон путыть аф фкат.',
-'userexists' => 'Тя лемсь кой-кие сявозь ни. Эняльттяма, арьсек иля лемсь.',
+'userexists' => 'Тя лемть сявозь ни.
+Эняльттяма, арьсек эстейть иля.',
'loginerror' => 'Сувама эльбятькс',
+'createaccounterror' => 'Сёрматфтомась аф тиеви: $1',
'nocookiesnew' => 'Тиить сёрматфтомаце анок, аньцек тон изеть сува. {{SITENAME}}-са тиихнень содафтоманкса функцие cookies эряви. Тяни тонь содама машинаса функцие cookies кардаф. Эняльттяма нолдамс тевс cookies, меле сувак од эсь тиить лемцень эди сувама валцень мархта.',
'nocookieslogin' => '{{SITENAME}} лопаса тиихнень содафтоманкса функцие cookies эряви. Тяни тонь содама машинаса функцие cookies кардаф. Эняльттяма нолдамс тевс cookies, меле сувак тага весть.',
+'nocookiesfornew' => 'Тиить сёрматфтомась апак тик сяс мес лисьмонц аф кемокстави.
+Варжак cookies нолдафт эли аф, одонзафтк лопать ди тяряфтт одукс.',
'noname' => 'Тон изеть пута кемокстаф тиить лемоц.',
'loginsuccesstitle' => 'Сувамась ётась лац',
'loginsuccess' => "'''Тон сувать {{SITENAME}}-с кода \"\$1\".'''",
Илякс тондейть эряви [[Special:UserLogin/signup|сёрматфтомс одукс]].',
'nosuchusershort' => 'Тиись "$1" лемса аш. Ванк, улема, тон сёрмадыть лемть аф лац.',
'nouserspecified' => 'Тиить лемсь эряви.',
+'login-userblocked' => 'Тиись перяф. Сувама кардаф.',
'wrongpassword' => 'Сувама валсь сёрматф аф лац. Варжак тага весть.',
'wrongpasswordempty' => 'Сувама валсь кадовсь апак сёрматк. Сёрматк одукс.',
'passwordtooshort' => 'Тонь сувама валценди эряви улемс аф {{PLURAL:$1|1 тяшкста|$1 тяшкста}} кържа',
+'password-name-match' => 'Сувама лемце ди сувама сувама валце улемат аф фкат.',
+'password-login-forbidden' => 'Тя сувама лемсь эди сувама валсь кардафт.',
'mailmypassword' => 'Кучт од сувама вал',
'passwordremindertitle' => 'Од ёткопингонь сувама валсь {{SITENAME}}с суваманди',
'passwordremindertext' => 'Кивок (улема, тон IP адресста $1) вешсь од сувама валсь {{SITENAME}} ($4)с суваманди.
Улендяряй киге иля кучсь тя вешфксть эли тон мяляфтсак тонь сувама валцень эди тонь тяни аш мяльце сонь полафтома, тят тие мезеге тя пачфтемась самда меле ди киртть тонь ингольдень сувама валцень.',
'noemail' => '"$1" тиить электрононь адресоц аш.',
+'noemailcreate' => 'Эряви тяштемс афкукс е-парга',
'passwordsent' => 'Од сувама валсь кучфоль "$1" тиить электрононь адресонцты.
Сувак сонь кундамда меле.',
'blocked-mailpassword' => 'Петнемат тиемась тонь IP адрестот кардаф. Сувама валть кемокстама функциес кундама аф мярьгови кальдяв тиемада аралама туфталонкса.',
'noemailprefs' => 'Мъзярс тон ашеть пута тонь электрононь адресце Викить сёрматнень коряс програмсь кодамога сёрмат аф кучсыне.',
'emailconfirmlink' => 'Кемокстак тонь электрононь адресце',
'invalidemailaddress' => 'Электрононь адресть аф пьрьняндави сяс сонь аф кондясти электрононь адресоц. Путт кондясти электрононь адресонц эли катк тя паксянять шавакс.',
+'cannotchangeemail' => 'Сёрматфтомать е-паргоц аф полафтови тя викить эса',
+'emaildisabled' => 'Тя лопанди аш кода кучемс е-сёрмат.',
'accountcreated' => 'Сёрматфтомась тиф',
'accountcreatedtext' => '$1 тиить сёрматфтомась тиф.',
'createaccount-title' => 'Сёрматфнемась {{SITENAME}}-с',
'createaccount-text' => 'Кати-кие тизе сёрматфтомась $2 {{SITENAME}} ($4)-са. "$2" -ть сувама валсь "$3". Тондейть эряви сувамс тозк эди арафтомс од сувама валть.
Улендяряль тя сёрматфтомась эльбятьксокс мезеге тят тие.',
+'usernamehasherror' => 'Тиить лемозонза тяфтама тяшкст аф мярьговихть',
'login-throttled' => 'Тон улхкомба вельф ламос тяряфнеть сувамс тя сувама валть вельде.
Эняльттяма, учт аф ламос тага весть тяряфтома инголе.',
+'login-abort-generic' => 'Сувамацень апак тиевсь лац - Валхтф',
'loginlanguagelabel' => 'Кяль: $1',
+'suspicious-userlogout' => 'Вешфксце лисемс кардафоль сяс мес няеви тянь кучезь колаф интернетс вятиень эли ётка ёкамань сервер вельде.',
+
+# E-mail sending
+'php-mail-error-unknown' => 'Аф содаф эльбятькс PHP сёрмавятемань функциеса.',
+'user-mail-no-addy' => 'Тяряфтыхть кучемс е-сёрма е-паргафтома',
# Change password dialog
'resetpass' => 'Полафтомс сувама валцень',
'resetpass_forbidden' => 'Сувама валхнень полафтомс аш кода',
'resetpass-no-info' => 'Тондейть эряви сёрматфтомс тя лопас видеста суваманди.',
'resetpass-submit-loggedin' => 'Полафтомс сувама валцень',
+'resetpass-submit-cancel' => 'Валхтомс',
'resetpass-wrong-oldpass' => 'Аф виде ёткопингонь эли тяниень сувама валсь.
Улема тон полафтыть сувама валце ни эли кучеть вешфкс од ёткопингонь сувама вал кундаманкса.',
'resetpass-temp-password' => 'Пингонь сувама валсь:',
+# Special:PasswordReset
+'passwordreset' => 'Полафтомс сувама валцень',
+'passwordreset-text' => 'Эряви пяшкодемс тя формать е-сёрма сёрматфтомацень колга сявоманди.',
+'passwordreset-legend' => 'Полафтомс сувама валцень',
+'passwordreset-disabled' => 'Сувама валсь аф полафтови тя викить эса.',
+'passwordreset-pretext' => '{{PLURAL:$1||Тяштьк содама пялькснень эзда фкя алу}}',
+'passwordreset-username' => 'Тиить лемоц',
+'passwordreset-domain' => 'Домен:',
+'passwordreset-capture' => 'Ваномс мекольце е-сёрма?',
+'passwordreset-capture-help' => 'Путондярят тяшкс тя паксять эса е-сёрма (пингонь сувама вал мархта) кармай няфтевома кодак кучф тиенди.',
+'passwordreset-emailtitle' => 'Серматфтомать колга {{SITENAME}}са',
+
# Edit page toolbar
'bold_sample' => 'Эчке сёрмадома',
'bold_tip' => 'Эчке сёрмадома',
'edit-no-change' => 'Тонь петнемацень тевс изь нолда, сяс мес тон текстть ашеть полафта.',
'edit-already-exists' => 'Аш кода од лопа ушедомс.
Тя лопась ульсь ни.',
+'content-failed-to-parse' => 'Аш кода $2 сёрматфть нолдамс тевс $1 моделень коряс: $3',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Инголе кардама: Тя лопаса пяк лама питни синтаксонь анализаторхнень тяшкста.
'allmessagestext' => 'Тя MediaWiki-са васьфневи системонь пачфтематнень лувомась.
Эняльттяма, сувак [//www.mediawiki.org/wiki/Localisation MediaWiki Локализациес] ди [//translatewiki.net translatewiki.net-с] кда тонь мяльце тиемс эсь путксце марстонь MediaWiki локализациес.',
'allmessagesnotsupportedDB' => "Тя лопас аш кода кунцемс сяс мес '''\$wgUseDatabaseMessages'''лоткафоль.",
+'allmessages-language' => 'Кяль:',
+'allmessages-filter-submit' => 'Ётамс',
# Thumbnails
'thumbnail-more' => 'Оцюлгофтомс',
'thumbnail_error' => 'Миниатюр тиема эльбятькс: $1',
'djvu_page_error' => 'DjVu лопась аф сатови',
'djvu_no_xml' => 'Аш кода латцемс XML DjVu файлти',
+'thumbnail-temp-create' => 'Пингонь миниатюрац аф тиеви',
+'thumbnail-dest-create' => 'Миниатюрась аф ванфтови коза эряви',
'thumbnail_invalid_params' => 'Аф кондясти миниатюронь арафнеманза',
'thumbnail_dest_directory' => 'Аш кода ушедомс од вастонь директориесь',
+'thumbnail_image-type' => 'Тя няйфкс форматсь аф нежедеви',
# Special:Import
'import' => 'Таргамс лопат',
Сембе ётковикинь таргама тефне тяшневихть [[Special:Log/import|таргамань лувомас]].',
'import-interwiki-source' => 'Вики лисьма/лопа:',
'import-interwiki-history' => 'Копияфтомс тя лопать сембе историянь верзиенза',
+'import-interwiki-templates' => 'Сувафтомс сембе шаблотт',
'import-interwiki-submit' => 'Таргамс',
'import-interwiki-namespace' => 'Пачфтема лемботма:',
+'import-interwiki-rootpage' => 'Ёнонь юрлопась (кочкамать коряс):',
'import-upload-filename' => 'Файллем:',
'import-comment' => 'Мяльполаткс:',
-'importtext' => 'Эняльттяма таргак файлть Вики лисьмостонза [[Special:Export|вима лезкссь]] тевс нолдазь, ванфтт тянь тонь содама машинаса ди тонк тязк.',
+'importtext' => 'Эняльттяма таргак файлать Вики лисьмостонза [[Special:Export|вима лезкссь]]. Ванфтк содама машиназот ди тонк тяза.',
'importstart' => 'Лопатне тарксевихть...',
'import-revision-count' => '$1 {{PLURAL:$1|илякстоптома|илякстоптомат}}',
'importnopages' => 'Ашет лопат таргаманди.',
+'imported-log-entries' => 'Таргак $1 {{PLURAL:$1|лувонь тяштема|лувонь тяштемат}}.',
'importfailed' => 'Таргамась колавсь: <nowiki>$1</nowiki>',
'importunknownsource' => 'Аф содаф таргама лисьмоть сортоц',
'importcantopen' => 'Аш кода панжемс таргама файлть',
'import-upload' => 'Тонгомс XML информациесь',
'import-token-mismatch' => 'Сессиянь нформациесь юмась. Тяряфтт тага весть.',
'import-invalid-interwiki' => 'Аш кода таргамс кочкаф Викить.',
+'import-error-edit' => '"$1" лопась апак тонк сяс мес тейть аф мярьгови петеманза.',
+'import-error-create' => '"$1" лопась апак тонк сяс мес тейть аф мярьгови тиеманза.',
+'import-error-interwiki' => '"$1" лопась апак тонк сяс мес лемоц ванфтфоль ушеширень сюлмаманди (interwiki).',
+'import-error-special' => '"$1" лопась апак тонк сяс мес сон башка лемботмоса, конаса лопат кардафт.',
+'import-error-invalid' => '"$1" лопась апак тонк сяс мес лемоц аф кондясти.',
+'import-options-wrong' => 'Аф виде {{PLURAL:$2|кочкама|кочкамат}}: <nowiki>$1</nowiki>',
# Import log
'importlogpage' => 'Таргамань лувома',
'qbbrowse' => 'Tadiavina',
'qbedit' => 'Hanova',
'qbpageoptions' => 'Ity pejy ity',
-'qbpageinfo' => 'Pejy fanoroana',
'qbmyoptions' => 'Ny pejiko',
'qbspecialpages' => 'Pejy manokana',
'faq' => 'FMM',
'qbbrowse' => 'Прелистај',
'qbedit' => 'Уреди',
'qbpageoptions' => 'Оваа страница',
-'qbpageinfo' => 'Содржина на страница',
'qbmyoptions' => 'Мои страници',
'qbspecialpages' => 'Специјални страници',
'faq' => 'ЧПП',
'lastmodifiedat' => 'Оваа страница последен пат е изменета на $1 во $2 ч.',
'viewcount' => 'Оваа страница била посетена {{PLURAL:$1|еднаш|$1 пати}}.',
'protectedpage' => 'Заштитена страница',
-'jumpto' => 'Скокни на:',
+'jumpto' => 'Ð\9fÑ\80еÑ\98ди на:',
'jumptonavigation' => 'содржини',
'jumptosearch' => 'барај',
'view-pool-error' => 'За жал во моментов опслужувачите се преоптоварени.
'shared-repo' => 'заедничко складиште',
'shared-repo-name-wikimediacommons' => 'Заедничката Ризница',
'filepage.css' => '/* Тука поставените каскадни стилски страници (CSS) се вклучени во страницата за опис на податотеката, како и на клиентските викија */',
-'upload-disallowed-here' => 'Нажалост, не можете да ја замените сликава со нова.',
+'upload-disallowed-here' => 'Нажалост, не можете да презапишете врз сликава.',
# File reversion
'filerevert' => 'Врати $1',
# Info page
'pageinfo-title' => 'Информации за „$1“',
+'pageinfo-not-current' => 'Информациите може да се прикажат само за тековната ревизија.',
'pageinfo-header-basic' => 'Основни информации',
'pageinfo-header-edits' => 'Историја на уредувања',
'pageinfo-header-restrictions' => 'Заштита на страницата',
'qbbrowse' => 'ബ്രൗസ്',
'qbedit' => 'തിരുത്തുക',
'qbpageoptions' => 'ഈ താൾ',
-'qbpageinfo' => 'സന്ദർഭം',
'qbmyoptions' => 'എന്റെ താളുകൾ',
'qbspecialpages' => 'പ്രത്യേക താളുകൾ',
'faq' => 'പതിവുചോദ്യങ്ങൾ',
'shared-repo' => 'ഒരു പങ്കുവെക്കപ്പെട്ട സംഭരണി',
'shared-repo-name-wikimediacommons' => 'വിക്കിമീഡിയ കോമൺസ്',
'filepage.css' => '/* ഇവിടെ നൽകുന്ന സി.എസ്.എസ്. പ്രമാണ വിവരണ താളുകളിൽ ഉൾപ്പെടുത്തപ്പെടുന്നതായിരിക്കും, ബാഹ്യ ക്ലൈന്റ് വിക്കികളിലും അത് ലഭ്യമായിരിക്കും */',
-'upload-disallowed-here' => 'നിർà´à´¾à´\97àµ\8dയവശാൽ à´\88 à´\9aà´¿à´¤àµ\8dà´°à´¤àµ\8dതിനàµ\81 à´®àµ\81à´\95ളിൽ മറàµ\8dà´±àµ\8aà´°àµ\81 à´\9aà´¿à´¤àµ\8dà´°ം ചേർക്കാൻ താങ്കൾക്ക് കഴിയില്ല.',
+'upload-disallowed-here' => 'à´\88 à´ªàµ\8dരമാണതàµ\8dതിനàµ\81 à´®àµ\81à´\95ളിൽ മറàµ\8dà´±àµ\8aà´°àµ\81 à´ªàµ\8dരമാണം ചേർക്കാൻ താങ്കൾക്ക് കഴിയില്ല.',
# File reversion
'filerevert' => '$1 തിരസ്ക്കരിക്കുക',
# Info page
'pageinfo-title' => '"$1" എന്ന താളിന്റെ വിവരങ്ങൾ',
+'pageinfo-not-current' => 'ഇപ്പോഴത്തെ നാൾപ്പതിപ്പിൽ മാത്രമേ വിവരങ്ങൾ പ്രദർശിപ്പിക്കപ്പെടാനിടയുള്ളു.',
'pageinfo-header-basic' => 'അടിസ്ഥാനവിവരങ്ങൾ',
'pageinfo-header-edits' => 'തിരുത്തൽചരിത്രം',
'pageinfo-header-restrictions' => 'സംരക്ഷണം',
'qbbrowse' => 'Дэлгэх',
'qbedit' => 'Засварлах',
'qbpageoptions' => 'Энэ хуудас',
-'qbpageinfo' => 'Агуулга',
'qbmyoptions' => 'Миний хуудсууд',
'qbspecialpages' => 'Тусгай хуудсууд',
'faq' => 'Тогтмол тавигддаг асуултууд',
'qbbrowse' => 'न्याहाळा',
'qbedit' => 'संपादन',
'qbpageoptions' => 'हे पान',
-'qbpageinfo' => 'सामग्री',
'qbmyoptions' => 'माझी पाने',
'qbspecialpages' => 'विशेष पाने',
'faq' => 'नेहमीची प्रश्नावली',
'qbbrowse' => 'Semak imbas',
'qbedit' => 'Sunting',
'qbpageoptions' => 'Laman ini',
-'qbpageinfo' => 'Konteks',
'qbmyoptions' => 'Laman-laman saya',
'qbspecialpages' => 'Laman khas',
'faq' => 'Soalan Lazim',
'qbbrowse' => 'Qalleb',
'qbedit' => 'Immodifika',
'qbpageoptions' => 'Din il-paġna',
-'qbpageinfo' => 'Kuntest',
'qbmyoptions' => 'Il-paġni tiegħi',
'qbspecialpages' => 'Paġni speċjali',
'faq' => 'Mistoqsijiet komuni',
'qbbrowse' => 'Bla gjennom',
'qbedit' => 'Rediger',
'qbpageoptions' => 'Sideinnstillinger',
-'qbpageinfo' => 'Sideinformasjon',
'qbmyoptions' => 'Egne innstillinger',
'qbspecialpages' => 'Spesialsider',
'faq' => 'Ofte stilte spørsmål',
'edit-no-change' => 'Redigeringen din ble ignorert fordi det ikke var noen endringer.',
'edit-already-exists' => 'Kunne ikke opprette ny side fordi den finnes fra før.',
'defaultmessagetext' => 'Standard meldingstekst',
+'content-failed-to-parse' => 'Klarte ikke å tolke innholdet $2 for innholdsmodellen $1: $3',
+'invalid-content-data' => 'Ugyldig innhold',
+'content-not-allowed-here' => 'Innholdsmodellen «$1» er ikke tillatt på siden [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'WikiTekst',
+'content-model-text' => 'Ren tekst',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Advarsel: Denne siden inneholder for mange prosesskrevende parserfunksjoner.
'undeletedrevisions' => '{{PLURAL:$1|Én revisjon|$1 revisjoner}} gjenopprettet',
'undeletedrevisions-files' => '{{PLURAL:$1|Én revisjon|$1 revisjoner}} og {{PLURAL:$2|én fil|$2 filer}} gjenopprettet',
'undeletedfiles' => '{{PLURAL:$1|Én fil|$1 filer}} gjenopprettet',
-'cannotundelete' => 'Kunne ikke gjenopprette siden (den kan være gjenopprettet av noen andre).',
+'cannotundelete' => 'Gjennoppretting feilet:
+$1',
'undeletedpage' => "'''$1 ble gjenopprettet'''
Sjekk [[Special:Log/delete|slettingsloggen]] for en liste over nylige slettinger og gjenopprettelser.",
'immobile-target-namespace-iw' => 'Du kan ikke flytte en side til et navn som er en interwikilenke.',
'immobile-source-page' => 'Denne siden kan ikke flyttes.',
'immobile-target-page' => 'Kan ikke flytte til det navnet.',
+'bad-target-model' => 'Det ønskede målet bruker en annen innholdsmodell. Kan ikke konvertere fra $1 til $2.',
'imagenocrossnamespace' => 'Kan ikke flytte filer til andre navnerom enn filnavnerommet',
'nonfile-cannot-move-to-file' => 'Kan ikke flytte ikke-filer til filnavnerom',
'imagetypemismatch' => 'Den nye filendelsen tilsvarer ikke filtypen',
'qbbrowse' => 'Blädern',
'qbedit' => 'Ännern',
'qbpageoptions' => 'Disse Sied',
-'qbpageinfo' => 'Sietendaten',
'qbmyoptions' => 'Instellen',
'qbspecialpages' => 'Spezialsieten',
'faq' => 'Faken stellte Fragen',
'qbbrowse' => 'Blaojen',
'qbedit' => 'Bewark',
'qbpageoptions' => 'Disse zied',
-'qbpageinfo' => 'Ziedinformasie',
'qbmyoptions' => 'Veurkeuren',
'qbspecialpages' => 'Spesiale ziejen',
'faq' => 'Vragen die vake esteld wörden',
'qbbrowse' => 'ब्राउज गर्ने',
'qbedit' => 'सम्पादन गर्ने',
'qbpageoptions' => 'यो पेज',
-'qbpageinfo' => 'सन्दर्भ',
'qbmyoptions' => 'मेरो पेज',
'qbspecialpages' => 'विशेष पृष्ठहरु',
'faq' => 'धैरै सोधिएका प्रश्नहरु',
* @author Trijnstel
* @author Troefkaart
* @author Tvdm
+ * @author Wiki13
* @author לערי ריינהארט
*/
'qbbrowse' => 'Bladeren',
'qbedit' => 'Bewerken',
'qbpageoptions' => 'Deze pagina',
-'qbpageinfo' => 'Pagina-informatie',
'qbmyoptions' => "Mijn pagina's",
'qbspecialpages' => 'Speciale pagina’s',
'faq' => 'Veel gestelde vragen',
'edit-already-exists' => 'De pagina is niet aangemaakt.
Deze bestaat al.',
'defaultmessagetext' => 'Standaardinhoud',
+'content-failed-to-parse' => 'Het was niet mogelijk de inhoud van het MIME-type $2 voor het model $1 te verwerken: $3.',
+'invalid-content-data' => 'Ongeldige inhoudsgegevens',
+'content-not-allowed-here' => 'De inhoud "$1" is niet toegestaan op pagina [[$2]].',
# Content models
'content-model-wikitext' => 'wikitekst',
'shared-repo' => 'een gedeelde mediadatabank',
'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
'filepage.css' => "/ * De CSS die hier geplaatst wordt, wordt opgenomen in de bestandsbeschrijvingspagina en wordt ook opgenomen op externe wiki's (via externe repositories) * /",
-'upload-disallowed-here' => 'U kunt deze afbeelding helaas niet overschrijven.',
+'upload-disallowed-here' => 'U kunt dit bestand niet overschrijven.',
# File reversion
'filerevert' => '$1 terugdraaien',
'undeletedrevisions' => '$1 {{PLURAL:$1|versie|versies}} teruggeplaatst',
'undeletedrevisions-files' => '{{PLURAL:$1|1 versie|$1 versies}} en {{PLURAL:$2|1 bestand|$2 bestanden}} teruggeplaatst',
'undeletedfiles' => '{{PLURAL:$1|1 bestand|$1 bestanden}} teruggeplaatst',
-'cannotundelete' => 'Het terugplaatsen is mislukt.
-Misschien heeft een andere gebruiker de pagina al teruggeplaatst.',
+'cannotundelete' => 'Het terugplaatsen is mislukt:
+$1',
'undeletedpage' => "'''$1 is teruggeplaatst'''
In het [[Special:Log/delete|verwijderingslogboek]] staan recente verwijderingen en herstelhandelingen.",
'immobile-target-namespace-iw' => 'Een interwikiverwijzing is geen geldige bestemming voor het hernoemen van een pagina.',
'immobile-source-page' => 'Deze pagina kan niet hernoemd worden.',
'immobile-target-page' => 'Het is niet mogelijk te hernoemen naar die paginanaam.',
+'bad-target-model' => 'De gewenste bestemming gebruikt een ander inhoudsmodel. Het is niet mogelijk om te zetten van $1 naar $2.',
'imagenocrossnamespace' => 'Een mediabestand kan niet naar een andere naamruimte verplaatst worden',
'nonfile-cannot-move-to-file' => 'Het is niet mogelijk te hernoemen van en naar de bestandsnaamruimte',
'imagetypemismatch' => 'De nieuwe bestandsextensie is niet gelijk aan het bestandstype',
# Info page
'pageinfo-title' => 'Informatie over "$1"',
+'pageinfo-not-current' => 'Gegegevens worden mogelijk alleen weergegeven voor de huidige versie.',
'pageinfo-header-basic' => 'Basisgegevens',
'pageinfo-header-edits' => 'Bewerkingsgeschiedenis',
'pageinfo-header-restrictions' => 'Paginabeveiliging',
* @author Guttorm Flatabø
* @author H92
* @author Harald Khan
+ * @author Jeblad
* @author Jon Harald Søby
* @author Jorunn
* @author Kaganer
'qbbrowse' => 'Bla gjennom',
'qbedit' => 'Endre',
'qbpageoptions' => 'Denne sida',
-'qbpageinfo' => 'Samanheng',
'qbmyoptions' => 'Sidene mine',
'qbspecialpages' => 'Spesialsider',
'faq' => 'OSS',
'edit-no-change' => 'Redigeringa di vart ignorert fordi det ikkje vart gjort endringar i teksten.',
'edit-already-exists' => 'Kunne ikkje opprette ny side fordi ho alt eksisterer.',
'defaultmessagetext' => 'Standard meldingstekst',
+'content-failed-to-parse' => 'Klarte ikkje å tolke innhaldet «$2» for innhaldsmodellen «$1»: $3',
+'invalid-content-data' => 'Ugyldig innhald',
+'content-not-allowed-here' => 'Innhaldsmodellen «$1» er ikkje tillaten på sida [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'WikiTekst',
+'content-model-text' => 'Rein tekst',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Åtvaring: Denne sida inneheld for mange prosesskrevande parserfunksjonar.
'upload-too-many-redirects' => 'URL-en inneheldt for mange omdirigeringar',
'upload-unknown-size' => 'Ukjend storleik',
'upload-http-error' => 'Ein HTTP-feil oppstod: $1',
+'upload-copy-upload-invalid-domain' => 'Kopiopplastingar er ikkje tilgjengelege frå dette domenet.',
# File backend
'backend-fail-stream' => 'Kunne ikkje strøyma fila «$1».',
'backend-fail-backup' => 'Kunne ikkje tryggingskopiera fila «$1».',
'backend-fail-notexists' => 'Fila $1 finst ikkje.',
+'backend-fail-hashes' => 'Kunne ikkje henta filnummer for samanlikning.',
'backend-fail-notsame' => 'Ein ikkje-identisk fil finst alt på «$1».',
'backend-fail-invalidpath' => '$1 er ikkje ein gyldig lagringsstig.',
'backend-fail-delete' => 'Kunne ikkje sletta fila «$1».',
'backend-fail-closetemp' => 'Kunne ikkje lata att mellombels fil.',
'backend-fail-read' => 'Kunne ikkje lesa fila «$1».',
'backend-fail-create' => 'Kunne ikkje oppretta fila «$1».',
+'backend-fail-maxsize' => 'Kunne ikkje skriva fila «$1» av di ho er større enn {{PLURAL:$2|éin byte|$2 byte}}.',
+'backend-fail-readonly' => "Largingsbaksystemet «$1» er for tida skriveverna. Oppgjeven grunn er: «''$2''»",
+'backend-fail-synced' => 'Fila «$1» er i ei inkonsistent stode i dei interne lagringsbaksystema',
+'backend-fail-connect' => 'Kunne ikkje kopla til filbaksystemet «$1».',
+'backend-fail-internal' => 'Ein ukjend feil oppstod i lagringsbaksystemet «$1».',
+
+# File journal errors
+'filejournal-fail-dbconnect' => 'Kunne ikkje kopla til journaldatabasen for lagringsbaksystemet «$1».',
+'filejournal-fail-dbquery' => 'Kunne ikkje oppdatera journaldatabasen for lagringsbaksystemet «$1».',
# Lock manager
+'lockmanager-notlocked' => 'Kunne ikkje låsa opp «$1» av di han ikkje er låst',
+'lockmanager-fail-closelock' => 'Kunne ikkje lata att låsefila for «$1».',
+'lockmanager-fail-deletelock' => 'Kunne ikkje sletta låsefila for «$1».',
+'lockmanager-fail-acquirelock' => 'Kunne ikkje henta lås for «$1».',
+'lockmanager-fail-openlock' => 'Kunne ikkje opna låsefila for «$1».',
'lockmanager-fail-releaselock' => 'Kunne ikkje løysa låsen for «$1».',
+'lockmanager-fail-db-bucket' => 'Kunne ikkje kontakta nok låsedatabasar i bytta $1.',
+'lockmanager-fail-db-release' => 'Kunne ikkje løysa låsane på databasen $1.',
+'lockmanager-fail-svr-acquire' => 'Kunne ikkje henta låsane på tenaren $1.',
+'lockmanager-fail-svr-release' => 'Kunne ikkje løysa låsane på tenaren $1.',
# ZipDirectoryReader
'zip-wrong-format' => 'Den oppgjevne fila var ikkje ei ZIP-fil',
'undeletedrevisions' => '{{PLURAL:$1|Éin versjon|$1 versjonar}} attoppretta.',
'undeletedrevisions-files' => '{{PLURAL:$1|Éin versjon|$1 versjonar}} og {{PLURAL:$2|éi fil|$2 filer}} er attoppretta',
'undeletedfiles' => '{{PLURAL:$1|Éi fil|$1 filer}} er attoppretta',
-'cannotundelete' => 'Feil ved attoppretting, andre kan allereie ha attoppretta sida.',
+'cannotundelete' => 'Attopprettinga gjekk ikkje:
+$1',
'undeletedpage' => "'''$1 er attoppretta'''
Sjå [[Special:Log/delete|sletteloggen]] for eit oversyn over sider som nyleg er sletta eller attoppretta.",
'exif-datetimeexpires' => 'Skal ikkje nyttast etter',
'exif-datetimereleased' => 'Frigjeve',
'exif-lens' => 'Objektiv',
+'exif-serialnumber' => 'Serienummeret på kameraet',
'exif-cameraownername' => 'Eigar av kameraet',
'exif-label' => 'Merkelapp',
+'exif-nickname' => 'Det uformelle namnet på biletet',
'exif-rating' => 'Vurdering (av 5)',
'exif-copyrighted' => 'Opphavsrettsstode',
'exif-copyrightowner' => 'Opphavsrettseigar',
'exif-usageterms' => 'Bruksvilkår',
+'exif-licenseurl' => 'URL for opphavsrettsløyve',
+'exif-morepermissionsurl' => 'Alternativ løyveinformasjon',
+'exif-attributionurl' => 'Når dette verket vert nytta, lenkja til',
+'exif-preferredattributionname' => 'Når dette verket vert nytta, godskriv',
'exif-pngfilecomment' => 'PNG-filkommentar',
'exif-disclaimer' => 'Atterhald',
'exif-contentwarning' => 'Innholdsåtvaring',
'exif-gpsdop-excellent' => 'Utmerkt ($1)',
'exif-gpsdop-good' => 'God ($1)',
'exif-gpsdop-moderate' => 'Moderat ($1)',
+'exif-gpsdop-fair' => 'Medels ($1)',
'exif-gpsdop-poor' => 'Dårleg ($1)',
'exif-objectcycle-a' => 'Berre morgon',
$5
+Denne stadfestingskoden vert forelda $4.',
+'confirmemail_body_changed' => 'Nokon, truleg deg, frå IP-adressa $1, har endra e-postadressa til kontoen «$2» på {{SITENAME}} til denne e-postadressa.
+
+For å stadfesta at denne kontoen faktisk høyrer til deg, og for å slå på
+funksjonar knytte til e-post på {{SITENAME}}, opna denne lenkja i nettlesaren din:
+
+$3
+
+Om brukarkontoen *ikkje* høyrer til deg, fylg denne lenkja for å bryta av stadfestinga av e-postadressa:
+
+$5
+
+Denne stadfestingskoden vert forelda $4.',
+'confirmemail_body_set' => 'Nokon, truleg deg, frå IP-adressa $1, har sett e-postadressa til kontoen «$2» på {{SITENAME}} til denne e-postadressa.
+
+For å stadfesta at denne kontoen faktisk høyrer til deg, og for å slå på
+funksjonar knytte til e-post på {{SITENAME}}, opna denne lenkja i nettlesaren din:
+
+$3
+
+Om brukarkontoen *ikkje* høyrer til deg, fylg denne lenkja for å bryta av stadfestinga av e-postadressa:
+
+$5
+
Denne stadfestingskoden vert forelda $4.',
'confirmemail_invalidated' => 'Stadfestinga av e-postadresse er avbrote',
'invalidateemail' => 'Avbryt stadfestinga av e-postadressa',
# Scary transclusion
'scarytranscludedisabled' => '[Interwiki-tilkopling er slått av]',
'scarytranscludefailed' => '[Henting av mal for $1 gjekk ikkje]',
+'scarytranscludefailed-httpstatus' => '[Henting av mal for $1 gjekk ikkje: HTTP $2]',
'scarytranscludetoolong' => '[URL-en er for lang]',
# Delete conflict
'qbbrowse' => 'Far desfilar',
'qbedit' => 'Modificar',
'qbpageoptions' => 'Opcions de la pagina',
-'qbpageinfo' => 'Pagina d’entresenhas',
'qbmyoptions' => 'Mas opcions',
'qbspecialpages' => 'Paginas especialas',
'faq' => 'FAQ',
'qbbrowse' => 'ଖୋଜିବା',
'qbedit' => 'ଏହାକୁ ବଦଳାନ୍ତୁ',
'qbpageoptions' => 'ଏହି ପୃଷ୍ଠାଟି',
-'qbpageinfo' => 'ଭିତର ଚିଜ',
'qbmyoptions' => 'ମୋ ପୃଷ୍ଠାଗୁଡ଼ିକ',
'qbspecialpages' => 'ବିଶେଷ ପୃଷ୍ଠା',
'faq' => 'ବାରମ୍ବାର ପଚରାଯାଉଥିବା ପ୍ରଶ୍ନ',
ଏହା ଅଗରୁ ଅଛି ।',
'defaultmessagetext' => 'ଡିଫଲ୍ଟ ମେସେଜ ଲେଖାଗୁଡିକ',
+# Content models
+'content-model-wikitext' => 'ଉଇକିଟେକ୍ସଟ',
+
# Parser/template warnings
'expensive-parserfunction-warning' => "'''ଚେତାବନୀ:''' ଏହି ପୃଷ୍ଠାରେ ଅନେକ ଗୁଡ଼ିଏ ମୂଲ୍ୟବାନ ପାର୍ସର ଫଙ୍କସନ କଲ ଅଛି ।
# Info page
'pageinfo-title' => '"$1"ର ବିବରଣୀ',
+'pageinfo-header-basic' => 'ସାଧାରଣ ଜାଣିବା କଥା',
'pageinfo-header-edits' => 'ବଦଳସବୁ',
'pageinfo-article-id' => 'ପୃଷ୍ଠା ଆଇଡ଼ି',
'pageinfo-views' => 'ଦେଖଣା ସଂଖ୍ୟା',
'pageinfo-watchers' => 'ଦେଖଣାହାରି ସଂଖ୍ୟା',
-'pageinfo-edits' => 'ସମ୍ପାଦନା ସଂଖ୍ୟା:',
+'pageinfo-edits' => 'ସମ୍ପାଦନା ସଂଖ୍ୟା',
'pageinfo-authors' => 'ନିଆରା ଲେଖକଙ୍କ ସଂଖ୍ୟା',
# Patrolling
'file-info-size-pages' => '$1 × $2 ପିକ୍ସେଲ, ଫାଇଲ ଆକାର: $3, MIME ପ୍ରକାର: $4, $5 ଗୋଟି {{PLURAL:$5|ପୃଷ୍ଠା|ପୃଷ୍ଠା}}',
'file-nohires' => 'ବଡ଼ ରେଜୋଲୁସନ ନାହିଁ ।',
'svg-long-desc' => 'SVG ଫାଇଲ, ସାଧାରଣ ମାପ $1 × $2 ପିକ୍ସେଲ, ଫାଇଲ ଆକାର: $3',
+'svg-long-desc-animated' => 'Animated SVG ଫାଇଲ, ସାଧାରଣ ମାପ $1 × $2 ପିକ୍ସେଲ, ଫାଇଲ ଆକାର: $3',
'show-big-image' => 'ପୁରା ବଡ଼ ଆକାରରେ',
'show-big-image-preview' => 'ଏହି ଦେଖଣାର ଆକାର: $1 ।',
'show-big-image-other' => 'ବାକି {{PLURAL:$2|ରେଜୋଲୁସନ|ରେଜୋଲୁସନ}}: $1.',
# Search suggestions
'searchsuggest-search' => 'ଖୋଜିବା',
+'searchsuggest-containing' => 'ଧାରଣ ହେଉଛି...',
# API errors
'api-error-badaccess-groups' => 'ଆପଣଙ୍କୁ ଏହି ଉଇକିରେ ଅପଲୋଡ଼ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇନାହିଁ ।',
'qbbrowse' => 'Фен',
'qbedit' => 'Ивын',
'qbpageoptions' => 'Ацы фарс',
-'qbpageinfo' => 'Фарсы контекст',
'qbmyoptions' => 'Мæ фæрстæ',
'qbspecialpages' => 'Сæрмагонд фæрстæ',
'faq' => 'FAQ',
'projectpage' => 'Проекты фарс фен',
'imagepage' => 'Файлы фарс фен',
'mediawikipage' => 'Фыстæджы фарс фен',
-'templatepage' => 'ШаблонÑ\8b Ñ\84аÑ\80Ñ\81 Ñ\84ен',
+'templatepage' => 'Ð¥Ñ\83Ñ\8bзæджÑ\8b Ñ\84аÑ\80Ñ\81 Ñ\84енÑ\8bн',
'viewhelppage' => 'Æххуысы фарс фен',
'categorypage' => 'Категорийы фарс фен',
'viewtalkpage' => 'Тæрхон фен',
'nstab-project' => 'Проекты тыххæй',
'nstab-image' => 'Файл',
'nstab-mediawiki' => 'Фыстæг',
-'nstab-template' => 'Шаблон',
+'nstab-template' => 'Ð¥Ñ\83Ñ\8bзæг',
'nstab-help' => 'Æххуысы фарс',
'nstab-category' => 'Категори',
'editconflict' => 'Ивыны конфликт: $1',
'yourtext' => 'Дæ текст',
'yourdiff' => 'Хицæндзинæдтæ',
-'templatesused' => 'Ð\90Ñ\86Ñ\8b Ñ\84аÑ\80Ñ\81Ñ\8b иÑ\81 {{PLURAL:$1|Ñ\88аблон|Ñ\88аблоны}}:',
+'templatesused' => 'Ð\90Ñ\86Ñ\8b Ñ\84аÑ\80Ñ\81Ñ\8b иÑ\81 {{PLURAL:$1|Ñ\85Ñ\83Ñ\8bзæг|Ñ\85Ñ\83Ñ\8bзæджы}}:',
'template-protected' => '(æхгæд)',
'template-semiprotected' => '(æрдæг-æхгæд)',
'hiddencategories' => 'Ацы фарс у {{PLURAL:$1|1 æмбæхст категорийы|$1 æмбæхст категориты}} уæнг:',
'edit-already-exists' => 'Ног фарс скæнæн нæй. Ахæм фарс ис.',
# Parser/template warnings
-'post-expand-template-inclusion-warning' => "'''СÑ\8bндæг: ''' Шаблоны бавæрд бæрц æгæр стыр у.
-Ð\9aæÑ\86Ñ\8bдæÑ\80 Ñ\88аблонтæ нæ бавæд уыдзысты.",
-'post-expand-template-inclusion-category' => 'ФæÑ\80Ñ\81Ñ\82æ, кæм Ñ\88аблоны бавæрд бæрц æгæр бирæ у',
-'post-expand-template-argument-warning' => "'''СÑ\8bндæг:''' Ð\90Ñ\86Ñ\8b Ñ\84аÑ\80Ñ\81Ñ\8b иÑ\81 Ñ\83æддæÑ\80 иÑ\83 Ñ\88аблоны аргумент, кæй райтынг у æгæр стыр.
+'post-expand-template-inclusion-warning' => "'''СÑ\8bндæг: ''' Ð¥Ñ\83Ñ\8bзæджы бавæрд бæрц æгæр стыр у.
+Ð\9aæÑ\86Ñ\8bдæÑ\80 Ñ\85Ñ\83Ñ\8bзæгтæ нæ бавæд уыдзысты.",
+'post-expand-template-inclusion-category' => 'ФæÑ\80Ñ\81Ñ\82æ, кæм Ñ\85Ñ\83Ñ\8bзæджы бавæрд бæрц æгæр бирæ у',
+'post-expand-template-argument-warning' => "'''СÑ\8bндæг:''' Ð\90Ñ\86Ñ\8b Ñ\84аÑ\80Ñ\81Ñ\8b иÑ\81 Ñ\83æддæÑ\80 иÑ\83 Ñ\85Ñ\83Ñ\8bзæджы аргумент, кæй райтынг у æгæр стыр.
Уыцы аргументтæ уагъд æрцыдысты.",
-'post-expand-template-argument-category' => 'ФæÑ\80Ñ\81Ñ\82æ, кæдонÑ\8b иÑ\81 Ñ\88аблоны уагъд аргумент',
+'post-expand-template-argument-category' => 'ФæÑ\80Ñ\81Ñ\82æ, кæдонÑ\8b иÑ\81 Ñ\85Ñ\83Ñ\8bзæджы уагъд аргумент',
# History pages
'viewpagelogs' => 'Ацы фарсæн йæ логтæ равдисын',
'download' => 'æрбавгæн',
# Unused templates
-'unusedtemplates' => 'Ð\9fайда кæмæй нæ Ñ\87Ñ\8bндæÑ\83Ñ\8b, аÑ\85æм Ñ\88аблонтæ',
+'unusedtemplates' => 'Ð\9fайда кæмæй нæ Ñ\87Ñ\8bндæÑ\83Ñ\8b, аÑ\85æм Ñ\85Ñ\83Ñ\8bзæгтæ',
# Random page
'randompage' => 'Халæй ист фарс',
'lonelypages' => 'Сидзæр фæрстæ',
'uncategorizedpages' => 'Æнæкатегори фæрстæ',
'uncategorizedimages' => 'Æнæкатегори файлтæ',
-'uncategorizedtemplates' => 'Ã\86нæкаÑ\82егоÑ\80и Ñ\88аблонтæ',
+'uncategorizedtemplates' => 'Ã\86нæкаÑ\82егоÑ\80и Ñ\85Ñ\83Ñ\8bзæгтæ',
'popularpages' => 'Популярон фæрстæ',
'wantedcategories' => 'Хъæугæ категоритæ',
'wantedpages' => 'Хъæугæ фæрстæ',
'tooltip-ca-nstab-special' => 'Ай сæрмагонд фарс у, дæ бон æй нæу ивын',
'tooltip-ca-nstab-project' => 'Фенын проекты фарс',
'tooltip-ca-nstab-image' => 'Нывы фарс',
-'tooltip-ca-nstab-template' => 'ФенÑ\8bн Ñ\88аблон',
+'tooltip-ca-nstab-template' => 'Ð¥Ñ\83Ñ\8bзæг Ñ\84енÑ\8bн',
'tooltip-ca-nstab-category' => 'Категорийы фарс',
'tooltip-minoredit' => 'Чысыл ивдæй йæ банысан кæнын',
'tooltip-save' => 'Бавæр дæ ивдтытæ',
'qbbrowse' => 'Bation (browse)',
'qbedit' => 'Mag-edit',
'qbpageoptions' => 'Ining bulung',
-'qbpageinfo' => 'Kontekstu/kabilian',
'qbmyoptions' => 'Deng kakung bulung',
'qbspecialpages' => 'Bulung a makabukud',
'faq' => 'Maralas a Kukutang (MAK)',
'tog-editsectiononrightclick' => "Pérmet l'édichion del sekchion par un droé buke su ch'tite del sekchion (i feut JavaScript)",
'tog-showtoc' => "Aficher l'tabe ed ches étnus (pou ches paches aveuc plu ed 3 intétes)",
'tog-rememberpassword' => "Warder min lodjine su chl'ordinateu-lo (pour un maximum éd $1 {{PLURAL:$1|jour|jours}})",
-'tog-watchcreations' => "Ajouter chés paches qu'éj crée dseu em lisse",
-'tog-watchdefault' => "Ajouter chés paches qu'éj édite dseu em lisse.",
-'tog-watchmoves' => "Ajouter chés paches qu'éj déplache dseu m'lisse.",
-'tog-watchdeletion' => "Ajouter chés paches qu'éj déface dseur m'lisse.",
+'tog-watchcreations' => "Ajouter chés paches qu'éj crée et pi chés fichiés qu'éj téléquertche édseur em lisse à suire",
+'tog-watchdefault' => "Ajouter chés paches pi chés fichiés qu'éj cange édseur em lisse à suire.",
+'tog-watchmoves' => "Ajouter chés paches pi chés fichiés qu'éj déplache édseur m'lisse à suire.",
+'tog-watchdeletion' => "Ajouter chés paches pi chés fichiés qu'éj déface édseur m'lisse à suire.",
'tog-previewontop' => "Aficher l'prévue édvint el bouéte édite",
'tog-previewonfirst' => "Aficher l'prévue au preumié édite.",
-'tog-enotifwatchlistpages' => "Éspédier din m'boéte un imèle quante eune pache su m'lisse est candgée",
+'tog-enotifwatchlistpages' => "M'éspédier un imèle quante eune pache su m'lisse à suire est cangée",
'tog-enotifusertalkpages' => 'Éspédier un imèle su em bouéte quante m\'pache "Dvise Uzeu" est candgée.',
-'tog-enotifminoredits' => 'Éspédier à mi étous un imèle pou ches tiots édites éd ches paches',
+'tog-enotifminoredits' => "M'éspédier étou un imèle pou chés tiots canjemints d'chés paches o d'chés fichiés",
'tog-shownumberswatching' => "Aficher ch'nombe ed gins qu'ont vu.",
'tog-watchlisthideown' => 'Muche mes édites dseur el lisse',
'tog-watchlisthidebots' => 'Muche ches robots édites su el lisse',
'qbbrowse' => 'Trifouille',
'qbedit' => 'Editer',
'qbpageoptions' => 'Chol pache-lo',
-'qbpageinfo' => 'Conteske',
'qbmyoptions' => 'Mes paches',
'qbspecialpages' => 'Espéciales paches',
'faq' => 'FAQ',
'vector-action-protect' => 'Garantir',
'vector-action-undelete' => "N'poin défacher",
'vector-action-unprotect' => "Canger l'garantie",
-'vector-simplesearch-preference' => "Déhousser chés avanches d'ércherche améliorées (seulemint pour Vector)",
+'vector-simplesearch-preference' => "Actionner l'barette pour chés traches simpes (seulemint pour l'habillure Vector)",
'vector-view-create' => 'Créer',
'vector-view-edit' => 'Éditer',
'vector-view-history' => "Vir l'histoère",
'hiddencategories' => '{{PLURAL:$1|Catégorie muchée|Catégories muchées}} pou chol pache:',
'permissionserrorstext-withaction' => "Vos n’avez poin l'pérmichon éd $2, pou {{PLURAL:$1|ch'motif suivant|chés motifs suivants}}:",
+# Parser/template warnings
+'post-expand-template-inclusion-warning' => "Affute : Chèle pache ale a trop d’modèles. Des inclusions n'sront poin foaites.",
+'post-expand-template-inclusion-category' => "Paches aveuc granmint d'modèles",
+
# History pages
'viewpagelogs' => 'Vir chés gasètes del pache-lo',
'currentrev-asof' => 'Coursaule vérchon in date du $1',
'revisionasof' => 'Ércordé conme $1',
+'revision-info' => 'Version du $1 pèr $2',
'previousrevision' => '← érvue dvant',
'nextrevision' => 'Cangemint pu nouvieu →',
'currentrevisionlink' => 'Érvision éd qhére',
# Revision deletion
'rev-delundel' => 'montrer/mucher',
'revdel-restore' => 'cange écmint vir',
+'revdel-restore-deleted' => 'canjemints abolis',
+'revdel-restore-visible' => 'canjemints visibes',
'pagehist' => 'Histoère del pache',
# Merge log
'nextn' => 'apreu {{PLURAL:$1|$1}}',
'prevn-title' => 'Dvant $1 {{PLURAL:$1|résultat|résultats}}',
'viewprevnext' => 'Vir ($1 {{int:pipe-separator}} $2) ($3)',
+'searchmenu-new' => "'''Créer l'pache « [[:$1|$1]] » édseur ech wiki !'''",
+'searchprofile-articles' => "Paches d'étnu",
+'searchprofile-project' => "Paches d’aïude et pi d'prodjé",
+'searchprofile-images' => 'Multimédia',
+'searchprofile-everything' => 'Tout',
+'searchprofile-advanced' => 'Értrache avanchée',
+'searchprofile-articles-tooltip' => 'tracher dins $1',
+'searchprofile-project-tooltip' => 'Tracher dins $1',
+'searchprofile-images-tooltip' => 'Tracher des fichiés multimédias',
+'searchprofile-everything-tooltip' => "Tracher dins tout ch'wikipédia (et ochi dins chés paches éd distchucion)",
+'searchprofile-advanced-tooltip' => "Couésir chés éspaches d'noms pour l'értrache",
'search-result-size' => '$1 ({{PLURAL:$2|1 mot|$2 mots}})',
'search-redirect' => '(érdirection $1)',
'search-section' => '(sekchon $1)',
'search-interwiki-caption' => 'Proujé analocq',
'search-interwiki-default' => '$1 résultats:',
'search-interwiki-more' => '(pus)',
+'searchall' => 'tout',
'nonefound' => "'''Note''': il y o tasseulemint quéques éspaces éd noms éq sont trachés pèr défeut. <br /> Pou tracher din tous chés contnus (paches éd pérlache, modéles, etc... comprins) insséyer in imploéyant ch'préfixe ''all:'' o bin imploéyer echl éspace éd noms édmindé conme préfixe.",
+'search-nonefound' => 'Y a autchun résultat pour chol dmanne.',
'powersearch' => 'Érvue avanchée',
'powersearch-legend' => 'Érvue avanchée',
'powersearch-ns' => 'Tracher din chés éspaches éd chés noms:',
# Associated actions - in the sentence "You do not have permission to X"
'action-read' => "Vir l'pache-lo",
'action-edit' => "édite l'pache-lo",
+'action-createpage' => 'créer des paches',
+'action-createtalk' => 'créer des paches éd dichtchussion',
+'action-createaccount' => "créer ech compte d'uzeu",
+'action-minoredit' => 'mértcher chol canjemint conme mineur',
+'action-move' => "érlonmer l'pache-lo",
+'action-move-subpages' => 'érlonmer chol pache et pi ses dsous-paches',
+'action-move-rootuserpages' => "érlonmer l' pache princhipale d’un uzeu",
+'action-movefile' => "érlonmer ch'fichié-lo",
+'action-upload' => 'téléquértcher ech fichié',
+'action-reupload' => "écatir l'anchien fichié",
+'action-upload_by_url' => "téléquértcher ch' fichié à partir d’eune URL",
+'action-writeapi' => "foaire aveuc l'écrivure API",
+'action-delete' => "Défacer l'pache-lo",
+'action-deleterevision' => "défacer ch'canjemint-lo",
+'action-deletedhistory' => 'vir l’histoère muchée éd chol pache',
+'action-browsearchive' => 'tracher des paches défacées',
+'action-undelete' => "n'poin défacer chol pache",
+'action-suppressrevision' => 'vir pi érfoaire chol version muchée',
+'action-suppressionlog' => 'vir ech jornal privé',
+'action-block' => "blotcher l'écrivure éd chol uzeu-lo",
+'action-import' => 'téléquértcher chol pache à partir d’un eute wiki',
+'action-importupload' => "téléquértcher chol pache à partir d'un fichié",
# Recent changes
'nchanges' => '$1 {{PLURAL:$1|cange|canges}}',
'uploadedimage' => '"[[$1]]" quértchée',
# File description page
+'file-anchor-link' => 'Fichié',
'filehist' => 'Histoère dech fichié',
'filehist-help' => "Buke su eune date/heure pou vir ch'fichié conme il étoait ach momint-lo.",
+'filehist-revert' => 'invérser',
'filehist-current' => 'courant',
'filehist-datetime' => 'Date/Tans',
'filehist-thumb' => 'Tiote image',
'filehist-user' => 'Uzeu',
'filehist-dimensions' => 'Diminsions',
'filehist-comment' => 'Fichié éd chés conmints',
-'imagelinks' => 'Loïens dech fichié',
+'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 :",
'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]).",
'uploadnewversion-linktext' => 'Quértcher eune novèle vérchion del pache-lo',
# Random page
'nbytes' => '$1 {{PLURAL:$1|octé|octés}}',
'nmembers' => '$1 {{PLURAL:$1|mimbe|mimbes}}',
'prefixindex' => 'Tertous chés paches aveuc préfix',
+'usercreated' => '{{GENDER:$3|Créé}} ech $1 à $2',
'newpages' => 'Novèles paches',
'move' => 'Déplacher',
'movethispage' => "Déplacher l'pache-lo",
# Watchlist
'watchlist' => 'Em lisse à suire',
'mywatchlist' => "M'lisse à suire",
+'watchlistfor2' => 'Pour $1 $2',
'addedwatchtext' => "L' pache « [[:$1]] » o té rajoutée à vote [[Special:Watchlist|lisse à suire]].<br /> Chés canjemints à vnir del pache-lo pi del page éd pérlache sront mis din l'lisse. L'pache sro '''in cros''' din el [[Special:RecentChanges|lisse d'chés darins canjemints]] pou les értreuver fachilmint. Pou értirer chol pache del ''lisse à suire'', bukez su « {{MediaWiki:Unwatch}} ».",
'removedwatchtext' => "L'pache « [[:$1]] » o té értirée éd vote [[Special:Watchlist|lisse à suire]].",
'watch' => 'Suire',
# Undelete
'undeletelink' => 'vir/érfoaire',
+'undeleteviewlink' => 'Vir',
# Namespace form on various pages
'namespace' => 'Éspace du nom:',
'sp-contributions-newbies' => 'Montrer chés contérbuchons éd chés nouvieus conptes seulemint',
'sp-contributions-blocklog' => 'jornal éd chés blotcåjhes',
+'sp-contributions-logs' => 'Gasètes',
+'sp-contributions-talk' => 'Dviser',
'sp-contributions-search' => 'Tracher pou chés contérbuchons',
'sp-contributions-username' => "Adérche IP ou nom d'uzeu",
'sp-contributions-toponly' => "n'montrer qu'chés darins canjemints",
# Export
'export' => 'Ésporter chés paches',
+# Namespace 8 related
+'allmessagesname' => 'Nom',
+
# Thumbnails
'thumbnail-more' => 'Pu grand',
'tooltip-rollback' => '« Racacher » cancéle aveuc un clic el (ou chés) modificachon(s) del pache-lo pèr sin darin contérbucheu.',
'tooltip-undo' => "« Undo » ( ''démangler'' ) értire ch'canjemint-lo pi ouvre l' fénéte d'édichon din ch'mode ''prévir''. <br /> In put mette un motif din ch'résumé.",
'tooltip-preferences-save' => 'Warder chés préférinches.',
+'tooltip-summary' => 'Intrer un tiot résumè',
# Browsing diffs
'previousdiff' => '← Pu vieille édition',
'underline-default' => 'Des nemme, was em Broweser gsaacht hoscht.',
# Dates
+'sunday' => 'Sundaach',
+'monday' => 'Mondaach',
+'tuesday' => 'Dienschdaach',
+'wednesday' => 'Midwoch',
+'thursday' => 'Dunnaschdaach',
+'friday' => 'Fraidaach',
+'saturday' => 'Somschdaach',
'january' => 'Jänner',
'february' => 'Fewwer',
'march' => 'März',
'qbmyoptions' => 'Mai Saide',
# Vector skin
+'vector-action-delete' => 'Lesche',
'vector-action-move' => 'Verschiewe',
+'vector-action-protect' => 'Schitze',
'vector-view-edit' => 'Bearwaide',
+'vector-view-view' => 'Lese',
+'actions' => 'Agzione',
'errorpagetitle' => 'Fehler',
'returnto' => 'Zrick zu $1.',
De Leschaidrach fa die Said isch do unne als Kwell aagewwe.',
# History pages
-'viewpagelogs' => 'D Lochbiecher fer die Said aagucke',
+'viewpagelogs' => 'Lochbicher fer die Said aagucke',
'currentrev-asof' => 'Aktuelle Version vun $1',
'revisionasof' => 'Version vun $1',
'previousrevision' => '← Ältere Versione',
'rclinks' => 'Zeich die letschte $1 Ännerunge in de letschte $2 Dache<br />$3',
'diff' => 'Unnerschied',
'hist' => 'Gschicht',
-'hide' => 'versteggeln',
-'show' => 'zaiche',
+'hide' => 'vaschdeggle',
+'show' => 'zaische',
'minoreditletter' => 'k',
'newpageletter' => 'N',
'boteditletter' => 'B',
'file-anchor-link' => 'Datei',
'filehist' => 'Dateigschicht',
'filehist-help' => 'Drick uff e Zaidpunkt zum aazääche, wie s dort ausgsähne hot.',
+'filehist-revert' => 'zuriggsedze',
'filehist-current' => 'aktuell',
'filehist-datetime' => 'Zaidpunkt',
'filehist-thumb' => 'Vorschaubild',
'filehist-user' => 'Benutzer',
'filehist-dimensions' => 'Moß',
'filehist-comment' => 'Kommentar',
-'imagelinks' => 'Dateilinks',
+'imagelinks' => 'Dadaivawendung',
'linkstoimage' => 'Die {{PLURAL:$1|Said verwaist|$1 Saire verwaise}} uff die Datei:',
'sharedupload' => 'Die Datei isch vun $1 un s kann sai, dass se ach vun annere Projekt gebraucht werd.',
'uploadnewversion-linktext' => 'E naiere Version vun derre Datei hochlade',
'pager-older-n' => '{{PLURAL:$1|vorich 1|voriche $1}}',
# Book sources
-'booksources' => 'Buchquelle',
+'booksources' => 'Buchqwelle',
'booksources-search-legend' => 'No Buchquelle suche',
'booksources-go' => 'Geh',
# Special:Log
-'log' => 'Logbiecher',
+'log' => 'Logbicher',
# Special:AllPages
'allpages' => 'Alle Saide',
'linkshere' => "Die Saide verlinke zu '''[[:$1]]''':",
'isredirect' => 'Wairerlaitungsaid',
'istemplate' => 'Vorlacheaibindung',
-'isimage' => 'Bildlink',
+'isimage' => "Dadailing'g",
'whatlinkshere-prev' => '{{PLURAL:$1|vorich|voriche $1}}',
'whatlinkshere-next' => '{{PLURAL:$1|negscht|negschte $1}}',
'whatlinkshere-links' => '← Links',
'ipbsubmit' => 'Benutzer bloggiere',
'ipboptions' => '2 Stunne:2 hours,1 Dach:1 day,3 Dache:3 days,1 Woch:1 week,2 Woche:2 weeks,1 Monet:1 month,3 Monet:3 months,6 Monet:6 months,1 Johr:1 year,Fer immer:infinite',
'ipusubmit' => 'Die Adreß freigewwe',
-'ipblocklist' => 'Gsperrte IP-Adresse un Benutzername',
+'ipblocklist' => 'Gschberrdi IP-Adress un Benudzernome',
'blocklink' => 'sperre',
-'unblocklink' => 'Sperr uffhewwe',
+'unblocklink' => 'Sperr uffhewe',
'change-blocklink' => 'Sperr ännere',
'contribslink' => 'Baidräch',
'blocklogpage' => 'Sperrlogbuch',
'tooltip-p-logo' => 'Haubdsaid',
'tooltip-n-mainpage' => 'Uff d Hääptsaid geh',
'tooltip-n-mainpage-description' => 'Haubdsaid aagucke',
-'tooltip-n-portal' => 'Iwwer s Projekt, was de duu kannscht, wo de ebbes finnscht',
+'tooltip-n-portal' => 'Iwwers Brojegd, wude duu kannschd, wu ebbes finne duschd',
'tooltip-n-currentevents' => 'hinnergundsinformatione finne iwwer naie Eraichnis',
'tooltip-n-recentchanges' => 'D Lischt vun de letschte Ännerunge in dem Wiki',
'tooltip-n-randompage' => 'E zufälliche Said lade',
'tooltip-n-help' => 'De Ort zum rausfinne',
-'tooltip-t-whatlinkshere' => 'Lischt vun alle Wikisaide, wo do her verlinkt sin',
+'tooltip-t-whatlinkshere' => 'Lischt vun alle Wikisaide, wu do her verlinkt sinn',
'tooltip-t-recentchangeslinked' => 'Letschte Ännerunge in Saide, wu vun do verlinkt sin',
'tooltip-feed-rss' => 'RSS feed fer die Said',
'tooltip-feed-atom' => 'Atom feed fer die Said',
'tooltip-t-contributions' => 'Die letschte Baidräch vun däm Benutzer aagucke',
'tooltip-t-emailuser' => 'Dem Benutzer e E-Mail schicke',
-'tooltip-t-upload' => 'Dateie nuflade',
+'tooltip-t-upload' => 'Dateije nufflade',
'tooltip-t-specialpages' => 'Lischt vun alle Spezialsaide',
'tooltip-t-print' => 'Druckversion vun derre Said',
'tooltip-t-permalink' => 'E dauerhafte Link zu derre Version vun de Said',
'tooltip-diff' => 'Guck, welle Ännerunge Du im Text gmacht hoscht',
'tooltip-compareselectedversions' => 'D Unnerschied zwische denne zwai ausgwehlte Versione aagucke',
'tooltip-watch' => 'Die Said zu Dainer Beowachdunglischd zufieche',
-'tooltip-rollback' => '„Zericksetze“ maxcht alle Bearwaidunge vum letschte Bearwaider rickgängich',
+'tooltip-rollback' => '„Zericksetze“ machd alle Bearwaidunge vum letschte Bearwaider rickgängich',
'tooltip-undo' => '„Zerick“ macht numme die Ännerung rickgängich un zaicht d Vorschau aa.
Du kannscht e Grund in dr Zammfassung aagewwe',
Wenn die Datei verännert worre isch, dann kann s sai, dass die zusätzlich Information fer die verännert Datei nimmi richtich isch.',
'metadata-expand' => 'Erwaiterte Details aazaiche',
'metadata-collapse' => 'Erwaiterte Details versteckeln',
-'metadata-fields' => 'Die EXIF-Metadate werre in de Bild-Bschraiwung ach aagezeicht, wenn d Metadate-Tabelle versteckelt isch.
-Annere Metadate sinn standardmäßig versteckelt.
+'metadata-fields' => 'Die EXIF-Medadaade werren inde Bild-Bschraiwung a ogzaischd, wonn die Medadaade-Tabelle verschdegld isch.
+Annere Medadaade sinn noamalawais verschdegld.
* make
* model
* datetimeoriginal
'qbbrowse' => 'Przeglądanie',
'qbedit' => 'Edycja',
'qbpageoptions' => 'Ta strona',
-'qbpageinfo' => 'Kontekst',
'qbmyoptions' => 'Moje strony',
'qbspecialpages' => 'strony specjalne',
'faq' => 'FAQ',
'qbbrowse' => 'Sfeuja',
'qbedit' => 'Modìfica',
'qbpageoptions' => 'Opsion dla pàgina',
-'qbpageinfo' => 'Anformassion rësguard a la pàgina',
'qbmyoptions' => 'Mie opsion',
'qbspecialpages' => 'Pàgine speciaj',
'faq' => 'Chestion frequente',
'edit-already-exists' => 'As peul nen creesse la pàgina.
A esist già.',
'defaultmessagetext' => "Test che a-i sarìa se a-i fusso pa 'd modìfiche",
+'content-failed-to-parse' => "Faliment ëd l'anàlisi dël contnù ëd $2 për ël model $1: $3",
+'invalid-content-data' => 'Dat dël contnù pa bon',
+'content-not-allowed-here' => "Ël contnù «$1» a l'é nen autorisà an sla pàgina [[$2]]",
+
+# Content models
+'content-model-wikitext' => 'test wiki',
+'content-model-text' => 'mach test',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => "'''Atension:''' Costa pàgina a l'ha tròpe ciamà costose a le fonsions ëd parser.
'undeletedrevisions' => '{{PLURAL:$1|Na revision pijàita|$1 revision pijàite}} andré',
'undeletedrevisions-files' => "{{PLURAL:$1|Na|$1}} revision e {{PLURAL:$2|n'|$2 }}archivi pijàit andré",
'undeletedfiles' => "{{PLURAL:$1|N'|$1 }}archivi pijàit andaré",
-'cannotundelete' => "Riprìstin falì; a peul esse che i fusse antra doi a felo ant l'istess temp e l'àutr a sia riva prima.",
+'cannotundelete' => 'Riprìstin falì:
+$1',
'undeletedpage' => "'''$1 a l'é stàit pijait andaré'''
Che as varda ël [[Special:Log/delete|Registr djë scancelament]] për ës-ciairé j'ùltim scancelament e arcuperassion.",
'immobile-target-namespace-iw' => "Na liura interwiki a l'é pa na destinassion vàlida për tramudé na pàgina.",
'immobile-source-page' => 'Sta pàgina-sì as peul pa tramudesse.',
'immobile-target-page' => 'As peul pa tramudesse vers cost tìtol ëd destinassion.',
+'bad-target-model' => 'La destinassion vorsùa a deuvra un model ëd contnù diferent. As peul pa convertisse da $1 a $2.',
'imagenocrossnamespace' => "As peul pa tramudesse n'archivi a në spassi nominal diferent",
'nonfile-cannot-move-to-file' => "As peul nen tramudesse lòn ch'a l'é pa n'archivi a lë spassi nominal dj'archivi",
'imagetypemismatch' => "La neuva estension ëd l'archivi a corispond pa a sò tipo",
'exif-orientation-1' => 'Normal',
'exif-orientation-2' => 'A specc',
'exif-orientation-3' => 'Arvirà ëd 180°',
-'exif-orientation-4' => 'Arvirà dzorsuta',
-'exif-orientation-5' => 'Arvirà dzorsota e ëd 90° contramostra',
+'exif-orientation-4' => 'Arvirà dzor-sota',
+'exif-orientation-5' => 'Arvirà dzor-sota e ëd 90° contramostra',
'exif-orientation-6' => 'Arvirà ëd 90° contramostra',
-'exif-orientation-7' => 'Arvirà dzorsota e ëd 90° ant ël sens dla mostra',
+'exif-orientation-7' => 'Arvirà dzor-sota e ëd 90° ant ël sens dla mostra',
'exif-orientation-8' => 'Arvirà ëd 90° ant ël sens dla mostra',
-'exif-planarconfiguration-1' => 'për blòch (chunky)',
+'exif-planarconfiguration-1' => 'dàit a blòch',
'exif-planarconfiguration-2' => 'an planar',
'exif-xyresolution-i' => '$1 pont për pòles (dpi)',
'exif-exposureprogram-2' => 'Programa normal',
'exif-exposureprogram-3' => 'Priorità ëd temp',
'exif-exposureprogram-4' => 'Priorità ëd diaframa',
-'exif-exposureprogram-5' => "Programa creativ (coregiù për avej pì ëd profondità 'd camp)",
-'exif-exposureprogram-6' => "Programa d'assion (coregiù për avej ël temp pì curt che as peul)",
+'exif-exposureprogram-5' => "Programa creativ (coregiù për avèj pì ëd profondità 'd camp)",
+'exif-exposureprogram-6' => "Programa d'assion (coregiù për avèj ël temp pì curt che as peul)",
'exif-exposureprogram-7' => 'Programa ritrat (për fotografìe pijaite da davsin, con lë sfond fòra feu)',
'exif-exposureprogram-8' => 'Panorama (sogèt lontan e con lë sfond a feu)',
'qbbrowse' => 'لبو',
'qbedit' => 'لکھو',
'qbpageoptions' => 'اے صفہ',
-'qbpageinfo' => 'محول',
'qbmyoptions' => 'میرے صفے',
'qbspecialpages' => 'خاص صفے',
'faq' => 'FAQ',
'qbbrowse' => 'Pradirēis',
'qbedit' => 'Redigīs',
'qbpageoptions' => 'Šin pāusan',
-'qbpageinfo' => 'Kōnteksts',
'qbmyoptions' => 'Majāi pāusai',
'qbspecialpages' => 'Speciālai pāusai',
'faq' => 'Ukadeznai prasīsenei',
'qbbrowse' => 'Navegar',
'qbedit' => 'Editar',
'qbpageoptions' => 'Esta página',
-'qbpageinfo' => 'Contexto',
'qbmyoptions' => 'Minhas páginas',
'qbspecialpages' => 'Páginas especiais',
'faq' => 'FAQ',
'qbbrowse' => 'Navegar',
'qbedit' => 'Editar',
'qbpageoptions' => 'Esta página',
-'qbpageinfo' => 'Contexto',
'qbmyoptions' => 'Minhas páginas',
'qbspecialpages' => 'Páginas especiais',
'faq' => 'FAQ',
ou [{{fullurl:{{FULLPAGENAME}}|action=edit}} criar esta página]</span>.',
'noarticletext-nopermission' => 'No momento, não há conteúdo nesta página
Você pode [[Special:Search/{{PAGENAME}}|pesquisar pelo título desta página]] em outras páginas,
-ou <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar por registros relacionados] </span>.',
+ou <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar por registros relacionados] </span>. Note que, no entanto, você não tem permissão para criar esta página.',
'missing-revision' => 'A revisão #$1 da página denominada "{{PAGENAME}}" não existe.
Isto é geralmente causado por seguir um link de histórico desatualizado para uma página que foi eliminada.
# Info page
'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-edits' => 'Table section header in action=info.',
'pageinfo-header-restrictions' => 'Table section header in action=info.',
'qbbrowse' => 'Maskapuy',
'qbedit' => "Llamk'apuy",
'qbpageoptions' => "P'anqap akllanankuna",
-'qbpageinfo' => "P'anqamanta willay",
'qbmyoptions' => 'Akllanaykuna',
'qbspecialpages' => "Sapaq p'anqakuna",
'faq' => 'Pasaq tapuykuna',
'qbbrowse' => 'Răsfoiește',
'qbedit' => 'Modificare',
'qbpageoptions' => 'Opțiuni ale paginii',
-'qbpageinfo' => 'Informații ale paginii',
'qbmyoptions' => 'Paginile mele',
'qbspecialpages' => 'Pagini speciale',
'faq' => 'Întrebări frecvente',
'uploadnewversion-linktext' => 'Încarcă o versiune nouă a acestui fișier',
'shared-repo-from' => 'de la $1',
'shared-repo' => 'un depozit partajat',
-'upload-disallowed-here' => 'Din păcate, nu puteți suprascrie această imagine.',
+'upload-disallowed-here' => 'Nu puteți suprascrie acest fișier.',
# File reversion
'filerevert' => 'Revenire $1',
# Info page
'pageinfo-title' => 'Informații pentru „$1”',
+'pageinfo-not-current' => 'Informațiile se pot afișa doar pentru versiunea curentă.',
'pageinfo-header-basic' => 'Informații de bază',
'pageinfo-header-edits' => 'Istoric modificări',
'pageinfo-header-restrictions' => 'Protecție pagină',
'qbbrowse' => 'Sfoglie',
'qbedit' => 'Cange',
'qbpageoptions' => 'Pàgene currende',
-'qbpageinfo' => 'Condeste',
'qbmyoptions' => 'Pàggene mije',
'qbspecialpages' => 'Pàggene speciale',
'faq' => 'FAQ',
* @author Sagan
* @author Shirayuki
* @author Sk
+ * @author Spider
* @author TarzanASG
* @author Temuri rajavi
* @author Vago
'qbbrowse' => 'Просмотреть',
'qbedit' => 'Править',
'qbpageoptions' => 'Настройки страницы',
-'qbpageinfo' => 'Сведения о странице',
'qbmyoptions' => 'Ваши настройки',
'qbspecialpages' => 'Специальные страницы',
'faq' => 'ЧаВО',
'vector-action-protect' => 'Защитить',
'vector-action-undelete' => 'Восстановить',
'vector-action-unprotect' => 'Изменить защиту',
-'vector-simplesearch-preference' => 'Ð\92клÑ\8eÑ\87иÑ\82Ñ\8c Ñ\80аÑ\81Ñ\88иÑ\80еннÑ\8bе поиÑ\81ковÑ\8bе подÑ\81казки (только для оформления «Векторное»)',
+'vector-simplesearch-preference' => 'Ð\92клÑ\8eÑ\87иÑ\82Ñ\8c Ñ\83пÑ\80оÑ\89Ñ\91ннÑ\83Ñ\8e Ñ\81Ñ\82Ñ\80окÑ\83 поиÑ\81ка (только для оформления «Векторное»)',
'vector-view-create' => 'Создание',
'vector-view-edit' => 'Правка',
'vector-view-history' => 'История',
'edit-already-exists' => 'Невозможно создать новую страницу.
Она уже существует.',
'defaultmessagetext' => 'Текст по умолчанию',
+'content-failed-to-parse' => 'Содержимое $2 не соответствует типу $1: $3.',
+'invalid-content-data' => 'Недопустимые данные',
+'content-not-allowed-here' => 'Содержимое "$1" недопустимо на странице [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'викитекст',
+'content-model-text' => 'обычный текст',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Внимание. Эта страница содержит слишком много вызовов ресурсоёмких функций.
'shared-repo-from' => 'из $1',
'shared-repo' => 'общего хранилища',
'shared-repo-name-wikimediacommons' => 'Викисклада',
-'upload-disallowed-here' => 'Ð\9a Ñ\81ожалениÑ\8e, вÑ\8b не можеÑ\82е пеÑ\80езапиÑ\81аÑ\82Ñ\8c Ñ\8dÑ\82о изобÑ\80ажение.',
+'upload-disallowed-here' => 'Ð\92Ñ\8b не можеÑ\82е пеÑ\80езапиÑ\81аÑ\82Ñ\8c Ñ\8dÑ\82оÑ\82 Ñ\84айл.',
# File reversion
'filerevert' => 'Возврат к старой версии $1',
'undeletedrevisions' => '$1 {{PLURAL:$1|изменение|изменения|изменений}} восстановлено',
'undeletedrevisions-files' => '$1 {{PLURAL:$1|версия|версии|версий}} и $2 {{PLURAL:$2|файл|файла|файлов}} восстановлено',
'undeletedfiles' => '$1 {{PLURAL:$1|файл восстановлен|файла восстановлено|файлов восстановлено}}',
-'cannotundelete' => 'Ошибка восстановления. Возможно, кто-то другой уже восстановил страницу.',
+'cannotundelete' => 'Ошибка восстановления:
+$1',
'undeletedpage' => "'''Страница «$1» была восстановлена.'''
Для просмотра списка последних удалений и восстановлений см. [[Special:Log/delete|журнал удалений]].",
'immobile-target-namespace-iw' => 'Ссылка интервики не может быть использована для переименования.',
'immobile-source-page' => 'Эту страницу нельзя переименовать.',
'immobile-target-page' => 'Нельзя присвоить странице это имя.',
+'bad-target-model' => 'Невозможно преобразовать $1 в $2: несовместимые модели данных.',
'imagenocrossnamespace' => 'Невозможно дать файлу имя из другого пространства имён',
'nonfile-cannot-move-to-file' => 'Невозможно переименовывать страницы в файлы',
'imagetypemismatch' => 'Новое расширение файла не соответствует его типу',
# Info page
'pageinfo-title' => 'Сведения по «$1»',
+'pageinfo-not-current' => 'Данные предоставляются только для текущей правки.',
'pageinfo-header-basic' => 'Основные сведения',
'pageinfo-header-edits' => 'История изменений',
'pageinfo-header-restrictions' => 'Защита страницы',
'pageinfo-magic-words' => '{{PLURAL:$1|Магическое слово|Магические слова}} ($1)',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Скрытая категория|Скрытых категорий}} ($1)',
'pageinfo-templates' => '{{PLURAL:$1|Шаблон|Шаблонов}} ($1)',
+'pageinfo-toolboxlink' => 'Сведения о странице',
# Skin names
'skinname-standard' => 'Классическое',
# Scary transclusion
'scarytranscludedisabled' => '[Интервики-включение отключено]',
'scarytranscludefailed' => '[Ошибка обращения к шаблону $1]',
+'scarytranscludefailed-httpstatus' => '[Не удалось загрузить шаблон для $1: HTTP $2]',
'scarytranscludetoolong' => '[Слишком длинный URL]',
# Delete conflict
'qbbrowse' => 'Переглядати',
'qbedit' => 'Едітовати',
'qbpageoptions' => 'Тота сторінка',
-'qbpageinfo' => 'Контекст',
'qbmyoptions' => 'Мої сторінкы',
'qbspecialpages' => 'Шпеціалны сторінкы',
'faq' => 'Часты звідованя',
'qbbrowse' => 'ब्राउस् इत्येतत् करोतु।',
'qbedit' => 'सम्पाद्यताम्',
'qbpageoptions' => 'इदं पृष्ठम्',
-'qbpageinfo' => 'प्रसंगः',
'qbmyoptions' => 'मम पृष्ठानि',
'qbspecialpages' => 'विशेषपृष्ठानि',
'faq' => 'बहुधा पृच्छ्यमानाः प्रश्नाः',
'qbbrowse' => 'Көр',
'qbedit' => 'Уларыт',
'qbpageoptions' => 'Бу сирэй',
-'qbpageinfo' => 'Ис хоһооно',
'qbmyoptions' => 'Мин сирэйдэрим',
'qbspecialpages' => 'Аналлаах сирэйдэр',
'faq' => 'FAQ',
'qbbrowse' => 'Sendra',
'qbedit' => 'Tońge',
'qbpageoptions' => 'Noa sakam',
-'qbpageinfo' => 'Sakam reaḱ thuti',
'qbmyoptions' => 'In̕anḱ sakamko',
'qbspecialpages' => 'Asokay teaḱ sakamko',
'faq' => 'Baḍae kupuliko',
'last' => 'Laha renaḱ',
'page_first' => 'Pahilaḱ',
'page_last' => 'Mucạt́aḱ',
-'histlegend' => "Farak bachao: oka nãwã aroeko tulạoem menet́kan, onako cinhạ em kate boloḱ se latar baṭon linmẽ.<br/>
+'histlegend' => "Farak bachao: oka nãwã aroeko tulạoem menet́kan, onako cinhạ em kate boloḱ se latar baṭon linmẽ.<br />
Unuduḱ: '''({{int:cur}})''' = nahaḱ nãwã aroeko saõte tulạo, '''({{int:last}})''' = laha reaḱ nãwã aroe sãote tulạo, '''{{int:minoreditletter}}''' = huḍiń sompadon.",
'history-fieldset-title' => 'Sendray jaṛ',
'history-show-deleted' => 'khạli get giḍiyaḱ koge',
'qbbrowse' => 'Sfogghia',
'qbedit' => 'Cancia',
'qbpageoptions' => 'Opzioni pàggina',
-'qbpageinfo' => 'Nfurmazzioni supra la pàggina',
'qbmyoptions' => 'Li mè pàggini',
'qbspecialpages' => 'Pàggini spiciali',
'faq' => 'Dumanni cumuni',
'qbbrowse' => 'Brouse',
'qbedit' => 'Edit',
'qbpageoptions' => 'This page',
-'qbpageinfo' => 'Context',
'qbmyoptions' => 'Ma pages',
'qbspecialpages' => 'Byordinar pages',
'faq' => 'ASQ',
'qbbrowse' => 'Iffuglia',
'qbedit' => 'Mudifigga',
'qbpageoptions' => 'Prifirenzi pàgina',
-'qbpageinfo' => "Infuimmazioni i' la pàgina",
'qbmyoptions' => "Li me' pàgini",
'qbspecialpages' => 'Pàgini ippiziari',
'faq' => 'FAQ (infuimmazioni e aggiuddu)',
'qbbrowse' => 'Bláđe',
'qbedit' => 'Rievdat',
'qbpageoptions' => 'Siidoásahusat',
-'qbpageinfo' => 'Siiddu dieđut',
'qbmyoptions' => 'Ásahusat',
'qbspecialpages' => 'Doaibmasiiddut',
'qbbrowse' => 'Prelistajte',
'qbedit' => 'Uredi',
'qbpageoptions' => 'Opcije stranice',
-'qbpageinfo' => 'Informacije o stranici',
'qbmyoptions' => 'Moje opcije',
'qbspecialpages' => 'Posebne stranice',
'faq' => 'ČPP',
'qbbrowse' => 'පිරික්සන්න',
'qbedit' => 'සංස්කරණය',
'qbpageoptions' => 'මෙම පිටුව',
-'qbpageinfo' => 'සන්දර්භය',
'qbmyoptions' => 'මගේ පිටු',
'qbspecialpages' => 'විශේෂ පිටු',
'faq' => 'නිවිප්ර',
'qbbrowse' => 'Prehliadať',
'qbedit' => 'Upraviť',
'qbpageoptions' => 'Táto stránka',
-'qbpageinfo' => 'Kontext',
'qbmyoptions' => 'Moje stránky',
'qbspecialpages' => 'Špeciálne stránky',
'faq' => 'Často kladené otázky',
'qbbrowse' => 'Prebrskaj',
'qbedit' => 'Uredi',
'qbpageoptions' => 'Možnosti strani',
-'qbpageinfo' => 'Podatki o strani',
'qbmyoptions' => 'Moje možnosti',
'qbspecialpages' => 'Posebne strani',
'faq' => 'Najpogostejša vprašanja',
Prosimo, preverite delovanje strani, počakajte kratek čas in poskusite ponovno.
Morda želite poskusiti ob času manjše zasedenosti.',
-'license' => 'Dovoljenje:',
-'license-header' => 'Dovoljenje',
+'license' => 'Licenca:',
+'license-header' => 'Licenca',
'nolicense' => 'Nobeno',
'license-nopreview' => '(Predogled ni na voljo)',
'upload_source_url' => ' (veljaven, javnosti dostopen URL)',
'shared-repo-from' => 'iz $1',
'shared-repo' => 'skupno skladišče',
'shared-repo-name-wikimediacommons' => 'Wikimedijina Zbirka',
-'upload-disallowed-here' => 'Slike žal ne morete prepisati.',
+'upload-disallowed-here' => 'Datoteke žal ne morete prepisati.',
# File reversion
'filerevert' => 'Vrni $1',
'file-info' => 'Velikost datoteke: $1, MIME-vrsta: <code>$2</code>',
'file-info-size' => '$1 × $2 točk, velikost datoteke: $3, vrsta MIME: $4',
'file-info-size-pages' => '$1 × $2 točk, velikost datoteke: $3, vrsta MIME: $4, $5 {{PLURAL:$5|stran|strani}}',
-'file-nohires' => 'Višja ločljivost slike ni na razpolago.',
+'file-nohires' => 'Višja ločljivost slike ni na voljo.',
'svg-long-desc' => 'datoteka SVG, v izvirniku $1 × $2 slikovnih točk, velikost datoteke: $3',
'svg-long-desc-animated' => 'animirana datoteka SVG, v izvirniku $1 × $2 slikovnih točk, velikost datoteke: $3',
'show-big-image' => 'Slika v višji ločljivosti',
'version-hook-name' => 'Ime razširitve',
'version-hook-subscribedby' => 'Naročen s strani',
'version-version' => '(Različica $1)',
-'version-license' => 'Dovoljenje',
+'version-license' => 'Licenca',
'version-poweredby-credits' => "Ta wiki poganja '''[//www.mediawiki.org/ MediaWiki]''', vse pravice pridržave © 2001-$1 $2.",
'version-poweredby-others' => 'drugi',
'version-license-info' => 'MediaWiki je prosto programje; lahko ga razširjate in / ali spreminjate pod pogoji GNU General Public License, kot ga je objavila Free Software Foundation; bodisi License različice 2 ali (po vaši izbiri) katere koli poznejše različice.
'qbfind' => 'Fenda',
'qbedit' => 'Ändern',
'qbpageoptions' => 'Seytaoptiona',
-'qbpageinfo' => 'Seytadata',
'qbmyoptions' => 'Menne Seyta',
'qbspecialpages' => 'Spezialseyta',
'faq' => 'FAQ',
'qbbrowse' => 'Ka soo raadi',
'qbedit' => 'Wax ka bedel',
'qbpageoptions' => 'Boggaan',
-'qbpageinfo' => 'isku xiran',
'qbmyoptions' => 'Boggageyga',
'qbspecialpages' => 'Bogaga qaaska ah',
'faq' => 'SIL',
'qbbrowse' => 'Shfletoni',
'qbedit' => 'Redaktoni',
'qbpageoptions' => 'Kjo faqe',
-'qbpageinfo' => 'Kontekst',
'qbmyoptions' => 'Faqet e mia',
'qbspecialpages' => 'Faqet speciale',
'faq' => 'Pyetje që bëhen shpesh',
'qbbrowse' => 'Потражи',
'qbedit' => 'Уреди',
'qbpageoptions' => 'Поставке странице',
-'qbpageinfo' => 'Садржај странице',
'qbmyoptions' => 'Моје странице',
'qbspecialpages' => 'Посебне странице',
'faq' => 'НПП',
'qbbrowse' => 'Potraži',
'qbedit' => 'Uredi',
'qbpageoptions' => 'Postavke stranice',
-'qbpageinfo' => 'Sadržaj stranice',
'qbmyoptions' => 'Moje stranice',
'qbspecialpages' => 'Posebne stranice',
'faq' => 'NPP',
'qbbrowse' => 'Bleederje',
'qbedit' => 'Annerje',
'qbpageoptions' => 'Disse Siede',
-'qbpageinfo' => 'Siedendoatäie',
'qbmyoptions' => 'Mien Sieden',
'qbspecialpages' => 'Spezialsieden',
'faq' => 'Oafte stoalde Froagen',
'qbbrowse' => 'Sungsi',
'qbedit' => 'Édit',
'qbpageoptions' => 'Kaca ieu',
-'qbpageinfo' => 'Kontéks',
'qbmyoptions' => 'Kaca kuring',
'qbspecialpages' => 'Kaca husus',
'faq' => 'NLD',
'qbbrowse' => 'Bläddra igenom',
'qbedit' => 'Redigera',
'qbpageoptions' => 'Denna sida',
-'qbpageinfo' => 'Sidinformation',
'qbmyoptions' => 'Mina inställningar',
'qbspecialpages' => 'Specialsidor',
'faq' => 'FAQ',
'qbbrowse' => 'Vinjari',
'qbedit' => 'Hariri',
'qbpageoptions' => 'Ukurasa huu',
-'qbpageinfo' => 'Muktadha',
'qbmyoptions' => 'Kurasa zangu',
'qbspecialpages' => 'Kurasa za pekee',
'faq' => 'Maswali ya kawaida',
'qbbrowse' => 'Uoglůndańy',
'qbedit' => 'Sprowjej',
'qbpageoptions' => 'Ta zajta',
-'qbpageinfo' => 'Kontekst',
'qbmyoptions' => 'Moje zajty',
'qbspecialpages' => 'Szpecyjalne zajty',
'faq' => 'FAQ',
'qbbrowse' => 'உலவு',
'qbedit' => 'தொகு',
'qbpageoptions' => 'பக்க விருப்பத் தேர்வுகள்',
-'qbpageinfo' => 'பக்கத் தகவல்கள்',
'qbmyoptions' => 'என் விருப்பத்தேர்வுகள்',
'qbspecialpages' => 'சிறப்புப் பக்கங்கள்',
'faq' => 'அடிக்கடி கேட்கப்படும் கேள்விகள்',
'qbbrowse' => 'విహరించు',
'qbedit' => 'సవరించు',
'qbpageoptions' => 'ఈ పేజీ',
-'qbpageinfo' => 'సందర్భం',
'qbmyoptions' => 'నా పేజీలు',
'qbspecialpages' => 'ప్రత్యేక పేజీలు',
'faq' => 'తరచూ అడిగే ప్రశ్నలు',
అది ఇప్పటికే ఉంది.',
'defaultmessagetext' => 'అప్రమేయ సందేశపు పాఠ్యం',
+# Content models
+'content-model-wikitext' => 'వికీపాఠ్యం',
+'content-model-text' => 'సాదా పాఠ్యం',
+'content-model-javascript' => 'జావాస్క్రిప్ట్',
+
# Parser/template warnings
'expensive-parserfunction-warning' => 'హెచ్చరిక: ఈ పేజీలో ఖరీదైన పార్సరు పిలుపులు చాలా ఉన్నాయి.
'mailnologin' => 'పంపించవలసిన చిరునామా లేదు',
'mailnologintext' => 'ఇతరులకు ఈ-మెయిలు పంపించాలంటే, మీరు [[Special:UserLogin|లాగిన్]] అయి ఉండాలి, మరియు మీ [[Special:Preferences|అభిరుచుల]]లో సరైన ఈ-మెయిలు చిరునామా ఇచ్చి ఉండాలి.',
'emailuser' => 'ఈ వాడుకరికి ఈ-మెయిలుని పంపించండి',
+'emailuser-title-target' => 'ఈ {{GENDER:$1|వాడుకరికి}} ఈమెయిలు పంపించండి',
'emailpage' => 'వాడుకరికి ఈ-మెయిలుని పంపించు',
'emailpagetext' => 'వాడుకరికి ఈమెయిలు సందేశము పంపించుటకు క్రింది ఫారంను ఉపయోగించవచ్చు. [[Special:Preferences|మీ వాడుకరి అభిరుచుల]]లో మీరిచ్చిన ఈ-మెయిలు చిరునామా "నుండి" ఆ సందేశం వచ్చినట్లుగా ఉంటుంది, కనుక వేగుని అందుకునేవారు నేరుగా మీకు జవాబివ్వగలుగుతారు.',
'usermailererror' => 'మెయిలు ఆబ్జెక్టు ఈ లోపాన్ని చూపింది:',
'pageinfo-views' => 'వీక్షణల సంఖ్య',
'pageinfo-watchers' => 'పేజీ వీక్షకుల సంఖ్య',
'pageinfo-edits' => 'మొత్తం మార్పుల సంఖ్య',
+'pageinfo-toolboxlink' => 'పేజీ సమాచారం',
# Skin names
'skinname-standard' => 'సంప్రదాయ',
'qbbrowse' => 'Мурур',
'qbedit' => 'Вироиш',
'qbpageoptions' => 'Ин саҳифа',
-'qbpageinfo' => 'Бофт',
'qbmyoptions' => 'Саҳифаҳои ман',
'qbspecialpages' => 'Саҳифаҳои вижа',
'faq' => 'Саволҳои тез-тез пурсидашуда',
'qbbrowse' => 'Murur',
'qbedit' => 'Viroiş',
'qbpageoptions' => 'In sahifa',
-'qbpageinfo' => 'Boft',
'qbmyoptions' => 'Sahifahoi man',
'qbspecialpages' => 'Sahifahoi viƶa',
'faq' => 'Savolhoi tez-tez pursidaşuda',
'qbbrowse' => 'สืบค้น',
'qbedit' => 'แก้ไข',
'qbpageoptions' => 'หน้านี้',
-'qbpageinfo' => 'บริบท',
'qbmyoptions' => 'หน้าของฉัน',
'qbspecialpages' => 'หน้าพิเศษ',
'faq' => 'คำถามถามบ่อย',
'qbbrowse' => 'Göz aýla',
'qbedit' => 'Redaktirle',
'qbpageoptions' => 'Bu sahypa',
-'qbpageinfo' => 'Kontekst',
'qbmyoptions' => 'Meniň sahypalarym',
'qbspecialpages' => 'Ýörite sahypalar',
'faq' => 'KSS',
'qbbrowse' => 'Basa-basahin',
'qbedit' => 'Baguhin',
'qbpageoptions' => 'Itong pahina',
-'qbpageinfo' => 'Konteksto',
'qbmyoptions' => 'Mga pahina ko',
'qbspecialpages' => 'Mga natatanging pahina',
'faq' => "Mga karaniwang itinatanong (''FAQ'')",
'qbbrowse' => 'Tara',
'qbedit' => 'Değiştir',
'qbpageoptions' => 'Bu sayfa',
-'qbpageinfo' => 'Bağlam',
'qbmyoptions' => 'Sayfalarım',
'qbspecialpages' => 'Özel sayfalar',
'faq' => 'SSS',
'qbbrowse' => 'كۆز يۈگۈرت',
'qbedit' => 'تەھرىر',
'qbpageoptions' => 'بۇ بەت',
-'qbpageinfo' => 'كونتېكست',
'qbmyoptions' => 'بەتلەرىم',
'qbspecialpages' => 'ئالاھىدە بەتلەر',
'faq' => 'كۆپ كۆرۈلىدىغان مەسىلىلەر',
'vector-action-protect' => 'قوغدا',
'vector-action-undelete' => 'ئەسلىگە قايتۇر',
'vector-action-unprotect' => 'قوغداش ئۆزگەرت',
-'vector-simplesearch-preference' => 'ئالىي ئىزدەش تەكلىپىنى ئاچ (Vector تېرىدىلا)',
+'vector-simplesearch-preference' => 'ئاددىي ئىزدەش ئىستون ئاچ (پەقەت ۋېكتور قېلىپ)',
'vector-view-create' => 'قۇر',
'vector-view-edit' => 'تەھرىر',
'vector-view-history' => 'تارىخ كۆرسەت',
[[Special:Version|نەشر بېتى]] نى كۆرۈڭ.',
'ok' => 'ماقۇل',
+'pagetitle' => '$1 - {{SITENAME}}',
'pagetitle-view-mainpage' => '{{SITENAME}}',
'backlinksubtitle' => '← $1',
'retrievedfrom' => '"$1" دىن ئېرىشكەن',
'site-atom-feed' => '$1 نىڭ Atom قانالى',
'page-rss-feed' => '"$1" نىڭ RSS قانىلى',
'page-atom-feed' => '"$1" نىڭ Atom قانىلى',
-'feed-atom' => 'ئاتوم',
+'feed-atom' => 'Atom',
'feed-rss' => 'RSS',
'red-link-title' => '$1 (بەت مەۋجۇد ئەمەس)',
'sort-descending' => 'كېمەيگۈچى تەرتىپ',
'dberrortext' => 'ساندان سۈرۈشتۈرۈشتە گرامماتىكىلىق خاتالىق يۈز بەردى.
يۇمشاق دېتالنىڭ ئۆزىدىكى خاتالىقتىن كېلىپ چىققان بولۇشى مۇمكىن.
ئاخىرقى قېتىملىق ساندان سۈرۈشتۈرۈش بۇيرۇقى:
-<blockquote><tt>$1</tt></blockquote>
- \\"<tt>$2</tt>\\"فۇنكسىيىدىن كەلگەن.
-MySQL قايتۇرغان خاتالىق \\"<tt>$3: $4</tt>\\".',
+<blockquote><code>$1</code></blockquote>
+ "<code>$2</code>"فۇنكسىيىدىن كەلگەن.
+ساندان قايتۇرغان خاتالىق "<samp>$3: $4</samp>".',
'dberrortextcl' => 'ساندان سۈرۈشتۈرۈشتە گرامماتىكىلىق خاتالىق يۈز بەردى.
ئاخىرقى قېتىملىق ساندان سۈرۈشتۈرۈش بۇيرۇقى:
"$1"
'protectedpagetext' => 'بۇ بەت تەھرىرلەشنىڭ ئالدىنى ئېلىش ئۈچۈن قۇلۇپلانغان.',
'viewsourcetext' => 'سىز بۇ بەتنى ئەسلى كودىنى كۆرەلەيسىز ۋە كۆچۈرەلەيسىز:',
'viewyourtext' => "بۇ بەتتىكى '''تەھرىرلىگەنلىرىڭىز'''نىڭ ئەسلى كودىنى كۆرۈپ كۆچۈرەلەيسىز.",
-'protectedinterface' => 'بۇ بەت يۇمشاق دېتالنىڭ كۆرۈنۈش تېكستىنى تەمىنلىگەن، خالىغانچە تەھرىرلەشتىن ساقلىنىش ئۈچۈن قۇلۇپلانغان.',
+'protectedinterface' => 'بۇ بەت يۇمشاق دېتالنىڭ كۆرۈنۈش تېكستىنى تەمىنلىگەن، خالىغانچە تەھرىرلەشتىن ساقلىنىش ئۈچۈن قۇلۇپلانغان.
+مەسىلەن ئەگەر تەرجىمە قىلسىڭىز [//translatewiki.net/wiki/Main_Page?setlang=ug translatewiki.net] ئۇنداقتا MediaWiki يەرلىكلەشتۈرۈش پىلانىنى ئىشلىتىشنى ئويلىشىڭ.',
'editinginterface' => "'''ئاگاھلاندۇرۇش:''' سىز تەھرىرلەۋاتقان بەت يۇمشاق دېتالنىڭ كۆرۈنۈش تېكستىگە ئىشلىتىلىدۇ.
بۇ بەت ئۆزگەرتىلسە باشقا ئىشلەتكۈچىلەرنىڭ كۆرۈنۈش ئۇسلۇبىغا تەسىر كۆرسىتىدۇ.
<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>',
+ سىز باشقا بەتتە [[Special:Search/{{PAGENAME}}|بۇ بەتنىڭ ماۋزۇسىنى ئىزدىيەلەيسىز]] ياكى <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}] مۇناسىۋەتلىك خاتىرىسىنى ئىزدىيەلەيسىز،</span>لىكىن سزنىڭ بەت قۇرۇش ھوقوقىڭز يوق.',
'missing-revision' => '"{{PAGENAME}}" ئاتلىق بەتنىڭ تۈزىتىلگەن نەشرى #$1 مەۋجۇت ئەمەس.
ئادەتتە بۇ ئۆچۈرۈلگەن بىر بەتنىڭ ئۇلانمىسىغا كىرگەنلىك سەۋەبىدىن بولىدۇ.
* '''Mozilla / Firefox / Safari:''' دا ''Shift'' كۇنۇپكىسىنى بېسىپ تۇرۇپ ''قايتا يۈكلە''نى ياكى ''Ctrl-F5'' ياكى ''Ctrl-R'' (''Mac تا Command-R'')؛
* '''Google Chrome:''' دا ''Ctrl-Shift-R'' (''Command-Shift-R'' Mac)
*'''Internet Explorer:''' دا ''Ctrl'' نى بېسىپ تۇرۇپ ''يېڭىلا,'' ياكى ''Ctrl-F5''؛
-* '''Konqueror: دا ''' ''قايتا يۈكلە'' ياكى ''F5''؛
* '''Opera:''' دا ''قورال → مايىللىق''؛ نى بېسىپ غەملەكنى تازىلاڭ.",
'usercssyoucanpreview' => "ئەسكەرتىش:''' ساقلاشتىن ئىلگىرى \"{{int:showpreview}}\" توپچىنى ئىشلىتىپ يېڭى CSS نى سىناڭ.",
'userjsyoucanpreview' => "ئەسكەرتىش:''' ساقلاشتىن ئىلگىرى \"{{int:showpreview}}\" توپچىنى ئىشلىتىپ يېڭى JS نى سىناڭ.",
'edit-already-exists' => 'يېڭى بەت قۇرالمىدى
ئۇ مەۋجۇد.',
'defaultmessagetext' => 'كۆڭۈلدىكى ئۇچۇر تېكستى',
+'content-failed-to-parse' => '$2 نى $1 گە ئانالىز قلش مەغلۇپ بولدى: $3',
# Parser/template warnings
'expensive-parserfunction-warning' => "'''ئاگاھلاندۇرۇش:''' بۇ بەت ناھايىتى كۆپ يۇقىرى سەرپىياتتىكى گىرامماتىكىلىق ئىقتىدارنى چاقىرغان.\\n
'username' => 'ئىشلەتكۇچى ئىسمى:',
'uid' => 'ئىشلەتكۈچى كىملىك:',
'prefs-memberingroups' => '{{PLURAL:$1|بىر|كۆپ}} گۇرۇپپا ئەزاسى:',
+'prefs-memberingroups-type' => '$1',
'prefs-registration' => 'خەتلەتكەن ۋاقىت:',
+'prefs-registration-date-time' => '$1',
'yourrealname' => 'ﺗﻮﻟﯘﻕ ئىسىم:',
'yourlanguage' => 'تىل:',
'yourvariant' => 'مەزمۇن تىل شالغۇتى:',
'userrights-notallowed' => 'ھېساباتىڭىزنىڭ ئىشلەتكۈچى ھوقۇقىنى قوشۇش ياكى ئۆزگەرتىش ھوقۇقى يوق.',
'userrights-changeable-col' => 'سىز ئۆزگەرتەلەيدىغان گۇرۇپپا',
'userrights-unchangeable-col' => 'سىز ئۆزگەرتەلمەيدىغان گۇرۇپپا',
+'userrights-irreversible-marker' => '$1*',
# Groups
'group' => 'گۇرۇپپا:',
'minoreditletter' => 'ئازراقلا',
'newpageletter' => 'يېڭى',
'boteditletter' => 'ماشىنا ئادەم',
+'unpatrolledletter' => '!',
'number_of_watching_users_pageview' => '[$1 {{PLURAL:$1|ئىشلەتكۈچى|ئىشلەتكۈچى}}كۆزىتىۋاتىدۇ]',
'rc_categories' => 'تۈر چېگرىسى ("|" بىلەن ئايرىلىدۇ )',
'rc_categories_any' => 'خالىغان',
+'rc-change-size' => '$1',
'newsectionsummary' => '* $1 * يېڭى ئابزاس',
'rc-enhanced-expand' => 'تەپسىلاتىنى كۆرسەت (JavaScript قوللىشى زۆرۈر)',
'rc-enhanced-hide' => 'تەپسىلاتىنى يوشۇر',
# Book sources
'booksources' => 'كىتاب مەنبەسى',
'booksources-search-legend' => 'كىتاب مەنبەسى ئىزدە',
+'booksources-isbn' => 'ISBN:',
'booksources-go' => 'يۆتكەل',
'booksources-text' => 'تۆۋەندىكىسى بىر قىسىم تور كىتابخانىلىرىنىڭ تىزىملىكى، ئىچىدە سىز ئىزدىمەكچى بولغان كىتابلارنىڭ تېخىمۇ كۆپ ئۇچۇرى بولۇشى مۇمكىن:',
'booksources-invalid-isbn' => 'تەمىنلىگەن ISBN نومۇرى توغرا ئەمەس. ئەسلى كۆچۈرگەن مەنبەدىكى نومۇردا خاتالىق بار يوقلۇقىنى تەكشۈرۈڭ.',
'listgrouprights-rights' => 'ھوقۇق',
'listgrouprights-helppage' => 'Help: گۇرۇپپا ھوقۇقى',
'listgrouprights-members' => '(ئەزالار تىزىملىكى)',
+'listgrouprights-right-revoked' => '<span class="listgrouprights-revoked">$1 <code>($2)</code></span>',
'listgrouprights-addgroup' => ' {{PLURAL:$2|بىر|بىر قانچە}} گۇرۇپپىغا قوشالايدۇ: $1',
'listgrouprights-removegroup' => ' {{PLURAL:$2|بىر|بىر قانچە}} گۇرۇپپىدىن چىقىرىۋېتەلەيدۇ: $1',
'listgrouprights-addgroup-all' => 'ھەممە گۇرۇپپىغا قوش',
$1',
'undelete-show-file-confirm' => '$2 $3 دىكى \\"<nowiki>$1</nowiki>\\" نىڭ ئۆچۈرۈلگەن تۈزىتىلگەن نەشرىنى راستىنلا كۆرەمسىز؟',
'undelete-show-file-submit' => 'ھەئە',
+'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
# Namespace form on various pages
'namespace' => 'ئات بوشلۇقى',
'proxyblockreason' => 'IP ئادرېسىڭىز ئوچۇق ۋاكالەتچى، ئۇ ئاللىبۇرۇن چەكلەنگەن.
ئىنتېرنېت مۇلازىمىتى تەمىنلىگۈچى سودىگەر ياكى تېخنىكىلىق قوللىغۇچى بىلەن ئالاقىلىشىڭ ھەمدە ئۇلارغا بۇ ئېغىر بىخەتەرلىك مەسىلىسىنى ئۇقتۇرۇڭ.',
'proxyblocksuccess' => 'تامام',
+'sorbs' => 'DNSBL',
'sorbsreason' => 'IP ئادرېسىڭىز {{SITENAME}} دا DNSBL تەرىپىدىن ئوچۇق ۋاكالەتچى تىزىملىكىگە قوشۇلغان.',
'sorbs_create_account_reason' => 'IP ئادرېسىڭىز {{SITENAME}} دا DNSBL تەرىپىدىن ئوچۇق ۋاكالەتچى تىزىملىكىگە قوشۇلغان.
شۇڭا سىز يېڭى ھېسابات قۇرالمايسىز.',
بەت چىقىرىشتا، تۆۋەندىكى تېكست رامكىسىغا بەت ماۋزۇسىنى كىرگۈزۈپ، ھەر بىر قۇردا بىر ماۋزۇ، ھەمدە بەت تارىخ بار ئىلگىرىكى تۈزىتىلگەن نەشرىنى تاللامسىز يوق، ياكى پەقەت ئاخىرقى قېتىملىق تەھرىر ئۇچۇرى بار نۆۋەتتىكى تۈزىتىلگەن نەشرىنى چىقىرىشنى تاللاڭ.
ئۇنىڭدىن باشقا ئۇلانمىدىن پايدىلىنىپ ھۆججەت چىقىرالايسىز، مەسىلەن سىز [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] دىن پايدىلىنىپ "[[{{MediaWiki:Mainpage}}]]"بەت چىقىرالايسىز.',
+'exportall' => 'بارلىق بەتنى چىقىرىش',
'exportcuronly' => 'ھەممە تارىخنى ئەمەس بەلكى نۆۋەتتىكى تۈزىتىلگەن نەشرىنىلا ئۆز ئىچىگە ئالىدۇ.',
'exportnohistory' => "----
'''دىققەت:''' ئىقتىدار سەۋەبلىك بۇ جەدۋەلدىن ھەممە تارىخنى چىقىرىش چەكلەنگەن.",
'thumbnail_error' => 'كىچىك رەسىم قۇرۇش خاتالىقى: $1',
'djvu_page_error' => 'DjVu بېتى دائىرىدىن ھالقىپ كەتتى',
'djvu_no_xml' => 'DjVu ھۆججىتىدىن XML گە ئېرىشەلمىدى',
+'thumbnail-dest-create' => 'قارار ھۈجەتتە ۋاقتلىق كىچىك ھۈجەت ساقلىغل بولمدى',
'thumbnail_invalid_params' => 'ئىناۋەتسىز كىچىك رەسىم پارامېتىرى',
'thumbnail_dest_directory' => 'نىشان مۇندەرىجە قۇرالمىدى',
'thumbnail_image-type' => 'سۈرەت فورماتىنى قوللىمايدۇ',
'tooltip-preferences-save' => 'مايىللىق ساقلا',
'tooltip-summary' => 'قىسقىچە ئۈزۈندە كىرگۈزۈڭ',
+# Stylesheets
+'common.css' => '/* CSS placed here will be applied to all skins */',
+'standard.css' => '/* CSS placed here will affect users of the Standard skin */',
+'nostalgia.css' => '/* CSS placed here will affect users of the Nostalgia skin */',
+'cologneblue.css' => '/* CSS placed here will affect users of the Cologne Blue skin */',
+'monobook.css' => '/* CSS placed here will affect users of the Monobook skin */',
+'myskin.css' => '/* CSS placed here will affect users of the MySkin skin */',
+'chick.css' => '/* CSS placed here will affect users of the Chick skin */',
+'simple.css' => '/* CSS placed here will affect users of the Simple skin */',
+'modern.css' => '/* CSS placed here will affect users of the Modern skin */',
+'vector.css' => '/* CSS placed here will affect users of the Vector skin */',
+'print.css' => '/* CSS placed here will affect the print output */',
+'noscript.css' => '/* CSS placed here will affect users with JavaScript disabled */',
+'group-autoconfirmed.css' => '/* CSS placed here will affect autoconfirmed users only */',
+'group-bot.css' => '/* CSS placed here will affect bots only */',
+'group-sysop.css' => '/* CSS placed here will affect sysops only */',
+'group-bureaucrat.css' => '/* CSS placed here will affect bureaucrats only */',
+
+# Scripts
+'common.js' => '/* Any JavaScript here will be loaded for all users on every page load. */',
+'standard.js' => '/* Any JavaScript here will be loaded for users using the Standard skin */',
+'nostalgia.js' => '/* Any JavaScript here will be loaded for users using the Nostalgia skin */',
+'cologneblue.js' => '/* Any JavaScript here will be loaded for users using the Cologne Blue skin */',
+'monobook.js' => '/* Any JavaScript here will be loaded for users using the MonoBook skin */',
+'myskin.js' => '/* Any JavaScript here will be loaded for users using the MySkin skin */',
+'chick.js' => '/* Any JavaScript here will be loaded for users using the Chick skin */',
+'simple.js' => '/* Any JavaScript here will be loaded for users using the Simple skin */',
+'modern.js' => '/* Any JavaScript here will be loaded for users using the Modern skin */',
+'vector.js' => '/* Any JavaScript here will be loaded for users using the Vector skin */',
+'group-autoconfirmed.js' => '/* Any JavaScript here will be loaded for autoconfirmed users only */',
+'group-bot.js' => '/* Any JavaScript here will be loaded for bots only */',
+'group-sysop.js' => '/* Any JavaScript here will be loaded for sysops only */',
+'group-bureaucrat.js' => '/* Any JavaScript here will be loaded for bureaucrats only */',
+
# Metadata
'notacceptable' => 'wiki مۇلازىمىتىرى سىزنىڭ خېرىدار تەرىپىڭىز ئوقۇيالايدىغان سانلىق مەلۇمات فورماتى بىلەن تەمىنلىيەلمەيدۇ.',
# Info page
'pageinfo-title' => '"$1" نىڭ ئۇچۇرى',
-'pageinfo-header-edits' => 'تەھرىر',
+'pageinfo-header-basic' => 'ئاساسىي ئۇچۇر',
+'pageinfo-header-edits' => 'تەھرىر خاتىرىسى',
+'pageinfo-header-restrictions' => 'بەت قوغداش',
+'pageinfo-header-properties' => 'بەت خاراكتېرى',
+'pageinfo-display-title' => 'كۆرسىتىدغان نام',
+'pageinfo-article-id' => 'بەت ID',
'pageinfo-views' => 'كۆرۈنۈش سانى',
-'pageinfo-watchers' => 'كۆزەتكۈچىلەر سانى',
+'pageinfo-watchers' => 'بەت كۆزەتكۈچىلەر سانى',
+'pageinfo-redirects-value' => '$1',
'pageinfo-edits' => 'تەھرىر سانى',
'pageinfo-authors' => 'يازغۇچىلار سانى',
+# Skin names
+'skinname-standard' => 'Classic',
+'skinname-nostalgia' => 'Nostalgia',
+'skinname-cologneblue' => 'Cologne Blue',
+'skinname-monobook' => 'MonoBook',
+'skinname-myskin' => 'MySkin',
+'skinname-chick' => 'Chick',
+'skinname-simple' => 'Simple',
+'skinname-modern' => 'Modern',
+'skinname-vector' => 'Vector',
+
# Patrolling
'markaspatrolleddiff' => 'چارلاش بەلگىسى قوي',
'markaspatrolledtext' => 'بۇ بەتكە چارلاش بەلگىسى قوي',
'mediawarning' => "'''ئاگاھلاندۇرۇش''': بۇ ھۆججەتتە زەھەرخەندە كود بولۇشى مۇمكىن، ئۇنى ئىجرا قىلسىڭىز سىستېمىڭىزغا خەۋپ ئېلىپ كېلىشى مۇمكىن.",
'imagemaxsize' => "سۈرەت چوڭلۇق چەكلىمىسى: <br />''(ھۆججەت چۈشەندۈرۈش بېتى ئۈچۈن)''",
'thumbsize' => 'كىچىك سۈرەت چوڭلۇقى:',
+'widthheight' => '$1 × $2',
'widthheightpage' => '$1 × $2, $3 {{PLURAL:$3|بەت|بەت}}',
'file-info' => 'ھۆججەت چوڭلۇقى: $1, MIME تىپى: $2',
'file-info-size' => '$1 × $2 پىكسېل، ھۆججەت چوڭلۇقى: $3، MIME تىپى: $4',
'bydate' => 'چېسلا بويىچە',
'sp-newimages-showfrom' => '$2 دىن $1 باشلاپ يېڭى ھۆججەت كۆرسىتىۋاتىدۇ',
+# Video information, used by Language::formatTimePeriod() to format lengths in the above messages
+'video-dims' => '$1, $2 × $3',
+'seconds-abbrev' => '$1s',
+'minutes-abbrev' => '$1m',
+'hours-abbrev' => '$1h',
+'days-abbrev' => '$1d',
+
# Bad image list
'bad_image_list' => 'تۆۋەندىكى فورماتتا يېزىڭ:
بۇ ھۆججەت قايسى بەتلەردە كۆرسىتىلىشىدىن قەتئىي نەزەر،
ئوخشاش بىر قۇرنىڭ ئاخىرىدىكى ئۇلانما مۇستەسنا دەپ قارىلىدۇ،',
+/*
+Short names for language variants used for language conversion links.
+To disable showing a particular link, set it to 'disable', e.g.
+'variantname-zh-sg' => 'disable',
+Variants for Chinese language
+*/
+'variantname-zh-hans' => 'hans',
+'variantname-zh-hant' => 'hant',
+'variantname-zh-cn' => 'cn',
+'variantname-zh-tw' => 'tw',
+'variantname-zh-hk' => 'hk',
+'variantname-zh-mo' => 'mo',
+'variantname-zh-sg' => 'sg',
+'variantname-zh-my' => 'my',
+'variantname-zh' => 'zh',
+
+# Variants for Gan language
+'variantname-gan-hans' => 'hans',
+'variantname-gan-hant' => 'hant',
+'variantname-gan' => 'gan',
+
+# Variants for Serbian language
+'variantname-sr-ec' => 'sr-ec',
+'variantname-sr-el' => 'sr-el',
+'variantname-sr' => 'sr',
+
+# Variants for Kazakh language
+'variantname-kk-kz' => 'kk-kz',
+'variantname-kk-tr' => 'kk-tr',
+'variantname-kk-cn' => 'kk-cn',
+'variantname-kk-cyrl' => 'kk-cyrl',
+'variantname-kk-arab' => 'kk-arab',
+'variantname-kk' => 'kk',
+
# Metadata
'metadata' => 'مېتا سانلىق مەلۇماتى',
'metadata-help' => 'بۇ ھۆججەت كېڭەيتىلگەن تەپسىلاتنى ئۆز ئىچىگە ئالغان. بۇ ئۇچۇرلارنى رەقەملىك ئاپپارات ياكى سكاننېر قۇرغان ياكى رەقەملەشتۈرۈش جەريانىدا قوشۇلغان بولۇشى مۇمكىن.
'qbbrowse' => 'Переглянути',
'qbedit' => 'Редагувати',
'qbpageoptions' => 'Налаштування сторінки',
-'qbpageinfo' => 'Інформація про сторінку',
'qbmyoptions' => 'Мої налаштування',
'qbspecialpages' => 'Спеціальні сторінки',
'faq' => 'Часті питання',
'sp-contributions-newbies' => 'Показати лише внесок з нових облікових записів',
'sp-contributions-newbies-sub' => 'Внесок новачків',
'sp-contributions-newbies-title' => 'Внесок з нових облікових записів',
-'sp-contributions-blocklog' => 'пÑ\80оÑ\82окол блокувань',
+'sp-contributions-blocklog' => 'жÑ\83Ñ\80нал блокувань',
'sp-contributions-deleted' => 'вилучені редагування користувача',
'sp-contributions-uploads' => 'завантаження',
'sp-contributions-logs' => 'журнали',
'qbbrowse' => "Ko'rish",
'qbedit' => 'Tahrirlash',
'qbpageoptions' => 'Ushbu sahifa',
-'qbpageinfo' => "Sahifa haqida ma'lumot",
'qbmyoptions' => 'Mening sahifalarim',
'qbspecialpages' => 'Maxsus sahifalar',
'faq' => 'TSS',
'qbbrowse' => 'Sfoja',
'qbedit' => 'Canbia',
'qbpageoptions' => 'Opsion pajina',
-'qbpageinfo' => 'Informasion so ła pajina',
'qbmyoptions' => 'Łe me pajine',
'qbspecialpages' => 'Pagine speciali',
'faq' => 'Domande frequenti',
'qbbrowse' => 'Kacelta',
'qbedit' => 'Redaktiruida',
'qbpageoptions' => 'Necen lehtpolen järgendused',
-'qbpageinfo' => 'Andmused lehtpoles',
'qbmyoptions' => 'Minun järgendused',
'qbspecialpages' => 'Specialižed lehtpoled',
'faq' => 'PPK',
'qbbrowse' => 'Duyệt',
'qbedit' => 'Sửa đổi',
'qbpageoptions' => 'Trang này',
-'qbpageinfo' => 'Ngữ cảnh',
'qbmyoptions' => 'Trang cá nhân',
'qbspecialpages' => 'Trang đặc biệt',
'faq' => 'Câu hỏi thường gặp',
'edit-already-exists' => 'Không thể tạo trang mới.
Nó đã tồn tại.',
'defaultmessagetext' => 'Nội dung mặc định',
+'content-failed-to-parse' => 'Thất bại phân tích nội dung $2 cho mô hình $1: $3',
+'invalid-content-data' => 'Dữ liệu nội dung không hợp lệ',
+'content-not-allowed-here' => 'Không cho phép đưa nội dung “$1” vào trang [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'mã wiki',
+'content-model-text' => 'văn bản thuần',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'expensive-parserfunction-warning' => 'Cảnh báo: Trang này có quá nhiều lần gọi hàm cú pháp cần mức độ xử lý cao.
'undeletedrevisions' => '$1 {{PLURAL:$1|bản|bản}} được phục hồi',
'undeletedrevisions-files' => '$1 {{PLURAL:$1|bản|bản}} và $2 {{PLURAL:$2|tập tin|tập tin}} đã được phục hồi',
'undeletedfiles' => '$1 {{PLURAL:$1|tập tin|tập tin}} đã được phục hồi',
-'cannotundelete' => 'Phục hồi thất bại;
-một người nào khác đã phục hồi trang này rồi.',
+'cannotundelete' => 'Phục hồi thất bại:
+$1',
'undeletedpage' => "'''$1 đã được khôi phục'''
Xem nhật trình xóa và phục hồi các trang gần đây tại [[Special:Log/delete|nhật trình xóa]].",
'immobile-target-namespace-iw' => 'Không cho phép di chuyển trang đến một liên kết liên wiki.',
'immobile-source-page' => 'Bạn không thể di chuyển trang này.',
'immobile-target-page' => 'Không thể di chuyển đến tựa đề đích.',
+'bad-target-model' => 'Trang đích sử dụng mô hình nội dung khác. Không thể chuyển đổi nội dung từ $1 đến $2.',
'imagenocrossnamespace' => 'Không thể di chuyển tập tin ra khỏi không gian tên Tập tin',
'nonfile-cannot-move-to-file' => 'Không thể di chuyển những gì không phải là tập tin vào không gian tên Tập tin',
'imagetypemismatch' => 'Phần mở rộng trong tên tập tin mới không hợp dạng của tập tin',
# Info page
'pageinfo-title' => 'Thông tin về “$1”',
+'pageinfo-not-current' => 'Thông tin được hiển thị có thể chỉ có liên quan đến phiên bản hiện hành.',
'pageinfo-header-basic' => 'Thông tin cơ bản',
'pageinfo-header-edits' => 'Lịch sử sửa đổi',
'pageinfo-header-restrictions' => 'Mức khóa trang',
'qbbrowse' => 'Padön',
'qbedit' => 'Redakön',
'qbpageoptions' => 'Pad at',
-'qbpageinfo' => 'Yumed',
'qbmyoptions' => 'Pads obik',
'qbspecialpages' => 'Pads patik',
'faq' => 'Säks suvo pasäköls',
# Groups
'group-user' => 'Сäüttijäd',
'group-sysop' => 'Praviťeľad',
-'group-all' => '{kõik)',
+'group-all' => '(kõik)',
'group-user-member' => 'cäüttijä',
'qbbrowse' => 'Kaeq',
'qbedit' => 'Toimõndaq',
'qbpageoptions' => 'Leheküle säädmine',
-'qbpageinfo' => 'Leheküle teedüs',
'qbmyoptions' => 'Mu säädmiseq',
'qbspecialpages' => 'Tallitusleheküleq',
'faq' => 'Sagõhõhe küsüdüq küsümiseq',
'qbbrowse' => 'Foyter',
'qbedit' => 'Candjî',
'qbpageoptions' => 'Cisse pådje ci',
-'qbpageinfo' => 'Contecse',
'qbmyoptions' => 'Mes pådjes',
'qbspecialpages' => 'Pådjes sipeciåles',
'qbbrowse' => 'Igdalikyat',
'qbedit' => 'Igliwat',
'qbpageoptions' => 'Ini nga pakli',
-'qbpageinfo' => 'Kontexto',
'qbmyoptions' => 'Akon mga pakli',
'qbspecialpages' => 'Mga pinaurog nga pakli',
'faq' => 'AGG',
'page-rss-feed' => '"$1" RSS nga feed',
'page-atom-feed' => '"$1" Atom nga feed',
'red-link-title' => '$1 (waray dida ini nga pakli)',
+'sort-descending' => 'Igpasunodsunod paubos',
+'sort-ascending' => 'Igpasunodsunod paigbaw',
# Short words for each namespace, by default used in the namespace tab in monobook
'nstab-main' => 'Pakli',
'directorycreateerror' => 'Waray makahimo han direktoryo nga "$1".',
'filenotfound' => 'Diri nabibilngan an paypay nga "$1"',
'fileexistserror' => "Diri nasusuratan ha paypay nga ''$1'': Aada na an paypay.",
+'unexpected' => 'Diri ginlalauman nga balor: "$1"="$2".',
'formerror' => 'Sayop: Diri nasusumite an porma.',
'badarticleerror' => 'Ini nga pagbuhat diri mahihimo dinhi nga pakli',
'cannotdelete' => 'An pakli o an fayl nga "$1" diri napapara.
Bangin na ini ginpara hin iba.',
'cannotdelete-title' => 'diri nakakapara han pakli "$1"',
+'delete-hook-aborted' => 'Pagpara ginpugngan han kawil. Waray eksplenasyon an ginhatag.',
'badtitle' => 'Maraot nga titulo',
'badtitletext' => 'An ginhangyo nga pakli diri puyde, waray sulod, o sayop nga nasumpay nga inter-pinunongan o inter-wiki nga titulo.
Bangin mayda usa o damo nga mga agi nga diri puyde magamit ha mga titulo.',
Kweri: $2',
'viewsource' => 'Kitaa an ginkuhaan',
'viewsource-title' => 'Kitaa an tinikangan para han $1',
+'actionthrottled' => 'Ginpahinay an ginbuhat',
'actionthrottledtext' => 'Komo uska pangontra ha spam, ikaw in ginlilimitaran paghimo hini nga pagbuhat hin sobra kadamo ha sulod hin gutiay nga oras, ngan ikaw in naglapos hini nga katubtuban.
Alayon pagutro kahuman hin pipira ka mga minuto.',
'protectedpagetext' => 'Ini nga pakli in pinasaliporan para mapugngan an mga pagliwat.',
'viewyourtext' => "Puydi nim makit-an ngan makopya an tinikangan han '''imo mga pagliwat''' ha dinhi nga pakli:",
'sqlhidden' => '(nakatago an SQL query)',
'namespaceprotected' => "Diri ka gintutugutan pagliwat han mga pakli ha ngaran-lat'ang nga '''$1'''.",
+'customcssprotected' => 'Diri ka gintutugotan pagliwat hini nga CSS nga pakli, tungod nga nagsusulod ini hin kanan iba nga tawo personal nga karuyagon.',
+'customjsprotected' => 'Diri ka gintutugotan pagliwat hini nga JavaScript nga pakli, tungod nga nagsusulod ini hin kanan iba nga tawo personal nga karuyagon.',
'ns-specialprotected' => 'Diri maliliwat an mga ispisyal nga pakli.',
'titleprotected' => 'Ini nga titulo pinasalipod ha paghimo ni [[User:$1|$1]].
An katadungan nga ginhatag amo in "\'\'$2\'\'".',
+'filereadonlyerror' => 'Diri maliliwat ini nga paypay "$1" tungod an ginsusudlan han paypay nga "$2" in aada la ha pagbasa-la nga kahimtang.
+
+An magdudurmara nga nagtrangka hini in naghatag hini nga eksplenasyon: "$3".',
'exception-nologin' => 'Diri nakalog-in',
'exception-nologin-text' => 'Ini nga pakli o pagbuhat in nagkikinahanglan nga ikaw in mag-log-in ha dinhi nga wiki.',
Alayon pagpili hin lain nga ngaran.',
'loginerror' => 'Sayop hin pagsakob',
'createaccounterror' => 'Diri makakahimo hin akawnt: $1',
+'nocookieslogin' => '{{SITENAME}} in nagkikinahanglan hin mga kuki para makapagpalog-in hin mga gumaramit. An im mga kuki in diri nagana.
+Alayon paganaha hira ngan utro liwat.',
'loginsuccesstitle' => 'Malinamposon an pagsulod',
+'loginsuccess' => "'''Ikaw in nakalog-in ha {{SITENAME}} komo \"\$1\".'''",
+'nosuchuser' => 'Waray gumaramit an may-ada ngaran nga "$1".
+It mga agnay-hi-gumaramit in case sensitive.
+Panginano-a it imo pagbaybay, o [[Special:UserLogin/signup|paghimo hin bag-o nga akawnt]].',
'nosuchusershort' => 'Waray nagamit it may ngaran nga "$1".
Kitaa kun amo it im pagbaybay.',
'nouserspecified' => 'Dapat nim magbutang hin agnay hit gumaramit.',
Alayon pagutro pagbutang.',
'passwordtooshort' => 'An tigaman-pagsulod dapat diri maubos hit {{PLURAL:$1|1 nga agi|$1 nga agi}}.',
'password-name-match' => 'An imo tigaman-pagsulod in kinahanglan iba ha imo agnay-hiton-gumaramit.',
+'password-login-forbidden' => 'An paggamit hini nga agnay-hit-gumaramit ngan tigaman-pagsulod in diri gintutugotan.',
'mailmypassword' => 'Ig-e-mail an bag-o nga tigaman-pagsulod',
'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".',
'newpassword' => 'Bag-o nga tigaman-pagsulod:',
'retypenew' => 'Utroha pagbutang an bag-o nga tigaman-pagsulod:',
'resetpass_forbidden' => 'Diri mababalyoan an mga tigaman-pagsulod',
+'resetpass-no-info' => 'Kinahanglan mo paglog-in para direkta ka makasakob dinhi nga pakli.',
'resetpass-submit-loggedin' => 'Igbal-iw an tigaman-pagsulod',
'resetpass-submit-cancel' => 'Pasagdi',
'resetpass-temp-password' => 'Temporaryo nga tigaman-pagsakob:',
# Special:PasswordReset
'passwordreset-username' => 'Agnay hiton gumaramit:',
'passwordreset-domain' => 'Dominyo:',
+'passwordreset-capture' => 'Kikitaon mo an resulta nga e-mail?',
'passwordreset-email' => 'E-mail adres:',
'passwordreset-emailtitle' => 'Mga detalye han akawnt ha {{SITENAME}}',
'passwordreset-emailelement' => 'Agnay han gumaramit: $1
'passwordreset-emailsent' => 'Ginpadara hin usa ka pahinumdom nga e-mail.',
# Special:ChangeEmail
+'changeemail' => 'Igliwan an e-mail address',
+'changeemail-header' => 'Igliwan an e-mail address akawnt',
+'changeemail-text' => 'Igkompleto ini nga porma para makapagliwan han imo e-mail address. Kinahanglanon mo igbutang an imo tigaman-pagsulod para makompirma ini nga pagbag-o.',
+'changeemail-no-info' => 'Kinahanglanon mo mag-log-in para ka direkta makasakob hini nga pakli.',
+'changeemail-oldemail' => 'Yana nga e-mail address:',
+'changeemail-newemail' => 'Bag-o nga e-mail address:',
'changeemail-none' => '(waray)',
'changeemail-submit' => 'Igbalyo an e-mail',
'changeemail-cancel' => 'Pasagdi',
'note' => "'''Pahibaro:'''",
'previewnote' => "'''Hinumdumi nga pahiuna-nga-paggawas pa la ini.'''
¡Waray pa katipig an imo mga ginbag-o!",
+'continue-editing' => 'Padayon pagliwat',
'editing' => 'Ginliliwat an $1',
'creating' => 'Ginhihimo an $1',
'editingsection' => 'Ginliliwat an $1 (bahin)',
'edit-no-change' => 'Ginpabay-an an im pagliwat, mahitungod nga waray pagbalyo nga nabuhat ha nakasurat.',
'edit-already-exists' => 'Diri nakakahimo hin bag-o nga pakli.
Aada na ito.',
+'defaultmessagetext' => 'Aada-nga-daan nga teksto han mensahe',
+
+# Content models
+'content-model-wikitext' => 'wikiteksto',
+'content-model-text' => 'yano nga teksto',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
# Parser/template warnings
'post-expand-template-inclusion-warning' => "'''Pahimatngon:''' An batakan nga ginlakip in sobra kadako.
'history-feed-item-nocomment' => '$1 ha $2',
# Revision deletion
+'rev-deleted-comment' => '(gintanggal an kaagi han dalikyat nga sumat)',
'rev-deleted-user' => '(gintanggal an agnay hiton gumaramit)',
+'rev-deleted-event' => '(gintanggal an talaan han mga buhat)',
+'rev-deleted-user-contribs' => '[gintanggal an agnay-hit-gumaramit o IP address - an pagliwat in gintago tikang han mga amot]',
+'rev-suppressed-no-diff' => "Diri mo makikita ini nga kaibhan tungod nga usa ha mga rebisyon in '''ginpara'''.",
'rev-delundel' => 'igpakita/igtago',
'rev-showdeleted' => 'igpakita',
'revdelete-show-file-confirm' => 'Sigurado ka nga gusto mo makita an ginpara nga pagliwat han file "<nowiki>$1</nowiki>" tikang $2 ha $3?',
'revdel-restore' => 'igliwat an nakikit-an',
'revdel-restore-deleted' => 'napara nga mga pagbag-o',
'revdel-restore-visible' => 'Mga nakikit-an nga pagbabag-o',
+'pagehist' => 'Kaagi han pakli',
+'deletedhist' => 'Ginpara nga kaagi',
+'revdelete-hide-current' => 'Sayop in natago ha butang nga may petsa $2, $1: Ini an yana nga rebisyon.
+Diri ini matatago.',
+'revdelete-show-no-access' => 'May-ada sayo nga nagpapakita ha butang nga may petsa $2, $1. Ini nga butang in nakamarka nga "diri malalabtan".
+Diri mo ini malalabtan.',
'revdelete-otherreason' => 'Lain/dugang nga katadungan:',
'revdelete-reasonotherlist' => 'Lain nga katadongan',
'revdelete-edit-reasonlist' => 'Igliwat an mga katadungan han pagpara',
'search-suggest' => 'Buot sidngon mo ba: $1',
'search-interwiki-caption' => 'Mga bugto nga proyekto',
'search-interwiki-default' => '$1 nga resulta:',
+'search-relatedarticle' => 'kasumapy',
'searchrelated' => 'kadugtong',
'searchall' => 'ngatanan',
'showingresultsheader' => "{{PLURAL:$5|Resulta '''$1''' han '''$3'''|Mga resulta '''$1 - $2''' han '''$3'''}} para ha '''$4'''",
'powersearch' => 'Abansado nga pagbiling',
'powersearch-legend' => 'Abansado nga pagbiling',
'powersearch-field' => 'Bilnga an',
+'powersearch-togglelabel' => 'Panginano-a:',
'powersearch-toggleall' => 'Ngatanan',
'powersearch-togglenone' => 'Waray',
'search-external' => 'Gawas nga pamiling',
+'searchdisabled' => '{{SITENAME}} nga pamiling in ginparong.
+Pamilnga la anay pinaagi ha Google ha pagkayana.
+Ginpapasabot nga an sulod han mga panudlok han {{SITENAME}} in bangin daan an.',
# Quickbar
+'qbsettings' => 'Quickbar',
'qbsettings-none' => 'Waray',
'qbsettings-fixedleft' => 'Ginayad an wala',
'qbsettings-fixedright' => 'Gin-ayad an to-o',
'prefs-rc' => 'Kalalabay la nga mga pagbabag-o',
'prefs-watchlist-days' => 'Mga adlaw nga makikita ha barantayan:',
'prefs-resetpass' => 'Igliwan an tigaman-pagsulod',
+'prefs-rendering' => 'Hitsura',
+'saveprefs' => 'Igtipig',
+'resetprefs' => 'Pabay-i an diri nakatipig nga mga pagbabag-o',
+'restoreprefs' => 'Igbalik ngatanan ngada ha kahimtang nga aada-nga-daan',
'prefs-editing' => 'Ginliliwat',
+'prefs-edit-boxsize' => 'Kadako han bintana han pagliwat.',
'rows' => 'Mga rumbay pahigda:',
'columns' => 'Mga rumbay patindog:',
'searchresultshead' => 'Bilnga',
'savedprefs' => 'Gintipig an im karuyag.',
'timezonelegend' => 'Zona hin oras',
'localtime' => 'Oras nga lokal',
+'servertime' => 'Oras han serbidor:',
+'guesstimezone' => 'Butanga tikang han panngaykay(browser)',
'timezoneregion-africa' => 'Aprika',
'timezoneregion-america' => 'Amerika',
'timezoneregion-antarctica' => 'Antarktika',
'timezoneregion-pacific' => 'Kalawdan Pasipiko',
'prefs-searchoptions' => 'Pamilnga',
'prefs-namespaces' => "Ngaran-lat'ang",
+'default' => 'aada-nga-daan',
'prefs-files' => 'Mga paypay',
'youremail' => 'E-mail:',
'username' => 'Agnay hiton gumaramit:',
'userrights-user-editname' => 'Igbutang an agnay han gumaramit:',
'editusergroup' => 'Igliwat han mga hugpo han gumaramit',
'editinguser' => "Igliliwat an mga katungod han gumaramit han gumaramit '''[[Gumaramit:$1|$1]]''' $2",
+'userrights-editusergroup' => 'Igliwat an mga hugpo hin gumaramit',
+'saveusergroups' => 'Igtipig an mga hugpo han gumaramit',
'userrights-groupsmember' => 'Api han:',
'userrights-reason' => 'Katadungan:',
'userrights-no-interwiki' => '
'action-createpage' => 'pahimo hin mga pakli',
'action-minoredit' => 'butanga hin tigaman hinin nga pagliwat komo gutiay',
'action-move' => 'balhina ini nga pakli',
+'action-movefile' => 'igbalhin ini nga paypay',
+'action-upload' => 'igkarga-pasaka ini nga paypay',
+'action-reupload' => 'igsapaw ini nga aanhi nga paypay',
'action-delete' => 'paraa ini nga pakli',
'action-deleterevision' => 'igpara ini nga pagbag-o',
# Upload
'upload' => 'Pagkarga hin file',
'uploadbtn' => 'Igkarga an file',
+'uploadnologin' => 'Diri nakalog-in',
'upload-recreate-warning' => "'''Pahimatngon: An fayl nga may-ada hiton nga ngaran in ginpara o ginbalhin.'''
An taramdan han pagpara ngan pagbalhin para hini nga pakli in ginhahatag para han imo kamurayaw:",
'illegal-filename' => 'An ngaran han fayl in diri gintutugutan.',
'unknown-error' => 'Nahitabo an waray kasasabti nga sayop.',
'uploadwarning' => 'Pahimatngon han pagkarga paigbaw',
+'savefile' => 'Igtipig an paypay',
'uploadedimage' => 'ginkarga-paigbaw "[[$1]]"',
+'overwroteimage' => 'Ginkaraga an bag-o nga bersyon han "[[$1]]"',
+'uploaddisabled' => 'Waray ginpagana an pagkarga paigbaw',
+'copyuploaddisabled' => 'An pagkarga paigbaw pinaagi hin URL in waray ginpagana',
+'uploadfromurl-queued' => 'An imo ginkarga-paigbaw hin nakapila.',
+'uploaddisabledtext' => 'An mga pagkarga-paigbaw in diri ginpapagana.',
+'php-uploaddisabledtext' => 'An mga pagkarga-paigbaw han paypay in diri ginpapagana ha PHP.
+Alayon panginanoi an kahimtang han file_uploads.',
+'uploadscripted' => 'Ini nga paypay in nagsusulod hin HTML o script code nga puydi masayopan paghubad an web browser.',
'uploadvirus' => 'Ini nga fayl may-ada sulod nga bayrus!
Mga detalye: $1',
'upload-source' => 'Tinikangan nga fayl',
'sourcefilename' => 'Tinikangan nga ngaran han fayl:',
+'sourceurl' => 'Tinikangan nga URL:',
+'destfilename' => 'Kakadtoan nga ngaran-hin-paypay:',
+'upload-maxfilesize' => 'Pinakadamo nga kadako han paypay: $1',
+'upload-description' => 'Pangilal-an han paypay',
+'upload-options' => 'Mga pirilion han pagkarga paigbaw',
+'watchthisupload' => 'Bantayi ini nga paypay',
+'upload-success-subj' => 'Malinamposan an imo pagkarga-paigbaw.',
+'upload-success-msg' => 'An imo pagkarga-paigbaw tikang ha [$2] in malinamposon. Ini in aada dinhi: [[:{{ns:file}}:$1]]',
+'upload-failure-subj' => 'May-ada problema an pagkarga-paigbaw',
+'upload-failure-msg' => 'May-ada problema an imo pagkarga-paigbaw tikang ha [$2]:
+
+$1',
'upload-warning-subj' => 'Pahimatngon han pagkarga paigbaw',
+'upload-proto-error' => 'Sayop nga protocol',
+'upload-file-error' => 'Sayop ha sulod',
'upload-unknown-size' => 'Waray kasabti an kadako',
+# File backend
+'backend-fail-delete' => 'Diri nakakapara han paypay nga "$1".',
+'backend-fail-alreadyexists' => 'May-ada na paypay nga "$1".',
+'backend-fail-store' => 'Diri nakakatipig han paypay "$1" ha "$".',
+'backend-fail-copy' => 'Diri nakakakopya han paypay nga "$1" ngada "$2".',
+'backend-fail-move' => 'Diri nakakabalhin han paypay "$1" ngada "$2".',
+'backend-fail-opentemp' => 'Diri nakakaabre han temporaryo nga paypay.',
+'backend-fail-writetemp' => 'Diri nakakasurat ngada ha temporaryo nga paypay.',
+'backend-fail-closetemp' => 'Diri nasasara an temporaryo nga paypay.',
+'backend-fail-read' => 'Diri nababasahan han paypay nga "$1".',
+'backend-fail-create' => 'Diri nasusuratan an paypay nga "$1".',
+'backend-fail-maxsize' => 'Diri nasusuratan an paypay nga "$1" tungod nga mas dako ini kaysa hin {{PLURAL:"$2|usa nga byte|$2 nga mga byte}}.',
+'backend-fail-readonly' => 'An panluyo nga tiripigan nga "$1" in ha pagkayana in panbasa-la. An rason nga ginhatag in: "\'\'$2\'\'"',
+
# img_auth script messages
'img-auth-accessdenied' => 'Diri gintutugutan makasulod',
'restriction-move' => 'Balhina',
'restriction-create' => 'Himo-a',
+# Restriction levels
+'restriction-level-all' => 'bisan ano nga katupngan',
+
# Undelete
+'undelete' => 'Igpakita an mga ginpara nga mga pakli',
'undeletelink' => 'igpakita/igbalik',
'undeleteviewlink' => 'kitaa',
'undeletecomment' => 'Katadungan:',
'blocklist-target' => 'Gin-iigo',
'blocklist-expiry' => 'Napan-os',
'blocklist-by' => 'Ginpupugngan an admin',
+'blocklist-reason' => 'Rason:',
'ipblocklist-submit' => 'Bilnga',
+'ipblocklist-localblock' => 'Lokal nga pagpugong',
'blocklink' => 'igpugong',
'unblocklink' => 'igtanggal an pagpugong',
'change-blocklink' => 'igliwan an papugong',
'blocklogpage' => 'Talaan han pagpugong',
'blocklogentry' => 'ginpugngan hi [[$1]] nga natatapos ha takna hin $2 $3',
'block-log-flags-nocreate' => 'diri gintutugutan an paghimo hin akawnt',
+'blockme' => 'Pugngi ako',
'proxyblocksuccess' => 'Human na.',
# Developer tools
'export-addcattext' => 'Igdugang an mga pakli tikang ha kaarangay:',
'export-addcat' => 'Dugngi',
'export-addnstext' => "Igdugang an mga pakli tikang ha ngaran-lat'ang:",
+'export-addns' => 'Dugngi',
# Namespace 8 related
'allmessagesname' => 'Ngaran',
# Special:Import
'import-upload-filename' => 'Ngaran han paypay:',
'import-comment' => 'Komento:',
+'importnopages' => 'Waray pakli nga ginpapaangbit.',
# Tooltip help for the actions
'tooltip-pt-userpage' => 'An imo pakli hin gumaramit',
# Attribution
'othercontribs' => 'Ginbasihan ha binuhat ni $1.',
+'others' => 'mga iba',
+'siteusers' => '{{SITENAME}} {{PLURAL:$2|gumaramit|mga gumaramit}} $1',
# Info page
+'pageinfo-header-basic' => 'Panguna nga pananabotan',
'pageinfo-header-edits' => 'Kaagi han pagliwat',
'pageinfo-header-restrictions' => 'Panalipod han pakli',
+'pageinfo-length' => 'Kahilaba han pakli (ha mga byte)',
+'pageinfo-article-id' => 'ID han pakli',
+'pageinfo-robot-policy' => 'Pamilnga an kahimtang han makina',
'pageinfo-robot-index' => 'Matutudlok',
'pageinfo-robot-noindex' => 'Diri matutudlok',
'pageinfo-views' => 'Ihap han mga naglantaw',
'exif-sharpness' => 'Pagkatarom',
'exif-gpstimestamp' => 'GPS nga oras (atomiko nga relo)',
'exif-gpsspeedref' => 'Sukol han kalaksi',
+'exif-countrydest' => 'Ginpapakita an nasod',
+'exif-countrycodedest' => 'Ginpapakita an kodigo han nasod',
+'exif-provinceorstatedest' => 'Ginpapakita an lalawigan o estado',
+'exif-citydest' => 'Ginpapakita an syudad',
+'exif-sublocationdest' => 'Ginpapakita an bahin-lokasyon han syudad',
+'exif-objectname' => 'Halipot nga titulo',
'exif-headline' => 'Katukiban',
'exif-source' => 'Tinikangan',
'exif-writer' => 'Manunurat',
'exif-languagecode' => 'Yinaknan',
'exif-iimcategory' => 'Kaarangay',
+'exif-datetimeexpires' => 'Ayaw gamita kahuman han',
+'exif-datetimereleased' => 'Ginpagawas han',
+'exif-cameraownername' => 'Tag-iya han kamera',
'exif-exposureprogram-1' => 'Mano-mano',
'exif-subjectdistance-value' => '$1 ka mga metro',
+'exif-meteringmode-0' => 'Waray kasabti',
+
'exif-lightsource-0' => 'Waray kasabti',
'exif-lightsource-9' => 'Maupay nga panahon',
'exif-lightsource-10' => 'Madampog nga panahon',
'exif-focalplaneresolutionunit-2' => 'pulgadas',
+'exif-gaincontrol-0' => 'Waray',
+
'exif-contrast-1' => 'Mahumok',
'exif-contrast-2' => 'Matig-a',
# Special:Version
'version' => 'Bersyon',
+'version-skins' => 'Mga panit',
'version-version' => '(Bersion $1)',
'version-license' => 'Lisensya',
'version-software-product' => 'Produkto',
# Special:FileDuplicateSearch
'fileduplicatesearch-submit' => 'Pamilnga',
-'fileduplicatesearch-noresults' => 'Waray nabilngan nga paypay nga an ngaran "$".',
+'fileduplicatesearch-noresults' => 'Waray nabilngan nga paypay nga an ngaran in "$".',
# Special:SpecialPages
'specialpages' => 'Mga pinaurog nga pakli',
+'specialpages-group-login' => 'Magpalista nga masakob / paghimo hin bag-o nga akawnt',
+'specialpages-group-users' => 'Mga gumaramit ngan mga katungod',
+'specialpages-group-highuse' => 'Mga pakli nga damo nagamit',
+'specialpages-group-pages' => 'Talaan hin mga pakli',
'specialpages-group-pagetools' => 'Mga higamit han pakli',
+'specialpages-group-wiki' => 'Datos ngan mga higamit han Wiki',
+'specialpages-group-redirects' => 'Ginreredirek an mga pakli nga pinaurog',
+'specialpages-group-spam' => 'Mga higamit han spam',
# Special:BlankPage
'blankpage' => 'Blanko nga pakli',
'qbbrowse' => 'Lemmi',
'qbedit' => 'Soppi',
'qbpageoptions' => 'Xëtuw tànneef',
-'qbpageinfo' => 'Xëtuw xibaar',
'qbmyoptions' => 'Samay tànneef',
'qbspecialpages' => 'Xëti jagleel',
'faq' => 'Laaj yi ëpp',
'qbbrowse' => 'בלעטערט',
'qbedit' => 'ענדערן',
'qbpageoptions' => 'דער בלאט',
-'qbpageinfo' => 'קאנטעקסט',
'qbmyoptions' => 'מיינע בלעטער',
'qbspecialpages' => 'ספעציעלע בלעטער',
'faq' => 'מערסטע געפרעגטע פראגעס',
'right-upload' => 'ארויפלאדן טעקעס',
'right-reupload' => 'איבערשרײַבן עקסיסטירנדע טעקע',
'right-reupload-own' => "איבערשרײַבן עקזיסטירנדע טעקעס וואָס מ'האט אַליין אַרויפֿגעלאָדן",
+'right-reupload-shared' => 'אריבערשרייבן טעקעס אויפן געמיינזאם מעדיע רעפאזיטאריום',
'right-upload_by_url' => 'ארויפֿלאָדן טעקעס פֿון אַ URL',
'right-purge' => 'ליידיקן דעם זייטל־זאפאס פאר א בלאט אן באשטעטיקונג',
'right-autoconfirmed' => 'רעדאקטירן האלב-געשיצטע בלעטער',
'badfilename' => 'טעקע נאמען איז געטוישט צו "$1".',
'filetype-mime-mismatch' => 'טעקע סופֿיקס ".$1" שטימט נישט מיטן MIME טיפ פון דער טעקע($2).',
'filetype-badmime' => 'טעקעס מיטן MIME טיפ "$1" טאר מען נישט ארויפלאדן.',
+'filetype-bad-ie-mime' => 'נישט מעגלעך ארויפלאד די טעקע ווייל אינטערנעץ עקספלארער וועט זי דערקענען ווי "$1", וואס איז א נישט דערלויבטער און פאטענציאעל געפערליכער טעקע טיפ.',
'filetype-unwanted-type' => "'''\".\$1\"''' איז אן אומרעקאמענדירטער טעקע־טיפ. {{PLURAL:\$3|רעקאמענדירטער טעקע־טיפ איז|רעקאמענדירטע טעקע־טיפן זענען}} \$2.",
'filetype-banned-type' => '\'\'\'".$1"\'\'\' {{PLURAL:$4|איז נישט קיין דערלויבטער טעקע־טיפ |זענען נישט קיין דערלויבטע טעקע־טיפן}}. {{PLURAL:$3|דערלויבטער טעקע־טיפ איז|דערלויבטע טעקע־טיפן זענען}} $2.',
'filetype-missing' => 'די טעקע האט נישט קיין פארברייטערונג (למשל ".jpg").',
'file-too-large' => 'די טעקע וואָס איר האט אײַנגעגעבן איז צו גרויס.',
'filename-tooshort' => 'דער טעקענאמען איז צו קורץ',
'filetype-banned' => 'דער טיפ טעקע איז געאַסרט',
+'verification-error' => 'די טעקע איז נישט אדורכגעגאנגען טעקע פרואוואונג.',
+'hookaborted' => 'די מאדיפיצירונג איר האט פרובירט קען נישט ווערן דורכגעפירט צוליב א פארברייטערונג.',
'illegal-filename' => 'דער טעקע־נאָמען איז נישט ערלויבט',
'overwrite' => 'מען טאָר נישט איבערשרײַבן אַן עקזיסטירנדע טעקע.',
'unknown-error' => 'אַן אומבאַקאַנט טעות איז פֿארגעקומען.',
'license-header' => 'ליצענץ:',
'nolicense' => 'גארנישט',
'license-nopreview' => '(פֿאראויסקוק נישט פֿאַראַן)',
+'upload_source_url' => ' (א גילטיקע , צוגעגנלעכער URL)',
'upload_source_file' => '(א טעקע אויף אײַער קאמפיוטער)',
# Special:ListFiles
'filerevert-defaultcomment' => 'צוריקגעשטעלט צו דער ווערסיע פֿון $2, $1',
'filerevert-submit' => 'צוריקדרייען',
'filerevert-success' => "'''[[Media:$1|$1]]''' צוריקגשטעלט צו דער [$4 ווערסיע פֿון $3, $2].",
+'filerevert-badversion' => 'נישט פאראן קיין פריערדיקע לאקאלע ווערסיע פון דער טעקע מיטן געזוכטן צייטשטעמפל.',
# File deletion
'filedelete' => 'מעק אויס $1',
'namespace' => 'נאמענטייל:',
'invert' => 'ווײַז אַלע אויסער די',
'namespace_association' => 'אָנגעבונדענער נאָמענטייל',
+'tooltip-namespace_association' => 'צייכנט דאס קעסטל כדי איינשליסן דעם שמועס אדער סוביעקט נאמענטייל וואס געהערט צום אויסגעקליבענעם נאמענטייל',
'blanknamespace' => '(הויפט)',
# Contributions
'imageinvalidfilename' => 'דער ציל טעקע נאָמען איז נישט גילטיק.',
'fix-double-redirects' => 'דערהײַנטיקן ווײַטערפֿירונגען צום ארגינעלן טיטל',
'move-leave-redirect' => 'איבערלאזן א ווײַטערפֿירונג',
+'move-over-sharedrepo' => '== טעקע עקזיסטירט ==
+[[:$1]] עקזיסטירט אויף א געטיילטן רעפאזיטאריום. ווען מען באוועגט א טעקע צו דעם טיטל וועט דאס איבערשרייבן די געטיילטע טעקע.',
+'file-exists-sharedrepo' => "ס'איז שוין פאראן א טעקע מיטן געקליבענעם נאמען אויף א געמיינזאם רעפאזיטאריום.
+זייט אזוי גוט קלייבט אן אנדער נאמען.",
# Export
'export' => 'עקספארטירן בלעטער',
'import-interwiki-templates' => 'איינשילסן אלע מוסטערן',
'import-interwiki-submit' => 'אימפארט',
'import-interwiki-namespace' => 'ציל נאמענטייל:',
+'import-interwiki-rootpage' => 'ציל שטאמבלאט (אפציאנאל):',
'import-upload-filename' => 'טעקע נאמען:',
'import-comment' => 'הערה:',
'importtext' => 'ביטע עקספארטירט די טעקע פון דער מקור וויקי ניצנדיג דאס [[Special:Export|עקספארט הילפמיטל]], שפייכלט אײַן אויף אײַער קאמפיוטער און לאדט אַרויף דא.',
'import-error-interwiki' => 'דעם בלאט "$1" קען מען נישט אימפארטירן ווייל זיין נאמען איז רעזערווירט פאר דרויסנדיקער פארבינדונג (אינטערוויקי).',
'import-error-special' => 'דעם בלאט "$1" קען מען נישט אימפארטירן ווייל ער געהערט צו א באזונדערן נאמענטייל וואס אנטהאלט נישט קיין בלעטער.',
'import-error-invalid' => 'דעם בלאט "$1" קען מען נישט אימפארטירן ווייל זיין נאמען איז אומגילטיק.',
+'import-options-wrong' => '{{PLURAL:$2|פאלשער אויסקלייב|פאלשע אויסקלייבן}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'געגעבענער שטאמבלאט איז אן אומגילטיקער טיטל.',
'import-rootpage-nosubpage' => 'נאמענטייל "$1" פונעם שטאמבלאט ערלויבט נישט קיין אונטערבלעטער.',
# Import log
'exif-saturation' => 'זעטיקונג',
'exif-sharpness' => 'שארף',
'exif-devicesettingdescription' => 'אפאראט שטעלונגען אראפמאלונג',
+'exif-imageuniqueid' => 'בילד־ID',
'exif-gpslatituderef' => 'צפון אדער דרום גארטל־ליניע',
'exif-gpslatitude' => 'גארטל־ליניע',
'exif-gpslongituderef' => 'מזרח אדער מערב לענג',
'exif-cameraownername' => 'אייגנטימער פון קאמערע',
'exif-label' => 'צעטל',
'exif-datetimemetadata' => 'דאטע ווען מעטאדאטן זענען געווען לעצט געענדערט',
+'exif-nickname' => 'אויספארמעלער נאמען פון בילד',
'exif-rating' => 'שאצונג (פֿון 5)',
'exif-rightscertificate' => 'רעכטן פארוואלטונג צערטיפיקאט',
'exif-copyrighted' => 'קאפירעכט סטאַטוס',
# EXIF attributes
'exif-compression-1' => 'אומ-צאמגעקוועטשט',
+'exif-copyrighted-true' => 'געשיצט מיט קאפירעכט',
+'exif-copyrighted-false' => 'פובליקער געביט',
+
'exif-unknowndate' => 'אומבאַוואוסטע דאַטע',
'exif-orientation-1' => 'נארמאַל',
'qbbrowse' => 'Ìṣíwò',
'qbedit' => 'Àtúnṣe',
'qbpageoptions' => 'Ojúewé yi',
-'qbpageinfo' => 'Àjọwípọ̀',
'qbmyoptions' => 'Àwọn ojúewé mi',
'qbspecialpages' => 'Àwọn ojúewé pàtàkì',
'faq' => 'FAQ',
'qbbrowse' => '瀏覽',
'qbedit' => '編輯',
'qbpageoptions' => '呢一頁',
-'qbpageinfo' => '附近文字',
'qbmyoptions' => '我嘅選項',
'qbspecialpages' => '特別頁',
'faq' => 'FAQ',
'qbbrowse' => 'Blaeren',
'qbedit' => 'Bewerk',
'qbpageoptions' => 'Paginaopties',
-'qbpageinfo' => 'Pagina-informaotie',
'qbmyoptions' => 'Mien opties',
'qbspecialpages' => 'Speciaole pahina’s',
'faq' => 'FAQ (veehestelde vraehen)',
'qbbrowse' => '浏览',
'qbedit' => '编辑',
'qbpageoptions' => '页面选项',
-'qbpageinfo' => '页面信息',
'qbmyoptions' => '我的选项',
'qbspecialpages' => '特殊页面',
'faq' => '常见问题',
'spam_deleting' => '正在删除所有包含至$1的版本',
# Info page
-'pageinfo-title' => '"$1" 的信息',
+'pageinfo-title' => '“$1”的信息',
'pageinfo-header-basic' => '基本信息',
'pageinfo-header-edits' => '编辑历史',
'pageinfo-header-restrictions' => '页面保护',
'pageinfo-robot-policy' => '搜索引擎状态',
'pageinfo-robot-index' => '可索引',
'pageinfo-robot-noindex' => '不可索引',
-'pageinfo-views' => '视图的数量',
+'pageinfo-views' => '查看次数',
'pageinfo-watchers' => '页面监视者人数',
'pageinfo-redirects-name' => '重定向到本页',
'pageinfo-subpages-name' => '本页的子页面',
'pageinfo-lasttime' => '最后编辑的日期',
'pageinfo-edits' => '总编辑次数',
'pageinfo-authors' => '不同编者总计',
-'pageinfo-recent-edits' => '最近的编辑数 ($1天内)',
+'pageinfo-recent-edits' => '最近的编辑数($1内)',
'pageinfo-recent-authors' => '最近的不同编者数',
'pageinfo-magic-words' => '魔术字 ($1)',
'pageinfo-hidden-categories' => '隐藏分类 ($1)',
'qbbrowse' => '瀏覽',
'qbedit' => '編輯',
'qbpageoptions' => '頁面選項',
-'qbpageinfo' => '頁面訊息',
'qbmyoptions' => '我的選項',
'qbspecialpages' => '特殊頁面',
'faq' => '常見問題解答',
'spam_deleting' => '所有包含連結至$1的修訂,刪除中',
# Info page
-'pageinfo-title' => '" $1 "的信息',
+'pageinfo-title' => '“$1”的信息',
+'pageinfo-not-current' => '資訊可能只顯示在當前的修訂版本。',
'pageinfo-header-basic' => '基本資料',
'pageinfo-header-edits' => '編輯歷史',
'pageinfo-header-restrictions' => '保護頁面',
--- /dev/null
+-- Add fa_sha1 and related index
+ALTER TABLE /*$wgDBprefix*/filearchive
+ ADD COLUMN fa_sha1 varbinary(32) NOT NULL default '';
+CREATE INDEX /*i*/fa_sha1 ON /*$wgDBprefix*/filearchive (fa_sha1(10));
--- /dev/null
+ALTER TABLE /*_*/job
+ ADD COLUMN job_random integer unsigned NOT NULL default 0,
+ ADD COLUMN job_token varbinary(32) NOT NULL default '',
+ ADD COLUMN job_token_timestamp varbinary(14) NULL default NULL,
+ ADD COLUMN job_sha1 varbinary(32) NOT NULL default '';
+
+CREATE INDEX /*i*/job_sha1 ON /*_*/job (job_sha1);
+CREATE INDEX /*i*/job_cmd_token ON /*_*/job (job_cmd,job_token,job_random);
+
--- /dev/null
+-- Patch to add the sites and site_identifiers tables.
+-- Licence: GNU GPL v2+
+-- Author: Jeroen De Dauw < jeroendedauw@gmail.com >
+
+
+-- Holds all the sites known to the wiki.
+CREATE TABLE IF NOT EXISTS /*_*/sites (
+-- Numeric id of the site
+ site_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+
+ -- Global identifier for the site, ie 'enwiktionary'
+ site_global_key varbinary(32) NOT NULL,
+
+ -- Type of the site, ie 'mediawiki'
+ site_type varbinary(32) NOT NULL,
+
+ -- Group of the site, ie 'wikipedia'
+ site_group varbinary(32) NOT NULL,
+
+ -- Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'
+ site_source varbinary(32) NOT NULL,
+
+ -- Language code of the sites primary language.
+ site_language varbinary(32) NOT NULL,
+
+ -- Protocol of the site, ie 'http://', 'irc://', '//'
+ -- This field is an index for lookups and is build from type specific data in site_data.
+ site_protocol varbinary(32) NOT NULL,
+
+ -- Domain of the site in reverse order, ie 'org.mediawiki.www.'
+ -- This field is an index for lookups and is build from type specific data in site_data.
+ site_domain VARCHAR(255) NOT NULL,
+
+ -- Type dependent site data.
+ site_data BLOB NOT NULL,
+
+ -- If site.tld/path/key:pageTitle should forward users to the page on
+ -- the actual site, where "key" is the local identifier.
+ site_forward bool NOT NULL,
+
+ -- Type dependent site config.
+ -- For instance if template transclusion should be allowed if it's a MediaWiki.
+ site_config BLOB NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/sites_global_key ON /*_*/sites (site_global_key);
+CREATE INDEX /*i*/sites_type ON /*_*/sites (site_type);
+CREATE INDEX /*i*/sites_group ON /*_*/sites (site_group);
+CREATE INDEX /*i*/sites_source ON /*_*/sites (site_source);
+CREATE INDEX /*i*/sites_language ON /*_*/sites (site_language);
+CREATE INDEX /*i*/sites_protocol ON /*_*/sites (site_protocol);
+CREATE INDEX /*i*/sites_domain ON /*_*/sites (site_domain);
+CREATE INDEX /*i*/sites_forward ON /*_*/sites (site_forward);
+
+
+
+-- Links local site identifiers to their corresponding site.
+CREATE TABLE IF NOT EXISTS /*_*/site_identifiers (
+ -- Key on site.site_id
+ si_site INT UNSIGNED NOT NULL,
+
+ -- local key type, ie 'interwiki' or 'langlink'
+ si_type varbinary(32) NOT NULL,
+
+ -- local key value, ie 'en' or 'wiktionary'
+ si_key varbinary(32) NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/site_ids_type ON /*_*/site_identifiers (si_type, si_key);
+CREATE INDEX /*i*/site_ids_site ON /*_*/site_identifiers (si_site);
+CREATE INDEX /*i*/site_ids_key ON /*_*/site_identifiers (si_key);
\ No newline at end of file
$repo = RepoGroup::singleton()->getLocalRepo();
# Get "active" revisions from the filearchive table
$output->handleOutput( "Searching for and deleting archived files...\n" );
- $res = $dbw->query( "SELECT fa_id,fa_storage_group,fa_storage_key FROM $tbl_arch" );
+ $res = $dbw->query( "SELECT fa_id,fa_storage_group,fa_storage_key,fa_sha1 FROM $tbl_arch" );
$count = 0;
foreach ( $res as $row ) {
$key = $row->fa_storage_key;
$group = $row->fa_storage_group;
$id = $row->fa_id;
$path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key;
- $sha1 = substr( $key, 0, strcspn( $key, '.' ) );
+ if( isset( $row->fa_sha1 ) ) {
+ $sha1 = $row->fa_sha1;
+ } else {
+ // old row, populate from key
+ $sha1 = LocalRepo::getHashFromKey( $key );
+ }
// Check if the file is used anywhere...
$inuse = $dbw->selectField( 'oldimage', '1',
array( 'oi_sha1' => $sha1,
}
if ( $d > 1 ) {
$lb = wfGetLB();
- $serverCount = $lb->getServerCount();
+ $serverCount = $lb->getServerCount();
for ( $i = 0; $i < $serverCount; $i++ ) {
$server = $lb->getServerInfo( $i );
$server['flags'] |= DBO_DEBUG;
$IP . '/includes/actions/',
$IP . '/includes/api/',
$IP . '/includes/cache/',
+ $IP . '/includes/content/',
$IP . '/includes/context/',
$IP . '/includes/db/',
$IP . '/includes/diff/',
private function getHooksFromFile( $file ) {
$content = file_get_contents( $file );
$m = array();
- preg_match_all( '/(?:wfRunHooks|Hooks\:\:run)\(\s*([\'"])(.*?)\1/', $content, $m );
+ preg_match_all( '/(?:wfRunHooks|Hooks\:\:run|ContentHandler\:\:runLegacyHooks)\(\s*([\'"])(.*?)\1/', $content, $m );
return $m[2];
}
'qbbrowse',
'qbedit',
'qbpageoptions',
- 'qbpageinfo',
'qbmyoptions',
'qbspecialpages',
'faq',
'info' => array(
'pageinfo-header',
'pageinfo-title',
+ 'pageinfo-not-current',
'pageinfo-header-basic',
'pageinfo-header-edits',
'pageinfo-header-restrictions',
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.archive ADD ar_content_format VARCHAR2(64);
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.archive ADD ar_content_model VARCHAR2(32);
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.category DROP COLUMN cat_hidden;
+
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.page ADD page_content_model VARCHAR2(32);
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.recentchanges DROP ( rc_moved_to_ns, rc_moved_to_title );
+
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.revision ADD rev_content_format VARCHAR2(64);
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.revision ADD rev_content_model VARCHAR2(32);
--- /dev/null
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.site_stats DROP COLUMN ss_admins;
+
page_random NUMBER(15,14) NOT NULL,
page_touched TIMESTAMP(6) WITH TIME ZONE,
page_latest NUMBER DEFAULT 0 NOT NULL, -- FK?
- page_len NUMBER DEFAULT 0 NOT NULL
+ page_len NUMBER DEFAULT 0 NOT NULL,
+ page_content_model VARCHAR2(32)
);
ALTER TABLE &mw_prefix.page ADD CONSTRAINT &mw_prefix.page_pk PRIMARY KEY (page_id);
CREATE UNIQUE INDEX &mw_prefix.page_u01 ON &mw_prefix.page (page_namespace,page_title);
-- Create a dummy page to satisfy fk contraints especially with revisions
INSERT INTO &mw_prefix.page
- VALUES (0, 0, ' ', NULL, 0, 0, 0, 0, current_timestamp, 0, 0);
+ VALUES (0, 0, ' ', NULL, 0, 0, 0, 0, current_timestamp, 0, 0, NULL);
/*$mw$*/
CREATE TRIGGER &mw_prefix.page_set_random BEFORE INSERT ON &mw_prefix.page
rev_deleted CHAR(1) DEFAULT '0' NOT NULL,
rev_len NUMBER NULL,
rev_parent_id NUMBER DEFAULT NULL,
- rev_sha1 VARCHAR2(32) NULL
+ rev_sha1 VARCHAR2(32) NULL,
+ rev_content_model VARCHAR2(32),
+ rev_content_format VARCHAR2(64)
);
ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_pk PRIMARY KEY (rev_id);
ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_fk1 FOREIGN KEY (rev_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
ar_len NUMBER,
ar_page_id NUMBER,
ar_parent_id NUMBER,
- ar_sha1 VARCHAR2(32) NULL
+ ar_sha1 VARCHAR2(32),
+ ar_content_model VARCHAR2(32),
+ ar_content_format VARCHAR2(64)
);
ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_fk1 FOREIGN KEY (ar_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX &mw_prefix.archive_i01 ON &mw_prefix.archive (ar_namespace,ar_title,ar_timestamp);
cat_title VARCHAR2(255) NOT NULL,
cat_pages NUMBER DEFAULT 0 NOT NULL,
cat_subcats NUMBER DEFAULT 0 NOT NULL,
- cat_files NUMBER DEFAULT 0 NOT NULL,
- cat_hidden NUMBER DEFAULT 0 NOT NULL
+ cat_files NUMBER DEFAULT 0 NOT NULL
);
ALTER TABLE &mw_prefix.category ADD CONSTRAINT &mw_prefix.category_pk PRIMARY KEY (cat_id);
CREATE UNIQUE INDEX &mw_prefix.category_u01 ON &mw_prefix.category (cat_title);
ss_total_pages NUMBER DEFAULT -1,
ss_users NUMBER DEFAULT -1,
ss_active_users NUMBER DEFAULT -1,
- ss_admins NUMBER DEFAULT -1,
ss_images NUMBER DEFAULT 0
);
CREATE UNIQUE INDEX &mw_prefix.site_stats_u01 ON &mw_prefix.site_stats (ss_row_id);
--- /dev/null
+<?php
+/**
+ * Optional upgrade script to populate the fa_sha1 field
+ *
+ * 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
+ */
+
+require_once( dirname( __FILE__ ) . '/Maintenance.php' );
+
+/**
+ * Maintenance script to populate the fa_sha1 field.
+ *
+ * @ingroup Maintenance
+ * @since 1.21
+ */
+class PopulateFilearchiveSha1 extends LoggedUpdateMaintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Populate the fa_sha1 field from fa_storage_key";
+ }
+
+ protected function getUpdateKey() {
+ return 'populate fa_sha1';
+ }
+
+ protected function updateSkippedMessage() {
+ return 'fa_sha1 column of filearchive table already populated.';
+ }
+
+ public function doDBUpdates() {
+ $startTime = microtime( true );
+ $dbw = wfGetDB( DB_MASTER );
+ $table = 'filearchive';
+ $conds = array( 'fa_sha1' => '', 'fa_storage_key IS NOT NULL' );
+ $this->output( "Populating fa_sha1 field from fa_storage_key\n" );
+ $endId = $dbw->selectField( $table, 'MAX(fa_id)', false, __METHOD__ );\r
+
+ $batchSize = $this->mBatchSize;
+ $done = 0;
+
+ do {
+ $res = $dbw->select(
+ $table,
+ array( 'fa_id', 'fa_storage_key' ),
+ $conds,
+ __METHOD__,
+ array( 'LIMIT' => $batchSize )
+ );
+
+ $i = 0;
+ foreach ( $res as $row ) {
+ $sha1 = LocalRepo::getHashFromKey( $row->fa_storage_key );
+ $dbw->update( $table,
+ array( 'fa_sha1' => $sha1 ),
+ array( 'fa_id' => $row->fa_id ),
+ __METHOD__
+ );
+ $lastId = $row->fa_id;
+ $i++;
+ }
+
+ $done += $i;
+ if( $i !== $batchSize ) {
+ break;
+ }
+
+ // print status and let slaves catch up
+ $this->output( sprintf(
+ "id %d done (up to %d), %5.3f%% \r", $lastId, $endId, $lastId / $endId * 100 ) );
+ wfWaitForSlaves();
+ } while( true );
+
+ $processingTime = microtime( true ) - $startTime;
+ $this->output( sprintf( "\nDone %d files in %.1f seconds\n", $done, $processingTime ) );
+
+ return true; // we only updated *some* files, don't log
+ }
+}
+
+$maintClass = "PopulateFilearchiveSha1";
+require_once( RUN_MAINTENANCE_IF_MAIN );
page_random NUMERIC(15,14) NOT NULL DEFAULT RANDOM(),
page_touched TIMESTAMPTZ,
page_latest INTEGER NOT NULL, -- FK?
- page_len INTEGER NOT NULL
+ page_len INTEGER NOT NULL,
+ page_content_model TEXT
);
CREATE UNIQUE INDEX page_unique_name ON page (page_namespace, page_title);
CREATE INDEX page_main_title ON page (page_title text_pattern_ops) WHERE page_namespace = 0;
CREATE SEQUENCE revision_rev_id_seq;
CREATE TABLE revision (
- rev_id INTEGER NOT NULL UNIQUE DEFAULT nextval('revision_rev_id_seq'),
- rev_page INTEGER NULL REFERENCES page (page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
- rev_text_id INTEGER NULL, -- FK
- rev_comment TEXT,
- rev_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED,
- rev_user_text TEXT NOT NULL,
- rev_timestamp TIMESTAMPTZ NOT NULL,
- rev_minor_edit SMALLINT NOT NULL DEFAULT 0,
- rev_deleted SMALLINT NOT NULL DEFAULT 0,
- rev_len INTEGER NULL,
- rev_parent_id INTEGER NULL,
- rev_sha1 TEXT NOT NULL DEFAULT ''
+ rev_id INTEGER NOT NULL UNIQUE DEFAULT nextval('revision_rev_id_seq'),
+ rev_page INTEGER NULL REFERENCES page (page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+ rev_text_id INTEGER NULL, -- FK
+ rev_comment TEXT,
+ rev_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED,
+ rev_user_text TEXT NOT NULL,
+ rev_timestamp TIMESTAMPTZ NOT NULL,
+ rev_minor_edit SMALLINT NOT NULL DEFAULT 0,
+ rev_deleted SMALLINT NOT NULL DEFAULT 0,
+ rev_len INTEGER NULL,
+ rev_parent_id INTEGER NULL,
+ rev_sha1 TEXT NOT NULL DEFAULT '',
+ rev_content_model TEXT,
+ rev_content_format TEXT
);
CREATE UNIQUE INDEX revision_unique ON revision (rev_page, rev_id);
CREATE INDEX rev_text_id_idx ON revision (rev_text_id);
CREATE INDEX page_props_propname ON page_props (pp_propname);
CREATE TABLE archive (
- ar_namespace SMALLINT NOT NULL,
- ar_title TEXT NOT NULL,
- ar_text TEXT, -- technically should be bytea, but not used anymore
- ar_page_id INTEGER NULL,
- ar_parent_id INTEGER NULL,
- ar_sha1 TEXT NOT NULL DEFAULT '',
- ar_comment TEXT,
- ar_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
- ar_user_text TEXT NOT NULL,
- ar_timestamp TIMESTAMPTZ NOT NULL,
- ar_minor_edit SMALLINT NOT NULL DEFAULT 0,
- ar_flags TEXT,
- ar_rev_id INTEGER,
- ar_text_id INTEGER,
- ar_deleted SMALLINT NOT NULL DEFAULT 0,
- ar_len INTEGER NULL
+ ar_namespace SMALLINT NOT NULL,
+ ar_title TEXT NOT NULL,
+ ar_text TEXT, -- technically should be bytea, but not used anymore
+ ar_page_id INTEGER NULL,
+ ar_parent_id INTEGER NULL,
+ ar_sha1 TEXT NOT NULL DEFAULT '',
+ ar_comment TEXT,
+ ar_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
+ ar_user_text TEXT NOT NULL,
+ ar_timestamp TIMESTAMPTZ NOT NULL,
+ ar_minor_edit SMALLINT NOT NULL DEFAULT 0,
+ ar_flags TEXT,
+ ar_rev_id INTEGER,
+ ar_text_id INTEGER,
+ ar_deleted SMALLINT NOT NULL DEFAULT 0,
+ ar_len INTEGER NULL,
+ ar_content_model TEXT,
+ ar_content_format TEXT
);
CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp);
CREATE INDEX archive_user_text ON archive (ar_user_text);
public function execute() {
global $wgTitle;
+
if ( $this->hasOption( 'procs' ) ) {
$procs = intval( $this->getOption( 'procs' ) );
if ( $procs < 1 || $procs > 1000 ) {
$dbw = wfGetDB( DB_MASTER );
$n = 0;
- if ( $type === false ) {
- $conds = Job::defaultQueueConditions( );
- } else {
- $conds = array( 'job_cmd' => $type );
- }
-
- while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) {
- $offset = 0;
- for ( ; ; ) {
- $job = !$type ? Job::pop( $offset ) : Job::pop_type( $type );
-
- if ( !$job ) {
- break;
- }
-
- wfWaitForSlaves();
+ $group = JobQueueGroup::singleton();
+ do {
+ $job = ( $type === false )
+ ? $group->pop() // job from any queue
+ : $group->get( $type )->pop(); // job from a single queue
+ if ( $job ) { // found a job
+ // Perform the job (logging success/failure and runtime)...
$t = microtime( true );
- $offset = $job->id;
$this->runJobsLog( $job->toString() . " STARTING" );
$status = $job->run();
+ $group->ack( $job ); // done
$t = microtime( true ) - $t;
$timeMs = intval( $t * 1000 );
if ( !$status ) {
} else {
$this->runJobsLog( $job->toString() . " t=$timeMs good" );
}
-
- if ( $maxJobs && ++$n > $maxJobs ) {
+ // Break out if we hit the job count or wall time limits...
+ if ( $maxJobs && ++$n >= $maxJobs ) {
break 2;
}
- if ( $maxTime && time() - $startTime > $maxTime ) {
+ if ( $maxTime && ( time() - $startTime ) > $maxTime ) {
break 2;
}
+ // Don't let any slaves/backups fall behind...
+ $group->get( $type )->waitForBackups();
}
- }
+ } while ( $job ); // stop when there are no jobs
}
/**
--- /dev/null
+ALTER TABLE /*_*/job ADD COLUMN job_random integer unsigned NOT NULL default 0;
+ALTER TABLE /*_*/job ADD COLUMN job_token varbinary(32) NOT NULL default '';
+ALTER TABLE /*_*/job ADD COLUMN job_sha1 varbinary(32) NOT NULL default '';
+ALTER TABLE /*_*/job ADD COLUMN job_token_timestamp varbinary(14) NULL default NULL;
+
+CREATE INDEX /*i*/job_sha1 ON /*_*/job (job_sha1);
+CREATE INDEX /*i*/job_cmd_token ON /*_*/job (job_cmd,job_token,job_random);
+
--- /dev/null
+-- Patch to add the sites and site_identifiers tables.
+-- Licence: GNU GPL v2+
+-- Author: Jeroen De Dauw < jeroendedauw@gmail.com >
+
+
+-- Holds all the sites known to the wiki.
+CREATE TABLE IF NOT EXISTS /*_*/sites (
+-- Numeric id of the site
+ site_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+
+ -- Global identifier for the site, ie 'enwiktionary'
+ site_global_key varbinary(32) NOT NULL,
+
+ -- Type of the site, ie 'mediawiki'
+ site_type varbinary(32) NOT NULL,
+
+ -- Group of the site, ie 'wikipedia'
+ site_group varbinary(32) NOT NULL,
+
+ -- Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'
+ site_source varbinary(32) NOT NULL,
+
+ -- Language code of the sites primary language.
+ site_language varbinary(32) NOT NULL,
+
+ -- Protocol of the site, ie 'http://', 'irc://', '//'
+ -- This field is an index for lookups and is build from type specific data in site_data.
+ site_protocol varbinary(32) NOT NULL,
+
+ -- Domain of the site in reverse order, ie 'org.mediawiki.www.'
+ -- This field is an index for lookups and is build from type specific data in site_data.
+ site_domain VARCHAR(255) NOT NULL,
+
+ -- Type dependent site data.
+ site_data BLOB NOT NULL,
+
+ -- If site.tld/path/key:pageTitle should forward users to the page on
+ -- the actual site, where "key" is the local identifier.
+ site_forward bool NOT NULL,
+
+ -- Type dependent site config.
+ -- For instance if template transclusion should be allowed if it's a MediaWiki.
+ site_config BLOB NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/sites_global_key ON /*_*/sites (site_global_key);
+CREATE INDEX /*i*/sites_type ON /*_*/sites (site_type);
+CREATE INDEX /*i*/sites_group ON /*_*/sites (site_group);
+CREATE INDEX /*i*/sites_source ON /*_*/sites (site_source);
+CREATE INDEX /*i*/sites_language ON /*_*/sites (site_language);
+CREATE INDEX /*i*/sites_protocol ON /*_*/sites (site_protocol);
+CREATE INDEX /*i*/sites_domain ON /*_*/sites (site_domain);
+CREATE INDEX /*i*/sites_forward ON /*_*/sites (site_forward);
+
+
+
+-- Links local site identifiers to their corresponding site.
+CREATE TABLE IF NOT EXISTS /*_*/site_identifiers (
+ -- Key on site.site_id
+ si_site INT UNSIGNED NOT NULL,
+
+ -- local key type, ie 'interwiki' or 'langlink'
+ si_type varbinary(32) NOT NULL,
+
+ -- local key value, ie 'en' or 'wiktionary'
+ si_key varbinary(32) NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/site_ids_type ON /*_*/site_identifiers (si_type, si_key);
+CREATE INDEX /*i*/site_ids_site ON /*_*/site_identifiers (si_site);
+CREATE INDEX /*i*/site_ids_key ON /*_*/site_identifiers (si_key);
\ No newline at end of file
page_len int unsigned NOT NULL,
-- content model, see CONTENT_MODEL_XXX constants
- page_content_model int unsigned default NULL
+ page_content_model varbinary(32) DEFAULT NULL
) /*$wgDBTableOptions*/;
CREATE UNIQUE INDEX /*i*/name_title ON /*_*/page (page_namespace,page_title);
rev_sha1 varbinary(32) NOT NULL default '',
-- content model, see CONTENT_MODEL_XXX constants
- rev_content_model int unsigned default NULL,
+ rev_content_model varbinary(32) DEFAULT NULL,
-- content format, see CONTENT_FORMAT_XXX constants
- rev_content_format int unsigned default NULL
+ rev_content_format varbinary(64) DEFAULT NULL
) /*$wgDBTableOptions*/ MAX_ROWS=10000000 AVG_ROW_LENGTH=1024;
-- In case tables are created as MyISAM, use row hints for MySQL <5.0 to avoid 4GB limit
ar_sha1 varbinary(32) NOT NULL default '',
-- content model, see CONTENT_MODEL_XXX constants
- ar_content_model int unsigned default NULL,
+ ar_content_model varbinary(32) DEFAULT NULL,
-- content format, see CONTENT_FORMAT_XXX constants
- ar_content_format int unsigned default NULL
+ ar_content_format varbinary(64) DEFAULT NULL
) /*$wgDBTableOptions*/;
fa_timestamp binary(14) default '',
-- Visibility of deleted revisions, bitfield
- fa_deleted tinyint unsigned NOT NULL default 0
+ fa_deleted tinyint unsigned NOT NULL default 0,
+
+ -- sha1 hash of file content
+ fa_sha1 varbinary(32) NOT NULL default ''
) /*$wgDBTableOptions*/;
-- pick out by image name
CREATE INDEX /*i*/fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp);
-- sort by uploader
CREATE INDEX /*i*/fa_user_timestamp ON /*_*/filearchive (fa_user_text,fa_timestamp);
+-- find file by sha1, 10 bytes will be enough for hashes to be indexed
+CREATE INDEX /*i*/fa_sha1 ON /*_*/filearchive (fa_sha1(10));
--
-- Any other parameters to the command
-- Stored as a PHP serialized array, or an empty string if there are no parameters
- job_params blob NOT NULL
+ job_params blob NOT NULL,
+
+ -- Random, non-unique, number used for concurrent job acquisition
+ job_random integer unsigned NOT NULL default 0,
+
+ -- Field that conveys process locks on rows via process UUIDs
+ job_token varbinary(32) NOT NULL default '',
+
+ -- Timestamp when the job was locked
+ job_token_timestamp varbinary(14) NULL default NULL,
+
+ -- Base 36 SHA1 of the job parameters relevant to detecting duplicates
+ job_sha1 varbinary(32) NOT NULL default ''
) /*$wgDBTableOptions*/;
+CREATE INDEX /*i*/job_sha1 ON /*_*/job (job_sha1);
+CREATE INDEX /*i*/job_cmd_token ON /*_*/job (job_cmd,job_token,job_random);
CREATE INDEX /*i*/job_cmd ON /*_*/job (job_cmd, job_namespace, job_title, job_params(128));
CREATE INDEX /*i*/job_timestamp ON /*_*/job (job_timestamp);
-- Should cover *most* configuration - strings, ints, bools, etc.
CREATE INDEX /*i*/cf_name_value ON /*_*/config (cf_name,cf_value(255));
+-- Holds all the sites known to the wiki.
+CREATE TABLE /*_*/sites (
+-- Numeric id of the site
+ site_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+
+ -- Global identifier for the site, ie 'enwiktionary'
+ site_global_key varbinary(32) NOT NULL,
+
+ -- Type of the site, ie 'mediawiki'
+ site_type varbinary(32) NOT NULL,
+
+ -- Group of the site, ie 'wikipedia'
+ site_group varbinary(32) NOT NULL,
+
+ -- Source of the site data, ie 'local', 'wikidata', 'my-magical-repo'
+ site_source varbinary(32) NOT NULL,
+
+ -- Language code of the sites primary language.
+ site_language varbinary(32) NOT NULL,
+
+ -- Protocol of the site, ie 'http://', 'irc://', '//'
+ -- This field is an index for lookups and is build from type specific data in site_data.
+ site_protocol varbinary(32) NOT NULL,
+
+ -- Domain of the site in reverse order, ie 'org.mediawiki.www.'
+ -- This field is an index for lookups and is build from type specific data in site_data.
+ site_domain VARCHAR(255) NOT NULL,
+
+ -- Type dependent site data.
+ site_data BLOB NOT NULL,
+
+ -- If site.tld/path/key:pageTitle should forward users to the page on
+ -- the actual site, where "key" is the local identifier.
+ site_forward bool NOT NULL,
+
+ -- Type dependent site config.
+ -- For instance if template transclusion should be allowed if it's a MediaWiki.
+ site_config BLOB NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/sites_global_key ON /*_*/sites (site_global_key);
+CREATE INDEX /*i*/sites_type ON /*_*/sites (site_type);
+CREATE INDEX /*i*/sites_group ON /*_*/sites (site_group);
+CREATE INDEX /*i*/sites_source ON /*_*/sites (site_source);
+CREATE INDEX /*i*/sites_language ON /*_*/sites (site_language);
+CREATE INDEX /*i*/sites_protocol ON /*_*/sites (site_protocol);
+CREATE INDEX /*i*/sites_domain ON /*_*/sites (site_domain);
+CREATE INDEX /*i*/sites_forward ON /*_*/sites (site_forward);
+
+-- Links local site identifiers to their corresponding site.
+CREATE TABLE /*_*/site_identifiers (
+ -- Key on site.site_id
+ si_site INT UNSIGNED NOT NULL,
+
+ -- local key type, ie 'interwiki' or 'langlink'
+ si_type varbinary(32) NOT NULL,
+
+ -- local key value, ie 'en' or 'wiktionary'
+ si_key varbinary(32) NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE UNIQUE INDEX /*i*/site_ids_type ON /*_*/site_identifiers (si_type, si_key);
+CREATE INDEX /*i*/site_ids_site ON /*_*/site_identifiers (si_site);
+CREATE INDEX /*i*/site_ids_key ON /*_*/site_identifiers (si_key);
+
-- vim: sw=2 sts=2 et
$updater->doUpdates( $updates );
foreach( $updater->getPostDatabaseUpdateMaintenance() as $maint ) {
- if ( $updater->updateRowExists( $maint ) ) {
+ $child = $this->runChild( $maint );
+
+ // LoggedUpdateMaintenance is checking the updatelog itself
+ $isLoggedUpdate = ( $child instanceof LoggedUpdateMaintenance );
+
+ if ( !$isLoggedUpdate && $updater->updateRowExists( $maint ) ) {
continue;
}
- $child = $this->runChild( $maint );
$child->execute();
- $updater->insertUpdateRow( $maint );
+ if ( !$isLoggedUpdate ) {
+ $updater->insertUpdateRow( $maint );
+ }
}
$this->output( "\nDone.\n" );
* @file
*/
-require './opensearch_desc.php';
+require './opensearch_desc.php';
/*!
- * jQuery UI Effects Blind 1.8.23
+ * jQuery UI Effects Blind 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Bounce 1.8.23
+ * jQuery UI Effects Bounce 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Clip 1.8.23
+ * jQuery UI Effects Clip 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects 1.8.23
+ * jQuery UI Effects 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/******************************************************************************/
$.extend($.effects, {
- version: "1.8.23",
+ version: "1.8.24",
// Saves a set of properties in a data storage
save: function(element, set) {
/*!
- * jQuery UI Effects Drop 1.8.23
+ * jQuery UI Effects Drop 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Explode 1.8.23
+ * jQuery UI Effects Explode 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Fade 1.8.23
+ * jQuery UI Effects Fade 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Fold 1.8.23
+ * jQuery UI Effects Fold 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Highlight 1.8.23
+ * jQuery UI Effects Highlight 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Pulsate 1.8.23
+ * jQuery UI Effects Pulsate 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Scale 1.8.23
+ * jQuery UI Effects Scale 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Shake 1.8.23
+ * jQuery UI Effects Shake 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Slide 1.8.23
+ * jQuery UI Effects Slide 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Effects Transfer 1.8.23
+ * jQuery UI Effects Transfer 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
currentText: '今天',
monthNames: ['一月','二月','三月','四月','五月','六月',
'七月','八月','九月','十月','十一月','十二月'],
- monthNamesShort: ['一','二','三','四','五','六',
- '七','八','九','十','十一','十二'],
+ monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
dayNamesMin: ['日','一','二','三','四','五','六'],
currentText: '今天',
monthNames: ['一月','二月','三月','四月','五月','六月',
'七月','八月','九月','十月','十一月','十二月'],
- monthNamesShort: ['一','二','三','四','五','六',
- '七','八','九','十','十一','十二'],
+ monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
dayNamesMin: ['日','一','二','三','四','五','六'],
currentText: '今天',
monthNames: ['一月','二月','三月','四月','五月','六月',
'七月','八月','九月','十月','十一月','十二月'],
- monthNamesShort: ['一','二','三','四','五','六',
- '七','八','九','十','十一','十二'],
+ monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
dayNamesMin: ['日','一','二','三','四','五','六'],
/*!
- * jQuery UI Accordion 1.8.23
+ * jQuery UI Accordion 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.accordion, {
- version: "1.8.23",
+ version: "1.8.24",
animations: {
slide: function( options, additions ) {
options = $.extend({
/*!
- * jQuery UI Autocomplete 1.8.23
+ * jQuery UI Autocomplete 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Button 1.8.23
+ * jQuery UI Button 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI 1.8.23
+ * jQuery UI 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
}
$.extend( $.ui, {
- version: "1.8.23",
+ version: "1.8.24",
keyCode: {
ALT: 18,
/*!
- * jQuery UI Datepicker 1.8.23
+ * jQuery UI Datepicker 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
*/
(function( $, undefined ) {
-$.extend($.ui, { datepicker: { version: "1.8.23" } });
+$.extend($.ui, { datepicker: { version: "1.8.24" } });
var PROP_NAME = 'datepicker';
var dpuuid = new Date().getTime();
$.datepicker = new Datepicker(); // singleton instance
$.datepicker.initialized = false;
$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "1.8.23";
+$.datepicker.version = "1.8.24";
// Workaround for #4055
// Add another global to avoid noConflict issues with inline event handlers
/*!
- * jQuery UI Dialog 1.8.23
+ * jQuery UI Dialog 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.dialog, {
- version: "1.8.23",
+ version: "1.8.24",
uuid: 0,
maxZ: 0,
/*!
- * jQuery UI Draggable 1.8.23
+ * jQuery UI Draggable 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
},
_mouseUp: function(event) {
- if (this.options.iframeFix === true) {
- $("div.ui-draggable-iframeFix").each(function() {
- this.parentNode.removeChild(this);
- }); //Remove frame helpers
- }
+ //Remove frame helpers
+ $("div.ui-draggable-iframeFix").each(function() {
+ this.parentNode.removeChild(this);
+ });
//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
});
$.extend($.ui.draggable, {
- version: "1.8.23"
+ version: "1.8.24"
});
$.ui.plugin.add("draggable", "connectToSortable", {
/*!
- * jQuery UI Droppable 1.8.23
+ * jQuery UI Droppable 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.droppable, {
- version: "1.8.23"
+ version: "1.8.24"
});
$.ui.intersect = function(draggable, droppable, toleranceMode) {
var parentInstance;
if (this.options.greedy) {
- var parent = this.element.parents(':data(droppable):eq(0)');
+ // find droppable parents with same scope
+ var scope = this.options.scope;
+ var parent = this.element.parents(':data(droppable)').filter(function () {
+ return $.data(this, 'droppable').options.scope === scope;
+ });
+
if (parent.length) {
parentInstance = $.data(parent[0], 'droppable');
parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
/*!
- * jQuery UI Mouse 1.8.23
+ * jQuery UI Mouse 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Position 1.8.23
+ * jQuery UI Position 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Progressbar 1.8.23
+ * jQuery UI Progressbar 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.progressbar, {
- version: "1.8.23"
+ version: "1.8.24"
});
})( jQuery );
/*!
- * jQuery UI Resizable 1.8.23
+ * jQuery UI Resizable 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.resizable, {
- version: "1.8.23"
+ version: "1.8.24"
});
/*
/*!
- * jQuery UI Selectable 1.8.23
+ * jQuery UI Selectable 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend($.ui.selectable, {
- version: "1.8.23"
+ version: "1.8.24"
});
})(jQuery);
/*!
- * jQuery UI Slider 1.8.23
+ * jQuery UI Slider 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.slider, {
- version: "1.8.23"
+ version: "1.8.24"
});
}(jQuery));
/*!
- * jQuery UI Sortable 1.8.23
+ * jQuery UI Sortable 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
if (!intersection) continue;
- if(itemElement != this.currentItem[0] //cannot intersect with itself
+ // Only put the placeholder inside the current Container, skip all
+ // items form other containers. This works because when moving
+ // an item from one container to another the
+ // currentContainer is switched before the placeholder is moved.
+ //
+ // Without this moving items in "sub-sortables" can cause the placeholder to jitter
+ // beetween the outer and inner container.
+ if (item.instance !== this.currentContainer) continue;
+
+ if (itemElement != this.currentItem[0] //cannot intersect with itself
&& this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
&& !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
- if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
- if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
- for (var i = this.containers.length - 1; i >= 0; i--){
- if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
- delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
- delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
- }
- };
- };
+
+ // Check if the items Container has Changed and trigger appropriate
+ // events.
+ if (this !== this.currentContainer) {
+ if(!noPropagation) {
+ delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
+ }
+ }
//Post events to containers
for (var i = this.containers.length - 1; i >= 0; i--){
});
$.extend($.ui.sortable, {
- version: "1.8.23"
+ version: "1.8.24"
});
})(jQuery);
/*!
- * jQuery UI Tabs 1.8.23
+ * jQuery UI Tabs 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
});
$.extend( $.ui.tabs, {
- version: "1.8.23"
+ version: "1.8.24"
});
/*
/*!
- * jQuery UI Widget 1.8.23
+ * jQuery UI Widget 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Accordion 1.8.23
+ * jQuery UI Accordion 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Autocomplete 1.8.23
+ * jQuery UI Autocomplete 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/*
- * jQuery UI Menu 1.8.23
+ * jQuery UI Menu 1.8.24
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Button 1.8.23
+ * jQuery UI Button 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI CSS Framework 1.8.23
+ * jQuery UI CSS Framework 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Datepicker 1.8.23
+ * jQuery UI Datepicker 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Dialog 1.8.23
+ * jQuery UI Dialog 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Progressbar 1.8.23
+ * jQuery UI Progressbar 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Resizable 1.8.23
+ * jQuery UI Resizable 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Selectable 1.8.23
+ * jQuery UI Selectable 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Slider 1.8.23
+ * jQuery UI Slider 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI Tabs 1.8.23
+ * jQuery UI Tabs 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/*!
- * jQuery UI CSS Framework 1.8.23
+ * jQuery UI CSS Framework 1.8.24
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
/**
- * Plugin that automatically truncates the plain text contents of an element and adds an ellipsis
+ * Plugin that automatically truncates the plain text contents of an element
+ * and adds an ellipsis.
*/
( function ( $ ) {
var
// Cache ellipsed substrings for every string-width-position combination
- cache = { },
+ cache = {},
// Use a separate cache when match highlighting is enabled
- matchTextCache = { };
+ matchTextCache = {};
$.fn.autoEllipsis = function ( options ) {
options = $.extend( {
hasSpan: false,
matchText: null
}, options );
- $(this).each( function () {
- var $container, $trimmableText,
+
+ return this.each( function () {
+ var $trimmableText,
text, trimmableText, w, pw,
l, r, i, side, m,
- $el = $(this);
+ // container element - used for measuring against
+ $container = $(this);
+
if ( options.restoreText ) {
- if ( !$el.data( 'autoEllipsis.originalText' ) ) {
- $el.data( 'autoEllipsis.originalText', $el.text() );
+ if ( !$container.data( 'autoEllipsis.originalText' ) ) {
+ $container.data( 'autoEllipsis.originalText', $container.text() );
} else {
- $el.text( $el.data( 'autoEllipsis.originalText' ) );
+ $container.text( $container.data( 'autoEllipsis.originalText' ) );
}
}
- // container element - used for measuring against
- $container = $el;
-
// trimmable text element - only the text within this element will be trimmed
if ( options.hasSpan ) {
- $trimmableText = $el.children( options.selector );
+ $trimmableText = $container.children( options.selector );
} else {
$trimmableText = $( '<span>' )
.css( 'whiteSpace', 'nowrap' )
- .text( $el.text() );
- $el
+ .text( $container.text() );
+ $container
.empty()
.append( $trimmableText );
}
};
$.fn.highlightText = function ( matchString ) {
- return $( this ).each( function () {
+ return this.each( function () {
var $el = $( this );
$el.data( 'highlightText', { originalText: $el.text() } );
$.highlightText.splitAndHighlight( this, matchString );
var jqXhr = $(this).data( 'request' );
// If the delay setting has caused the fetch to have not even happened
// yet, the jqXHR object will have never been set.
- if ( jqXhr && $.isFunction ( jqXhr.abort ) ) {
+ if ( jqXhr && $.isFunction( jqXhr.abort ) ) {
jqXhr.abort();
$(this).removeData( 'request' );
}
.append(
$( '<div>' )
.addClass( 'special-label' )
- .text( mw.msg( 'searchsuggest-containing' ) )
- )
- .append(
+ .text( mw.msg( 'searchsuggest-containing' ) ),
$( '<div>' )
.addClass( 'special-query' )
.text( query )
.show();
} else {
$el.find( '.special-query' )
- .empty()
.text( query )
.autoEllipsis();
}
. "<input type='submit' class=\"searchButton\" name=\"go\" value=\"" . wfMessage( 'searcharticle' )->escaped() . "\" />";
if( $wgUseTwoButtonsSearchForm ) {
- $s .= " <input type='submit' class=\"searchButton\" name=\"fulltext\" value=\"" . wfMessage( 'search' )->escaped() . "\" />\n";
+ $s .= " <input type='submit' class=\"searchButton\" name=\"fulltext\" value=\"" . wfMessage( 'searchbutton' )->escaped() . "\" />\n";
} else {
$s .= '<div><a href="' . $action . '" rel="search">' . wfMessage( 'powersearch-legend' )->escaped() . "</a></div>\n";
}
"$dir/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg",
"$dir/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg",
"$dir/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/1280px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/30px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/40px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/960px-Foobar.jpg",
"$dir/0/09/Bad.jpg",
{{{1}}}
!! endarticle
+!! article
+Template:echo_with_span
+!! text
+<span>{{{1}}}</span>
+!! endarticle
+
+!! article
+Template:echo_with_div
+!! text
+<div>{{{1}}}</div>
+!! endarticle
+
!! article
Template:attr_str
!! text
!!end
+!!test
+Templates: Ugly nesting: 1. Quotes opened/closed across templates (echo)
+!!input
+{{echo|''a}}{{echo|b''c''d}}{{echo|''e}}
+!!result
+<p><i>ab</i>c<i>d</i>e
+</p>
+!!end
+
+!!test
+Templates: Ugly nesting: 2. Quotes opened/closed across templates (echo_with_span)
+(PHP parser generates misnested html)
+!! options
+disabled
+!!input
+{{echo_with_span|''a}}{{echo_with_span|b''c''d}}{{echo_with_span|''e}}
+!!result
+<p><span><i>a</i></span><i><span>b</span></i><span>c</span><i>d</i><span>e</span></p>
+!!end
+
+!!test
+Templates: Ugly nesting: 3. Quotes opened/closed across templates (echo_with_div)
+(PHP parser generates misnested html)
+!! options
+disabled
+!!input
+{{echo_with_div|''a}}{{echo_with_div|b''c''d}}{{echo_with_div|''e}}
+!!result
+<div><i>a</i></div>
+<div><i>b</i>c<i>d</i></div>
+<div>e</div>
+!!end
+
+!!test
+Templates: Ugly nesting: 4. Divs opened/closed across templates
+!!input
+a<div>b{{echo|c</div>d}}e
+!!result
+a<div>bc</div>de
+
+!!end
+
!!test
Parser Functions: 1. Simple example
!!input
public function dataGetParserOutput() {
return array(
array("MediaWiki:Test.css", null, "hello <world>\n",
- "<pre class=\"mw-code mw-css\" dir=\"ltr\">\nhello <world>\n\n</pre>\n"),
+ "<pre class=\"mw-code mw-css\" dir=\"ltr\">\nhello <world>\n\n</pre>"),
// @todo: more...?
);
}
}
}
-
-
+
+
function testDebugFunctionTest() {
-
+
global $wgDebugLogFile, $wgDebugTimestamps;
-
+
$old_log_file = $wgDebugLogFile;
$wgDebugLogFile = tempnam( wfTempDir(), 'mw-' );
- # @todo FIXME: This setting should be tested
+ # @todo FIXME: $wgDebugTimestamps should be tested
+ $old_wgDebugTimestamps = $wgDebugTimestamps;
$wgDebugTimestamps = false;
-
-
-
+
+
wfDebug( "This is a normal string" );
$this->assertEquals( "This is a normal string", file_get_contents( $wgDebugLogFile ) );
unlink( $wgDebugLogFile );
-
-
+
wfDebug( "This is nöt an ASCII string" );
$this->assertEquals( "This is nöt an ASCII string", file_get_contents( $wgDebugLogFile ) );
unlink( $wgDebugLogFile );
-
-
+
+
wfDebug( "\00305This has böth UTF and control chars\003" );
$this->assertEquals( " 05This has böth UTF and control chars ", file_get_contents( $wgDebugLogFile ) );
unlink( $wgDebugLogFile );
wfDebugMem();
$this->assertGreaterThan( 5000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
unlink( $wgDebugLogFile );
-
+
wfDebugMem(true);
$this->assertGreaterThan( 5000000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
unlink( $wgDebugLogFile );
-
-
-
+
+
$wgDebugLogFile = $old_log_file;
-
+ $wgDebugTimestamps = $old_wgDebugTimestamps;
}
-
+
function testClientAcceptsGzipTest() {
$settings = array(
* @group Database
* ^--- needed, because we do need the database to test link updates
*/
-class JavascriptContentTest extends WikitextContentTest {
+class JavascriptContentTest extends TextContentTest {
public function newContent( $text ) {
return new JavascriptContent( $text );
public function dataGetParserOutput() {
return array(
array("MediaWiki:Test.js", null, "hello <world>\n",
- "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello <world>\n\n</pre>\n"),
+ "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello <world>\n\n</pre>"),
// @todo: more...?
);
}
}
// XXX: currently, preSaveTransform is applied to scripts. this may change or become optional.
- /*
public function dataPreSaveTransform() {
return array(
array( 'hello this is ~~~',
- "hello this is ~~~",
+ "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 dataPreloadTransform() {
return array(
--- /dev/null
+<?php
+
+/**
+ * @group ContentHandler
+ *
+ * @group Database
+ * ^--- needed, because we do need the database to test link updates
+ */
+class TextContentTest extends MediaWikiTestCase {
+
+ public function setup() {
+ global $wgUser;
+
+ // anon user
+ $wgUser = new User();
+ $wgUser->setName( '127.0.0.1' );
+
+ $this->context = new RequestContext( new FauxRequest() );
+ $this->context->setTitle( Title::newFromText( "Test" ) );
+ $this->context->setUser( $wgUser );
+ }
+
+ public function newContent( $text ) {
+ return new TextContent( $text );
+ }
+
+
+ public function dataGetParserOutput() {
+ return array(
+ array("TextContentTest_testGetParserOutput", CONTENT_MODEL_TEXT, "hello ''world'' & stuff\n", "hello ''world'' & stuff"),
+ // @todo: more...?
+ );
+ }
+
+ /**
+ * @dataProvider dataGetParserOutput
+ */
+ public function testGetParserOutput( $title, $model, $text, $expectedHtml ) {
+ $title = Title::newFromText( $title );
+ $content = ContentHandler::makeContent( $text, $title, $model );
+
+ $po = $content->getParserOutput( $title );
+
+ $html = $po->getText();
+ $html = preg_replace( '#<!--.*?-->#sm', '', $html ); // strip comments
+
+ $this->assertEquals( $expectedHtml, trim( $html ) );
+ // @todo: assert more properties
+ }
+
+ public function dataPreSaveTransform() {
+ return array(
+ array( 'hello this is ~~~',
+ "hello this is ~~~",
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider dataPreSaveTransform
+ */
+ public function testPreSaveTransform( $text, $expected ) {
+ global $wgContLang;
+
+ $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
+
+ $content = $this->newContent( $text );
+ $content = $content->preSaveTransform( $this->context->getTitle(), $this->context->getUser(), $options );
+
+ $this->assertEquals( $expected, $content->getNativeData() );
+ }
+
+ public function dataPreloadTransform() {
+ return array(
+ array( 'hello this is ~~~',
+ "hello this is ~~~",
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider dataPreloadTransform
+ */
+ public function testPreloadTransform( $text, $expected ) {
+ global $wgContLang;
+ $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
+
+ $content = $this->newContent( $text );
+ $content = $content->preloadTransform( $this->context->getTitle(), $options );
+
+ $this->assertEquals( $expected, $content->getNativeData() );
+ }
+
+ public function dataGetRedirectTarget() {
+ return array(
+ array( '#REDIRECT [[Test]]',
+ null,
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider dataGetRedirectTarget
+ */
+ public function testGetRedirectTarget( $text, $expected ) {
+ $content = $this->newContent( $text );
+ $t = $content->getRedirectTarget( );
+
+ if ( is_null( $expected ) ) {
+ $this->assertNull( $t, "text should not have generated a redirect target: $text" );
+ } else {
+ $this->assertEquals( $expected, $t->getPrefixedText() );
+ }
+ }
+
+ /**
+ * @dataProvider dataGetRedirectTarget
+ */
+ public function isRedirect( $text, $expected ) {
+ $content = $this->newContent( $text );
+
+ $this->assertEquals( !is_null($expected), $content->isRedirect() );
+ }
+
+
+ /**
+ * @todo: test needs database! Should be done by a test class in the Database group.
+ */
+ /*
+ public function getRedirectChain() {
+ $text = $this->getNativeData();
+ return Title::newFromRedirectArray( $text );
+ }
+ */
+
+ /**
+ * @todo: test needs database! Should be done by a test class in the Database group.
+ */
+ /*
+ public function getUltimateRedirectTarget() {
+ $text = $this->getNativeData();
+ return Title::newFromRedirectRecurse( $text );
+ }
+ */
+
+
+ public function dataIsCountable() {
+ return array(
+ array( '',
+ null,
+ 'any',
+ true
+ ),
+ array( 'Foo',
+ null,
+ 'any',
+ true
+ ),
+ array( 'Foo',
+ null,
+ 'comma',
+ false
+ ),
+ array( 'Foo, bar',
+ null,
+ 'comma',
+ false
+ ),
+ );
+ }
+
+
+ /**
+ * @dataProvider dataIsCountable
+ * @group Database
+ */
+ public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
+ global $wgArticleCountMethod;
+
+ $old = $wgArticleCountMethod;
+ $wgArticleCountMethod = $mode;
+
+ $content = $this->newContent( $text );
+
+ $v = $content->isCountable( $hasLinks, $this->context->getTitle() );
+ $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\"" );
+ }
+
+ public function dataGetTextForSummary() {
+ return array(
+ array( "hello\nworld.",
+ 16,
+ 'hello world.',
+ ),
+ array( 'hello world.',
+ 8,
+ 'hello...',
+ ),
+ array( '[[hello world]].',
+ 8,
+ '[[hel...',
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider dataGetTextForSummary
+ */
+ public function testGetTextForSummary( $text, $maxlength, $expected ) {
+ $content = $this->newContent( $text );
+
+ $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
+ }
+
+
+ public function testGetTextForSearchIndex( ) {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( "hello world.", $content->getTextForSearchIndex() );
+ }
+
+ public function testCopy() {
+ $content = $this->newContent( "hello world." );
+ $copy = $content->copy();
+
+ $this->assertTrue( $content->equals( $copy ), "copy must be equal to original" );
+ $this->assertEquals( "hello world.", $copy->getNativeData() );
+ }
+
+ public function testGetSize( ) {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( 12, $content->getSize() );
+ }
+
+ public function testGetNativeData( ) {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( "hello world.", $content->getNativeData() );
+ }
+
+ public function testGetWikitextForTransclusion( ) {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( "hello world.", $content->getWikitextForTransclusion() );
+ }
+
+ # =================================================================================================================
+
+ public function testGetModel() {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() );
+ }
+
+ public function testGetContentHandler() {
+ $content = $this->newContent( "hello world." );
+
+ $this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() );
+ }
+
+ public function dataIsEmpty( ) {
+ return array(
+ array( '', true ),
+ array( ' ', false ),
+ array( '0', false ),
+ array( 'hallo welt.', false ),
+ );
+ }
+
+ /**
+ * @dataProvider dataIsEmpty
+ */
+ public function testIsEmpty( $text, $empty ) {
+ $content = $this->newContent( $text );
+
+ $this->assertEquals( $empty, $content->isEmpty() );
+ }
+
+ public function dataEquals( ) {
+ return array(
+ array( new TextContent( "hallo" ), null, false ),
+ array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ),
+ array( new TextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
+ array( new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ),
+ array( new TextContent( "hallo" ), new TextContent( "HALLO" ), false ),
+ );
+ }
+
+ /**
+ * @dataProvider dataEquals
+ */
+ public function testEquals( Content $a, Content $b = null, $equal = false ) {
+ $this->assertEquals( $equal, $a->equals( $b ) );
+ }
+
+ public function dataGetDeletionUpdates() {
+ return array(
+ array("TextContentTest_testGetSecondaryDataUpdates_1",
+ CONTENT_MODEL_TEXT, "hello ''world''\n",
+ array( )
+ ),
+ array("TextContentTest_testGetSecondaryDataUpdates_2",
+ CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n",
+ array( )
+ ),
+ // @todo: more...?
+ );
+ }
+
+ /**
+ * @dataProvider dataGetDeletionUpdates
+ */
+ public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) {
+ $title = Title::newFromText( $title );
+ $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
+
+ $content = ContentHandler::makeContent( $text, $title, $model );
+
+ $updates = $content->getDeletionUpdates( WikiPage::factory( $title ) );
+
+ // make updates accessible by class name
+ foreach ( $updates as $update ) {
+ $class = get_class( $update );
+ $updates[ $class ] = $update;
+ }
+
+ if ( !$expectedStuff ) {
+ $this->assertTrue( true ); // make phpunit happy
+ return;
+ }
+
+ foreach ( $expectedStuff as $class => $fieldValues ) {
+ $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
+
+ $update = $updates[ $class ];
+
+ foreach ( $fieldValues as $field => $value ) {
+ $v = $update->$field; #if the field doesn't exist, just crash and burn
+ $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
+ }
+ }
+ }
+
+}
return $po;
}
+ /**
+ * @dataProvider provideGetParserOutput
+ */
+ public function testGetParserOutput_nonexisting( ) {
+ static $count = 0;
+ $count ++;
+
+ $page = new WikiPage( new Title( "testGetParserOutput_nonexisting_$count" ) );
+
+ $opt = new ParserOptions();
+ $po = $page->getParserOutput( $opt );
+
+ $this->assertFalse( $po, "getParserOutput() shall return false for non-existing pages." );
+ }
+
static $sections =
"Intro
* @group Database
* ^--- needed, because we do need the database to test link updates
*/
-class WikitextContentTest extends MediaWikiTestCase {
-
- public function setup() {
- global $wgUser;
-
- // anon user
- $wgUser = new User();
- $wgUser->setName( '127.0.0.1' );
-
- $this->context = new RequestContext( new FauxRequest() );
- $this->context->setTitle( Title::newFromText( "Test" ) );
- $this->context->setUser( $wgUser );
- }
+class WikitextContentTest extends TextContentTest {
public function newContent( $text ) {
return new WikitextContent( $text );
}
-
public function dataGetParserOutput() {
return array(
array("WikitextContentTest_testGetParserOutput", CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i>\n</p>"),
);
}
- /**
- * @dataProvider dataGetParserOutput
- */
- public function testGetParserOutput( $title, $model, $text, $expectedHtml ) {
- $title = Title::newFromText( $title );
- $content = ContentHandler::makeContent( $text, $title, $model );
-
- $po = $content->getParserOutput( $title );
-
- $this->assertEquals( $expectedHtml, $po->getText() );
- // @todo: assert more properties
- }
-
public function dataGetSecondaryDataUpdates() {
return array(
array("WikitextContentTest_testGetSecondaryDataUpdates_1",
$content = $this->newContent( $text );
$sectionContent = $content->getSection( $sectionId );
+ if ( is_object( $sectionContent ) ) {
+ $sectionText = $sectionContent->getNativeData();
+ } else {
+ $sectionText = $sectionContent;
+ }
- $this->assertEquals( $expectedText, is_null( $sectionContent ) ? null : $sectionContent->getNativeData() );
+ $this->assertEquals( $expectedText, $sectionText );
}
public function dataReplaceSection() {
);
}
- /**
- * @dataProvider dataPreSaveTransform
- */
- public function testPreSaveTransform( $text, $expected ) {
- global $wgContLang;
-
- $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
-
- $content = $this->newContent( $text );
- $content = $content->preSaveTransform( $this->context->getTitle(), $this->context->getUser(), $options );
-
- $this->assertEquals( $expected, $content->getNativeData() );
- }
-
public function dataPreloadTransform() {
return array(
array( 'hello this is ~~~',
);
}
- /**
- * @dataProvider dataPreloadTransform
- */
- public function testPreloadTransform( $text, $expected ) {
- global $wgContLang;
- $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
-
- $content = $this->newContent( $text );
- $content = $content->preloadTransform( $this->context->getTitle(), $options );
-
- $this->assertEquals( $expected, $content->getNativeData() );
- }
-
public function dataGetRedirectTarget() {
return array(
array( '#REDIRECT [[Test]]',
);
}
- /**
- * @dataProvider dataGetRedirectTarget
- */
- public function testGetRedirectTarget( $text, $expected ) {
- $content = $this->newContent( $text );
- $t = $content->getRedirectTarget( );
-
- if ( is_null( $expected ) ) {
- $this->assertNull( $t, "text should not have generated a redirect target: $text" );
- } else {
- $this->assertEquals( $expected, $t->getPrefixedText() );
- }
- }
-
- /**
- * @dataProvider dataGetRedirectTarget
- */
- public function isRedirect( $text, $expected ) {
- $content = $this->newContent( $text );
-
- $this->assertEquals( !is_null($expected), $content->isRedirect() );
+ public function dataGetTextForSummary() {
+ return array(
+ array( "hello\nworld.",
+ 16,
+ 'hello world.',
+ ),
+ array( 'hello world.',
+ 8,
+ 'hello...',
+ ),
+ array( '[[hello world]].',
+ 8,
+ 'hel...',
+ ),
+ );
}
-
/**
* @todo: test needs database! Should be done by a test class in the Database group.
*/
);
}
-
- /**
- * @dataProvider dataIsCountable
- * @group Database
- */
- public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
- global $wgArticleCountMethod;
-
- $old = $wgArticleCountMethod;
- $wgArticleCountMethod = $mode;
-
- $content = $this->newContent( $text );
-
- $v = $content->isCountable( $hasLinks, $this->context->getTitle() );
- $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\"" );
- }
-
- public function dataGetTextForSummary() {
- return array(
- array( "hello\nworld.",
- 16,
- 'hello world.',
- ),
- array( 'hello world.',
- 8,
- 'hello...',
- ),
- array( '[[hello world]].',
- 8,
- 'hel...',
- ),
- );
- }
-
- /**
- * @dataProvider dataGetTextForSummary
- */
- public function testGetTextForSummary( $text, $maxlength, $expected ) {
- $content = $this->newContent( $text );
-
- $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
- }
-
-
- public function testGetTextForSearchIndex( ) {
- $content = $this->newContent( "hello world." );
-
- $this->assertEquals( "hello world.", $content->getTextForSearchIndex() );
- }
-
- public function testCopy() {
- $content = $this->newContent( "hello world." );
- $copy = $content->copy();
-
- $this->assertTrue( $content->equals( $copy ), "copy must be equal to original" );
- $this->assertEquals( "hello world.", $copy->getNativeData() );
- }
-
- public function testGetSize( ) {
- $content = $this->newContent( "hello world." );
-
- $this->assertEquals( 12, $content->getSize() );
- }
-
- public function testGetNativeData( ) {
- $content = $this->newContent( "hello world." );
-
- $this->assertEquals( "hello world.", $content->getNativeData() );
- }
-
- public function testGetWikitextForTransclusion( ) {
- $content = $this->newContent( "hello world." );
-
- $this->assertEquals( "hello world.", $content->getWikitextForTransclusion() );
- }
-
public function testMatchMagicWord( ) {
$mw = MagicWord::get( "staticredirect" );
$this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
}
- public function dataIsEmpty( ) {
- return array(
- array( '', true ),
- array( ' ', false ),
- array( '0', false ),
- array( 'hallo welt.', false ),
- );
- }
-
- /**
- * @dataProvider dataIsEmpty
- */
- public function testIsEmpty( $text, $empty ) {
- $content = $this->newContent( $text );
-
- $this->assertEquals( $empty, $content->isEmpty() );
- }
-
public function dataEquals( ) {
return array(
array( new WikitextContent( "hallo" ), null, false ),
array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ),
array( new WikitextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
+ array( new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ),
array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ),
);
}
- /**
- * @dataProvider dataEquals
- */
- public function testEquals( Content $a, Content $b = null, $equal = false ) {
- $this->assertEquals( $equal, $a->equals( $b ) );
- }
-
public function dataGetDeletionUpdates() {
return array(
array("WikitextContentTest_testGetSecondaryDataUpdates_1",
);
}
- /**
- * @dataProvider dataGetDeletionUpdates
- */
- public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) {
- $title = Title::newFromText( $title );
- $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
-
- $content = ContentHandler::makeContent( $text, $title, $model );
-
- $updates = $content->getDeletionUpdates( WikiPage::factory( $title ) );
-
- // make updates accessible by class name
- foreach ( $updates as $update ) {
- $class = get_class( $update );
- $updates[ $class ] = $update;
- }
-
- foreach ( $expectedStuff as $class => $fieldValues ) {
- $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
-
- $update = $updates[ $class ];
-
- foreach ( $fieldValues as $field => $value ) {
- $v = $update->$field; #if the field doesn't exist, just crash and burn
- $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
- }
- }
- }
-
}
$this->assertEquals( $data, $page->getContent()->serialize() );
}
- function testEditAppend() {
- $this->markTestIncomplete( "not yet implemented" );
+ static function provideEditAppend() {
+ return array(
+ array( #0: append
+ 'foo', 'append', 'bar', "foobar"
+ ),
+ array( #1: prepend
+ 'foo', 'prepend', 'bar', "barfoo"
+ ),
+ array( #2: append to empty page
+ '', 'append', 'foo', "foo"
+ ),
+ array( #3: prepend to empty page
+ '', 'prepend', 'foo', "foo"
+ ),
+ array( #4: append to non-existing page
+ null, 'append', 'foo', "foo"
+ ),
+ array( #5: prepend to non-existing page
+ null, 'prepend', 'foo', "foo"
+ ),
+ );
}
- function testEditSection() {
- $this->markTestIncomplete( "not yet implemented" );
+ /**
+ * @dataProvider provideEditAppend
+ */
+ function testEditAppend( $text, $op, $append, $expected ) {
+ static $count = 0;
+ $count++;
+
+ // assume NS_HELP defaults to wikitext
+ $name = "Help:ApiEditPageTest_testEditAppend_$count";
+
+ // -- create page (or not) -----------------------------------------
+ if ( $text !== null ) {
+ if ( $text === '' ) {
+ // can't create an empty page, so create it with some content
+ list( $re,, ) = $this->doApiRequestWithToken( array(
+ 'action' => 'edit',
+ 'title' => $name,
+ 'text' => '(dummy)', ) );
+ }
+
+ list( $re,, ) = $this->doApiRequestWithToken( array(
+ 'action' => 'edit',
+ 'title' => $name,
+ 'text' => $text, ) );
+
+ $this->assertEquals( 'Success', $re['edit']['result'] ); // sanity
+ }
+
+ // -- try append/prepend --------------------------------------------
+ list( $re,, ) = $this->doApiRequestWithToken( array(
+ 'action' => 'edit',
+ 'title' => $name,
+ $op . 'text' => $append, ) );
+
+ $this->assertEquals( 'Success', $re['edit']['result'] );
+
+ // -- validate -----------------------------------------------------
+ $page = new WikiPage( Title::newFromText( $name ) );
+ $content = $page->getContent();
+ $this->assertNotNull( $content, 'Page should have been created' );
+
+ $text = $content->getNativeData();
+
+ $this->assertEquals( $expected, $text );
}
- function testUndo() {
+ function testEditSection() {
$this->markTestIncomplete( "not yet implemented" );
}
- function testEditNonText() {
+ function testUndo() {
$this->markTestIncomplete( "not yet implemented" );
}
}
--- /dev/null
+<?php
+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()->getModules();
+ 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()->getModules();
+ $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;
+ }
+
+}
$instances = array();
foreach ( $this->elementInstancesProvider() as $elementInstances ) {
- $instances[] = $this->getNew( $elementInstances );
+ $instances[] = $this->getNew( $elementInstances[0] );
}
return $this->arrayWrap( $instances );
return;
}
+ if ( !$this->isWikitextNS( NS_MAIN ) ) {
+ // parser tests frequently assume that the main namespace contains wikitext.
+ // @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" );
+ }
+
wfDebug( "Running parser test: $desc\n" );
$opts = $this->parseOptions( $opts );
--- /dev/null
+<?php
+
+/**
+ * Tests for the MediaWikiSite class.
+ *
+ * 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
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class MediaWikiSiteTest extends SiteObjectTest {
+
+ public function setUp() {
+ parent::setUp();
+
+ static $hasSites = false;
+
+ if ( !$hasSites ) {
+ TestSites::insertIntoDb();
+ $hasSites = true;
+ }
+ }
+
+ public function testFactoryConstruction() {
+ $this->assertInstanceOf( 'MediaWikiSite', MediaWikiSite::newFromGlobalId( 'enwiki' ) );
+ $this->assertInstanceOf( 'Site', MediaWikiSite::newFromGlobalId( 'enwiki' ) );
+ $this->assertInstanceOf( 'MediaWikiSite', SitesTable::singleton()->newRow( array( 'type' => Site::TYPE_MEDIAWIKI ) ) );
+ }
+
+ public function testNormalizePageTitle() {
+ $site = MediaWikiSite::newFromGlobalId( 'enwiki' );
+
+ //NOTE: this does not actually call out to the enwiki site to perform the normalization,
+ // but uses a local Title object to do so. This is hardcoded on SiteLink::normalizePageTitle
+ // for the case that MW_PHPUNIT_TEST is set.
+ $this->assertEquals( 'Foo', $site->normalizePageName( ' foo ' ) );
+ }
+
+ public function fileUrlProvider() {
+ return array(
+ // url, filepath, path arg, expected
+ array( 'https://en.wikipedia.org', '/w/$1', 'api.php', 'https://en.wikipedia.org/w/api.php' ),
+ array( 'https://en.wikipedia.org', '/w/', 'api.php', 'https://en.wikipedia.org/w/' ),
+ array( 'https://en.wikipedia.org', '/foo/page.php?name=$1', 'api.php', 'https://en.wikipedia.org/foo/page.php?name=api.php' ),
+ array( 'https://en.wikipedia.org', '/w/$1', '', 'https://en.wikipedia.org/w/' ),
+ array( 'https://en.wikipedia.org', '/w/$1', 'foo/bar/api.php', 'https://en.wikipedia.org/w/foo/bar/api.php' ),
+ );
+ }
+
+ /**
+ * @dataProvider fileUrlProvider
+ */
+ public function testGetFileUrl( $url, $filePath, $pathArgument, $expected ) {
+ $site = MediaWikiSite::newFromGlobalId( 'enwiki' );
+
+ $site->setFilePath( $url . $filePath );
+
+ $this->assertEquals( $expected, $site->getFileUrl( $pathArgument ) );
+ }
+
+ public function provideGetPageUrl() {
+ return array(
+ // path, page, expected substring
+ array( 'http://acme.test/wiki/$1', 'Berlin', '/wiki/Berlin' ),
+ array( 'http://acme.test/wiki/', 'Berlin', '/wiki/' ),
+ array( 'http://acme.test/w/index.php?title=$1', 'Berlin', '/w/index.php?title=Berlin' ),
+ array( 'http://acme.test/wiki/$1', '', '/wiki/' ),
+ array( 'http://acme.test/wiki/$1', 'Berlin/sub page', '/wiki/Berlin/sub_page' ),
+ array( 'http://acme.test/wiki/$1', 'Cork (city) ', '/Cork_(city)' ),
+ array( 'http://acme.test/wiki/$1', 'M&M', '/wiki/M%26M' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideGetPageUrl
+ */
+ public function testGetPageUrl( $path, $page, $expected ) {
+ /* @var MediaWikiSite $site */
+ $site = MediaWikiSite::newFromGlobalId( 'enwiki' );
+
+ $site->setLinkPath( $path );
+ $this->assertContains( $path, $site->getPageUrl() );
+ $this->assertContains( $expected, $site->getPageUrl( $page ) );
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Tests for the SiteArray class.
+ * The tests for methods defined in the SiteList interface are in SiteListTest.
+ *
+ * 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
+ *Both
+ * Bith
+ * @file
+ * @since 1.21
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SiteArrayTest extends GenericArrayObjectTest {
+
+ /**
+ * @see GenericArrayObjectTest::elementInstancesProvider
+ *
+ * @since 1.21
+ *
+ * @return array
+ */
+ public function elementInstancesProvider() {
+ $sites = TestSites::getSites();
+
+ $siteArrays = array();
+
+ $siteArrays[] = $sites;
+
+ $siteArrays[] = array( array_shift( $sites ) );
+
+ $siteArrays[] = array( array_shift( $sites ), array_shift( $sites ) );
+
+ return $this->arrayWrap( $siteArrays );
+ }
+
+ /**
+ * @see GenericArrayObjectTest::getInstanceClass
+ *
+ * @since 1.21
+ *
+ * @return array
+ */
+ public function getInstanceClass() {
+ return 'SiteArray';
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Tests for the SiteList implementing classes.
+ *
+ * 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
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SiteListTest extends MediaWikiTestCase {
+
+ /**
+ * Returns instances of SiteList implementing objects.
+ * @return array
+ */
+ public function siteListProvider() {
+ $sitesArrays = $this->siteArrayProvider();
+
+ $listInstances = array();
+
+ foreach ( $sitesArrays as $sitesArray ) {
+ $listInstances[] = new SiteArray( $sitesArray[0] );
+ }
+
+ return $this->arrayWrap( $listInstances );
+ }
+
+ /**
+ * Returns arrays with instances of Site implementing objects.
+ * @return array
+ */
+ public function siteArrayProvider() {
+ $sites = TestSites::getSites();
+
+ $siteArrays = array();
+
+ $siteArrays[] = $sites;
+
+ $siteArrays[] = array( array_shift( $sites ) );
+
+ $siteArrays[] = array( array_shift( $sites ), array_shift( $sites ) );
+
+ return $this->arrayWrap( $siteArrays );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ */
+ public function testIsEmpty( SiteList $sites ) {
+ $this->assertEquals( count( $sites ) === 0, $sites->isEmpty() );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ */
+ public function testGetSiteByGlobalId( SiteList $sites ) {
+ if ( $sites->isEmpty() ) {
+ $this->assertTrue( true );
+ }
+ else {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertEquals( $site, $sites->getSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ */
+ public function testGetSiteByInternalId( $sites ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ if ( is_integer( $site->getInternalId() ) ) {
+ $this->assertEquals( $site, $sites->getSiteByInternalId( $site->getInternalId() ) );
+ }
+ }
+
+ $this->assertTrue( true );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ */
+ public function testHasGlobalId( $sites ) {
+ $this->assertFalse( $sites->hasSite( 'non-existing-global-id' ) );
+ $this->assertFalse( $sites->hasInternalId( 720101010 ) );
+
+ if ( !$sites->isEmpty() ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ */
+ public function testHasInternallId( $sites ) {
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ if ( is_integer( $site->getInternalId() ) ) {
+ $this->assertTrue( $site, $sites->hasInternalId( $site->getInternalId() ) );
+ }
+ }
+
+ $this->assertFalse( $sites->hasInternalId( -1 ) );
+ }
+
+ /**
+ * @dataProvider siteListProvider
+ * @param SiteList $sites
+ */
+ public function testGetGlobalIdentifiers( SiteList $sites ) {
+ $identifiers = $sites->getGlobalIdentifiers();
+
+ $this->assertTrue( is_array( $identifiers ) );
+
+ $expected = array();
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $expected[] = $site->getGlobalId();
+ }
+
+ $this->assertArrayEquals( $expected, $identifiers );
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Tests for the SiteObject class.
+ *
+ * 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
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SiteObjectTest extends ORMRowTest {
+
+ /**
+ * @see ORMRowTest::getRowClass
+ * @since 1.21
+ * @return string
+ */
+ protected function getRowClass() {
+ return 'SiteObject';
+ }
+
+ /**
+ * @see ORMRowTest::getTableInstance
+ * @since 1.21
+ * @return IORMTable
+ */
+ protected function getTableInstance() {
+ return SitesTable::singleton();
+ }
+
+ /**
+ * @see ORMRowTest::constructorTestProvider
+ * @since 1.21
+ * @return array
+ */
+ public function constructorTestProvider() {
+ $argLists = array();
+
+ $argLists[] = array( 'global_key' => '42' );
+
+ $argLists[] = array( 'global_key' => '42', 'type' => Site::TYPE_MEDIAWIKI );
+
+ $constructorArgs = array();
+
+ foreach ( $argLists as $argList ) {
+ $constructorArgs[] = array( $argList, true );
+ }
+
+ return $constructorArgs;
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testGetInterwikiIds( Site $site ) {
+ $this->assertInternalType( 'array', $site->getInterwikiIds() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testGetNavigationIds( Site $site ) {
+ $this->assertInternalType( 'array', $site->getNavigationIds() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testAddNavigationId( Site $site ) {
+ $site->addNavigationId( 'foobar' );
+ $this->assertTrue( in_array( 'foobar', $site->getNavigationIds(), true ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testAddInterwikiId( Site $site ) {
+ $site->addInterwikiId( 'foobar' );
+ $this->assertTrue( in_array( 'foobar', $site->getInterwikiIds(), true ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testGetLanguageCode( Site $site ) {
+ $this->assertTypeOrFalse( 'string', $site->getLanguageCode() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testSetLanguageCode( Site $site ) {
+ $site->setLanguageCode( 'en' );
+ $this->assertEquals( 'en', $site->getLanguageCode() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testNormalizePageName( Site $site ) {
+ $this->assertInternalType( 'string', $site->normalizePageName( 'Foobar' ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testGetGlobalId( Site $site ) {
+ $this->assertInternalType( 'string', $site->getGlobalId() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testSetGlobalId( Site $site ) {
+ $site->setGlobalId( 'foobar' );
+ $this->assertEquals( 'foobar', $site->getGlobalId() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testGetType( Site $site ) {
+ $this->assertInternalType( 'string', $site->getType() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testGetPath( Site $site ) {
+ $this->assertTypeOrFalse( 'string', $site->getPath( 'page_path' ) );
+ $this->assertTypeOrFalse( 'string', $site->getPath( 'file_path' ) );
+ $this->assertTypeOrFalse( 'string', $site->getPath( 'foobar' ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testGetAllPaths( Site $site ) {
+ $this->assertInternalType( 'array', $site->getAllPaths() );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ * @param Site $site
+ */
+ public function testSetAndRemovePath( Site $site ) {
+ $count = count( $site->getAllPaths() );
+
+ $site->setPath( 'spam', 'http://www.wikidata.org/$1' );
+ $site->setPath( 'spam', 'http://www.wikidata.org/foo/$1' );
+ $site->setPath( 'foobar', 'http://www.wikidata.org/bar/$1' );
+
+ $this->assertEquals( $count + 2, count( $site->getAllPaths() ) );
+
+ $this->assertInternalType( 'string', $site->getPath( 'foobar' ) );
+ $this->assertEquals( 'http://www.wikidata.org/foo/$1', $site->getPath( 'spam' ) );
+
+ $site->removePath( 'spam' );
+ $site->removePath( 'foobar' );
+
+ $this->assertEquals( $count, count( $site->getAllPaths() ) );
+
+ $this->assertFalse( $site->getPath( 'foobar' ) );
+ $this->assertFalse( $site->getPath( 'spam' ) );
+ }
+
+ public function testSetLinkPath() {
+ /* @var SiteObject $site */
+ $site = $this->getRowInstance( $this->getMockFields(), false );
+ $path = "TestPath/$1";
+
+ $site->setLinkPath( $path );
+ $this->assertEquals( $path, $site->getLinkPath() );
+ }
+
+ public function testGetLinkPathType() {
+ /* @var SiteObject $site */
+ $site = $this->getRowInstance( $this->getMockFields(), false );
+
+ $path = 'TestPath/$1';
+ $site->setLinkPath( $path );
+ $this->assertEquals( $path, $site->getPath( $site->getLinkPathType() ) );
+
+ $path = 'AnotherPath/$1';
+ $site->setPath( $site->getLinkPathType(), $path );
+ $this->assertEquals( $path, $site->getLinkPath() );
+ }
+
+ public function testSetPath() {
+ /* @var SiteObject $site */
+ $site = $this->getRowInstance( $this->getMockFields(), false );
+
+ $path = 'TestPath/$1';
+ $site->setPath( 'foo', $path );
+
+ $this->assertEquals( $path, $site->getPath( 'foo' ) );
+ }
+
+ public function provideGetPageUrl() {
+ //NOTE: the assumption that the URL is built by replacing $1
+ // with the urlencoded version of $page
+ // is true for SiteObject but not guaranteed for subclasses.
+ // Subclasses need to override this provider appropriately.
+
+ return array(
+ array( #0
+ 'http://acme.test/TestPath/$1',
+ 'Foo',
+ '/TestPath/Foo',
+ ),
+ array( #1
+ 'http://acme.test/TestScript?x=$1&y=bla',
+ 'Foo',
+ 'TestScript?x=Foo&y=bla',
+ ),
+ array( #2
+ 'http://acme.test/TestPath/$1',
+ 'foo & bar/xyzzy (quux-shmoox?)',
+ '/TestPath/foo%20%26%20bar%2Fxyzzy%20%28quux-shmoox%3F%29',
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider provideGetPageUrl
+ */
+ public function testGetPageUrl( $path, $page, $expected ) {
+ /* @var SiteObject $site */
+ $site = $this->getRowInstance( $this->getMockFields(), false );
+
+ //NOTE: the assumption that getPageUrl is based on getLinkPath
+ // is true for SiteObject but not guaranteed for subclasses.
+ // Subclasses need to override this test case appropriately.
+ $site->setLinkPath( $path );
+ $this->assertContains( $path, $site->getPageUrl() );
+
+ $this->assertContains( $expected, $site->getPageUrl( $page ) );
+ }
+
+ protected function assertTypeOrFalse( $type, $value ) {
+ if ( $value === false ) {
+ $this->assertTrue( true );
+ }
+ else {
+ $this->assertInternalType( $type, $value );
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Tests for the Sites class.
+ *
+ * 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
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SitesTest extends MediaWikiTestCase {
+
+ public function setUp() {
+ parent::setUp();
+ TestSites::insertIntoDb();
+ }
+
+ public function testSingleton() {
+ $this->assertInstanceOf( 'Sites', Sites::singleton() );
+ $this->assertTrue( Sites::singleton() === Sites::singleton() );
+ }
+
+ public function testGetSites() {
+ $this->assertInstanceOf( 'SiteList', Sites::singleton()->getSites() );
+ }
+
+
+ public function testGetSite() {
+ $count = 0;
+ $sites = Sites::singleton()->getSites();
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertInstanceOf( 'Site', $site );
+
+ $this->assertEquals(
+ $site,
+ Sites::singleton()->getSite( $site->getGlobalId() )
+ );
+
+ if ( ++$count > 100 ) {
+ break;
+ }
+ }
+ }
+
+ public function testNewSite() {
+ $this->assertInstanceOf( 'Site', Sites::newSite() );
+ $this->assertInstanceOf( 'Site', Sites::newSite( 'enwiki' ) );
+ }
+
+ public function testGetGroup() {
+ $wikipedias = Sites::singleton()->getSiteGroup( "wikipedia" );
+
+ $this->assertFalse( $wikipedias->isEmpty() );
+
+ /* @var Site $site */
+ foreach ( $wikipedias as $site ) {
+ $this->assertEquals( 'wikipedia', $site->getGroup() );
+ }
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Holds sites for testing purposes.
+ *
+ * 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
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class TestSites {
+
+ /**
+ * @since 1.21
+ *
+ * @return array
+ */
+ public static function getSites() {
+ $sites = array();
+
+ $site = Sites::newSite( 'foobar' );
+ $sites[] = $site;
+
+ $site = Sites::newSite( 'enwiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setType( Site::TYPE_MEDIAWIKI );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'enwiktionary' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://en.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://en.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ $site = Sites::newSite( 'dewiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setType( Site::TYPE_MEDIAWIKI );
+ $site->setLanguageCode( 'de' );
+ $site->addInterwikiId( 'dewiktionary' );
+ $site->addInterwikiId( 'wiktionaryde' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://de.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://de.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ $site = Sites::newSite( 'spam' );
+ $site->setGroup( 'spam' );
+ $site->setType( Site::TYPE_UNKNOWN );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'spam' );
+ $site->addNavigationId( 'spamz' );
+ $site->addInterwikiId( 'spamzz' );
+ $site->setLinkPath( "http://spamzz.test/testing/" );
+ $sites[] = $site;
+
+ foreach ( array( 'en', 'de', 'nl', 'sv', 'sr', 'no', 'nn' ) as $langCode ) {
+ $site = Sites::newSite( $langCode . 'wiki' );
+ $site->setGroup( 'wikipedia' );
+ $site->setType( Site::TYPE_MEDIAWIKI );
+ $site->setLanguageCode( $langCode );
+ $site->addInterwikiId( $langCode );
+ $site->addNavigationId( $langCode );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://$langCode.wikipedia.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://$langCode.wikipedia.org/w/$1" );
+ $sites[] = $site;
+ }
+
+ return $sites;
+ }
+
+ /**
+ * Inserts sites into the database for the unit tests that need them.
+ *
+ * @since 0.1
+ */
+ public static function insertIntoDb() {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $dbw->begin( __METHOD__ );
+
+ $dbw->delete( 'sites', '*', __METHOD__ );
+ $dbw->delete( 'site_identifiers', '*', __METHOD__ );
+
+ /**
+ * @var Site $site
+ */
+ foreach ( TestSites::getSites() as $site ) {
+ $site->save();
+ }
+
+ $dbw->commit( __METHOD__ );
+
+ Sites::singleton()->getSites( false ); // re-cache
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Sanity checks for making sure registered resources are sane.
+ *
+ * @file
+ * @author Niklas Laxström, 2012
+ * @author Antoine Musso, 2012
+ * @author Santhosh Thottingal, 2012
+ * @author Timo Tijhof, 2012
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ */
+class ResourcesTest extends MediaWikiTestCase {
+
+ /**
+ * @dataProvider provideResourceFiles
+ */
+ public function testFileExistence( $filename, $module, $resource ) {
+ $this->assertFileExists( $filename,
+ "File '$resource' referenced by '$module' must exist."
+ );
+ }
+
+ /**
+ * This ask the ResouceLoader for all registered files from modules
+ * created by ResourceLoaderFileModule (or one of its descendants).
+ *
+ *
+ * Since the raw data is stored in protected properties, we have to
+ * overrride this through ReflectionObject methods.
+ */
+ public static function provideResourceFiles() {
+ global $wgEnableJavaScriptTest;
+
+ // Test existance of test suite files as well
+ // (can't use setUp or setMwGlobals because providers are static)
+ $live_wgEnableJavaScriptTest = $wgEnableJavaScriptTest;
+ $wgEnableJavaScriptTest = true;
+
+ // Array with arguments for the test function
+ $cases = array();
+
+ // Initialize ResourceLoader
+ $rl = new ResourceLoader();
+
+ // See also ResourceLoaderFileModule::__construct
+ $filePathProps = array(
+ // Lists of file paths
+ 'lists' => array(
+ 'scripts',
+ 'debugScripts',
+ 'loaderScripts',
+ 'styles',
+ ),
+
+ // Collated lists of file paths
+ 'nested-lists' => array(
+ 'languageScripts',
+ 'skinScripts',
+ 'skinStyles',
+ ),
+ );
+
+ foreach ( $rl->getModuleNames() as $moduleName ) {
+ $module = $rl->getModule( $moduleName );
+ if ( ! $module instanceof ResourceLoaderFileModule ) {
+ continue;
+ }
+
+ $reflectedModule = new ReflectionObject( $module );
+
+ $files = array();
+
+ foreach ( $filePathProps['lists'] as $propName ) {
+ $property = $reflectedModule->getProperty( $propName );
+ $property->setAccessible( true );
+ $list = $property->getValue( $module );
+ foreach ( $list as $key => $value ) {
+ // 'scripts' are numeral arrays.
+ // 'styles' can be numeral or associative.
+ // In case of associative the key is the file path
+ // and the value is the 'media' attribute.
+ if ( is_int( $key ) ) {
+ $files[] = $value;
+ } else {
+ $files[] = $key;
+ }
+ }
+ }
+
+ foreach ( $filePathProps['nested-lists'] as $propName ) {
+ $property = $reflectedModule->getProperty( $propName );
+ $property->setAccessible( true );
+ $lists = $property->getValue( $module );
+ foreach ( $lists as $group => $list ) {
+ foreach ( $list as $key => $value ) {
+ // We need the same filter as for 'lists',
+ // due to 'skinStyles'.
+ if ( is_int( $key ) ) {
+ $files[] = $value;
+ } else {
+ $files[] = $key;
+ }
+ }
+ }
+ }
+
+ // Get method for resolving the paths to full paths
+ $method = $reflectedModule->getMethod( 'getLocalPath' );
+ $method->setAccessible( true );
+
+ // Populate cases
+ foreach ( $files as $file ) {
+ $cases[] = array(
+ $method->invoke( $module, $file ),
+ $module->getName(),
+ $file,
+ );
+ }
+
+ }
+
+ // Restore settings
+ $wgEnableJavaScriptTest = $live_wgEnableJavaScriptTest;
+
+ return $cases;
+ }
+
+}
* @ingroup Media
*/
-require './thumb.php';
+require './thumb.php';