"in-place", as long as you have the necessary prerequisites available.
Required software:
-* Web server with PHP 5.3.2 or higher.
+* Web server with PHP 5.3.3 or higher.
* A SQL server, the following types are supported
** MySQL 5.0.2 or higher
** PostgreSQL 8.3 or higher
https://www.mediawiki.org/wiki/Manual:Skinning#Page_status_indicators
* Edit tokens may now be time-limited: passing a maximum age to
User::matchEditToken will reject any older tokens.
+* The debug logging internals have been overhauled, and are now using the
+ PSR-3 interfaces.
=== Bug fixes in 1.25 ===
* (bug 71003) No additional code will be generated to try to load CSS-embedded
== Compatibility ==
-MediaWiki 1.25 requires PHP 5.3.2 or later. There is experimental support for
+MediaWiki 1.25 requires PHP 5.3.3 or later. There is experimental support for
HHVM 3.3.0.
MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but
define( 'MW_API', true );
// Bail if PHP is too low
-if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.3' ) < 0 ) {
// We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
wfPHPVersionError( 'api.php' );
"wiki": "https://www.mediawiki.org/"
},
"require": {
- "php": ">=5.3.2",
+ "php": ">=5.3.3",
"psr/log": "1.0.0"
},
"require-dev": {
to inject an MWLoggerSpi instance into MWLogger and bypass the use of this
configuration variable.
+The MWLoggerLegacySpi class implements a service provider to generate
+MWLoggerLegacyLogger instances. The MWLoggerLegacyLogger class implements the
+PSR-3 logger interface and provides output and configuration equivalent to the
+historic logging output of wfDebug, wfDebugLog, wfLogDBError and wfErrorLog.
+The MWLoggerLegacySpi class is the default service provider configured in
+DefaultSettings.php. It's usage should be transparent for users who are not
+ready or do not wish to switch to a alternate logging platform.
+
The MWLoggerMonologSpi class implements a service provider to generate
MWLogger instances that use the Monolog [1] logging library. See the PHP docs
(or source) for MWLoggerMonologSpi for details on the configuration of this
: Service provider interface for MWLogger factories
; MWLoggerNullSpi
: MWLoggerSpi for creating instances that discard all log events
+; MWLoggerLegacySpi
+: Service provider for creating MWLoggerLegacyLogger instances
+; MWLoggerLegacyLogger
+: PSR-3 logger that mimics the historical output and configuration of wfDebug,
+ wfErrorLog and other global logging functions.
; MWLoggerMonologSpi
: MWLoggerSpi for creating instances backed by the monolog logging library
; MwLoggerMonologHandler
# includes/debug
'MWDebug' => 'includes/debug/MWDebug.php',
'MWLogger' => 'includes/debug/logger/Logger.php',
+ 'MWLoggerLegacyLogger' => 'includes/debug/logger/legacy/Logger.php',
+ 'MWLoggerLegacySpi' => 'includes/debug/logger/legacy/Spi.php',
'MWLoggerMonologHandler' => 'includes/debug/logger/monolog/Handler.php',
'MWLoggerMonologProcessor' => 'includes/debug/logger/monolog/Processor.php',
'MWLoggerMonologSpi' => 'includes/debug/logger/monolog/Spi.php',
* @see MwLogger
*/
$wgMWLoggerDefaultSpi = array(
- 'class' => 'MWLoggerNullSpi',
+ 'class' => 'MWLoggerLegacySpi',
);
/**
/**
* Compatibility functions
*
- * We support PHP 5.3.2 and up.
+ * We support PHP 5.3.3 and up.
* Re-implementations of newer functions or functions in non-standard
* PHP extensions may be included here.
*/
* - false: same as 'log'
*/
function wfDebug( $text, $dest = 'all' ) {
- global $wgDebugLogFile, $wgDebugRawPage, $wgDebugLogPrefix;
+ global $wgDebugRawPage, $wgDebugLogPrefix;
if ( !$wgDebugRawPage && wfIsDebugRawPage() ) {
return;
$timer = wfDebugTimer();
if ( $timer !== '' ) {
+ // Prepend elapsed request time and real memory usage to each line
$text = preg_replace( '/[^\n]/', $timer . '\0', $text, 1 );
}
MWDebug::debugMsg( $text );
}
- if ( $wgDebugLogFile != '' ) {
- # Strip unprintables; they can switch terminal modes when binary data
- # gets dumped, which is pretty annoying.
- $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $text );
- $text = $wgDebugLogPrefix . $text;
- wfErrorLog( $text, $wgDebugLogFile );
+ $ctx = array();
+ if ( $wgDebugLogPrefix !== '' ) {
+ $ctx['prefix'] = $wgDebugLogPrefix;
}
+
+ $logger = MWLogger::getInstance( 'wfDebug' );
+ $logger->debug( rtrim( $text, "\n" ), $ctx );
}
/**
function wfDebugLog( $logGroup, $text, $dest = 'all' ) {
global $wgDebugLogGroups;
- $text = trim( $text ) . "\n";
-
// Turn $dest into a string if it's a boolean (for b/c)
if ( $dest === true ) {
$dest = 'all';
$dest = 'private';
}
- if ( !isset( $wgDebugLogGroups[$logGroup] ) ) {
- if ( $dest !== 'private' ) {
- wfDebug( "[$logGroup] $text", $dest );
- }
- return;
- }
+ $text = trim( $text );
if ( $dest === 'all' ) {
- MWDebug::debugMsg( "[$logGroup] $text" );
- }
-
- $logConfig = $wgDebugLogGroups[$logGroup];
- if ( $logConfig === false ) {
- return;
- }
- if ( is_array( $logConfig ) ) {
- if ( isset( $logConfig['sample'] ) && mt_rand( 1, $logConfig['sample'] ) !== 1 ) {
- return;
- }
- $destination = $logConfig['destination'];
- } else {
- $destination = strval( $logConfig );
+ MWDebug::debugMsg( "[{$logGroup}] {$text}\n" );
}
- $time = wfTimestamp( TS_DB );
- $wiki = wfWikiID();
- $host = wfHostname();
- wfErrorLog( "$time $host $wiki: $text", $destination );
+ $logger = MWLogger::getInstance( $logGroup );
+ $logger->debug( $text, array(
+ 'private' => ( $dest === 'private' ),
+ ) );
}
/**
* @param string $text Database error message.
*/
function wfLogDBError( $text ) {
- global $wgDBerrorLog, $wgDBerrorLogTZ;
- static $logDBErrorTimeZoneObject = null;
-
- if ( $wgDBerrorLog ) {
- $host = wfHostname();
- $wiki = wfWikiID();
-
- if ( $wgDBerrorLogTZ && !$logDBErrorTimeZoneObject ) {
- $logDBErrorTimeZoneObject = new DateTimeZone( $wgDBerrorLogTZ );
- }
-
- // Workaround for https://bugs.php.net/bug.php?id=52063
- // Can be removed when min PHP > 5.3.2
- if ( $logDBErrorTimeZoneObject === null ) {
- $d = date_create( "now" );
- } else {
- $d = date_create( "now", $logDBErrorTimeZoneObject );
- }
-
- $date = $d->format( 'D M j G:i:s T Y' );
-
- $text = "$date\t$host\t$wiki\t" . trim( $text ) . "\n";
- wfErrorLog( $text, $wgDBerrorLog );
- }
+ $logger = MWLogger::getInstance( 'wfLogDBError' );
+ $logger->error( trim( $text ) );
}
/**
* @throws MWException
*/
function wfErrorLog( $text, $file ) {
- if ( substr( $file, 0, 4 ) == 'udp:' ) {
- # Needs the sockets extension
- if ( preg_match( '!^(tcp|udp):(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
- // IPv6 bracketed host
- $host = $m[2];
- $port = intval( $m[3] );
- $prefix = isset( $m[4] ) ? $m[4] : false;
- $domain = AF_INET6;
- } elseif ( preg_match( '!^(tcp|udp):(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
- $host = $m[2];
- if ( !IP::isIPv4( $host ) ) {
- $host = gethostbyname( $host );
- }
- $port = intval( $m[3] );
- $prefix = isset( $m[4] ) ? $m[4] : false;
- $domain = AF_INET;
- } else {
- throw new MWException( __METHOD__ . ': Invalid UDP specification' );
- }
-
- // Clean it up for the multiplexer
- if ( strval( $prefix ) !== '' ) {
- $text = preg_replace( '/^/m', $prefix . ' ', $text );
-
- // Limit to 64KB
- if ( strlen( $text ) > 65506 ) {
- $text = substr( $text, 0, 65506 );
- }
-
- if ( substr( $text, -1 ) != "\n" ) {
- $text .= "\n";
- }
- } elseif ( strlen( $text ) > 65507 ) {
- $text = substr( $text, 0, 65507 );
- }
-
- $sock = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
- if ( !$sock ) {
- return;
- }
-
- socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port );
- socket_close( $sock );
- } else {
- wfSuppressWarnings();
- $exists = file_exists( $file );
- $size = $exists ? filesize( $file ) : false;
- if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
- file_put_contents( $file, $text, FILE_APPEND );
- }
- wfRestoreWarnings();
- }
+ $logger = MWLogger::getInstance( 'wfErrorLog' );
+ $logger->info( trim( $text ), array(
+ 'destination' => $file,
+ ) );
}
/**
if ( $ifWritesSince && !$lb->hasMasterConnection() ) {
continue; // assume no writes done
}
- $dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
+ // Use the empty string to not trigger selectDB() since the connection
+ // may have been to a server that does not have a DB for the current wiki.
+ $dbw = $lb->getConnection( DB_MASTER, array(), '' );
if ( $ifWritesSince && $dbw->lastDoneWrites() < $ifWritesSince ) {
continue; // no writes since the last wait
}
*/
function wfPHPVersionError( $type ) {
$mwVersion = '1.25';
- $minimumVersionPHP = '5.3.2';
+ $minimumVersionPHP = '5.3.3';
$phpVersion = PHP_VERSION;
$protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=block&user=192.0.2.5&expiry=3%20days&reason=First%20strike&token=123ABC'
=> 'apihelp-block-example-ip-simple',
return false;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=clearhasmsg'
=> 'apihelp-clearhasmsg-example-1',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=compare&fromrev=1&torev=2'
=> 'apihelp-compare-example-1',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=createaccount&name=testuser&password=test123'
=> 'apihelp-createaccount-example-pass',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=delete&title=Main%20Page&token=123ABC'
=> 'apihelp-delete-example-simple',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=edit&title=Test&summary=test%20summary&' .
'text=article%20content&basetimestamp=2007-08-24T12:34:54Z&token=123ABC'
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=emailuser&target=WikiSysop&text=Content&token=123ABC'
=> 'apihelp-emailuser-example-email',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=expandtemplates&text={{Project:Sandbox}}'
=> 'apihelp-expandtemplates-example-simple',
return $ret;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=feedcontributions&user=Example'
=> 'apihelp-feedcontributions-example-simple',
return $ret;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=feedrecentchanges'
=> 'apihelp-feedrecentchanges-example-simple',
return $ret;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=feedwatchlist'
=> 'apihelp-feedwatchlist-example-default',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=filerevert&filename=Wiki.png&comment=Revert&' .
'archivename=20110305152740!Wiki.png&token=123ABC'
return $this->mBuffer;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&meta=siteinfo&siprop=namespaces&format=' . $this->getModuleName()
=> array( 'apihelp-format-example-generic', $this->getFormat() )
->parse();
}
- if ( !$description && !$info ) {
- $description[] = self::wrap(
+ if ( !array_filter( $description ) ) {
+ $description = array( self::wrap(
$context->msg( 'api-help-param-no-description' ),
'apihelp-empty'
- );
+ ) );
}
// Add "deprecated" flag
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=help'
=> 'apihelp-help-example-main',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=imagerotate&titles=File:Example.jpg&rotation=90&token=123ABC'
=> 'apihelp-imagerotate-example-simple',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=import&interwikisource=meta&interwikipage=Help:ParserFunctions&' .
'namespace=100&fullhistory=&token=123ABC'
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=login&lgname=user&lgpassword=password'
=> 'apihelp-login-example-gettoken',
return false;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=logout'
=> 'apihelp-logout-example-logout',
}
/** @see ApiBase::getExamplesMessages() */
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=help'
=> 'apihelp-help-example-main',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=move&from=Badtitle&to=Goodtitle&token=123ABC&' .
'reason=Misspelled%20title&movetalk=&noredirect='
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=opensearch&search=Te'
=> 'apihelp-opensearch-example-te',
return 'https://www.mediawiki.org/wiki/API:Options';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=options&reset=&token=123ABC'
=> 'apihelp-options-example-reset',
/**
* Populate this PageSet from a rowset returned from the database
+ *
+ * Note that the query result must include the columns returned by
+ * $this->getPageTableFields().
+ *
* @param DatabaseBase $db
* @param ResultWrapper $queryResult Query result object
*/
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=paraminfo&modules=parse|phpfm|query+allpages|query+siteinfo'
=> 'apihelp-paraminfo-example-1',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=parse&page=Project:Sandbox'
=> 'apihelp-parse-example-page',
return 'patrol';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=patrol&token=123ABC&rcid=230672766'
=> 'apihelp-patrol-example-rcid',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=protect&title=Main%20Page&token=123ABC&' .
'protections=edit=sysop|move=sysop&cascade=&expiry=20070901163000|never'
return $result;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=purge&titles=Main_Page|API'
=> 'apihelp-purge-example-simple',
return true;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=revisions&meta=siteinfo&' .
'titles=Main%20Page&rvprop=user|comment&continue='
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=allcategories&acprop=size'
=> 'apihelp-query+allcategories-example-size',
private $propertyFilter = array( 'archivename', 'thumbmime', 'uploadwarning' );
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=allimages&aifrom=B'
=> 'apihelp-query+allimages-example-B',
return $allowedParams;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
$p = $this->getModulePrefix();
$name = $this->getModuleName();
$path = $this->getModulePath();
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&meta=allmessages&refix=ipb-'
=> 'apihelp-query+allmessages-example-ipb',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=allpages&apfrom=B'
=> 'apihelp-query+allpages-example-B',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=allusers&aufrom=Y'
=> 'apihelp-query+allusers-example-Y',
return $retval;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
static $examples = array(
'backlinks' => array(
'action=query&list=backlinks&bltitle=Main%20Page'
return $ret;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
$settings = self::$settings[$this->getModuleName()];
$name = $this->getModuleName();
$path = $this->getModulePath();
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=blocks'
=> 'apihelp-query+blocks-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=categories&titles=Albert%20Einstein'
=> 'apihelp-query+categories-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=categoryinfo&titles=Category:Foo|Category:Bar'
=> 'apihelp-query+categoryinfo-example-simple',
return $ret;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=categorymembers&cmtitle=Category:Physics'
=> 'apihelp-query+categorymembers-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=contributors&titles=Main_Page'
=> 'apihelp-query+contributors-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&' .
'drprop=user|comment|content'
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&titles=File:Albert_Einstein_Head.jpg&prop=duplicatefiles'
=> 'apihelp-query+duplicatefiles-example-simple',
}
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=exturlusage&euquery=www.mediawiki.org'
=> 'apihelp-query+exturlusage-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=extlinks&titles=Main%20Page'
=> 'apihelp-query+extlinks-example-simple',
) ) );
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&meta=filerepoinfo&friprop=apiurl|name|displayname'
=> 'apihelp-query+filerepoinfo-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=filearchive'
=> 'apihelp-query+filearchive-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=iwbacklinks&iwbltitle=Test&iwblprefix=wikibooks'
=> 'apihelp-query+iwbacklinks-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=iwlinks&titles=Main%20Page'
=> 'apihelp-query+iwlinks-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo'
=> 'apihelp-query+imageinfo-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=images&titles=Main%20Page'
=> 'apihelp-query+images-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=info&titles=Main%20Page'
=> 'apihelp-query+info-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=langbacklinks&lbltitle=Test&lbllang=fr'
=> 'apihelp-query+langbacklinks-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=langlinks&titles=Main%20Page&redirects='
=> 'apihelp-query+langlinks-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
$name = $this->getModuleName();
$path = $this->getModulePath();
return $ret;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=logevents'
=> 'apihelp-query+logevents-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=pagepropnames'
=> 'apihelp-query+pagepropnames-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=pageprops&titles=Category:Foo'
=> 'apihelp-query+pageprops-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=pageswithprop&pwppropname=displaytitle&pwpprop=ids|title|value'
=> 'apihelp-query+pageswithprop-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=prefixsearch&pssearch=meaning'
=> 'apihelp-query+prefixsearch-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=protectedtitles'
=> 'apihelp-query+protectedtitles-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=querypage&qppage=Ancientpages'
=> 'apihelp-query+querypage-example-ancientpages',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=random&rnnamespace=0&rnlimit=2'
=> 'apihelp-query+random-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=recentchanges'
=> 'apihelp-query+recentchanges-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=revisions&titles=API|Main%20Page&' .
'rvprop=timestamp|user|comment|content'
return $params;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=search&srsearch=meaning'
=> 'apihelp-query+search-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics'
=> 'apihelp-query+siteinfo-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&prop=stashimageinfo&siifilekey=124sd34rsdf567'
=> 'apihelp-query+stashimageinfo-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=tags&tgprop=displayname|description|hitcount'
=> 'apihelp-query+tags-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=usercontribs&ucuser=Example'
=> 'apihelp-query+usercontribs-example-user',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&meta=userinfo'
=> 'apihelp-query+userinfo-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=users&ususers=Example&usprop=groups|editcount|gender'
=> 'apihelp-query+users-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=watchlist'
=> 'apihelp-query+watchlist-example-simple',
);
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=query&list=watchlistraw'
=> 'apihelp-query+watchlistraw-example-simple',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=revisiondelete&target=Main%20Page&type=revision&ids=12345&' .
'hide=content&token=123ABC'
return $this->mTitleObj;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=rollback&title=Main%20Page&user=Example&token=123ABC' =>
'apihelp-rollback-example-simple',
return new ApiFormatXmlRsd( $this->getMain(), 'xml' );
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=rsd'
=> 'apihelp-rsd-example-simple',
return $result;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=setnotificationtimestamp&entirewatchlist=&token=123ABC'
=> 'apihelp-setnotificationtimestamp-example-all',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=unblock&id=105'
=> 'apihelp-unblock-example-id',
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=undelete&title=Main%20Page&token=123ABC&reason=Restoring%20main%20page'
=> 'apihelp-undelete-example-page',
$this->dieUsage( 'No upload module set', 'nomodule' );
}
} catch ( UploadStashException $e ) { // XXX: don't spam exception log
- $this->dieUsage( get_class( $e ) . ": " . $e->getMessage(), 'stasherror' );
+ $this->handleStashException( $e );
}
// First check permission to upload
$result['imageinfo'] = $this->mUpload->getImageInfo( $this->getResult() );
}
} catch ( UploadStashException $e ) { // XXX: don't spam exception log
- $this->dieUsage( get_class( $e ) . ": " . $e->getMessage(), 'stasherror' );
+ $this->handleStashException( $e );
}
$this->getResult()->addValue( null, $this->getModuleName(), $result );
if ( $warnings && count( $warnings ) > 0 ) {
$result['warnings'] = $warnings;
}
+ } catch ( UploadStashException $e ) {
+ $this->handleStashException( $e );
} catch ( MWException $e ) {
$this->dieUsage( $e->getMessage(), 'stashfailed' );
}
try {
$result['filekey'] = $this->performStash();
$result['sessionkey'] = $result['filekey']; // backwards compatibility
+ } catch ( UploadStashException $e ) {
+ $this->handleStashException( $e );
} catch ( MWException $e ) {
$result['warnings']['stashfailed'] = $e->getMessage();
}
if ( $this->mParams['offset'] == 0 ) {
try {
$filekey = $this->performStash();
+ } catch ( UploadStashException $e ) {
+ $this->handleStashException( $e );
} catch ( MWException $e ) {
// FIXME: Error handling here is wrong/different from rest of this
$this->dieUsage( $e->getMessage(), 'stashfailed' );
} catch ( MWException $e ) {
$message = 'Stashing temporary file failed: ' . get_class( $e ) . ' ' . $e->getMessage();
wfDebug( __METHOD__ . ' ' . $message . "\n" );
- throw new MWException( $message );
+ $className = get_class( $e );
+ throw new $className( $message );
}
return $fileKey;
return $warnings;
}
+ /**
+ * Handles a stash exception, giving a useful error to the user.
+ * @param Exception $e The exception we encountered.
+ */
+ protected function handleStashException( $e ) {
+ $exceptionType = get_class( $e );
+
+ switch ( $exceptionType ) {
+ case 'UploadStashFileNotFoundException':
+ $this->dieUsage( 'Could not find the file in the stash: ' . $e->getMessage(), 'stashedfilenotfound' );
+ break;
+ case 'UploadStashBadPathException':
+ $this->dieUsage( 'File key of improper format or otherwise invalid: ' . $e->getMessage(), 'stashpathinvalid' );
+ break;
+ case 'UploadStashFileException':
+ $this->dieUsage( 'Could not store upload in the stash: ' . $e->getMessage(), 'stashfilestorage' );
+ break;
+ case 'UploadStashZeroLengthFileException':
+ $this->dieUsage( 'File is of zero length, and could not be stored in the stash: ' . $e->getMessage(), 'stashzerolength' );
+ break;
+ case 'UploadStashNotLoggedInException':
+ $this->dieUsage( 'Not logged in: ' . $e->getMessage(), 'stashnotloggedin' );
+ break;
+ case 'UploadStashWrongOwnerException':
+ $this->dieUsage( 'Wrong owner: ' . $e->getMessage(), 'stashwrongowner' );
+ break;
+ case 'UploadStashNoSuchKeyException':
+ $this->dieUsage( 'No such filekey: ' . $e->getMessage(), 'stashnosuchfilekey' );
+ break;
+ default:
+ $this->dieUsage( $exceptionType . ": " . $e->getMessage(), 'stasherror' );
+ break;
+ }
+ }
+
/**
* Perform the actual upload. Returns a suitable result array on success;
* dies on failure.
return 'csrf';
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=upload&filename=Wiki.png' .
'&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png&token=123ABC'
return $this->getUrUser( $params )->getName();
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=userrights&user=FooBot&add=bot&remove=sysop|bureaucrat&token=123ABC'
=> 'apihelp-userrights-example-user',
return $result;
}
- public function getExamplesMessages() {
+ protected function getExamplesMessages() {
return array(
'action=watch&titles=Main_Page&token=123ABC'
=> 'apihelp-watch-example-watch',
--- /dev/null
+{
+ "@metadata": {
+ "authors": [
+ "Red Winged Duck"
+ ]
+ },
+ "apihelp-main-param-action": "Дзеяньне для выкананьня."
+}
"apihelp-edit-param-nocreate": "رها کردن خطا در صورتی که صفحه وجود ندارد.",
"apihelp-edit-param-watch": "افزودن صفحه به فهرست پیگیری شما",
"apihelp-edit-param-unwatch": "حذف صفحه از فهرست پیگیری شما",
+ "apihelp-edit-param-prependtext": "این متن را به ابتدای صفحه اضافه کنید. $1text را لغو میکند.",
"apihelp-edit-param-redirect": "اصلاح خودکار تغییرمسیرها.",
"apihelp-edit-example-edit": "ویرایش صفحه",
"apihelp-emailuser-description": "ایمیل به کاربر",
"apihelp-feedcontributions-param-newonly": "فقط نمایش ویرایشهایی که تولیدهای صفحه هستند.",
"apihelp-feedcontributions-param-showsizediff": "نمایش تفاوت حجم تغییرات بین نسخهها.",
"apihelp-feedrecentchanges-param-feedformat": "فرمت خوراک.",
+ "apihelp-feedrecentchanges-param-namespace": "فضای نام برای محدودکردن نتایج به.",
+ "apihelp-feedrecentchanges-param-invert": "همهٔ فضاهای نام به جز انتخابشدهها.",
"apihelp-feedrecentchanges-param-days": "روز برای محدود کردن نتایج.",
"apihelp-feedrecentchanges-param-limit": "حداکثر تعداد نتایج خروجی.",
"apihelp-feedrecentchanges-param-from": "نمایش تغییرات پس از آن.",
"apihelp-move-param-movesubpages": "انتقال زیر صفحهها اگر امکانپذیر است.",
"apihelp-move-param-noredirect": "عدم ساخت تغییرمسیر.",
"apihelp-move-param-ignorewarnings": "چشمپوشی از همهٔ هشدارها.",
+ "apihelp-opensearch-param-search": "جستجوی رشته.",
+ "apihelp-opensearch-param-limit": "حداکثر تعداد نتایج برای بازگرداندن.",
"apihelp-opensearch-param-namespace": "فضاهای نامی برای جستجو",
"apihelp-opensearch-param-format": "فرمت خروجی.",
+ "apihelp-opensearch-example-te": "یافتن صفحههایی که با «ته» آغاز میشوند",
"apihelp-options-example-reset": "بازنشانی همه تنظیمات.",
"apihelp-parse-example-page": "تجزیه یک صفحه.",
"apihelp-parse-example-text": "تجزیه متن ویکی.",
"apihelp-protect-param-reason": "دلیل برای (عدم) حفاظت.",
"apihelp-protect-example-protect": "محافظت از صفحه",
"apihelp-purge-param-forcelinkupdate": "بهروزرسانی جداول پیوندها.",
+ "apihelp-query+allpages-param-filterredir": "صفحههایی که باید فهرست شوند.",
+ "apihelp-query+allpages-param-minsize": "محدودکردن به صفحههایی که همراه دست کم این تعداد بایت است.",
+ "apihelp-query+allredirects-param-limit": "تعداد آیتمها برای بازگرداندن.",
+ "apihelp-query+categorymembers-description": "فهرستکردن همهٔ صفحهها در یک ردهٔ مشخصشده.",
+ "apihelp-query+categorymembers-param-startsortkey": "جایش از $1starthexsortkey استفاده کنید.",
+ "apihelp-query+imageinfo-param-urlheight": "مشابه $1urlwidth.",
+ "apihelp-query+info-description": "دریافت اطلاعات سادهٔ صفحه.",
+ "apihelp-query+iwbacklinks-param-prefix": "پیشوند میانویکی.",
+ "apihelp-query+iwbacklinks-param-title": "پیوند میانویکی برای جستجو. باید همراه $1blprefix استفاده شود.",
+ "apihelp-query+iwbacklinks-param-limit": "تعداد صفحهها برای بازگرداندن.",
+ "apihelp-query+linkshere-param-limit": "تعداد برای بازگرداندن.",
+ "apihelp-query+logevents-description": "دریافت رویدادها از سیاههها.",
+ "apihelp-query+protectedtitles-param-namespace": "فقط عنوانها در این فضاهای نام را فهرست کنید.",
+ "apihelp-query+protectedtitles-param-level": "فقط عنوانها در این سطحهای حفاظت را فهرست کنید.",
+ "apihelp-query+protectedtitles-param-limit": "تعداد صفحهها برای بازگرداندن.",
+ "apihelp-query+protectedtitles-param-start": "آغاز فهرستکردن از این برچسب زمانی حفاظت.",
+ "apihelp-query+protectedtitles-param-end": "متوقفکردن فهرستکردن در این برچسب زمانی حفاظت.",
+ "apihelp-query+random-param-namespace": "بازگرداندن صفحههای فقط در این فضاهای نام.",
+ "apihelp-query+random-param-limit": "محدود کنید چه تعداد صفحه بازگردانده خواهد شد.",
+ "apihelp-query+random-param-redirect": "یک تغییرمسیر تصادفی جای یک صفحه تصادفی بارگیری کنید.",
+ "apihelp-query+random-example-simple": "بازگرداندن تو صفحهٔ تصادفی از فضای نام اصلی",
+ "apihelp-query+random-example-generator": "بازگرداندن اطلاعات صفحه دربارهٔ دو صفحهٔ تصادفی از فضای نام اصلی",
+ "apihelp-query+recentchanges-param-start": "برچسب زمانی برای آغاز شمارش از.",
+ "apihelp-query+recentchanges-param-end": "برچسب زمانی برای پایان شمارش.",
+ "apihelp-query+redirects-param-limit": "تعداد تغییرمسیرها برای بازگرداندن.",
"apihelp-upload-param-ignorewarnings": "چشمپوشی از همهٔ هشدارها.",
"apihelp-userrights-param-user": "نام کاربری.",
"api-help-param-deprecated": "توصیه.",
"apihelp-query+allfileusages-param-to": "Le titre du fichier auquel arrêter l’énumération.",
"apihelp-query+allfileusages-param-prefix": "Rechercher tous les titres de fichier qui commencent par cette valeur.",
"apihelp-query+allfileusages-param-unique": "Afficher uniquement les titres de fichier distincts. Impossible à utiliser avec $1prop=ids.\nQuand utilisé comme générateur, produit les pages cibles au lieu des sources.",
+ "apihelp-query+allfileusages-param-prop": "Quelles informations inclure :\n;ids:Ajoute l’ID de la page utilisatrice (impossible à utiliser avec $1unique).\n;title:Ajoute le titre du fichier.",
"apihelp-query+allfileusages-param-limit": "Combien d’éléments renvoyer au total.",
"apihelp-query+allfileusages-param-dir": "La direction dans laquelle lister.",
"apihelp-query+allfileusages-example-B": "Lister les titres de fichier, y compris les manquants, avec les ids de page d’où ils proviennent, en commençant à B",
"apihelp-query+allimages-param-to": "Le titre de l’image auquel arrêter l’énumération. Ne peut être utilisé qu’avec $1sort=name.",
"apihelp-query+allimages-param-start": "L’horodatage depuis lequel énumérer. Ne peut être utilisé qu’avec $1sort=timestamp.",
"apihelp-query+allimages-param-end": "L’horodatage de fin de l’énumération. Ne peut être utilisé qu’avec $1sort=timestamp.",
+ "apihelp-query+allimages-param-prop": "Quelle information obtenir sur l’image :\n;timestamp:Ajoute l’horodatage de la version téléchargée.\n;user:Ajoute l’utilisateur qui a téléchargé la version de l’image.\n;userid:Ajoute l’ID de l’utilisateur qui a téléchargé la version de l’image.\n;comment:Commentaire sur la version.\n;parsedcomment:Analyser le commentaire de la version.\n;canonicaltitle:Ajoute le titre canonique du fichier image.\n;url:Fournit l’URL vers l’image et la page de description.\n;size:Ajoute la taille de l’image en octets et sa hauteur et largeur, et le numéro de page (si applicable).\n;dimensions:Alias de la taille.\n;sha1:Ajoute le hachage SHA-1 de l’image.\n;mime:Ajoute le type MIME de l’image.\n;mediatype:Ajoute le type de média de l’image.\n;metadata:Liste les métadonnées Exif de la version de l’image.\n;commonmetadata:Liste les métadonnées génériques du format de fichier pour la version de l’image.\n;extmetadata:Liste les métadonnées mises en forme regroupées depuis différentes sources. Les résultats sont au format HTML.\n;bitdepth:Ajoute la profondeur de couleur de la version.",
+ "apihelp-query+allimages-param-prefix": "Rechercher tous les titres d’image commençant par cette valeur. Utilisable uniquement avec $1sort=name.",
+ "apihelp-query+allimages-param-minsize": "Restreindre aux images avec au moins ce nombre d’octets.",
+ "apihelp-query+allimages-param-maxsize": "Restreindre aux images avec au plus ce nombre d’octets.",
+ "apihelp-query+allimages-param-sha1": "Hachage SHA1 de l’image. Écrase $1sha1base36.",
+ "apihelp-query+allimages-param-sha1base36": "Hachage SHA1 de l’image en base 36 (utilisé dans MédiaWiki).",
+ "apihelp-query+allimages-param-user": "Renvoyer seulement les fichiers téléchargés par cet utilisateur. Utilisable uniquement avec $1sort=timestamp. Impossible à utiliser avec $1filterbots.",
+ "apihelp-query+allimages-param-filterbots": "Comment filtrer les fichiers téléchargés par des robots. Peut être utilisé uniquement avec $1sort=timestamp. Impossible à utiliser avec $1user.",
+ "apihelp-query+allimages-param-mime": "Quel type MIME rechercher, par ex. image/jpeg.",
+ "apihelp-query+allimages-param-limit": "Combien d’images renvoyer au total.",
+ "apihelp-query+allimages-example-B": "Afficher une liste des fichiers commençant par la lettre « B »",
"apihelp-query+alllinks-param-namespace": "L’espace de noms à énumérer.",
"apihelp-query+alllinks-param-limit": "Combien d’éléments renvoyer au total.",
"apihelp-query+alllinks-param-dir": "La direction dans laquelle lister.",
--- /dev/null
+{
+ "@metadata": {
+ "authors": [
+ "Csega"
+ ]
+ },
+ "apihelp-userrights-param-userid": "Felhasználói azonosító."
+}
--- /dev/null
+{
+ "@metadata": {
+ "authors": [
+ "Papuass"
+ ]
+ },
+ "apihelp-userrights-param-userid": "Lietotāja ID:"
+}
"apihelp-import-param-namespace": "За меѓујазични увози: увези во овој именски простор.",
"apihelp-import-param-rootpage": "Увези како потстраница на страницава.",
"apihelp-import-example-import": "Увези [[meta:Help:Parserfunctions]] во именскиот простор 100 со целата историја.",
+ "apihelp-login-description": "Најавете се и добијте колачиња за заверка.\n\nВо случај кога ќе се најавите успешно, потребните колачиња ќе се придодадат кон заглавијата на HTTP-одѕивот. Во случај да не успеете да се најавите, понатамошните обиди може да се ограничат за да се ограничат нападите со автоматизирано погодување на лозинката.",
"apihelp-login-param-name": "Корисничко име.",
"apihelp-login-param-password": "Лозинка.",
"apihelp-login-param-domain": "Домен (незадолжително).",
"apihelp-opensearch-param-format": "Формат на изводот.",
"apihelp-opensearch-example-te": "Најди страници што почнуваат со „Те“",
"apihelp-options-param-reset": "Ги враќа поставките по основно.",
+ "apihelp-options-param-resetkinds": "Писок на типови можности за повраток кога е зададена можноста „$1reset“.",
+ "apihelp-options-param-change": "Список на промени во форматот name=value (на пр. skin=vector). Вредностите не треба да содржат исправени црти. Ако не зададете вредност (дури ни знак за равенство), на пр., можност|другаможност|..., ќе биде зададена вредноста на можноста по основно.",
+ "apihelp-options-param-optionname": "Назив на можноста што треба да ѝ се зададе на вредноста дадена од „$1optionvalue“.",
+ "apihelp-options-param-optionvalue": "Вредноста на можноста укажана од „$1optionnam“. Може да содржи исправени црти.",
"apihelp-options-example-reset": "Врати ги сите поставки по основно",
"apihelp-options-example-change": "Смени ги поставките „skinЗ“ и „hideminor“",
"apihelp-options-example-complex": "Врати ги сите нагодувања по основно, а потоа задај ги „skin“ и „nickname“",
"apihelp-paraminfo-description": "Набави информации за прилошки (API) модули.",
"apihelp-paraminfo-param-modules": "Список на називи на модули (вредности на параметрите action= и format=, или пак „main“). Може да се укажат подмодули со „+“.",
"apihelp-paraminfo-param-helpformat": "Формат на помошните низи.",
+ "apihelp-paraminfo-param-querymodules": "Список на називи на модули за барања (вредност на параметарот prop=, meta= или list=). Користете го „$1modules=query+foo“ наместо „$1querymodules=foo“.",
+ "apihelp-paraminfo-param-mainmodule": "Добави информации и за главниот (врховен) модул. Користете го „$1modules=main“ наместо тоа.",
"apihelp-parse-param-summary": "Опис за расчленување.",
+ "apihelp-parse-param-preview": "Расчлени во прегледен режим.",
"apihelp-parse-param-sectionpreview": "Расчлени во прегледен режим на поднасловот (го овозможува и прегледниот режим).",
"apihelp-parse-param-disabletoc": "Изземи го преглед на содржината во изводеот.",
"apihelp-parse-param-contentformat": "Формат на серијализацијата на содржината во вносниот текст. Важи само кога се користи со $1text.",
"apihelp-parse-example-text": "Расчлени викитекст.",
"apihelp-parse-example-texttitle": "Расчлени страница, укажувајќи го насловот на страницата.",
"apihelp-parse-example-summary": "Расчлени опис.",
+ "apihelp-patrol-description": "Испатролирај страница или ревизија.",
+ "apihelp-patrol-param-rcid": "Назнака на спорешните промени за патролирање.",
+ "apihelp-patrol-param-revid": "Назнака на преработката за патролирање.",
+ "apihelp-patrol-example-rcid": "Испатролирај скорешна промена",
+ "apihelp-patrol-example-revid": "Патролирај праработка",
+ "apihelp-protect-description": "Смени го степенот на заштита на страница.",
+ "apihelp-protect-param-title": "Наслов на страница што се (од)заштитува. Не може да се користи заедно со $1pageid.",
+ "apihelp-protect-param-pageid": "Назнака на страница што се (од)заштитува. Не може да се користи заедно со $1title.",
"apihelp-protect-param-reason": "Причиина за (од)заштитување",
"apihelp-protect-example-protect": "Заштити страница",
+ "apihelp-purge-example-simple": "Превчитај ги „Главна страница“ и „Прилог“",
+ "apihelp-query-param-list": "Кои списоци да се набават.",
+ "apihelp-query-param-meta": "Кои метаподатоци да се набават.",
"apihelp-query+backlinks-example-simple": "Прикажи врски до [[Главна страница|Главната страница]]",
"apihelp-query+backlinks-example-generator": "Дава информации за страниците што водат до [[Главна страница|Главната страница]]",
"apihelp-query+blocks-description": "Список на сите блокирани корисници и IP-адреси",
"apihelp-query+blocks-param-end": "На кој датум и време да запре набројувањето.",
"apihelp-query+blocks-param-ids": "Список на назнаки на блоковите за испис (незадолжително)",
"apihelp-query+blocks-param-users": "Список на корисници што ќе се пребаруваат (незадолжително)",
+ "apihelp-query+imageinfo-param-urlheight": "Слично на $1urlwidth.",
"apihelp-format-example-generic": "Форматирај го резултатот од барањето во $1-формат",
"apihelp-dbg-description": "Давај го изводот во PHP-форматот var_export().",
"apihelp-dbgfm-description": "Давај го изводот во PHP-форматот var_export() (подобрен испис во HTML).",
"@metadata": {
"authors": [
"Siebrand",
- "Sjoerddebruin"
+ "Sjoerddebruin",
+ "Robin0van0der0vliet"
]
},
"apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page Documentatie]\n* [https://www.mediawiki.org/wiki/API:FAQ FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-maillijst]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-aankondigingen]\n* [https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts Bugs & verzoeken]\n</div>\n<strong>Status:</strong> Alle funties die op deze pagina worden weergegeven horen te werken. Aan de API wordt actief gewerkt, en deze kan gewijzigd worden. Abonneer u op de [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-maillijst mediawiki-api-announce] voor meldingen over aanpassingen.\n\n<strong>Foutieve verzoeken:</strong> als de API foutieve verzoeken ontvangt, wordt er geantwoord met een HTTP-header met de sleutel \"MediaWiki-API-Error\" en daarna worden de waarde van de header en de foutcode op dezelfde waarde ingesteld. Zie https://www.mediawiki.org/wiki/API:Errors_and_warnings voor meer informatie.",
"apihelp-main-param-maxlag": "De maximale vertraging kan gebruikt worden als MediaWiki is geïnstalleerd op een databasecluster die gebruik maakt van replicatie. Om te voorkomen dat handelingen nog meer databasereplicatievertraging veroorzaken, kan deze parameter er voor zorgen dat de client wacht totdat de replicatievertraging lager is dan de aangegeven waarde. In het geval van buitensporige vertraging, wordt de foutcode \"maxlag\" teruggegeven met een bericht als \"Waiting for $host: $lag seconds lagged\".<br />Zie https://www.mediawiki.org/wiki/Manual:Maxlag_parameter voor mee informatie.",
"apihelp-main-param-smaxage": "Stelt de header \"s-maxage\" in op het aangegeven aantal seocnden. Foutmeldingen komen nooit in de cache.",
"apihelp-main-param-maxage": "Stelt de header \"max-age\" in op het aangegeven aantal seocnden. Foutmeldingen komen nooit in de cache.",
+ "apihelp-block-description": "Gebruiker blokkeren.",
+ "apihelp-block-param-reason": "Reden voor blokkade.",
+ "apihelp-edit-example-edit": "Pagina bewerken",
+ "apihelp-emailuser-description": "Gebruiker e-mailen.",
+ "apihelp-emailuser-param-subject": "Onderwerp header.",
+ "apihelp-emailuser-param-text": "Mailbody",
+ "apihelp-expandtemplates-param-title": "Titel van de pagina.",
+ "apihelp-feedcontributions-param-year": "Van jaar (en eerder).",
+ "apihelp-feedcontributions-param-month": "Van maand (en eerder).",
+ "apihelp-login-param-name": "Gebruikersnaam.",
+ "apihelp-login-param-password": "Wachtwoord.",
+ "apihelp-login-param-domain": "Domein (optioneel).",
+ "apihelp-login-example-login": "Aanmelden",
+ "apihelp-move-description": "Pagina hernoemen.",
"api-help-parameters": "{{PLURAL:$1|Parameter|Parameters}}:",
"api-help-param-deprecated": "Verouderd.",
"api-help-param-default": "Standaard: $1",
* Takes an array of field names with prefix and returns the unprefixed equivalent.
*
* @since 1.20
+ * @deprecated since 1.25, will be removed
*
- * @param array $fieldNames
+ * @param string[] $fieldNames
*
- * @return array
+ * @return string[]
*/
public function unprefixFieldNames( array $fieldNames );
* Takes a field name with prefix and returns the unprefixed equivalent.
*
* @since 1.20
+ * @deprecated since 1.25, will be removed
*
* @param string $fieldName
*
* Takes an array of field names with prefix and returns the unprefixed equivalent.
*
* @since 1.20
+ * @deprecated since 1.25, will be removed
*
- * @param array $fieldNames
+ * @param string[] $fieldNames
*
- * @return array
+ * @return string[]
*/
public function unprefixFieldNames( array $fieldNames ) {
+ wfDeprecated( __METHOD__, '1.25' );
+
+ return $this->stripFieldPrefix( $fieldNames );
+ }
+
+ /**
+ * Takes an array of field names with prefix and returns the unprefixed equivalent.
+ *
+ * @param string[] $fieldNames
+ *
+ * @return string[]
+ */
+ private function stripFieldPrefix( array $fieldNames ) {
$start = strlen( $this->fieldPrefix );
return array_map( function( $fieldName ) use ( $start ) {
* Takes a field name with prefix and returns the unprefixed equivalent.
*
* @since 1.20
+ * @deprecated since 1.25, will be removed
*
* @param string $fieldName
*
* @return string
*/
public function unprefixFieldName( $fieldName ) {
+ wfDeprecated( __METHOD__, '1.25' );
+
return substr( $fieldName, strlen( $this->fieldPrefix ) );
}
$result = (array)$result;
$rawFields = array_combine(
- $this->unprefixFieldNames( array_keys( $result ) ),
+ $this->stripFieldPrefix( array_keys( $result ) ),
array_values( $result )
);
protected static $debug = array();
/**
- * SQL statements of the databses queries.
+ * SQL statements of the database queries.
*
* @var array $query
*/
--- /dev/null
+<?php
+/**
+ * @section LICENSE
+ * 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
+ */
+
+/**
+ * PSR-3 logger that mimics the historic implementation of MediaWiki's
+ * wfErrorLog logging implementation.
+ *
+ * This logger is configured by the following global configuration variables:
+ * - `$wgDebugLogFile`
+ * - `$wgDebugLogGroups`
+ * - `$wgDBerrorLog`
+ * - `$wgDBerrorLogTZ`
+ *
+ * See documentation in DefaultSettings.php for detailed explanations of each
+ * variable.
+ *
+ * @see MWLogger
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ */
+class MWLoggerLegacyLogger extends \Psr\Log\AbstractLogger {
+
+ /**
+ * @var string $channel
+ */
+ protected $channel;
+
+
+ /**
+ * @param string $channel
+ */
+ public function __construct( $channel ) {
+ $this->channel = $channel;
+ }
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param string|int $level
+ * @param string $message
+ * @param array $context
+ */
+ public function log( $level, $message, array $context = array() ) {
+ if ( self::shouldEmit( $this->channel, $message, $context ) ) {
+ $text = self::format( $this->channel, $message, $context );
+ $destination = self::destination( $this->channel, $message, $context );
+ self::emit( $text, $destination );
+ }
+ }
+
+
+ /**
+ * Determine if the given message should be emitted or not.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return bool True if message should be sent to disk/network, false
+ * otherwise
+ */
+ protected static function shouldEmit( $channel, $message, $context ) {
+ global $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
+
+ if ( $channel === 'wfLogDBError' ) {
+ // wfLogDBError messages are emitted if a database log location is
+ // specfied.
+ $shouldEmit = (bool) $wgDBerrorLog;
+
+ } elseif ( $channel === 'wfErrorLog' ) {
+ // All messages on the wfErrorLog channel should be emitted.
+ $shouldEmit = true;
+
+ } elseif ( isset( $wgDebugLogGroups[$channel] ) ) {
+ $logConfig = $wgDebugLogGroups[$channel];
+
+ if ( is_array( $logConfig ) && isset( $logConfig['sample'] ) ) {
+ // Emit randomly with a 1 in 'sample' chance for each message.
+ $shouldEmit = mt_rand( 1, $logConfig['sample'] ) === 1;
+
+ } else {
+ // Emit unless the config value is explictly false.
+ $shouldEmit = $logConfig !== false;
+ }
+
+ } elseif ( isset( $context['private'] ) && $context['private'] ) {
+ // Don't emit if the message didn't match previous checks based on the
+ // channel and the event is marked as private. This check discards
+ // messages sent via wfDebugLog() with dest == 'private' and no explicit
+ // wgDebugLogGroups configuration.
+ $shouldEmit = false;
+ } else {
+ // Default return value is the the same as the historic wfDebug
+ // method: emit if $wgDebugLogFile has been set.
+ $shouldEmit = $wgDebugLogFile != '';
+ }
+
+ return $shouldEmit;
+ }
+
+
+ /**
+ * Format a message.
+ *
+ * Messages to the 'wfDebug', 'wfLogDBError' and 'wfErrorLog' channels
+ * receive special fomatting to mimic the historic output of the functions
+ * of the same name. All other channel values are formatted based on the
+ * historic output of the `wfDebugLog()` global function.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected static function format( $channel, $message, $context ) {
+ global $wgDebugLogGroups;
+
+ if ( $channel === 'wfDebug' ) {
+ $text = self::formatWfDebug( $channel, $message, $context );
+
+ } elseif ( $channel === 'wfLogDBError' ) {
+ $text = self::formatWfLogDBError( $channel, $message, $context );
+
+ } elseif ( $channel === 'wfErrorLog' ) {
+ $text = "{$message}\n";
+
+ } elseif ( !isset( $wgDebugLogGroups[$channel] ) ) {
+ $text = self::formatWfDebug(
+ $channel, "[{$channel}] {$message}", $context );
+
+ } else {
+ // Default formatting is wfDebugLog's historic style
+ $time = wfTimestamp( TS_DB );
+ $wiki = wfWikiID();
+ $host = wfHostname();
+ $text = "{$time} {$host} {$wiki}: {$message}\n";
+ }
+ return $text;
+ }
+
+
+ /**
+ * Format a message as `wfDebug()` would have formatted it.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected static function formatWfDebug( $channel, $message, $context ) {
+ $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $message );
+ if ( isset( $context['prefix'] ) ) {
+ $text = "{$context['prefix']}{$text}";
+ }
+ return "{$text}\n";
+ }
+
+
+ /**
+ * Format a message as `wfLogDBError()` would have formatted it.
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected static function formatWfLogDBError( $channel, $message, $context ) {
+ global $wgDBerrorLogTZ;
+ static $cachedTimezone = null;
+
+ if ( $wgDBerrorLogTZ && !$cachedTimezone ) {
+ $cachedTimezone = new DateTimeZone( $wgDBerrorLogTZ );
+ }
+
+ // Workaround for https://bugs.php.net/bug.php?id=52063
+ // Can be removed when min PHP > 5.3.6
+ if ( $cachedTimezone === null ) {
+ $d = date_create( 'now' );
+ } else {
+ $d = date_create( 'now', $cachedTimezone );
+ }
+ $date = $d->format( 'D M j G:i:s T Y' );
+
+ $host = wfHostname();
+ $wiki = wfWikiID();
+
+ $text = "{$date}\t{$host}\t{$wiki}\t{$message}\n";
+ return $text;
+ }
+
+
+ /**
+ * Select the appropriate log output destination for the given log event.
+ *
+ * If the event context contains 'destination'
+ *
+ * @param string $channel
+ * @param string $message
+ * @param array $context
+ * @return string
+ */
+ protected static function destination( $channel, $message, $context ) {
+ global $wgDebugLogFile, $wgDBerrorLog, $wgDebugLogGroups;
+
+ // Default destination is the debug log file as historically used by
+ // the wfDebug function.
+ $destination = $wgDebugLogFile;
+
+ if ( isset( $context['destination'] ) ) {
+ // Use destination explicitly provided in context
+ $destination = $context['destination'];
+
+ } elseif ( $channel === 'wfDebug' ) {
+ $destination = $wgDebugLogFile;
+
+ } elseif ( $channel === 'wfLogDBError' ) {
+ $destination = $wgDBerrorLog;
+
+ } elseif ( isset( $wgDebugLogGroups[$channel] ) ) {
+ $logConfig = $wgDebugLogGroups[$channel];
+
+ if ( is_array( $logConfig ) ) {
+ $destination = $logConfig['destination'];
+ } else {
+ $destination = strval( $logConfig );
+ }
+ }
+
+ return $destination;
+ }
+
+
+ /**
+ * Log to a file without getting "file size exceeded" signals.
+ *
+ * Can also log to UDP with the syntax udp://host:port/prefix. This will send
+ * lines to the specified port, prefixed by the specified prefix and a space.
+ *
+ * @param string $text
+ * @param string $file Filename
+ * @throws MWException
+ */
+ public static function emit( $text, $file ) {
+ if ( substr( $file, 0, 4 ) == 'udp:' ) {
+ # Needs the sockets extension
+ if ( preg_match( '!^udp:(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
+ // IPv6 bracketed host
+ $host = $m[1];
+ $port = intval( $m[2] );
+ $prefix = isset( $m[3] ) ? $m[3] : false;
+ $domain = AF_INET6;
+ } elseif ( preg_match( '!^udp:(?://)?([a-zA-Z0-9.-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
+ $host = $m[1];
+ if ( !IP::isIPv4( $host ) ) {
+ $host = gethostbyname( $host );
+ }
+ $port = intval( $m[2] );
+ $prefix = isset( $m[3] ) ? $m[3] : false;
+ $domain = AF_INET;
+ } else {
+ throw new MWException( __METHOD__ . ': Invalid UDP specification' );
+ }
+
+ // Clean it up for the multiplexer
+ if ( strval( $prefix ) !== '' ) {
+ $text = preg_replace( '/^/m', $prefix . ' ', $text );
+
+ // Limit to 64KB
+ if ( strlen( $text ) > 65506 ) {
+ $text = substr( $text, 0, 65506 );
+ }
+
+ if ( substr( $text, -1 ) != "\n" ) {
+ $text .= "\n";
+ }
+ } elseif ( strlen( $text ) > 65507 ) {
+ $text = substr( $text, 0, 65507 );
+ }
+
+ $sock = socket_create( $domain, SOCK_DGRAM, SOL_UDP );
+ if ( !$sock ) {
+ return;
+ }
+
+ socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port );
+ socket_close( $sock );
+ } else {
+ wfSuppressWarnings();
+ $exists = file_exists( $file );
+ $size = $exists ? filesize( $file ) : false;
+ if ( !$exists ||
+ ( $size !== false && $size + strlen( $text ) < 0x7fffffff )
+ ) {
+ file_put_contents( $file, $text, FILE_APPEND );
+ }
+ wfRestoreWarnings();
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * @section LICENSE
+ * 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
+ */
+
+/**
+ * MWLogger service provider that creates MWLoggerLegacyLogger instances.
+ *
+ * Usage:
+ * @code
+ * $wgMWLoggerDefaultSpi = array(
+ * 'class' => 'MWLoggerLegacySpi',
+ * );
+ * @endcode
+ *
+ * @see MWLogger
+ * @since 1.25
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ */
+class MWLoggerLegacySpi implements MWLoggerSpi {
+
+ /**
+ * @var array $singletons
+ */
+ protected $singletons = array();
+
+
+ /**
+ * Get a logger instance.
+ *
+ * @param string $channel Logging channel
+ * @return MWLogger Logger instance
+ */
+ public function getLogger( $channel ) {
+ if ( !isset( $this->singletons[$channel] ) ) {
+ $this->singletons[$channel] = new MWLoggerLegacyLogger($channel);
+ }
+ return $this->singletons[$channel];
+ }
+
+}
);
if ( $dbw->affectedRows() == 0 ) {
if ( $allowTimeKludge ) {
- # Use FOR UPDATE to ignore any transaction snapshotting
+ # Use LOCK IN SHARE MODE to ignore any transaction snapshotting
$ltimestamp = $dbw->selectField( 'image', 'img_timestamp',
- array( 'img_name' => $this->getName() ), __METHOD__, array( 'FOR UPDATE' ) );
+ array( 'img_name' => $this->getName() ),
+ __METHOD__,
+ array( 'LOCK IN SHARE MODE' ) );
$lUnixtime = $ltimestamp ? wfTimestamp( TS_UNIX, $ltimestamp ) : false;
# Avoid a timestamp that is not newer than the last version
# TODO: the image/oldimage tables should be like page/revision with an ID field
"config-restart": "Ja, opnieuw starten",
"config-welcome": "=== Controle omgeving ===\nEr worden een aantal basiscontroles uitgevoerd met als doel vast te stellen of deze omgeving geschikt is voor een installatie van MediaWiki.\nLever deze gegevens dan ook aan indien u support vraagt bij de installatie.",
"config-copyright": "=== Auteursrechten en voorwaarden ===\n\n$1\n\nDit programma is vrije software. U mag het verder verspreiden en/of aanpassen in overeenstemming met de voorwaarden van de GNU General Public License zoals uitgegeven door de Free Software Foundation; ofwel versie 2 van de Licentie of - naar uw keuze - enige latere versie.\n\nDit programma wordt verspreid in de hoop dat het nuttig is, maar '''zonder enige garantie''', zelfs zonder de impliciete garantie van '''verkoopbaarheid''' of '''geschiktheid voor een bepaald doel'''.\nZie de GNU General Public License voor meer informatie.\n\nSamen met dit programma hoort u een <doclink href=Copying>exemplaar van de GNU General Public License</doclink> ontvangen te hebben; zo niet, schrijf dan aan de Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, Verenigde Staten. Of [http://www.gnu.org/copyleft/gpl.html lees de licentie online].",
- "config-sidebar": "* [//www.mediawiki.org MediaWiki thuispagina]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Gebruikershandleiding] (Engelstalig)\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Beheerdershandleiding] (Engelstalig)\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Veel gestelde vragen] (Engelstalig)\n----\n* <doclink href=Readme>Leesmij</doclink> (Engelstalig)\n* <doclink href=ReleaseNotes>Release notes</doclink> (Engelstalig)\n* <doclink href=Copying>Kopiëren</doclink> (Engelstalig)\n* <doclink href=UpgradeDoc>Versie bijwerken</doclink> (Engelstalig)",
+ "config-sidebar": "* [//www.mediawiki.org MediaWiki thuispagina]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Gebruikershandleiding] (Engelstalig)\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Beheerdershandleiding] (Engelstalig)\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Veelgestelde vragen] (Engelstalig)\n----\n* <doclink href=Readme>Leesmij</doclink> (Engelstalig)\n* <doclink href=ReleaseNotes>Release notes</doclink> (Engelstalig)\n* <doclink href=Copying>Kopiëren</doclink> (Engelstalig)\n* <doclink href=UpgradeDoc>Versie bijwerken</doclink> (Engelstalig)",
"config-env-good": "De omgeving is gecontroleerd.\nU kunt MediaWiki installeren.",
"config-env-bad": "De omgeving is gecontroleerd.\nU kunt MediaWiki niet installeren.",
"config-env-php": "PHP $1 is op dit moment geïnstalleerd.",
public static function indicator( $content, array $attributes, Parser $parser, PPFrame $frame ) {
if ( !isset( $attributes['name'] ) || trim( $attributes['name'] ) === '' ) {
return '<span class="error">' .
- wfMessage( 'invalid-indicator-name' )->inContentLanguage()->text() .
+ wfMessage( 'invalid-indicator-name' )->inContentLanguage()->parse() .
'</span>';
}
public function crypt( $plaintext ) {
global $wgPasswordSalt;
- if ( $wgPasswordSalt && count( $this->args ) == 1 ) {
+ if ( $wgPasswordSalt && count( $this->args ) === 1 ) {
$this->hash = md5( $this->args[0] . '-' . md5( $plaintext ) );
} else {
$this->args = array();
}
public function toString() {
- return
- ':' . $this->config['type'] . ':' .
- implode( $this->getDelimiter(), array_merge( $this->params, $this->args ) ) .
- $this->getDelimiter() . $this->hash;
+ $str = ':' . $this->config['type'] . ':';
+
+ if ( count( $this->params ) || count( $this->args ) ) {
+ $str .= implode( $this->getDelimiter(), array_merge( $this->params, $this->args ) );
+ $str .= $this->getDelimiter();
+ }
+
+ return $str . $this->hash;
}
/**
if ( is_array( $wgProfiler ) ) {
if ( !isset( $wgProfiler['class'] ) ) {
$class = 'ProfilerStub';
- } elseif ( $wgProfiler['class'] === 'Profiler' ) {
- $class = 'ProfilerStub'; // b/c; don't explode
} else {
$class = $wgProfiler['class'];
}
self::$__instance = new $class( $wgProfiler );
- } elseif ( $wgProfiler instanceof Profiler ) {
- self::$__instance = $wgProfiler; // back-compat
} else {
self::$__instance = new ProfilerStub( array() );
}
case 'messages':
$out .= self::makeMessageSetScript( new XmlJsCode( $messagesBlob ) );
break;
+ case 'templates':
+ $out .= Xml::encodeJsCall(
+ 'mw.templates.set',
+ array( $name, (object)$module->getTemplates() ),
+ ResourceLoader::inDebugMode()
+ );
+ break;
default:
$out .= self::makeLoaderImplementScript(
$name,
$scripts,
$styles,
- new XmlJsCode( $messagesBlob )
+ new XmlJsCode( $messagesBlob ),
+ $module->getTemplates()
);
break;
}
* @param mixed $messages List of messages associated with this module. May either be an
* associative array mapping message key to value, or a JSON-encoded message blob containing
* the same data, wrapped in an XmlJsCode object.
+ * @param array $templates Keys are name of templates and values are the source of
+ * the template.
* @throws MWException
* @return string
*/
- public static function makeLoaderImplementScript( $name, $scripts, $styles, $messages ) {
+ public static function makeLoaderImplementScript( $name, $scripts, $styles,
+ $messages, $templates
+ ) {
if ( is_string( $scripts ) ) {
$scripts = new XmlJsCode( "function ( $, jQuery ) {\n{$scripts}\n}" );
} elseif ( !is_array( $scripts ) ) {
throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' );
}
+
return Xml::encodeJsCall(
'mw.loader.implement',
array(
// PHP/json_encode() consider empty arrays to be numerical arrays and
// output javascript "[]" instead of "{}". This fixes that.
(object)$styles,
- (object)$messages
+ (object)$messages,
+ (object)$templates,
),
ResourceLoader::inDebugMode()
);
/** @var string Remote base path, see __construct() */
protected $remoteBasePath = '';
+ /** @var array Saves a list of the templates named by the modules. */
+ protected $templates = array();
+
/**
* @var array List of paths to JavaScript files to always include
* @par Usage:
* 'loaderScripts' => [file path string or array of file path strings],
* // Modules which must be loaded before this module
* 'dependencies' => [module name string or array of module name strings],
+ * 'templates' => array(
+ * [template alias with file.ext] => [file path to a template file],
+ * ),
* // Styles to always load
* 'styles' => [file path string or array of file path strings],
* // Styles to include in specific skin contexts
$localBasePath = null,
$remoteBasePath = null
) {
+ // Flag to decide whether to automagically add the mediawiki.template module
+ $hasTemplates = false;
// localBasePath and remoteBasePath both have unbelievably long fallback chains
// and need to be handled separately.
list( $this->localBasePath, $this->remoteBasePath ) =
case 'styles':
$this->{$member} = (array)$option;
break;
+ case 'templates':
+ $hasTemplates = true;
+ $this->{$member} = (array)$option;
+ break;
// Collated lists of file paths
case 'languageScripts':
case 'skinScripts':
break;
}
}
+ if ( $hasTemplates ) {
+ $this->dependencies[] = 'mediawiki.template';
+ }
}
/**
$files = array_merge(
$files,
$this->scripts,
+ $this->templates,
$context->getDebug() ? $this->debugScripts : array(),
$this->getLanguageScripts( $context->getLanguage() ),
self::tryForKey( $this->skinScripts, $context->getSkin(), 'default' ),
'dependencies',
'messages',
'targets',
+ 'templates',
'group',
'position',
'skipFunction',
protected function getLessCompiler( ResourceLoaderContext $context = null ) {
return ResourceLoader::getLessCompiler( $this->getConfig() );
}
+
+ /**
+ * Takes named templates by the module and returns an array mapping.
+ *
+ * @return array of templates mapping template alias to content
+ */
+ public function getTemplates() {
+ $templates = array();
+
+ foreach ( $this->templates as $alias => $templatePath ) {
+ // Alias is optional
+ if ( is_int( $alias ) ) {
+ $alias = $templatePath;
+ }
+ $localPath = $this->getLocalPath( $templatePath );
+ if ( file_exists( $localPath ) ) {
+ $content = file_get_contents( $localPath );
+ $templates[ $alias ] = $content;
+ } else {
+ $msg = __METHOD__ . ": template file not found: \"$localPath\"";
+ wfDebugLog( 'resourceloader', $msg );
+ throw new MWException( $msg );
+ }
+ }
+ return $templates;
+ }
}
return '';
}
+ /**
+ * Takes named templates by the module and returns an array mapping.
+ *
+ * @return array of templates mapping template alias to content
+ */
+ public function getTemplates() {
+ // Stub, override expected.
+ return array();
+ }
+
/**
* @return Config
* @since 1.24
return $retval;
}
+ /**
+ * Pre-fill the link cache
+ *
+ * @param DatabaseBase $db
+ * @param ResultWrapper $res
+ */
+ function preprocessResults( $db, $res ) {
+ if ( $res->numRows() > 0 ) {
+ $linkBatch = new LinkBatch();
+
+ foreach ( $res as $row ) {
+ $linkBatch->add( $row->namespace, $row->title );
+ }
+
+ $res->seek( 0 );
+ $linkBatch->execute();
+ }
+ }
+
/**
* @param Skin $skin
* @param object $result Result row
*
* @todo What about non-BitmapHandler handled files?
*/
- static public function rotationEnabled() {
+ public static function rotationEnabled() {
$bitmapHandler = new BitmapHandler();
return $bitmapHandler->autoRotateEnabled();
}
$this->getContext()->getLanguage()->formatSize( $this->mMaxUploadSize['url'] )
)->parse() .
$this->msg( 'word-separator' )->escaped() .
- $this->msg( 'upload_source_url' )->escaped(),
+ $this->msg( 'upload_source_url' )->parse(),
'checked' => $selectedSourceType == 'url',
);
}
if ( !$this->files[$key]->exists() ) {
wfDebug( __METHOD__ . " tried to get file at $key, but it doesn't exist\n" );
+ // @todo Is this not an UploadStashFileNotFoundException case?
throw new UploadStashBadPathException( "path doesn't exist" );
}
# has structures (try/catch, foo()->bar(), etc etc) which throw parse errors in
# PHP 4. Setup.php and ObjectCache.php have structures invalid in PHP 5.0 and
# 5.1, respectively.
-if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.3' ) < 0 ) {
// We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
wfPHPVersionError( 'index.php' );
"viewyourtext": "Vostè pot veure i copiar la font de ' ' les modificacions ' ' d'aquesta pàgina:",
"protectedinterface": "Aquesta pàgina proporciona el text de la interfície del software d'aquest wiki i està protegida per evitar els abusos.\nPer afegir o canviar les traduccions per a tots els wikis, feu 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. Per afegir o modificar traduccions a totes les wikis, plantegeu-vos utilitzar la [//translatewiki.net/ translatewiki.net], el projecte de localització de MediaWiki.",
+ "translateinterface": "Per afegir o canviar traduccions per a tots els wikis, utilitzeu [//translatewiki.net/ translatewiki.net], el projecte de localització de MediaWiki.",
"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»:\n$2",
"namespaceprotected": "No teniu permís per a modificar pàgines en l'espai de noms '''$1'''.",
"customcssprotected": "No teniu permisos per editar la pàgina CSS perquè conté els paràmetres personals d'un altre usuari.",
"content-model-text": "цхьалхе йоза",
"content-model-javascript": "JavaScript",
"content-model-css": "CSS",
+ "duplicate-args-category": "Кепийн дехарашкахь юх юха аргументаш йолу агӀонаш",
"expensive-parserfunction-warning": "'''Тидам бе!''' Ресурсийн функцийн дехарш сов даьлла агӀонаш .\n\nДукху хилла ца деза {{PLURAL:$2|$2 дехар|$2 дехарш|1=цхьана дехар}}, хӀинца $1 {{PLURAL:$1|дехар}} ду.",
"expensive-parserfunction-category": "Ресурсийн функцийн дехарш сов даьлла агӀонаш",
"post-expand-template-inclusion-warning": "ДӀахьедар: юкъа тоьхна кепашан жамӀан барам тӀех бокха бу. Цхьайолу кепаш юкъа тухур яц.",
"search-result-category-size": "$1 {{PLURAL:$1|юкъаяр}} ($2 {{PLURAL:$2|1=бухара категори|бухара категореш}}, $3 {{PLURAL:$3|1=файл|файлаш}}).",
"search-redirect": "(дlасахьажийна $1)",
"search-section": "(дакъа $1)",
+ "search-category": "(категори $1)",
"search-file-match": "(файлан чулацаме тера хилар)",
"search-suggest": "Хила мега ахьа лоьхарг: $1",
"search-interwiki-caption": "Гергара проекташ",
- "search-interwiki-default": "$1 хилам.:",
+ "search-interwiki-default": "$1 хилам:",
"search-interwiki-more": "(кхин)",
"search-relatedarticle": "ХӀоттаделларг",
"searchrelated": "хlоттаделларг",
"searchall": "массо",
- "showingresults": "Лахахьа {{PLURAL:$1|гойта|гойту|гойту}} <strong>$1</strong> {{PLURAL:$1|хилам|хиламаш|хиламаш}}, дlаболало кху № <strong>$2</strong>.",
+ "showingresults": "Лахахьа {{PLURAL:$1|гойту}} <strong>$1</strong> {{PLURAL:$1|хилам}}, дӀаболало кху № <strong>$2</strong>.",
"showingresultsinrange": "Лахахь гайтина {{PLURAL:$1|<strong>1</strong> хилам}} диапазонехь <strong>$2</strong> тӀера <strong>$3</strong> кхаччалц.",
"search-showingresults": "{{PLURAL:$4|Хилам <strong>$1</strong> <strong>$3</strong> нах}}",
"search-nonefound": "Дехаре терра цхьа хӀума ца карийна.",
"brokenredirects-delete": "дӀаяккха",
"withoutinterwiki": "Юкъарвики-хьажоргаш йоцу агӀонаш",
"withoutinterwiki-summary": "Лахара агӀонийн юкъарвики-хьажоргаш яц:",
+ "withoutinterwiki-legend": "ТӀетоьхна элпаш",
"withoutinterwiki-submit": "Гайта",
"fewestrevisions": "ЧӀогӀа кӀезиг версеш йолу агӀонаш",
"nbytes": "$1 {{PLURAL:$1|байт}}",
"pager-newer-n": "{{PLURAL:$1|алсамо керла 1|алсамо керланаш $1}}",
"pager-older-n": "{{PLURAL:$1|алсамо шира 1|алсамо ширниш $1}}",
"suppress": "Хьулдар",
+ "apihelp": "API гӀо",
+ "apihelp-no-such-module": "Модуль «$1» цакарий.",
"booksources": "Жайнан хьосташ",
"booksources-search-legend": "Жайнех лаьцна хаам лахар",
"booksources-search": "Лаха",
"locknoconfirm": "Ахьа бакъдеш йолу меттиге билгало йилина яц.",
"lockdbsuccesssub": "Хаамийн базан блоктоьхна",
"unlockdbsuccesssub": "Хаамийн базан тӀера блокдӀаяьккхина",
+ "lockedbyandtime": "($1 $2 $3)",
"move-page": "$1 — цӀе хийцар",
"move-page-legend": "ЦӀe хийца яр",
"movepagetext": "Бухахь йолу форманца агӀон цӀе хийцало. Цул совнах цуьна хийцаман тептар кхоьчу метте доккха. Хьалхалера цӀарахь хиръю керла кхоьллина агӀонан хьажораг.\n\nХьовсалаш [[Special:DoubleRedirects|шалха]] а [[Special:BrokenRedirects|йохна хьажоргаш]] юй техь аьлла.\n\nШу жоьпехь ду хьажоргаш нийса некъ гойтуш хиларан.\n\nТидам бе хьалхалера агӀон цӀе ‘’’хийцалур яц’’’ иштта цӀе йолу агӀо йолуш елахь. Юкъардаккхар: йолуш йолу агӀо кхоьчухьа хьажораг елахь, я еса елахь а, цуьна хийцаме истори яцахь а.\n\nИ бохург ду шун агӀонан цӀе юха а хьалха хилларгчунтӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
"movenotallowedfile": "Хьан файлийн цӀераш хийца бакъо яц.",
"cant-move-user-page": "Хьан бакъо яц декъашхойн коьрта агӀонийн цӀераш хийца.",
"cant-move-to-user-page": "Хьан бакъо яц агӀона цӀе декъашхочун агӀон тӀе хийца (бухара агӀон тӀе хийца мега).",
+ "cant-move-category-page": "Хьан категорийн цӀераш хийца бакъо яц.",
+ "cant-move-to-category-page": "Хьан категорийн цӀераш хийца бакъо яц.",
"newtitle": "Керла цӀе",
"move-watch": "Латайé хӀара агӀо тергаме могӀанан юкъахь",
"movepagebtn": "АгӀон цӀе хийца",
"nextdiff": "Тlяхьа догlа нисдинарг →",
"imagemaxsize": "Суьртан бараман доза тохар:<br />''(Файла агӀона куц дийцар)''",
"thumbsize": "Жима дина суьртан барам:",
- "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|агlо|агlонаш|агlонаш}}",
+ "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|агӀо}}",
"file-info": "файлан барам: $1, MIME-тайп: $2",
"file-info-size": "$1 × $2 пиксель, файлан барам: $3, MIME-тайп: $4",
"file-info-size-pages": "$1 × $2 пиксель, файлан барам: $3, MIME-тайп: $4, $5 {{PLURAL:$5|1=агӀо|агӀонаш}}",
"confirm-unwatch-button": "ХӀаъ",
"confirm-unwatch-top": "ДӀаяккха хӀара агӀо хьай тергаме могӀанан юкъар?",
"comma-separator": ", ",
+ "quotation-marks": "«$1»",
"imgmultipageprev": "← хьалхара агlо",
"imgmultipagenext": "тlаьхьара агlо →",
"imgmultigo": "ДехьагӀо!",
"imgmultigoto": "АгӀончу $1 гӀо",
"img-lang-default": "(Ӏад битарца болу мотт)",
+ "img-lang-info": "Гайта хӀара сурт $1 $2 маттахь",
"img-lang-go": "Кхочушдé",
+ "ascending_abbrev": "гар",
+ "descending_abbrev": "йина",
"table_pager_next": "Тlаьхьа йогlу агlо",
"table_pager_prev": "Хьалха йоьду агlо",
"table_pager_first": "Дуьххьаралера агlо",
"watchlistedit-raw-explain": "Лахахь гойтуш ю хьа тергаме могӀанийн юкъахь йолу агӀонаш. Хьан йиш ю могӀан хийцам ба, оьцу чура цӀераш тӀетухуш а дӀайохкуш а.\nХийцамаш бина баьлчи тӀетаӀе кнопка «{{int:Watchlistedit-raw-submit}}».\nХьа кхин йиш ю [[Special:EditWatchlist|лело стандартни тадар]].",
"watchlistedit-raw-titles": "ДӀаяздарш:",
"watchlistedit-raw-submit": "МогӀам Ӏалашбар",
+ "watchlistedit-raw-done": "Хьан тергаман могӀам Ӏалашбина",
"watchlistedit-raw-added": "{{PLURAL:$1|ТӀетоьхна}} $1 {{PLURAL:$1|дӀаяздар|дӀаяздарш}}:",
"watchlistedit-raw-removed": "{{PLURAL:$1|ДӀаяьккхина|ДӀаяьхна}} $1 {{PLURAL:$1|дӀаяздар|дӀаяздарш}}:",
"watchlistedit-clear-title": "Тергаман могӀам дӀацӀанбар",
"watchlisttools-edit": "Хьажа/нисбé могӀам",
"watchlisttools-raw": "Йоза санна тае",
"signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|дийцаре]])",
+ "unknown_extension_tag": "«$1» шордаран ца йоьвзу тег",
"version": "Верси MediaWiki",
"version-extensions": "ДӀахӀоттийна шордарш",
"version-skins": "ДӀахӀоттийна кечяран темаш",
"version-software-version": "Верси",
"version-entrypoints": "ЧугӀо адресин тӀадамаш",
"version-entrypoints-header-entrypoint": "Яздаран тӀадам",
+ "version-entrypoints-header-url": "URL",
"version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath АгӀона тӀе некъ]",
"version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Скриптан тӀе некъ]",
"redirect": "Декъашхочун файлан тӀера дӀасхьажор",
"fileduplicatesearch-result-1": "«$1» файлах тера хӀума яц.",
"fileduplicatesearch-noresults": "ЦӀе «$1» йолуш файл цакарий.",
"specialpages": "Леррина агӀонаш",
+ "specialpages-note-top": "Легенда",
"specialpages-note": "* Гуттарлера белха агlонаш.\n* <strong class=\"mw-specialpagerestricted\">Кlеззиг таронаш йолу леррина агlонаш.</strong>",
"specialpages-group-maintenance": "Жамlаш гlирса хьашташ кхочушдар",
"specialpages-group-other": "Кхин белхан агӀонаш",
"api-error-stashfailed": "Interner Fehler: Der Server konnte keine temporäre Datei speichern.",
"api-error-publishfailed": "Interner Fehler: Der Server konnte die temporäre Datei nicht veröffentlichen.",
"api-error-stasherror": "Beim Hochladen der Datei gab es einen Fehler.",
+ "api-error-stashedfilenotfound": "Die vorab gespeicherte Datei wurde beim Versuch, sie vom Speicher hochzuladen, nicht gefunden.",
+ "api-error-stashpathinvalid": "Der Pfad, unter dem die gespeicherte Datei gefunden werden sollte, war ungültig.",
+ "api-error-stashfilestorage": "Beim Speichern der Datei in den Speicher gab es einen Fehler.",
+ "api-error-stashzerolength": "Der Server konnte die Datei nicht speichern, da sie eine Länge von Null hat.",
+ "api-error-stashnotloggedin": "Du musst angemeldet sein, um Dateien in den Hochladespeicher zu speichern.",
+ "api-error-stashwrongowner": "Die Datei, auf die du im Speicher zugreifen möchtest, gehört nicht dir.",
+ "api-error-stashnosuchfilekey": "Der Dateischlüssel, auf den du im Speicher zugreifen möchtest, ist nicht vorhanden.",
"api-error-timeout": "Der Server hat nicht innerhalb der erwarteten Zeit reagiert.",
"api-error-unclassified": "Ein unbekannter Fehler ist aufgetreten.",
"api-error-unknown-code": "Unbekannter Fehler: „$1“",
"api-error-stashfailed": "Internal error: Server failed to store temporary file.",
"api-error-publishfailed": "Internal error: Server failed to publish temporary file.",
"api-error-stasherror": "There was an error while uploading the file to stash.",
+ "api-error-stashedfilenotfound": "The stashed file was not found when attempting to upload it from the stash.",
+ "api-error-stashpathinvalid": "The path at which the stashed file should have been found was invalid.",
+ "api-error-stashfilestorage": "There was an error while storing the file in the stash.",
+ "api-error-stashzerolength": "The server could not stash the file, because it had zero length.",
+ "api-error-stashnotloggedin": "You must be logged in to save files in the upload stash.",
+ "api-error-stashwrongowner": "The file you were attempting to access in the stash does not belong to you.",
+ "api-error-stashnosuchfilekey": "The file key you were attempting to access in the stash does not exist.",
"api-error-timeout": "The server did not respond within the expected time.",
"api-error-unclassified": "An unknown error occurred.",
"api-error-unknown-code": "Unknown error: \"$1\".",
"revdelete-restricted": "administratzaileentzako mugak ezarri dira",
"revdelete-unrestricted": "administratzaileentzako mugak kendu dira",
"logentry-move-move": "$1 {{GENDER:$2|wikilariak}} «$3» orria «$4» izenera aldatu du",
- "logentry-move-move-noredirect": "$1 {{GENDER:$2|wikilariak}} $3 orria $4 izenera aldatu du, birzuzenketarik utzi gabe",
+ "logentry-move-move-noredirect": "$1 {{GENDER:$2|wikilariak}} «$3» orria «$4» izenera aldatu du, birzuzenketarik utzi gabe",
"logentry-move-move_redir": "$1 {{GENDER:$2|wikilariak}} «$3» orria «$4» izenera aldatu du, birzuzenketaren gainetik",
"logentry-move-move_redir-noredirect": "$1 {{GENDER:wikilariak}} «$3» orria «$4» izenera aldatu du, birbideratze bat gainidatzita, birbideratzerik utzi gabe",
"logentry-patrol-patrol": "$1(e)k $3 orrialdearen $4 berrikuzpena patruilatutzat {{GENDER:$2|markatu}} du",
"showhideselectedversions": "تغییر پدیداری نسخههای انتخابشده",
"editundo": "خنثیسازی",
"diff-empty": "(بدون تفاوت)",
- "diff-multi-sameuser": "({{PLURAL:$1|یک نسخهٔ میانی|$1 نسخهٔ میانی}} توسط کاربر مشابهی که نشان داده نشده)",
+ "diff-multi-sameuser": "({{PLURAL:$1|یک نسخهٔ میانی|$1 نسخهٔ میانی}}ِ همین کاربر نمایش داده نشده است)",
"diff-multi-otherusers": "({{PLURAL:$1|یک نسخهٔ متوسط|$1 نسخههای متوسط}} توسط {{PLURAL:$2|کاربر دیگری|$2 کاربران}} نشان داده نشده)",
"diff-multi-manyusers": "({{PLURAL:$1|یک|$1}} ویرایش میانی توسط بیش از {{PLURAL:$2|یک|$2}} کاربر نشان داده نشدهاست)",
"difference-missing-revision": "{{PLURAL:$2|یک ویرایش|$2 ویرایش}} از تفاوت نسخهها ($1) {{PLURAL:$2|یافت|یافت}} نشد.\n\nمعمولاً در اثر پیوند به تاریخچهٔ بهروز نشدهٔ صفحهٔ حذف شده است.\nمیتوانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.",
"tog-watchdefault": "Sälber gändereti Syte un Dateie automatisch beobachte",
"tog-watchmoves": "Sälber verschobeni Sytene un Dateie automatisch beobachte",
"tog-watchdeletion": "Sälber gleschti Sytene un Dateie automatisch beobachte",
+ "tog-watchrollback": "Syte, wun i zruckgsetzt haa, automatisch beobachte",
"tog-minordefault": "Alli dyni Änderigen als «chlyni Änderige» markiere",
"tog-previewontop": "Vorschou vor em Editierfänschter aazeige",
"tog-previewonfirst": "Vorschou aazeige bim erschten Editiere",
"otherlanguages": "Anderi Sproche",
"redirectedfrom": "(Witergleitet vun $1)",
"redirectpagesub": "Umgleiteti Syte",
+ "redirectto": "Wyterleitig uf:",
"lastmodifiedat": "Letschti Änderig vo dere Syte: $2, $1<br />",
"viewcount": "Die Syte isch {{PLURAL:$1|eimol|$1 Mol}} bsuecht wore.",
"protectedpage": "Gschützti Syte",
"hidetoc": "zueklappe",
"collapsible-collapse": "zueklappe",
"collapsible-expand": "ufklappe",
+ "confirmable-confirm": "{{GENDER:$1|Bisch}} sicher?",
+ "confirmable-yes": "Jo",
+ "confirmable-no": "Nei",
"thisisdeleted": "Aaluege oder widerherstelle vu $1?",
"viewdeleted": "$1 aaluege?",
"restorelink": "{{PLURAL:$1|gleschti Änderig|$1 gleschti Ändrige}}",
"viewsourcetext": "Quelltext vo dere Syte:",
"viewyourtext": "Du chasch dr Quälltext vu '''Dyre Bearbeitig''' vu däre Syte aaluege un kopiere:",
"protectedinterface": "In däre Syte het s Text fir s Sproch-Interface vu dr Software un si isch gsperrt, zum Missbruch z verhindre.",
- "editinginterface": "'''Obacht:''' Du bisch e Syten am Verändere, wu zum User.Interface ghert. Wänn Du die Syte veränderesch, no änderet sich s User-Interface au fir di andere Benutzer vu däm Wiki. Fir Ibersetzige lueg bitte, eb Du doodefir s [//translatewiki.net/wiki/Main_Page?setlang=gsw Translatewiki] witt bruuche, s MediaWiki-Lokalisierigsprojäkt.",
+ "editinginterface": "<strong>Warnig:</strong> Uf däre Syte het s Täxt, wu vu dr MediaWiki-Software brucht wird. Änderigen uf däre Syte wirke si uf d Benutzeroberflechi vu däm Wiki uus.",
+ "translateinterface": "Go Ibersetzige fir alli Wiki zuefiege oder ändere, bruuch bitte [//translatewiki.net/ translatewiki.net], s MediaWiki-Lokalisierigsprojäkt.",
"cascadeprotected": "Die Syte isch fir s Bearbeite gsperrt. Si isch yybunde in {{PLURAL:$1|die Syte, wu do chunnt|die Syte, wu do chemme}} , wu mit ere Kaskadesperroption gschitzt {{PLURAL:$1|isch|sin}}:\n$2",
"namespaceprotected": "Du hesch kei Berächtigung, die Syte im '''$1'''-Namensruum z bearbeite.",
"customcssprotected": "Du bisch nid berächtigt, die Syte mit CSS z bearbeite, wel si zue dr persenlige Yystellige vun eme andere Benutzer ghert.",
"invalidtitle-knownnamespace": "Nit-gültige Titel mit Namensruum „$2“ un Text „$3“",
"invalidtitle-unknownnamespace": "Ungültige Titel mit unbekannte Namensruumnummer $1 un Text „$2“",
"exception-nologin": "Nit aagmäldet",
- "exception-nologin-text": "Du muesch Di [[Special:Userlogin|aamälde]] go die Syte oder Aktion ufruefe chenne.",
+ "exception-nologin-text": "Du muesch Di aamälde go die Syte oder Aktion ufruefe chenne.",
"exception-nologin-text-manual": "Du muesch Di $1 go die Syte oder Aktion ufruefe chenne.",
"virus-badscanner": "Fählerhafti Konfiguration: Virescanner, wu nid bekannt isch: ''$1''",
"virus-scanfailed": "Scan het nid funktioniert (code $1)",
"createaccount-text": "Fir Dii isch e Benutzerkonto \"$2\" uf {{SITENAME}} ($4) aaglait wore. S Passwort fir \"$2\" , wu automatisch generiert woren isch, isch \"$3\". Du sottsch Di jetz aamälde un s Passwort ändere.\n\nWänn s Benutzerkonto us Versäh aaglait woren isch, chasch die Nochricht ignoriere.",
"login-throttled": "Du hesch z vilmol umesuscht versuecht, Di aazmälde. Bitte wart $1, voreb Du s non emol versuechsch.",
"login-abort-generic": "Dyy Aamäldig isch nit erfolgryych gsii – Abbroche",
+ "login-migrated-generic": "Dy Benutzerkonto isch migriert wore, Dy Benutzername git s nimi uf däm Wiki.",
"loginlanguagelabel": "Sproch: $1",
"suspicious-userlogout": "Dyy Versuech di abzmälde isch abbroche wore, wel s uusgsäh het, wie wänn s vun eme bschedigte Browser oder eme Cacheproxy uus gsändet woren isch.",
"createacct-another-realname-tip": "Dr richtig Name isch optional.\nWänn Du ne aagiisch, wird er bruucht fir d Zueornig vu dr Byytreg.",
"resetpass-temp-password": "Temporär Passwort:",
"resetpass-abort-generic": "D Passwortänderig isch dur e Erwyterig abbroche wore.",
"resetpass-expired": "Dy Passwort isch abglofe. Bitte leg e nej Passwort fir d Aamäldig fescht.",
+ "resetpass-expired-soft": "Dy Passwort isch abgloffe un mueß zruckgsetzt wäre. Bitte wehl jetz e nei Passwort uus oder klick uf „{{int:resetpass-submit-cancel}}“, go s speter zrucksetze.",
+ "resetpass-validity-soft": "Dy Passwort isch nit giltig: $1\n\nBitte wehl jetz e nei Passwort oder klick uf „{{int:resetpass-submit-cancel}}“, go s speter zrucksetze.",
"passwordreset": "Passwort zruggsetze",
"passwordreset-text-one": "Fill des Formular uus go Dy Passwort zrucksetze.",
"passwordreset-text-many": "{{PLURAL:$1|Fill eis vu dr Fälder uus go Dy Passwort zrucksetze.}}",
"changeemail-none": "(nyt)",
"changeemail-password": "Dy {{SITENAME}}-Passwort:",
"changeemail-submit": "E-Mail Adräss ändre",
+ "changeemail-throttled": "Du hesch z vilmol versuecht Di aazmälde. Bitte wart $1, voreb Du s non emol versuechsch.",
"resettokens": "Token zrucksetze",
"resettokens-text": "Du chasch Token zrucksetze, wu Dir dr Zuegriff uf bstimmti privati Date megli mache, wu mit Dym Benutzerkonto do verchnipft sin.\n\nDes sottsch nume mache, wänn Du d Token us Versää mit eberem teilt hesch oder Dy Konto gfehrdet isch.",
"resettokens-no-tokens": "S git kei Token zum Zrucksetze.",
"preview": "Vorschou",
"showpreview": "Vorschau aaluege",
"showdiff": "Zeig Änderige",
- "anoneditwarning": "'''Warnig:''' Si sin nit aagmäldet. Ihri IP-Adrässe wird in de Gschicht vo däm Artikel gspeicheret.",
+ "blankarticle": "<strong>Warnig:</strong> D Syte, wu Du aalaisch, isch läär.\nWänn Du nomol uf „{{int:savearticle}}“ klicksch, wird d Syte ohni Inhalt aaglait.",
+ "anoneditwarning": "<strong>Warnig:</strong> Du bisch nit aagmäldet. Dy IP-Adräss wird effetli sichtbar, wänn Du Bearbeitige machsch. Wänn di <strong>[$1 aamälde duesch]</strong> oder <strong>[$2 e Benutzerkonto aalaisch]</strong>, wäre Bearbeitige zämme mit andere Bytreg Dym Nenutzername zuegordnet.",
"anonpreviewwarning": "''Du bisch nit aagmäldet. Bim Spychere wird Dyy IP-Adräss yydrait in d Versionsgschicht vu däre Syte.''",
"missingsummary": "'''Obacht:''' Du hesch kei Zämefassig aagee. Wenn du nomol uf Spychere drucksch, wird d Änderung ohni gspychert.",
"missingcommenttext": "Bitte gib Dyy Kommentar unte yy.",
"edit-gone-missing": "D Syte het nid chenne aktalisiert wäre.\nSi isch schyns glescht wore.",
"edit-conflict": "Bearbeitigskonflikt.",
"edit-no-change": "Dyyni Bearbeitig isch ignoriert wore, wel kei Änderig am Täxt gmacht woren isch.",
+ "postedit-confirmation-created": "D Syte isch aaglait wore.",
+ "postedit-confirmation-restored": "D Syte isch widerhärgstellt wore.",
"postedit-confirmation-saved": "Dyy Bearbeitig isch gspycheret wore.",
"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",
- "editwarning-warning": "Wänn Du die Syte verlosch, cha s syy, ass Du alli Bearbeitige verliersch, wu Du do dra gmacht hesch.\nWänn Du aagmäldet bisch, chasch s Anzeige vu däre Warnig im „Bearbeite“-Beryych vu Dyyne Yystelligen abstelle.",
+ "editwarning-warning": "Wänn Du die Syte verlosch, cha s syy, ass Du alli Bearbeitige verliersch, wu Du do dra gmacht hesch.\nWänn Du aagmäldet bisch, chasch s Anzeige vu däre Warnig im „{{int:prefs-editing}}“-Beryych vu Dyyne Yystelligen abstelle.",
+ "editpage-notsupportedcontentformat-title": "S Inhaltsformat wird nit unterstitzt",
+ "editpage-notsupportedcontentformat-text": "S Inhaltsformat $1 wird vum Inhaltsmodäll $2 nit unterstitzt.",
"content-model-wikitext": "Wikitext",
"content-model-text": "Klartext",
"content-model-javascript": "JavaScript",
"content-model-css": "CSS",
+ "duplicate-args-category": "Syte, wu doppleti Argumänt in Vorlagenufruef verwände",
+ "duplicate-args-category-desc": "Uf dr Syte het s Vorlagenufruef, wu Duplikat vu Argumänt verwände, wie <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> oder <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
"expensive-parserfunction-warning": "Achtig: In däre Syte het s z vyyl Ufruef vu ufwändige Parserfunktione.\n\nS {{PLURAL:$2|derf nid meh wie ein Ufruef|derfe nid meh wie $1 Ufruef}} gee.",
"expensive-parserfunction-category": "Syte, wu ufwändigi Parserfunktione z vyylmol ufruefe",
"post-expand-template-inclusion-warning": "Warnig: D Gressi vu yybundene Vorlage isch z gross, e Teil Vorlage chenne nid yybunde wäre.",
"parser-template-recursion-depth-warning": "Vorlagerekursionstiefegränz iberschritte ($1)",
"language-converter-depth-warning": "Gränz vu dr Sprochkonvertertiefi iberschritte ($1)",
"node-count-exceeded-category": "Syte, wo d Chnotezaal überschritte hen",
- "node-count-exceeded-warning": "Die Syte het d Chnotepunktzaal überschritte.",
+ "node-count-exceeded-category-desc": "D Syte iberschrytet di maximal Chnotenaazahl.",
+ "node-count-exceeded-warning": "Die Syte het d Chnotepunktzaal iberschritte.",
"expansion-depth-exceeded-category": "Syte, wo d Expansionsdiefi überschritte hen",
+ "expansion-depth-exceeded-category-desc": "D Syte iberschrytet di maximal Expandierigstiefi.",
"expansion-depth-exceeded-warning": "Die Syte het d Expansionsdiefi überschritte.",
"parser-unstrip-loop-warning": "Zirkelbezug festgstellt",
"parser-unstrip-recursion-limit": "Rekursionsgränz bim Ufflöse überschritte ($1)",
"undo-success": "Zum die Änderig ruckgängig z mache, kontrollier bitte d Bearbeitig in dr Verglichsaasicht un druck derno uf „Syte spichere“.",
"undo-failure": "D Änderig het nid chenne ruckgängig gmacht wäre, wel dää Abschnitt mittlerwyli gänderet woren isch.",
"undo-norev": "D Bearbeitig het nid chenne ruckgängig gmacht wäre, wel si nid vorhande oder glescht isch.",
+ "undo-nochange": "Schyns isch die Bearbeitig scho rugggängig gmacht wore.",
"undo-summary": "D Änderig $1 vu [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussion]]) isch ruckgängig gmacht wore.",
"undo-summary-username-hidden": "Änderig $1 vun eme versteckte Benutzer ruckgängig gmacht.",
"cantcreateaccounttitle": "Benutzerkonto cha nid aagleit wäre.",
"cantcreateaccount-text": "S Aalege vu me Benutzerkonto vu dr IP-Adräss '''($1)''' isch dur [[User:$3|$3]] gsperrt wore.\n\nGrund vu dr Sperri: ''$2''",
+ "cantcreateaccount-range-text": "S Aalege vu Benutzerkonte vu IP-Adrässen im Berych '''$1''', wu s Dyni IP-Adräss ('''$4''') din het, isch vu [[User:$3|$3]] gsperrt wore.\n\nDr Grund, wu vu $3 aagee woren isch: ''$2''",
"viewpagelogs": "Logbüecher für die Syten azeige",
"nohistory": "S git kei Versionsgschicht fir die Syte.",
"currentrev": "Itzigi Version",
"currentrev-asof": "Aktuälli Version vu $1",
"revisionasof": "Version vo $1",
- "revision-info": "Alti Bearbeitig vom $1 dür $2",
+ "revision-info": "Version vu $4, $5 Uhr vu {{GENDER:$6|$2}}$7",
"previousrevision": "← Vorderi Version",
"nextrevision": "Nächschti Version →",
"currentrevisionlink": "Itzigi Version",
"rev-deleted-event": "(Logbuechaktion uusegnuh)",
"rev-deleted-user-contribs": "[Benutzername oder IP-Adräss uusegnuu - Bearbeitig in dr Byytragslischt versteckt]",
"rev-deleted-text-permission": "Die Version isch '''glescht''' wore.\nInformation zue dr Leschig un e Begrindig het s im [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Lesch-Logbuech].",
+ "rev-suppressed-text-permission": "Die Version isch <strong>unterdruckt</strong> wore.\nEinzelheite het s im [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Oversight-Logbuech].",
"rev-deleted-text-unhide": "Die Version isch '''gelöscht''' worde.\nMee Angabe chasch im [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} Lösch-Logbuech] finde.\nDu chasch [$1 die Version allno aaluege], wänn de wottsch.",
"rev-suppressed-text-unhide": "Die Version isch '''unterdrückt''' worde.\nMee Angabe chasch im [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} Unterdrückigs-Logbuech] finde.\nDu chasch [$1 die Version allno aaluege], wänn de wottsch.",
"rev-deleted-text-view": "Die Version isch '''glescht''' wore.\nDu chasch si allno aaluege. Details findsch im [{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} Lösch-Logbuech].",
"revdelete-no-file": "D Datei, wu Du aagee hesch, git s nit.",
"revdelete-show-file-confirm": "Bisch sicher, ass Du di glescht Version vu dr Datei „<nowiki>$1</nowiki>“ vum $2 am $3 witt aaluege?",
"revdelete-show-file-submit": "Jo",
+ "revdelete-selected-text": "Uusgwehlti {{PLURAL:$1|Version|Versione}} vu [[:$2]]:",
+ "revdelete-selected-file": "Uusgwehlti {{PLURAL:$1|Dateiversion|Dateiversione}} vu [[:$2]]:",
"logdelete-selected": "{{PLURAL:$1|Usgwehlte Logbuechyytrag|Usgwehlti Logbuechyytreg}}:",
+ "revdelete-text-text": "Gleschti Versione blybe no dr Versionsgschicht, Teil vu ihrem Inhalt sin aber nimi effetli zuegängig.",
+ "revdelete-text-file": "Gleschti Dateiversione blybe no in dr Datei-Versionsgschicht, Teil vu ihrem Inhalt sin aber nimi effetli zuegängig.",
+ "logdelete-text": "Gleschti Logbuechyytreg blybe no dr Logbiecher, Teil vu ihrem Inhalt sin aber nimi effetli zuegängig.",
+ "revdelete-text-others": "Anderi Administratore hän no Zuegriff uf dr verdeckt Inhalt un chenne ne au widerhärstelle, solang keini zuesetzlige Bschränkige feschtgleit wäre.",
"revdelete-confirm": "Bitte tue bstetige, ass Du vor hesch, des z mache, d Konsequänze drus verstohsch un s machsch in Inbereinstimmig mit dr [[{{MediaWiki:Policy-url}}|Richtlinie]].",
"revdelete-suppress-text": "Unterdruckige sotte '''nume''' in däne Fäll bruucht wäre:\n* Nit aabrochti Informatione\n*: ''Adrässe, Telifonnummere, Sozialversicherigsnummere usw.'",
"revdelete-legend": "Setze vu dr Sichtbarkeits-Yyschränkige",
"api-error-stashfailed": "שגיאה פנימית: השרת נכשל באחסון הקובץ הזמני.",
"api-error-publishfailed": "שגיאה פנימית: השרת נכשל בפרסום הקובץ הזמני.",
"api-error-stasherror": "הייתה שגיאה בהעלאת הקובץ למאגר.",
+ "api-error-stashedfilenotfound": "הקובץ שבמאגר לא נמצא בעת הניסיון להעלות אותו מהמאגר.",
+ "api-error-stashpathinvalid": "הנתיב שבו הקובץ שבמאגר אמור היה להימצא היה בלתי תקין.",
+ "api-error-stashfilestorage": "הייתה שגיאה בעת אחסון הקובץ במאגר.",
+ "api-error-stashzerolength": "השרת לא יכול היה לאחסן במאגר את הקובץ, כי אורכו היה אפס.",
+ "api-error-stashnotloggedin": "נדרשת כניסה לחשבון כדי לשמור קבצים במאגר ההעלאות.",
+ "api-error-stashwrongowner": "הקובץ שניסית לגשת אליו במאגר אינו שייך לך.",
+ "api-error-stashnosuchfilekey": "מפתח הקובץ שניסית לגשת אליו במאגר אינו קיים.",
"api-error-timeout": "השרת לא השיב בזמן המצופה.",
"api-error-unclassified": "אירעה שגיאה בלתי ידועה.",
"api-error-unknown-code": "שגיאה בלתי ידועה: \"$1\".",
"Sapral Mikail",
"Tagir",
"Умар",
- "아라"
+ "아라",
+ "Shirayuki"
]
},
"tog-underline": "Ӏинкаш белгалде:",
"searchresults": "Тохкама гIулакхахилар",
"searchresults-title": "\"$1\" тохка",
"notextmatches": "ОагIувнаша яздамий вIашагIакхетараш дац",
- "prevn": "{{PLURAL:$1|хьалхйоаг|ар $1|хьалхйоаг|араш $1|хьалхйоаг|араш $1}}",
+ "prevn": "{{PLURAL:$1|хьалхйоагlар $1|хьалхйоагlараш $1|хьалхйоагlараш $1}}",
"nextn": "{{PLURAL:$1|тlехьайоагlар $1|тlехьайоагlараш $1|тlехьайоагlараш $1}}",
"prevn-title": "{{PLURAL:$1|1=$1 хьалхара йоазув|$1 хьалхара йоазувнаш}}",
"nextn-title": "{{PLURAL:$1|1=$1 тIехьара йоазув|$1 тIехьара йоазувнаш}}",
"Keysuck",
"Infinity",
"Bluemersen",
- "Revi"
+ "Revi",
+ "Namoroka"
]
},
"tog-underline": "링크에 밑줄:",
"content-model-text": "일반 텍스트",
"content-model-javascript": "자바스크립트",
"content-model-css": "CSS",
+ "duplicate-args-category": "중복된 인수를 사용한 틀을 포함한 문서",
"expensive-parserfunction-warning": "'''경고:''' 이 문서는 너무 많은 파서 함수를 포함하고 있습니다.\n\n$2개 보다 적게 {{PLURAL:$2|써야}} 하지만 {{PLURAL:$1|지금은 $1개를 쓰고 있습니다}}.",
"expensive-parserfunction-category": "느린 파서 함수 호출을 너무 많이 하는 문서",
"post-expand-template-inclusion-warning": "'''경고:''' 틀 포함 크기가 너무 큽니다.\n일부 틀은 포함되지 않을 수 있습니다.",
"virus-unknownscanner": "onbekend antivirusprogramma:",
"logouttext": "'''U bent nu afgemeld.'''\n\nSommige pagina's kunnen blijven weergegeven alsof u nog aangemeld bent, totdat u uw browsercache leegt.",
"welcomeuser": "Welkom, $1!",
- "welcomecreation-msg": "Uw account is aangemaakt.\nIndien gewenst kunt u uw [[Special:Preferences|voorkeuren]] voor {{SITENAME}} aanpassen.",
+ "welcomecreation-msg": "Uw gebruiker is aangemaakt.\nIndien gewenst kunt u uw [[Special:Preferences|voorkeuren]] voor {{SITENAME}} aanpassen.",
"yourname": "Gebruikersnaam:",
"userlogin-yourname": "Gebruikersnaam",
"userlogin-yourname-ph": "Geef uw gebruikersnaam op",
"userlogin-signwithsecure": "Beveiligde verbinding gebruiken",
"yourdomainname": "Uw domein:",
"password-change-forbidden": "U kunt uw wachtwoord niet wijzigen in deze wiki.",
- "externaldberror": "Er is een fout opgetreden bij het aanmelden bij de database of u hebt geen toestemming uw externe account bij te werken.",
+ "externaldberror": "Er is een fout opgetreden bij het aanmelden bij de database of u hebt geen toestemming uw externe gebruiker bij te werken.",
"login": "Aanmelden",
"nav-login-createaccount": "Aanmelden / registreren",
"userlogin": "Aanmelden / registreren",
"logout": "Afmelden",
"userlogout": "Afmelden",
"notloggedin": "Niet aangemeld",
- "userlogin-noaccount": "Hebt u geen account?",
+ "userlogin-noaccount": "Hebt u geen gebruiker?",
"userlogin-joinproject": "Word lid van {{SITENAME}}",
- "nologin": "Hebt u geen account? $1.",
+ "nologin": "Hebt u geen gebruiker? $1.",
"nologinlink": "Registreren",
"createaccount": "Registreren",
- "gotaccount": "Hebt u al een account? $1.",
+ "gotaccount": "Hebt u al een gebruiker? $1.",
"gotaccountlink": "Aanmelden",
"userlogin-resetlink": "Bent u uw aanmeldgegevens vergeten?",
"userlogin-resetpassword-link": "Wachtwoord vergeten?",
"userlogin-helplink2": "Hulp bij aanmelden",
"userlogin-loggedin": "U bent al aangemeld als {{GENDER:$1|$1}}.\nGebruik het onderstaande formulier om aan te melden als een andere gebruiker.",
- "userlogin-createanother": "Een andere account aanmaken",
+ "userlogin-createanother": "Een andere gebruiker aanmaken",
"createacct-emailrequired": "E-mailadres",
"createacct-emailoptional": "E-mailadres (optioneel)",
"createacct-email-ph": "Geef uw e-mailadres op",
"noname": "U hebt geen geldige gebruikersnaam opgegeven.",
"loginsuccesstitle": "Aanmelden geslaagd",
"loginsuccess": "'''U bent nu aangemeld bij {{SITENAME}} als \"$1\".'''",
- "nosuchuser": "De gebruiker \"$1\" bestaat niet.\nGebruikersnamen zijn hoofdlettergevoelig.\nControleer de schrijfwijze of [[Special:UserLogin/signup|maak een nieuw account aan]].",
+ "nosuchuser": "De gebruiker \"$1\" bestaat niet.\nGebruikersnamen zijn hoofdlettergevoelig.\nControleer de schrijfwijze of [[Special:UserLogin/signup|maak een nieuw gebruiker aan]].",
"nosuchusershort": "De gebruiker \"$1\" bestaat niet.\nControleer de schrijfwijze.",
"nouserspecified": "Geef een gebruikersnaam op.",
"login-userblocked": "Deze gebruiker is geblokkeerd.\nAanmelden is niet mogelijk.",
"invalidemailaddress": "Het e-mailadres is niet aanvaard, omdat het een ongeldige opmaak heeft.\nGeef een geldig e-mailadres op of laat het veld leeg.",
"cannotchangeemail": "Het e-mailadres voor een gebruiker kan op deze wiki niet gewijzigd worden.",
"emaildisabled": "Deze site kan geen e-mails verzenden.",
- "accountcreated": "Account aangemaakt",
+ "accountcreated": "Gebruiker aangemaakt",
"accountcreatedtext": "Het gebruikersaccount voor [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|overleg]]) is aangemaakt.",
"createaccount-title": "Gebruikers registreren voor {{SITENAME}}",
"createaccount-text": "Iemand heeft een gebruiker op {{SITENAME}} ($4) aangemaakt met de naam \"$2\" en uw e-mailadres.\nHet wachtwoord voor \"$2\" is \"$3\".\nMeld u aan en wijzig uw wachtwoord.\n\nNegeer dit bericht als deze gebruiker zonder uw medeweten is aangemaakt.",
"login-throttled": "U heeft recentelijk te veel mislukte aanmeldpogingen gedaan.\nWacht alstublieft $1 voordat u het opnieuw probeert.",
"login-abort-generic": "U bent niet aangemeld. De procedure is afgebroken.",
- "login-migrated-generic": "Uw account is verplaatst, en uw gebruikersnaam bestaat niet langer op deze wiki.",
+ "login-migrated-generic": "Uw gebruikersnaam is hernoemd, en uw gebruikersnaam bestaat niet langer op deze wiki.",
"loginlanguagelabel": "Taal: $1",
"suspicious-userlogout": "Uw verzoek om af te melden is genegeerd, omdat het lijkt alsof het verzoek is verzonden door een browser of cacheproxy die stuk is.",
"createacct-another-realname-tip": "Echte naam is optioneel.\nAls u deze opgeeft, wordt deze naam gebruikt worden om u erkenning te geven voor uw werk.",
"showpreview": "Bewerking ter controle bekijken",
"showdiff": "Wijzigingen bekijken",
"blankarticle": "<strong>Waarschuwing:</strong> de pagina die u wilt aanmaken is leeg.\nAls u opnieuw op \"{{int:savearticle}}\" klikt, wordt de pagina aangemaakt zonder enige inhoud.",
- "anoneditwarning": "<strong>Waarschuwing:</strong> u bent niet aangemeld.\nUw IP-adres wordt opgeslagen als u wijzigingen op deze pagina maakt. Wanneer u <strong>[$1 inlogt]</strong> of <strong>[$2 een account maakt]</strong zullen uw bewerkingen verschijnen onder u gebruikersnaam, met ook andere voordelen.",
+ "anoneditwarning": "<strong>Waarschuwing:</strong> u bent niet aangemeld.\nUw IP-adres wordt opgeslagen als u wijzigingen op deze pagina maakt. Wanneer u <strong>[$1 aanmeldt]</strong> of <strong>[$2 een gebruiker aanmaakt]</strong verschijnen uw bewerkingen onder uw gebruikersnaam, naast andere voordelen.",
"anonpreviewwarning": "''U bent niet aangemeld.''\n''Door uw bewerking op te slaan wordt uw IP-adres opgeslagen in de paginageschiedenis.''",
"missingsummary": "'''Let op:''' u hebt geen bewerkingssamenvatting opgegeven.\nAls u nogmaals op \"{{int:savearticle}}\" klikt wordt de bewerking zonder samenvatting opgeslagen.",
"missingcommenttext": "Plaats uw reactie hieronder.",
"MIKHEIL",
"Malafaya",
"MarkvA",
+ "marktraceur",
"Matma Rex",
"MaxSem",
"McDutchie",
"rcshowhidebots": "Option text in [[Special:RecentChanges]]. Parameters:\n* $1 - the \"show/hide\" command, with the text taken from either {{msg-mw|rcshowhidebots-show}} or {{msg-mw|rcshowhidebots-hide}}\n{{Identical|$1 bots}}",
"rcshowhidebots-show": "{{doc-actionlink}}\nOption text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidebots}}.\n\nSee also:\n* {{msg-mw|rcshowhidebots-show}}\n{{Identical|Show}}",
"rcshowhidebots-hide": "{{doc-actionlink}}\nOption text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidebots}}.\n\nSee also:\n* {{msg-mw|rcshowhidebots-hide}}\n{{Identical|Hide}}",
- "rcshowhideliu": "Option text in [[Special:RecentChanges]]. Parameters:\n* $1 - any one of the following messages:\n** {{msg-mw|rcshowhideliu-show}}\n** {{msg-mw|rcshowhideliu-hide}}",
+ "rcshowhideliu": "Option text in [[Special:RecentChanges]]. Parameters:\n* $1 - any one of the following messages:\n** {{msg-mw|rcshowhideliu-show}}\n** {{msg-mw|rcshowhideliu-hide}}\n{{Identical|Registered user}}",
"rcshowhideliu-show": "{{doc-actionlink}}\nOption text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideliu}}.\n\nSee also:\n* {{msg-mw|rcshowhideliu-hide}}\n{{Identical|Show}}",
"rcshowhideliu-hide": "{{doc-actionlink}}\nOption text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideliu}}.\n\nSee also:\n* {{msg-mw|rcshowhideliu-show}}\n{{Identical|Hide}}",
"rcshowhideanons": "Option text in [[Special:RecentChanges]]. Parameters:\n* $1 - the \"show/hide\" command, with the text taken from either {{msg-mw|Rcshowhideanons-show}} or {{msg-mw|Rcshowhideanons-hide}}\n{{Identical|Anonymous user}}",
"tooltip-ca-move": "See also:\n* {{msg-mw|Move}}\n* {{msg-mw|Accesskey-ca-move}}\n* {{msg-mw|Tooltip-ca-move}}\n{{Identical|Move this page}}",
"tooltip-ca-watch": "See also:\n* {{msg-mw|Watch}}\n* {{msg-mw|Accesskey-ca-watch}}\n* {{msg-mw|Tooltip-ca-watch}}\n{{Identical|Add this page to your watchlist}}",
"tooltip-ca-unwatch": "Tooltip shown when hovering over the {{msg-mw|Unwatch}} tab.\n\nSee also:\n* {{msg-mw|Unwatch}}\n* {{msg-mw|Accesskey-ca-unwatch}}\n* {{msg-mw|Tooltip-ca-unwatch}}",
- "tooltip-search": "The tooltip when hovering over the search menu.\n\nSee also:\n* {{msg-mw|Search}}\n* {{msg-mw|Accesskey-search}}\n* {{msg-mw|Tooltip-search}}",
+ "tooltip-search": "The tooltip when hovering over the search menu.\n\nSee also:\n* {{msg-mw|Search}}\n* {{msg-mw|Accesskey-search}}\n* {{msg-mw|Tooltip-search}}\n{{Identical|Search}}",
"tooltip-search-go": "This is the text of the tooltip displayed when hovering the mouse over the {{msg-mw|Go}} button next to the search box.\n\nSee also:\n* {{msg-mw|Go}}\n* {{msg-mw|Accesskey-search-go}}\n* {{msg-mw|Tooltip-search-go}}",
"tooltip-search-fulltext": "This is the text of the tooltip displayed when hovering the mouse over the {{msg-mw|Search}} button under the search box.\n\nSee also:\n* {{msg-mw|Search}}\n* {{msg-mw|Accesskey-search-fulltext}}\n* {{msg-mw|Tooltip-search-fulltext}}",
"tooltip-p-logo": "Tool tip shown when hovering the mouse over the logo that links to [[Main Page]].\n\nSee also:\n* {{msg-mw|Accesskey-p-logo}}\n* {{msg-mw|Tooltip-p-logo}}\n{{Identical|Visit the main page}}",
"version-credits-title": "Page title for an about/credits page for a MediaWiki extension.\n\nUsed as heading in credits page. e.g. [[Special:Version/Credits]] and [[Special:Version/Credits/UniversalLanguageSelector]]\n\nParameters:\n* $1 - the name of the extension",
"version-credits-not-found": "Descriptive error used when detailed about/credits for an extension are not available.\n\nSee example: [[Special:Version/Credits/Foo]]",
"version-poweredby-credits": "Message shown on [[Special:Version]]. Parameters:\n* $1 - the current year\n* $2 - a list of selected MediaWiki authors",
- "version-poweredby-others": "Used at the end of {{msg-mw|version-poweredby-credits}} on [[Special:Version]]. First, there's a long list of selected MediaWiki authors, then a comma and then this translation, which is supposed to credit the many other people than developer helping with MediaWiki.",
+ "version-poweredby-others": "Used at the end of {{msg-mw|version-poweredby-credits}} on [[Special:Version]]. First, there's a long list of selected MediaWiki authors, then a comma and then this translation, which is supposed to credit the many other people than developer helping with MediaWiki.\n{{Identical|Other}}",
"version-poweredby-translators": "Used as label for a link to [[Translating:MediaWiki/Credits]].\n\nPreceded by {{msg-mw|version-poweredby-others}} and {{msg-mw|and}}.\n\nUsed at the end of {{msg-mw|version-poweredby-credits}} on [[Special:Version]].",
"version-credits-summary": "Summary of the [[Special:Version/Credits]] sub page, which lists all developers etc. who contributed to MediaWiki. Shown at the top.",
"version-license-info": "[[wikipedia:GNU GPL|GNU GPL]] notice shown at [[Special:Version]]. See //www.gnu.org/licenses/old-licenses/gpl-2.0-translations.html for available translations.",
"api-error-stashfailed": "API error message that can be used for client side localisation of API errors.",
"api-error-publishfailed": "API error message that can be used for client side localisation of API errors.",
"api-error-stasherror": "API error message that can be used for client side localisation of API errors.",
+ "api-error-stashedfilenotfound": "API error message that can be used for client side localisation of API errors.",
+ "api-error-stashpathinvalid": "API error message that can be used for client side localisation of API errors.",
+ "api-error-stashfilestorage": "API error message that can be used for client side localisation of API errors.",
+ "api-error-stashzerolength": "API error message that can be used for client side localisation of API errors.",
+ "api-error-stashnotloggedin": "API error message that can be used for client side localisation of API errors.",
+ "api-error-stashwrongowner": "API error message that can be used for client side localisation of API errors.",
+ "api-error-stashnosuchfilekey": "API error message that can be used for client side localisation of API errors.",
"api-error-timeout": "API error message that can be used for client side localisation of API errors.",
"api-error-unclassified": "API error message that can be used for client side localisation of API errors.",
"api-error-unknown-code": "API error message that can be used for client side localisation of API errors.\n\nParameters:\n* $1 - may contain more error details\n{{Identical|Unknown error}}",
"deletepage": "Обриши страницу",
"confirm": "Потврди",
"excontent": "садржај је био: „$1“",
- "excontentauthor": "садржај је био: „$1“ (а једини уредник је био „[[Special:Contribs/$2|$2]]“)",
+ "excontentauthor": "садржај је био: „$1“ (а једини уредник [[Special:Contribs/$2|$2]])",
"exbeforeblank": "садржај пре брисања је био: „$1“",
"delete-confirm": "Брисање странице „$1“",
"delete-legend": "Обриши",
"deletepage": "Obriši stranicu",
"confirm": "Potvrdi",
"excontent": "sadržaj je bio: „$1“",
- "excontentauthor": "sadržaj je bio: „$1“ (a jedini urednik je bio „[[Special:Contribs/$2|$2]]“)",
+ "excontentauthor": "sadržaj je bio: „$1“ (a jedini urednik [[Special:Contribs/$2|$2]])",
"exbeforeblank": "sadržaj pre brisanja je bio: „$1“",
"delete-confirm": "Brisanje stranice „$1“",
"delete-legend": "Obriši",
"file-info-size-pages": "$1 × $2 pixel, ukuran berkas: $3, tipeu MIME: $4, $5 {{PLURAL:$5|kaca|kaca}}",
"file-nohires": "Euweuh résolusi nu leuwih luhur.",
"svg-long-desc": "Koropak SVG, nominalna $1 × $2 piksel, ukuranana $3",
- "show-big-image": "Résolusi pinuh",
+ "show-big-image": "Berkas asli",
"show-big-image-preview": "Ukuran ieu pramidang: $1.",
"show-big-image-other": "Résolusi lianna: $1.",
"show-big-image-size": "$1 × $2 pixel",
"exif-orientation-3": "Diputer 180°",
"exif-orientation-4": "Dibalikkeun vértikal",
"exif-orientation-5": "Diputer 90° CCW jeung dibalikkeun vértikal",
- "exif-orientation-6": "Diputer 90° CW",
+ "exif-orientation-6": "Diputer 90° CCW",
"exif-orientation-7": "Diputer 90° CW jeung dibalikkeun vértikal",
"exif-orientation-8": "Diputer 90° CCW",
"exif-planarconfiguration-2": "format datar",
"version-hook-name": "Ngaran kait",
"version-hook-subscribedby": "Didaptarkeun ku",
"version-version": "(Vérsi $1)",
- "version-license": "Lisénsi",
+ "version-license": "Lisénsi MediaWiki",
"version-software": "Sopwér nu geus diinstal",
"version-software-product": "Produk",
"version-software-version": "Vérsi",
"fileduplicatesearch-result-1": "Koropak \"$1\" teu boga duplikat idéntik.",
"fileduplicatesearch-result-n": "Koropak \"$1\" mibanda {{PLURAL:$2|1 duplikat idéntik|$2 duplikat idéntik}}.",
"specialpages": "Kaca husus",
- "specialpages-note": "* Kaca husus bisa di buka ku umum.\n* <strong class=\"mw-specialpagerestricted\">Cetak kandel kaca husus nu kawates.</strong>",
+ "specialpages-note": "* Kaca husus normal.\n* <span class=\"mw-specialpagerestricted\">Kaca husus diwates.</span>",
"specialpages-group-maintenance": "Laporan pigawéeun",
"specialpages-group-other": "Kaca husus lainna",
- "specialpages-group-login": "Asup log / Nyieun rekening",
+ "specialpages-group-login": "Asup log / jieun akun",
"specialpages-group-changes": "Nuanyar robah sarta log",
"specialpages-group-media": "Laporan sarta muatkeun koropak",
"specialpages-group-users": "Pamaké sarta hak pamaké",
"specialpages-group-highuse": "Pamakéan kaca nu badag",
"specialpages-group-pages": "Daptar kaca",
"specialpages-group-pagetools": "Parabot kaca",
- "specialpages-group-wiki": "Data wiki jeung parabot",
+ "specialpages-group-wiki": "Data jeung parabot",
"specialpages-group-redirects": "Alihan kaca husus",
"specialpages-group-spam": "Parabot Spam",
"blankpage": "Kaca kosong",
"tooltip-n-portal": "เกี่ยวกับโครงการ สิ่งที่คุณทำได้ วิธีการค้นหา",
"tooltip-n-currentevents": "ค้นหาเหตุการณ์ปัจจุบัน",
"tooltip-n-recentchanges": "รายการปรับปรุงล่าสุดในวิกินี้",
- "tooltip-n-randompage": "สุà¹\88มหà¸\99à¹\89าà¸\82ึà¹\89à¸\99มา",
+ "tooltip-n-randompage": "à¹\82หลà¸\94หà¸\99à¹\89าสุà¹\88ม",
"tooltip-n-help": "อธิบายการใช้งาน",
"tooltip-t-whatlinkshere": "รายการทุกหน้าวิกิที่ลิงก์มาที่นี่",
"tooltip-t-recentchangeslinked": "รายการปรับปรุงล่าสุดในหน้าที่ลิงก์จากหน้านี้",
"templatesusedpreview": "Sjabloon'n gebruukt in deêze voevertoônieng:",
"templatesusedsection": "Sjabloon'n die an gebruukt worn in deêze subkop:",
"template-protected": "(beveiligd)",
- "template-semiprotected": "(semi-beveiligd)",
+ "template-semiprotected": "(semibeveiligd)",
"hiddencategories": "Deêze pagina val in de volhende verborhen {{PLURAL:$1|categorie|categorieën}}:",
"nocreatetext": "{{SITENAME}} ei de meuhlijkeid om nieuwe pagina's an te maeken beperkt.\nJe kan a bestaende pagina's wiezigen, of je kan [[Special:UserLogin|jen eihen anmelden of een gebruker anmaeken]].",
"nocreate-loggedin": "Je kan hin nieuwe pagina's anmaeken.",
"listingcontinuesabbrev": "续",
"index-category": "已索引页面",
"noindex-category": "不可索引页面",
- "broken-file-category": "有受损文件链接的页面",
+ "broken-file-category": "含有受损文件链接的页面",
"categoryviewer-pagedlinks": "($1)($2)",
"about": "关于",
"article": "内容页面",
"createacct-another-submit": "建立另一個帳號",
"createacct-benefit-heading": "{{SITENAME}} 是由像您一樣貢獻的人所建立的。",
"createacct-benefit-body1": " {{PLURAL:$1|次編輯}}",
- "createacct-benefit-body2": " $1 頁",
+ "createacct-benefit-body2": "$1 頁",
"createacct-benefit-body3": " 位最近的{{PLURAL:$1|貢獻者}}",
"badretype": "兩次輸入的密碼並不相同。",
"userexists": "您所輸入的使用者名稱已存在,請另選一個名稱。",
*/
// Bail if PHP is too low
-if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.3' ) < 0 ) {
// We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
wfPHPVersionError( 'load.php' );
* @defgroup Maintenance Maintenance
*/
-// Make sure we're on PHP5.3.2 or better
-if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+// Make sure we're on PHP5.3.3 or better
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.3' ) < 0 ) {
// We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require_once dirname( __FILE__ ) . '/../includes/PHPVersionError.php';
wfPHPVersionError( 'cli' );
"mw.html",
"mw.html.Cdata",
"mw.html.Raw",
- "mw.hook"
+ "mw.hook",
+ "mw.template"
]
},
{
* @ingroup Maintenance
*/
-if ( !function_exists( 'version_compare' ) || ( version_compare( PHP_VERSION, '5.3.2' ) < 0 ) ) {
+if ( !function_exists( 'version_compare' ) || ( version_compare( PHP_VERSION, '5.3.3' ) < 0 ) ) {
require dirname( __FILE__ ) . '/../includes/PHPVersionError.php';
wfPHPVersionError( 'cli' );
}
*/
// Bail if PHP is too low
-if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.3' ) < 0 ) {
// We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require dirname( dirname( __FILE__ ) ) . '/includes/PHPVersionError.php';
wfPHPVersionError( 'mw-config/index.php' );
'mediawiki.hlist',
),
),
+ 'mediawiki.template' => array(
+ 'scripts' => 'resources/src/mediawiki/mediawiki.template.js',
+ 'targets' => array( 'desktop', 'mobile' ),
+ ),
'mediawiki.apipretty' => array(
'styles' => 'resources/src/mediawiki/mediawiki.apipretty.css',
'targets' => array( 'desktop', 'mobile' ),
'position' => 'bottom',
),
'mediawiki.feedback' => array(
+ 'templates' => array(
+ 'dialog.html' => 'resources/src/mediawiki/templates/dialog.html',
+ ),
'scripts' => 'resources/src/mediawiki/mediawiki.feedback.js',
'styles' => 'resources/src/mediawiki/mediawiki.feedback.css',
'dependencies' => array(
),
),
'mediawiki.action.view.postEdit' => array(
+ 'templates' => array(
+ 'postEdit.html' => 'resources/src/mediawiki.action/templates/postEdit.html',
+ ),
'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.postEdit.js',
'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.postEdit.css',
'dependencies' => array(
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js',
),
'mediawiki.special.upload' => array(
+ 'templates' => array(
+ 'thumbnail.html' => 'resources/src/mediawiki.special/templates/thumbnail.html',
+ ),
'scripts' => 'resources/src/mediawiki.special/mediawiki.special.upload.js',
'messages' => array(
'widthheight',
/*!
- * OOjs UI v0.1.0-pre (deccd11549)
+ * OOjs UI v0.1.0-pre (da4b0d5c14)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-10-28T16:52:27Z
+ * Date: 2014-10-30T00:10:19Z
*/
/* @noflip */
.oo-ui-rtl {
margin-left: 0;
}
.oo-ui-progressBarWidget {
- width: 20em;
+ width: 100%;
+ max-width: 50em;
border: solid 1px #a6cee1;
border-radius: 0.25em;
}
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
- width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-textInputWidget input,
.oo-ui-textInputWidget textarea {
position: relative;
display: inline-block;
margin: 0.25em 0;
- min-width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-inlineMenuWidget-handle {
width: 100%;
.oo-ui-comboBoxWidget {
display: inline-block;
position: relative;
- min-width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
width: 100%;
/*!
- * OOjs UI v0.1.0-pre (deccd11549)
+ * OOjs UI v0.1.0-pre (da4b0d5c14)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-10-28T16:52:18Z
+ * Date: 2014-10-30T00:10:09Z
*/
/* Instantiation */
/*!
- * OOjs UI v0.1.0-pre (deccd11549)
+ * OOjs UI v0.1.0-pre (da4b0d5c14)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-10-28T16:52:27Z
+ * Date: 2014-10-30T00:10:19Z
*/
/* @noflip */
.oo-ui-rtl {
margin-left: 0;
}
.oo-ui-progressBarWidget {
- width: 20em;
+ width: 100%;
+ max-width: 50em;
border: solid 1px #a6cee1;
border-radius: 0.25em;
}
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
- width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-textInputWidget input,
.oo-ui-textInputWidget textarea {
position: relative;
display: inline-block;
margin: 0.25em 0;
- min-width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-inlineMenuWidget-handle {
width: 100%;
.oo-ui-comboBoxWidget {
display: inline-block;
position: relative;
- min-width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
width: 100%;
/*!
- * OOjs UI v0.1.0-pre (deccd11549)
+ * OOjs UI v0.1.0-pre (da4b0d5c14)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-10-28T16:52:27Z
+ * Date: 2014-10-30T00:10:19Z
*/
/* @noflip */
.oo-ui-rtl {
background-color: #ffffff;
}
.oo-ui-progressBarWidget {
- width: 20em;
+ width: 100%;
+ max-width: 50em;
border: solid 1px #0274ff;
border-radius: 0.1em;
}
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
- width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-textInputWidget input,
.oo-ui-textInputWidget textarea {
position: relative;
display: inline-block;
margin: 0.25em 0;
- min-width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-inlineMenuWidget-handle {
width: 100%;
.oo-ui-comboBoxWidget {
display: inline-block;
position: relative;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
width: 100%;
/*!
- * OOjs UI v0.1.0-pre (deccd11549)
+ * OOjs UI v0.1.0-pre (da4b0d5c14)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-10-28T16:52:18Z
+ * Date: 2014-10-30T00:10:09Z
*/
/**
* @class
- * @extends {OO.ui.Theme}
+ * @extends OO.ui.Theme
*
* @constructor
*/
/*!
- * OOjs UI v0.1.0-pre (deccd11549)
+ * OOjs UI v0.1.0-pre (da4b0d5c14)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-10-28T16:52:27Z
+ * Date: 2014-10-30T00:10:19Z
*/
/* @noflip */
.oo-ui-rtl {
background-color: #ffffff;
}
.oo-ui-progressBarWidget {
- width: 20em;
+ width: 100%;
+ max-width: 50em;
border: solid 1px #0274ff;
border-radius: 0.1em;
}
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
- width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-textInputWidget input,
.oo-ui-textInputWidget textarea {
position: relative;
display: inline-block;
margin: 0.25em 0;
- min-width: 20em;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-inlineMenuWidget-handle {
width: 100%;
.oo-ui-comboBoxWidget {
display: inline-block;
position: relative;
+ width: 100%;
+ max-width: 50em;
}
.oo-ui-comboBoxWidget > .oo-ui-selectWidget {
width: 100%;
/*!
- * OOjs UI v0.1.0-pre (deccd11549)
+ * OOjs UI v0.1.0-pre (da4b0d5c14)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2014-10-28T16:52:18Z
+ * Date: 2014-10-30T00:10:09Z
*/
( function ( OO ) {
* @constructor
* @param {Object} [config] Configuration options
* @cfg {Function} [$] jQuery for the frame the widget is in
- * @cfg {string[]} [classes] CSS class names
+ * @cfg {string[]} [classes] CSS class names to add
* @cfg {string} [text] Text to insert
* @cfg {jQuery} [$content] Content elements to append (after text)
*/
*
* @static
* @param {HTMLElement} el Element to scroll into view
- * @param {Object} [config={}] Configuration config
+ * @param {Object} [config] Configuration options
* @param {string} [config.duration] jQuery animation duration value
* @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
* to scroll in both directions
* Check if element supports one or more methods.
*
* @param {string|string[]} methods Method or list of methods to check
- * @return boolean All methods are supported
+ * @return {boolean} All methods are supported
*/
OO.ui.Element.prototype.supports = function ( methods ) {
var i, len,
/**
* Scroll element into view.
*
- * @param {Object} [config={}]
+ * @param {Object} [config] Configuration options
*/
OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
return OO.ui.Element.scrollIntoView( this.$element[0], config );
/**
* Get a list of classes to be applied to a widget.
*
- * @localdoc The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or
- * removes, otherwise state transitions will not work properly.
+ * The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or removes,
+ * otherwise state transitions will not work properly.
*
* @param {OO.ui.Element} element Element for which to get classes
* @return {Object.<string,string[]>} Categorized class names with `on` and `off` lists
*
* For elements with theme logic hooks, this should be called anytime there's a state change.
*
- * @param {OO.ui.Element} Element for which to update classes
+ * @param {OO.ui.Element} element Element for which to update classes
* @return {Object.<string,string[]>} Categorized class names with `on` and `off` lists
*/
OO.ui.Theme.prototype.updateElementClasses = function ( element ) {
* @param {Object} [config] Configuration options
* @cfg {jQuery} [$button] Button node, assigned to #$button, omit to use a generated `<a>`
* @cfg {boolean} [framed=true] Render button with a frame
- * @cfg {number} [tabIndex=0] Button's tab index, use null to have no tabIndex
+ * @cfg {number} [tabIndex=0] Button's tab index. Use 0 to use default ordering, use -1 to prevent
+ * tab focusing.
* @cfg {string} [accessKey] Button's access key
*/
OO.ui.ButtonElement = function OoUiButtonElement( config ) {
/**
* Add items.
*
- * Adding an existing item (by value) will move it.
+ * Adding an existing item will move it.
*
* @param {OO.ui.Element[]} items Items
* @param {number} [index] Index to insert items at
};
/**
- * Set icon.
+ * Set icon name.
*
* @param {Object|string|null} icon Symbolic icon name, or map of icon names keyed by language ID;
* use the 'default' key to specify the icon to be used when there is no icon in the user's
};
/**
- * Get icon.
+ * Get icon name.
*
- * @return {string} Icon
+ * @return {string} Icon name
*/
OO.ui.IconElement.prototype.getIcon = function () {
return this.icon;
*
* @static
* @inheritable
- * @property {string|null} Symbolic indicator name or null for no indicator
+ * @property {string|null} Symbolic indicator name
*/
OO.ui.IndicatorElement.static.indicator = null;
};
/**
- * Set indicator.
+ * Set indicator name.
*
* @param {string|null} indicator Symbolic name of indicator to use or null for no indicator
* @chainable
};
/**
- * Get indicator.
+ * Get indicator name.
*
* @return {string} title Symbolic name of indicator
*/
* Set the label.
*
* An empty string will result in the label being hidden. A string containing only whitespace will
- * be converted to a single
+ * be converted to a single ` `.
*
* @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
* text; or null for no label
*
* @constructor
* @param {Object} [config] Configuration options
- * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
+ * @cfg {string|string[]} [flags] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
* @cfg {jQuery} [$flagged] Flagged node, assigned to #$flagged, omit to use #$element
*/
OO.ui.FlaggedElement = function OoUiFlaggedElement( config ) {
* @constructor
* @param {Object} [config] Configuration options
* @cfg {jQuery} [$titled] Titled node, assigned to #$titled, omit to use #$element
- * @cfg {string|Function} [title] Title text or a function that returns text
+ * @cfg {string|Function} [title] Title text or a function that returns text. If not provided, the
+ * static property 'title' is used.
*/
OO.ui.TitledElement = function OoUiTitledElement( config ) {
// Config intialization
/**
* Layout made of a field and optional label.
*
- * @class
- * @extends OO.ui.Layout
- * @mixins OO.ui.LabelElement
- *
* Available label alignment modes include:
* - left: Label is before the field and aligned away from it, best for when the user will be
* scanning for a specific label in a form with many fields
* - inline: Label is after the field and aligned toward it, best for small boolean fields like
* checkboxes or radio buttons
*
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.LabelElement
+ *
* @constructor
* @param {OO.ui.Widget} fieldWidget Field widget
* @param {Object} [config] Configuration options
OO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout );
OO.mixinClass( OO.ui.FieldLayout, OO.ui.LabelElement );
+/* Static Properties */
+
+OO.ui.FieldLayout.static.tagName = 'label';
+
/* Methods */
/**
/**
* Set the field alignment mode.
*
+ * @private
* @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'
* @chainable
*/
*
* @class
* @extends OO.ui.Layout
- * @mixins OO.ui.LabelElement
* @mixins OO.ui.IconElement
+ * @mixins OO.ui.LabelElement
* @mixins OO.ui.GroupElement
*
* @constructor
return [];
};
+/**
+ * Get lookup cache item from server response data.
+ *
+ * @abstract
+ * @param {Mixed} data Response from server
+ * @return {Mixed} Cached result data
+ */
+OO.ui.LookupInputWidget.prototype.getLookupCacheItemFromData = function () {
+ // Stub, implemented in subclass
+ return [];
+};
+
/**
* Set of controls for an OO.ui.OutlineWidget.
*
*
* @constructor
* @param {Object} [config] Configuration options
- * @cfg {OO.ui.ButtonWidget} [items] Buttons to add
+ * @cfg {OO.ui.ButtonWidget[]} [items] Buttons to add
*/
OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {
// Parent constructor
* @param {Object} [config] Configuration options
* @cfg {string} [name=''] HTML input name
* @cfg {string} [value=''] Input value
- * @cfg {boolean} [readOnly=false] Prevent changes
* @cfg {Function} [inputFilter] Filter function to apply to the input. Takes a string argument and returns a string.
*/
OO.ui.InputWidget = function OoUiInputWidget( config ) {
- // Config intialization
- config = $.extend( { readOnly: false }, config );
+ // Configuration initialization
+ config = config || {};
// Parent constructor
OO.ui.InputWidget.super.call( this, config );
// Properties
this.$input = this.getInputElement( config );
this.value = '';
- this.readOnly = false;
this.inputFilter = config.inputFilter;
// Events
this.$input
.attr( 'name', config.name )
.prop( 'disabled', this.isDisabled() );
- this.setReadOnly( config.readOnly );
this.$element.addClass( 'oo-ui-inputWidget' ).append( this.$input );
this.setValue( config.value );
};
/**
* Get input element.
*
+ * @private
* @param {Object} [config] Configuration options
* @return {jQuery} Input element
*/
/**
* Sanitize incoming value.
*
- * Ensures value is a string, and converts undefined and null to empty strings.
+ * Ensures value is a string, and converts undefined and null to empty string.
*
+ * @private
* @param {string} value Original value
* @return {string} Sanitized value
*/
}
};
-/**
- * Check if the widget is read-only.
- *
- * @return {boolean}
- */
-OO.ui.InputWidget.prototype.isReadOnly = function () {
- return this.readOnly;
-};
-
-/**
- * Set the read-only state of the widget.
- *
- * This should probably change the widgets's appearance and prevent it from being used.
- *
- * @param {boolean} state Make input read-only
- * @chainable
- */
-OO.ui.InputWidget.prototype.setReadOnly = function ( state ) {
- this.readOnly = !!state;
- this.$input.prop( 'readOnly', this.readOnly );
- return this;
-};
-
/**
* @inheritdoc
*/
};
/**
- * A button that is an input widget. Intended to be used within FormLayouts.
+ * A button that is an input widget. Intended to be used within a OO.ui.FormLayout.
*
* @class
* @extends OO.ui.InputWidget
// Configuration initialization
config = $.extend( { type: 'button', useInputTag: false }, config );
+ // Properties (must be set before parent constructor, which calls #setValue)
+ this.useInputTag = config.useInputTag;
+
// Parent constructor
OO.ui.ButtonInputWidget.super.call( this, config );
OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$input } ) );
OO.ui.FlaggedElement.call( this, config );
- // Properties
- this.useInputTag = config.useInputTag;
-
// Events
this.$input.on( {
click: this.onClick.bind( this ),
/**
* Get input element.
*
+ * @private
* @param {Object} [config] Configuration options
* @return {jQuery} Input element
*/
};
/**
- * Set the label.
+ * Set label value.
*
* Overridden to support setting the 'value' of `<input/>` elements.
*
return this;
};
+/**
+ * Set the value of the input.
+ *
+ * Overridden to disable for `<input/>` elements, which have value identical to the label.
+ *
+ * @param {string} value New value
+ * @chainable
+ */
+OO.ui.ButtonInputWidget.prototype.setValue = function ( value ) {
+ if ( !this.useInputTag ) {
+ OO.ui.ButtonInputWidget.super.prototype.setValue.call( this, value );
+ }
+ return this;
+};
+
/**
* Handles mouse click events.
*
/**
* Get input element.
*
+ * @private
* @return {jQuery} Input element
*/
OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
* @param {Object} [config] Configuration options
* @cfg {string} [type='text'] HTML tag `type` attribute
* @cfg {string} [placeholder] Placeholder text
+ * @cfg {boolean} [readOnly=false] Prevent changes
* @cfg {boolean} [multiline=false] Allow multiple lines of text
* @cfg {boolean} [autosize=false] Automatically resize to fit content
* @cfg {boolean} [maxRows=10] Maximum number of rows to make visible when autosizing
*/
OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
// Configuration initialization
- config = config || {};
+ config = $.extend( { readOnly: false }, config );
// Parent constructor
OO.ui.TextInputWidget.super.call( this, config );
OO.ui.PendingElement.call( this, config );
// Properties
+ this.readOnly = false;
this.multiline = !!config.multiline;
this.autosize = !!config.autosize;
this.maxRows = config.maxRows !== undefined ? config.maxRows : 10;
this.$element
.addClass( 'oo-ui-textInputWidget' )
.append( this.$icon, this.$indicator );
+ this.setReadOnly( config.readOnly );
if ( config.placeholder ) {
this.$input.attr( 'placeholder', config.placeholder );
}
return this;
};
+/**
+ * Check if the widget is read-only.
+ *
+ * @return {boolean}
+ */
+OO.ui.TextInputWidget.prototype.isReadOnly = function () {
+ return this.readOnly;
+};
+
+/**
+ * Set the read-only state of the widget.
+ *
+ * This should probably change the widgets's appearance and prevent it from being used.
+ *
+ * @param {boolean} state Make input read-only
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.setReadOnly = function ( state ) {
+ this.readOnly = !!state;
+ this.$input.prop( 'readOnly', this.readOnly );
+ return this;
+};
+
/**
* Automatically adjust the size of the text input.
*
/**
* Get input element.
*
+ * @private
* @param {Object} [config] Configuration options
* @return {jQuery} Input element
*/
data.message = $.parseHTML( mw.message( 'postedit-confirmation-saved', data.user || mw.user ).escaped() );
}
- $div = $(
- '<div class="postedit-container">' +
- '<div class="postedit">' +
- '<div class="postedit-icon postedit-icon-checkmark postedit-content"></div>' +
- '<a href="#" class="postedit-close">×</a>' +
- '</div>' +
- '</div>'
- );
+ $div = mw.template.get( 'mediawiki.action.view.postEdit', 'postEdit.html' ).render();
if ( typeof data.message === 'string' ) {
$div.find( '.postedit-content' ).text( data.message );
--- /dev/null
+<div class="postedit-container">
+ <div class="postedit">
+ <div class="postedit-icon postedit-icon-checkmark postedit-content"></div>
+ <a href="#" class="postedit-close">×</a>
+ </div>
+</div>
'nomodule',
'mustbeposted',
'badaccess-groups',
- 'stashfailed',
'missingresult',
'missingparam',
'invalid-file-key',
'fetchfileerror',
'fileexists-shared-forbidden',
'invalidtitle',
- 'notloggedin'
+ 'notloggedin',
+
+ // Stash-specific errors - expanded
+ 'stashfailed',
+ 'stasherror',
+ 'stashedfilenotfound',
+ 'stashpathinvalid',
+ 'stashfilestorage',
+ 'stashzerolength',
+ 'stashnotloggedin',
+ 'stashwrongowner',
+ 'stashnosuchfilekey'
];
/**
ctx,
meta,
previewSize = 180,
- thumb = $( '<div id="mw-upload-thumbnail" class="thumb tright">' +
- '<div class="thumbinner">' +
- '<div class="mw-small-spinner" style="width: 180px; height: 180px"></div>' +
- '<div class="thumbcaption"><div class="filename"></div><div class="fileinfo"></div></div>' +
- '</div>' +
- '</div>' );
+ thumb = mw.template.get( 'mediawiki.special.upload', 'thumbnail.html' ).render();
thumb.find( '.filename' ).text( file.name ).end()
.find( '.fileinfo' ).text( prettySize( file.size ) ).end();
--- /dev/null
+<div id="mw-upload-thumbnail" class="thumb tright">
+ <div class="thumbinner">
+ <div class="mw-small-spinner" style="width: 180px; height: 180px"></div>
+ <div class="thumbcaption">
+ <div class="filename"></div>
+ <div class="fileinfo"></div>
+ </div>
+ </div>
+</div>
}, 1 );
// show an alert with this message
- return options.message;
+ if ( $.isFunction( options.message ) ) {
+ return options.message();
+ } else {
+ return options.message;
+ }
}
} ).on( showEventName, function () {
// Re-add onbeforeunload handler
target: '_blank'
} );
- // TODO: Use a stylesheet instead of these inline styles
- this.$dialog =
- $( '<div style="position: relative;"></div>' ).append(
- $( '<div class="feedback-mode feedback-form"></div>' ).append(
- $( '<small>' ).append(
- $( '<p>' ).msg(
- 'feedback-bugornote',
- $bugNoteLink,
- fb.title.getNameText(),
- $feedbackPageLink.clone()
- )
- ),
- $( '<div style="margin-top: 1em;"></div>' )
- .msg( 'feedback-subject' )
- .append(
- $( '<br>' ),
- $( '<input type="text" class="feedback-subject" name="subject" maxlength="60" style="width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;"/>' )
- ),
- $( '<div style="margin-top: 0.4em;"></div>' )
- .msg( 'feedback-message' )
- .append(
- $( '<br>' ),
- $( '<textarea name="message" class="feedback-message" rows="5" cols="60"></textarea>' )
- )
- ),
- $( '<div class="feedback-mode feedback-bugs"></div>' ).append(
- $( '<p>' ).msg( 'feedback-bugcheck', $bugsListLink )
- ),
- $( '<div class="feedback-mode feedback-submitting" style="text-align: center; margin: 3em 0;"></div>' )
- .msg( 'feedback-adding' )
- .append(
- $( '<br>' ),
- $( '<span class="feedback-spinner"></span>' )
- ),
- $( '<div class="feedback-mode feedback-thanks" style="text-align: center; margin:1em"></div>' ).msg(
- 'feedback-thanks', fb.title.getNameText(), $feedbackPageLink.clone()
- ),
- $( '<div class="feedback-mode feedback-error" style="position: relative;"></div>' ).append(
- $( '<div class="feedback-error-msg style="color: #990000; margin-top: 0.4em;"></div>' )
- )
- );
+ // TODO: Use a stylesheet instead of these inline styles in the template
+ this.$dialog = mw.template.get( 'mediawiki.feedback', 'dialog.html' ).render();
+ this.$dialog.find( '.feedback-mode small p' ).msg(
+ 'feedback-bugornote',
+ $bugNoteLink,
+ fb.title.getNameText(),
+ $feedbackPageLink.clone()
+ );
+ this.$dialog.find( '.feedback-form .subject span' ).msg( 'feedback-subject' );
+ this.$dialog.find( '.feedback-form .message span' ).msg( 'feedback-message' );
+ this.$dialog.find( '.feedback-bugs p' ).msg( 'feedback-bugcheck', $bugsListLink );
+ this.$dialog.find( '.feedback-submitting span' ).msg( 'feedback-adding' );
+ this.$dialog.find( '.feedback-thanks' ).msg( 'feedback-thanks', fb.title.getNameText(),
+ $feedbackPageLink.clone() );
this.$dialog.dialog( {
width: 500,
*/
messages: new Map(),
+ /**
+ * Templates associated with a module
+ * @property {mw.Map}
+ */
+ templates: new Map(),
+
/* Public Methods */
/**
mw.messages.set( registry[module].messages );
}
+ // Initialise templates
+ if ( registry[module].templates ) {
+ mw.templates.set( module, registry[module].templates );
+ }
+
if ( $.isReady || registry[module].async ) {
// Make sure we don't run the scripts until all (potentially asynchronous)
// stylesheet insertions have completed.
* whether it's safe to extend the stylesheet (see #canExpandStylesheetWith).
*
* @param {Object} msgs List of key/value pairs to be added to mw#messages.
+ * @param {Object} [templates] List of key/value pairs to be added to mw#templates.
*/
- implement: function ( module, script, style, msgs ) {
+ implement: function ( module, script, style, msgs, templates ) {
// Validate input
if ( typeof module !== 'string' ) {
throw new Error( 'module must be a string, not a ' + typeof module );
if ( !$.isPlainObject( msgs ) ) {
throw new Error( 'msgs must be an object, not a ' + typeof msgs );
}
+ if ( templates !== undefined && !$.isPlainObject( templates ) ) {
+ throw new Error( 'templates must be an object, not a ' + typeof templates );
+ }
// Automatically register module
if ( registry[module] === undefined ) {
mw.loader.register( module );
registry[module].script = script;
registry[module].style = style;
registry[module].messages = msgs;
+ // Templates are optional (for back-compat)
+ registry[module].templates = templates || {};
// The module may already have been marked as erroneous
if ( $.inArray( registry[module].state, ['error', 'missing'] ) === -1 ) {
registry[module].state = 'loaded';
* @param {Function} [ready] Callback to execute when all dependencies are ready
* @param {Function} [error] Callback to execute if one or more dependencies failed
* @return {jQuery.Promise}
+ * @since 1.23 this returns a promise
*/
using: function ( dependencies, ready, error ) {
var deferred = $.Deferred();
// Unversioned, private, or site-/user-specific
( !descriptor.version || $.inArray( descriptor.group, [ 'private', 'user', 'site' ] ) !== -1 ) ||
// Partial descriptor
- $.inArray( undefined, [ descriptor.script, descriptor.style, descriptor.messages ] ) !== -1
+ $.inArray( undefined, [ descriptor.script, descriptor.style,
+ descriptor.messages, descriptor.templates ] ) !== -1
) {
// Decline to store
return false;
String( descriptor.script ) :
JSON.stringify( descriptor.script ),
JSON.stringify( descriptor.style ),
- JSON.stringify( descriptor.messages )
+ JSON.stringify( descriptor.messages ),
+ JSON.stringify( descriptor.templates )
];
// Attempted workaround for a possible Opera bug (bug 57567).
// This regex should never match under sane conditions.
--- /dev/null
+/**
+ * @class mw.template
+ * @singleton
+ */
+( function ( mw, $ ) {
+ var compiledTemplates = {},
+ compilers = {};
+
+ mw.template = {
+ /**
+ * Register a new compiler and template.
+ *
+ * @param {string} name of compiler. Should also match with any file extensions of templates that want to use it.
+ * @param {Function} compiler which must implement a compile function
+ */
+ registerCompiler: function ( name, compiler ) {
+ if ( !compiler.compile ) {
+ throw new Error( 'Compiler must implement compile method.' );
+ }
+ compilers[name] = compiler;
+ },
+
+ /**
+ * Get the name of the compiler associated with a template based on its name.
+ *
+ * @param {string} templateName Name of template (including file suffix)
+ * @return {String} Name of compiler
+ */
+ getCompilerName: function ( templateName ) {
+ var templateParts = templateName.split( '.' );
+
+ if ( templateParts.length < 2 ) {
+ throw new Error( 'Unable to identify compiler. Template name must have a suffix.' );
+ }
+ return templateParts[ templateParts.length - 1 ];
+ },
+
+ /**
+ * Get the compiler for a given compiler name.
+ *
+ * @param {string} compilerName Name of the compiler
+ * @return {Object} The compiler associated with that name
+ */
+ getCompiler: function ( compilerName ) {
+ var compiler = compilers[ compilerName ];
+ if ( !compiler ) {
+ throw new Error( 'Unknown compiler ' + compilerName );
+ }
+ return compiler;
+ },
+
+ /**
+ * Register a template associated with a module.
+ *
+ * Compiles the newly added template based on the suffix in its name.
+ *
+ * @param {string} moduleName Name of ResourceLoader module to get the template from
+ * @param {string} templateName Name of template to add including file extension
+ * @param {string} templateBody Contents of a template (e.g. html markup)
+ * @return {Function} Compiled template
+ */
+ add: function ( moduleName, templateName, templateBody ) {
+ var compiledTemplate,
+ compilerName = this.getCompilerName( templateName );
+
+ if (!compiledTemplates[moduleName]) {
+ compiledTemplates[moduleName] = {};
+ }
+
+ compiledTemplate = this.compile( templateBody, compilerName );
+ compiledTemplates[moduleName][ templateName ] = compiledTemplate;
+ return compiledTemplate;
+ },
+
+ /**
+ * Retrieve a template by module and template name.
+ *
+ * @param {string} moduleName Name of the module to retrieve the template from
+ * @param {string} templateName Name of template to be retrieved
+ * @return {Object} Compiled template
+ */
+ get: function ( moduleName, templateName ) {
+ var moduleTemplates, compiledTemplate;
+
+ // Check if the template has already been compiled, compile it if not
+ if ( !compiledTemplates[ moduleName ] || !compiledTemplates[ moduleName ][ templateName ] ) {
+ moduleTemplates = mw.templates.get( moduleName );
+ if ( !moduleTemplates || !moduleTemplates[ templateName ] ) {
+ throw new Error( 'Template ' + templateName + ' not found in module ' + moduleName );
+ }
+
+ // Add compiled version
+ compiledTemplate = this.add( moduleName, templateName, moduleTemplates[ templateName ] );
+ } else {
+ compiledTemplate = compiledTemplates[ moduleName ][ templateName ];
+ }
+ return compiledTemplate;
+ },
+
+ /**
+ * Wrap our template engine of choice.
+ *
+ * @param {string} templateBody Template body
+ * @param {string} compilerName The name of a registered compiler
+ * @return {Object} Template interface
+ */
+ compile: function ( templateBody, compilerName ) {
+ return this.getCompiler( compilerName ).compile( templateBody );
+ }
+ };
+
+ // Register basic html compiler
+ mw.template.registerCompiler( 'html', {
+ compile: function ( src ) {
+ return {
+ render: function () {
+ return $( $.parseHTML( $.trim( src ) ) );
+ }
+ };
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
--- /dev/null
+<div style="position: relative; display: block;" class="ui-dialog-content ui-widget-content">
+ <div class="feedback-mode feedback-form">
+ <small><p></p></small>
+ <div class="subject" style="margin-top: 1em;">
+ <span></span><br>
+ <input type="text" class="feedback-subject" name="subject" maxlength="60"
+ style="width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;">
+ </div>
+ <div class="message" style="margin-top: 0.4em;">
+ <span></span><br>
+ <textarea name="message" class="feedback-message" rows="5" cols="60"></textarea>
+ </div>
+ </div>
+ <div class="feedback-mode feedback-bugs">
+ <p></p>
+ </div>
+ <div class="feedback-mode feedback-submitting" style="text-align: center; margin: 3em 0;">
+ <span></span><br>
+ <span class="feedback-spinner"></span>
+ </div>
+ <div class="feedback-mode feedback-thanks" style="text-align: center; margin:1em"></div>
+ <div class="feedback-mode feedback-error" style="position: relative;">
+ <div class="feedback-error-msg" style=" color:#990000; margin-top:0.4em;"></div>
+ </div>
+</div>
},
banana: {
core: 'languages/i18n/',
+ api: 'includes/api/i18n/',
installer: 'includes/installer/i18n/'
},
watch: {
$wgDebugTimestamps = false;
wfDebug( "This is a normal string" );
- $this->assertEquals( "This is a normal string", file_get_contents( $wgDebugLogFile ) );
+ $this->assertEquals( "This is a normal string\n", 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 ) );
+ $this->assertEquals( "This is nöt an ASCII string\n", 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 ",
+ " 05This has böth UTF and control chars \n",
file_get_contents( $wgDebugLogFile )
);
unlink( $wgDebugLogFile );
array(
array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
'<script>if(window.mw){
-mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]},{});
+mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]},{},{});
}</script>
'
$passwordFactory = $this->user->getPasswordFactory();
$oldDefaultType = $passwordFactory->getDefaultType();
- // B is salted MD5 (thus fast) ... we don't care about security here, this is test only
- $passwordFactory->setDefaultType( 'B' ); // @TODO: Change this to A once that is fixed: https://gerrit.wikimedia.org/r/167523
+ // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
+ $passwordFactory->setDefaultType( 'A' );
$newPassword = $passwordFactory->newFromPlaintext( $password , $this->user->getPassword() );
$change = false;
<?php
+/**
+ * @group ResourceLoader
+ */
class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
protected function setUp() {
);
}
+ public static function getModules() {
+ $base = array(
+ 'localBasePath' => realpath( dirname( __FILE__ ) ),
+ );
+
+ return array(
+ 'noTemplateModule' => array(),
+
+ 'htmlTemplateModule' => $base + array(
+ 'templates' => array(
+ 'templates/template.html',
+ 'templates/template2.html',
+ )
+ ),
+
+ 'aliasedHtmlTemplateModule' => $base + array(
+ 'templates' => array(
+ 'foo.html' => 'templates/template.html',
+ 'bar.html' => 'templates/template2.html',
+ )
+ ),
+
+ 'templateModuleHandlebars' => $base + array(
+ 'templates' => array(
+ 'templates/template_awesome.handlebars',
+ ),
+ ),
+ );
+ }
+
+ public static function providerGetTemplates() {
+ $modules = self::getModules();
+
+ return array(
+ array(
+ $modules['noTemplateModule'],
+ array(),
+ ),
+ array(
+ $modules['templateModuleHandlebars'],
+ array(
+ 'templates/template_awesome.handlebars' => "wow\n",
+ ),
+ ),
+ array(
+ $modules['htmlTemplateModule'],
+ array(
+ 'templates/template.html' => "<strong>hello</strong>\n",
+ 'templates/template2.html' => "<div>goodbye</div>\n",
+ ),
+ ),
+ array(
+ $modules['aliasedHtmlTemplateModule'],
+ array(
+ 'foo.html' => "<strong>hello</strong>\n",
+ 'bar.html' => "<div>goodbye</div>\n",
+ ),
+ ),
+ );
+ }
+
+ public static function providerGetModifiedTime() {
+ $modules = self::getModules();
+
+ return array(
+ // Check the default value when no templates present in module is 1
+ array( $modules['noTemplateModule'], 1 ),
+ );
+ }
+
/**
* @covers ResourceLoaderFileModule::getAllSkinStyleFiles
*/
array_map( 'basename', $module->getAllStyleFiles() )
);
}
+
+ /**
+ * @dataProvider providerGetTemplates
+ * @covers ResourceLoaderFileModule::getTemplates
+ */
+ public function testGetTemplates( $module, $expected ) {
+ $rl = new ResourceLoaderFileModule( $module );
+
+ $this->assertEquals( $rl->getTemplates(), $expected );
+ }
+
+ /**
+ * @dataProvider providerGetModifiedTime
+ * @covers ResourceLoaderFileModule::getModifiedTime
+ */
+ public function testGetModifiedTime( $module, $expected ) {
+ $rl = new ResourceLoaderFileModule( $module );
+ $ts = $rl->getModifiedTime( new ResourceLoaderContext(
+ new ResourceLoader, new FauxRequest() ) );
+ $this->assertEquals( $ts, $expected );
+ }
}
--- /dev/null
+<strong>hello</strong>
--- /dev/null
+<div>goodbye</div>
'tests/qunit/suites/resources/mediawiki/mediawiki.jscompat.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js',
+ 'tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.toc.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js',
'mediawiki.toc',
'mediawiki.Uri',
'mediawiki.user',
+ 'mediawiki.template',
'mediawiki.util',
'mediawiki.special.recentchanges',
'mediawiki.language',
--- /dev/null
+( function ( mw ) {
+
+ QUnit.module( 'mediawiki.template', {
+ setup: function () {
+ var abcCompiler = {
+ compile: function () {
+ return 'abc default compiler';
+ }
+ };
+
+ // Register some template compiler languages
+ mw.template.registerCompiler( 'abc', abcCompiler );
+ mw.template.registerCompiler( 'xyz', {
+ compile: function () {
+ return 'xyz compiler';
+ }
+ } );
+
+ // Stub register some templates
+ this.sandbox.stub( mw.templates, 'get' ).returns( {
+ 'test_templates_foo.xyz': 'goodbye',
+ 'test_templates_foo.abc': 'thankyou'
+ } );
+ }
+ } );
+
+ QUnit.test( 'add', 1, function ( assert ) {
+ assert.throws(
+ function () {
+ mw.template.add( 'module', 'test_templates_foo', 'hello' );
+ },
+ 'When no prefix throw exception'
+ );
+ } );
+
+ QUnit.test( 'compile', 1, function ( assert ) {
+ assert.throws(
+ function () {
+ mw.template.compile( '{{foo}}', 'rainbow' );
+ },
+ 'Unknown compiler names throw exceptions'
+ );
+ } );
+
+ QUnit.test( 'get', 4, function ( assert ) {
+ assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.xyz' ), 'xyz compiler' );
+ assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.abc' ), 'abc default compiler' );
+ assert.throws(
+ function () {
+ mw.template.get( 'this.should.not.exist', 'hello' );
+ },
+ 'When bad module name given throw error.'
+ );
+
+ assert.throws(
+ function () {
+ mw.template.get( 'mediawiki.template', 'hello' );
+ },
+ 'The template hello should not exist in the mediawiki.templates module and should throw an exception.'
+ );
+ } );
+
+}( mediaWiki ) );