tag is meant to be hidden from user interfaces.
* action=import no longer allows both the namespace= and rootpage= parameters
to be set. If they are both set, the value of rootpage= will be ignored.
+* prop=revision output in enum mode is now sorted by timestamp rather than
+ revision ID. This usually won't make any difference.
=== Action API internal changes in 1.26 ===
// Enum mode can only be used when exactly one page is provided.
// Enumerating revisions on multiple pages make it extremely
// difficult to manage continuations and require additional SQL indexes
- $enumRevMode = ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ||
- !is_null( $params['limit'] ) || !is_null( $params['startid'] ) ||
- !is_null( $params['endid'] ) || $params['dir'] === 'newer' ||
- !is_null( $params['start'] ) || !is_null( $params['end'] ) );
+ $enumRevMode = ( $params['user'] !== null || $params['excludeuser'] !== null ||
+ $params['limit'] !== null || $params['startid'] !== null ||
+ $params['endid'] !== null || $params['dir'] === 'newer' ||
+ $params['start'] !== null || $params['end'] !== null );
$pageSet = $this->getPageSet();
$pageCount = $pageSet->getGoodTitleCount();
}
} else {
$this->limit = $this->getParameter( 'limit' ) ?: 10;
- $this->addFields( array( 'rev_id', 'rev_page' ) );
+ $this->addFields( array( 'rev_id', 'rev_timestamp', 'rev_page' ) );
}
if ( $this->fld_tags ) {
$this->addFields( 'ts_tags' );
}
- if ( !is_null( $params['tag'] ) ) {
+ if ( $params['tag'] !== null ) {
$this->addTables( 'change_tag' );
$this->addJoinConds(
array( 'change_tag' => array( 'INNER JOIN', array( 'rev_id=ct_rev_id' ) ) )
}
if ( $enumRevMode ) {
+ // Indexes targeted:
+ // page_timestamp if we don't have rvuser
+ // page_user_timestamp if we have a logged-in rvuser
+ // page_timestamp or usertext_timestamp if we have an IP rvuser
+
// This is mostly to prevent parameter errors (and optimize SQL?)
- if ( !is_null( $params['startid'] ) && !is_null( $params['start'] ) ) {
+ if ( $params['startid'] !== null && $params['start'] !== null ) {
$this->dieUsage( 'start and startid cannot be used together', 'badparams' );
}
- if ( !is_null( $params['endid'] ) && !is_null( $params['end'] ) ) {
+ if ( $params['endid'] !== null && $params['end'] !== null ) {
$this->dieUsage( 'end and endid cannot be used together', 'badparams' );
}
- if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
+ if ( $params['user'] !== null && $params['excludeuser'] !== null ) {
$this->dieUsage( 'user and excludeuser cannot be used together', 'badparams' );
}
- // Continuing effectively uses startid. But we can't use rvstartid
- // directly, because there is no way to tell the client to ''not''
- // send rvstart if it sent it in the original query. So instead we
- // send the continuation startid as rvcontinue, and ignore both
- // rvstart and rvstartid when that is supplied.
- if ( !is_null( $params['continue'] ) ) {
- $params['startid'] = $params['continue'];
- $params['start'] = null;
+ if ( $params['continue'] !== null ) {
+ $cont = explode( '|', $params['continue'] );
+ $this->dieContinueUsageIf( count( $cont ) != 2 );
+ $op = ( $params['dir'] === 'newer' ? '>' : '<' );
+ $continueTimestamp = $db->addQuotes( $db->timestamp( $cont[0] ) );
+ $continueId = (int)$cont[1];
+ $this->dieContinueUsageIf( $continueId != $cont[1] );
+ $this->addWhere( "rev_timestamp $op $continueTimestamp OR " .
+ "(rev_timestamp = $continueTimestamp AND " .
+ "rev_id $op= $continueId)"
+ );
}
- // This code makes an assumption that sorting by rev_id and rev_timestamp produces
- // the same result. This way users may request revisions starting at a given time,
- // but to page through results use the rev_id returned after each page.
- // Switching to rev_id removes the potential problem of having more than
- // one row with the same timestamp for the same page.
- // The order needs to be the same as start parameter to avoid SQL filesort.
- if ( is_null( $params['startid'] ) && is_null( $params['endid'] ) ) {
- $this->addTimestampWhereRange( 'rev_timestamp', $params['dir'],
- $params['start'], $params['end'] );
- } else {
- $this->addWhereRange( 'rev_id', $params['dir'],
- $params['startid'], $params['endid'] );
- // One of start and end can be set
- // If neither is set, this does nothing
- $this->addTimestampWhereRange( 'rev_timestamp', $params['dir'],
- $params['start'], $params['end'], false );
+ // Query optimization: since we're targeting ranges of
+ // rev_timestamp,rev_id, if we're given an id then extract the
+ // corresponding timestamp from the DB.
+ // Note we don't use Revision::getTimestampFromId() since we don't
+ // have a Title to pass it and there's not any real need to create one.
+ if ( $params['startid'] !== null ) {
+ $params['start'] = $db->selectField( 'revision', 'rev_timestamp',
+ array( 'rev_id' => $params['startid'] ), __METHOD__ );
+ }
+ if ( $params['endid'] !== null ) {
+ $params['end'] = $db->selectField( 'revision', 'rev_timestamp',
+ array( 'rev_id' => $params['endid'] ), __METHOD__ );
}
+ $this->addTimestampWhereRange( 'rev_timestamp', $params['dir'],
+ $params['start'], $params['end'] );
+ $this->addWhereRange( 'rev_id', $params['dir'],
+ $params['startid'], $params['endid'] );
+
// There is only one ID, use it
$ids = array_keys( $pageSet->getGoodTitles() );
$this->addWhereFld( 'rev_page', reset( $ids ) );
- if ( !is_null( $params['user'] ) ) {
- $this->addWhereFld( 'rev_user_text', $params['user'] );
- } elseif ( !is_null( $params['excludeuser'] ) ) {
- $this->addWhere( 'rev_user_text != ' .
- $db->addQuotes( $params['excludeuser'] ) );
+ if ( $params['user'] !== null ) {
+ $user = User::newFromName( $params['user'] );
+ if ( $user && $user->getId() > 0 ) {
+ $this->addWhereFld( 'rev_user', $user->getId() );
+ } else {
+ $this->addWhereFld( 'rev_user_text', $params['user'] );
+ }
+ } elseif ( $params['excludeuser'] !== null ) {
+ $user = User::newFromName( $params['excludeuser'] );
+ if ( $user && $user->getId() > 0 ) {
+ $this->addWhere( 'rev_user != ' . $user->getId() );
+ } else {
+ $this->addWhere( 'rev_user_text != ' .
+ $db->addQuotes( $params['excludeuser'] ) );
+ }
}
- if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) {
+ if ( $params['user'] !== null || $params['excludeuser'] !== null ) {
// Paranoia: avoid brute force searches (bug 17342)
if ( !$this->getUser()->isAllowed( 'deletedhistory' ) ) {
$bitmask = Revision::DELETED_USER;
}
}
} elseif ( $revCount > 0 ) {
+ // Always targets the PRIMARY index
+
$revs = $pageSet->getLiveRevisionIDs();
// Get all revision IDs
$this->addWhereFld( 'rev_id', array_keys( $revs ) );
- if ( !is_null( $params['continue'] ) ) {
+ if ( $params['continue'] !== null ) {
$this->addWhere( 'rev_id >= ' . intval( $params['continue'] ) );
}
$this->addOption( 'ORDER BY', 'rev_id' );
} elseif ( $pageCount > 0 ) {
+ // Always targets the rev_page_id index
+
$titles = $pageSet->getGoodTitles();
// When working in multi-page non-enumeration mode,
// Every time someone relies on equality propagation, god kills a kitten :)
$this->addWhereFld( 'rev_page', array_keys( $titles ) );
- if ( !is_null( $params['continue'] ) ) {
+ if ( $params['continue'] !== null ) {
$cont = explode( '|', $params['continue'] );
$this->dieContinueUsageIf( count( $cont ) != 2 );
$pageid = intval( $cont[0] );
// We've reached the one extra which shows that there are
// additional pages to be had. Stop here...
if ( $enumRevMode ) {
- $this->setContinueEnumParameter( 'continue', intval( $row->rev_id ) );
+ $this->setContinueEnumParameter( 'continue',
+ $row->rev_timestamp . '|' . intval( $row->rev_id ) );
} elseif ( $revCount > 0 ) {
$this->setContinueEnumParameter( 'continue', intval( $row->rev_id ) );
} else {
$fit = $this->addPageSubItem( $row->rev_page, $rev, 'rev' );
if ( !$fit ) {
if ( $enumRevMode ) {
- $this->setContinueEnumParameter( 'continue', intval( $row->rev_id ) );
+ $this->setContinueEnumParameter( 'continue',
+ $row->rev_timestamp . '|' . intval( $row->rev_id ) );
} elseif ( $revCount > 0 ) {
$this->setContinueEnumParameter( 'continue', intval( $row->rev_id ) );
} else {
"YjM",
"Juandev",
"Aktron",
- "Cvanca"
+ "Cvanca",
+ "Utar"
]
},
"apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Dokumentace]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-mailová konference]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Oznámení k API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Chyby a požadavky]\n</div>\n<strong>Stav:</strong> Všechny funkce uvedené na této stránce by měly fungovat, ale API se stále aktivně vyvíjí a může se kdykoli změnit. Upozornění na změny získáte přihlášením se k [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-mailové konferenci mediawiki-api-announce].\n\n<strong>Chybné požadavky:</strong> Pokud jsou do API zaslány chybné požadavky, bude vrácena HTTP hlavička s klíčem „MediaWiki-API-Error“ a hodnota této hlavičky a chybový kód budou nastaveny na stejnou hodnotu. Více informací najdete [[mw:API:Errors_and_warnings|v dokumentaci]].",
"apihelp-help-example-help": "Nápověda k samotnému modulu nápovědy",
"apihelp-help-example-query": "Nápověda pro dva podmoduly query",
"apihelp-imagerotate-description": "Otočit jeden nebo více obrázků.",
+ "apihelp-imagerotate-example-generator": "Otočte všechny obrázky v <kbd>Category:Flip</kbd> o <kbd>180</kbd> stupňů.",
"apihelp-import-param-summary": "Import shrnutí.",
"apihelp-import-param-xml": "Nahraný XML soubor.",
"apihelp-import-param-rootpage": "Importovat jako podstránku k této stránce.",
"apihelp-import-param-interwikipage": "Für Interwiki-Importe: zu importierende Seite.",
"apihelp-import-param-fullhistory": "Für Interwiki-Importe: importiere die komplette Versionsgeschichte, nicht nur die aktuelle Version.",
"apihelp-import-param-templates": "Für Interwiki-Importe: importiere auch alle eingebundenen Vorlagen.",
- "apihelp-import-param-namespace": "Für Interwiki-Importe: importiere in diesen Namensraum.",
- "apihelp-import-param-rootpage": "Als Unterseite dieser Seite importieren.",
+ "apihelp-import-param-namespace": "Importiere in diesen Namensraum. Überschreibt den Parameter <kbd>$1rootpage</kbd>.",
+ "apihelp-import-param-rootpage": "Als Unterseite dieser Seite importieren. Wird ignoriert, falls der Parameter <kbd>$1namespace</kbd> angegeben ist.",
"apihelp-import-example-import": "Importiere [[meta:Help:Parserfunctions]] mit der kompletten Versionsgeschichte in den Namensraum 100.",
"apihelp-login-description": "Anmelden und Authentifizierungs-Cookies beziehen.\n\nFalls das Anmelden erfolgreich war, werden die benötigten Cookies im Header der HTTP-Antwort des Servers übermittelt. Bei fehlgeschlagenen Anmeldeversuchen können weitere Versuche gedrosselt werden, um automatische Passwortermittlungsattacken zu verhinden.",
"apihelp-login-param-name": "Benutzername.",
"apihelp-import-param-interwikipage": "Para importacións interwiki: páxina a importar.",
"apihelp-import-param-fullhistory": "Para importacións interwiki: importar o historial completo, non só a versión actual.",
"apihelp-import-param-templates": "Para importacións interwiki: importar tódolos modelos incluídos.",
- "apihelp-import-param-namespace": "Para importacións interwiki: importar a este espazo de nomes.",
- "apihelp-import-param-rootpage": "Importar como subpáxina desta páxina.",
+ "apihelp-import-param-namespace": "Importar a este espazo de nomes. Ignora o parámetro <kbd>$1rootpage</kbd>.",
+ "apihelp-import-param-rootpage": "Importar como subpáxina desta páxina. Ignorado se se proporciona o parámetro <kbd>$1namespace</kbd>.",
"apihelp-import-example-import": "Importar [[meta:Help:Parserfunctions]] ó espazo de nomes 100 con todo o historial.",
"apihelp-login-description": "No caso dunha conexión correcta, as cookies necesarias incluiranse nas cabeceiras HTTP de resposta. No caso dunha conexión fallida, os intentos posteriores poden ser reducidos para limitar ataques automaticos de roubo de contrasinais.",
"apihelp-login-param-name": "Nome de usuario.",
"apihelp-query+allfileusages-param-to": "Título do ficheiro no que rematar de enumerar.",
"apihelp-query+allfileusages-param-prefix": "Buscar tódolos títulos de ficheiro que comezan con este valor.",
"apihelp-query+allfileusages-param-unique": "Mostrar só nomes de ficheiro distintos. Non pode usarse con $1prop=ids.\nCando se usa como xenerador, produce páxinas obxectivo no canto de páxinas fonte.",
- "apihelp-query+allfileusages-param-prop": "Que partes de información incluír:\n;ids:Engade o ID de páxina usada (non pode usarse con $1unique).\n;title:Engade o nome do ficheiro.",
+ "apihelp-query+allfileusages-param-prop": "Que partes de información incluír:\n;ids:Engade os IDs das páxinas usadas (non pode usarse con $1unique).\n;title:Engade o nome do ficheiro.",
"apihelp-query+allfileusages-param-limit": "Número total de obxectos a devolver.",
"apihelp-query+allfileusages-param-dir": "Dirección na cal listar.",
"apihelp-query+allfileusages-example-B": "Lista títulos de ficheiro, incluíndo os eliminados, cos IDs de páxina dos que proveñen, comezando en <kbd>B</kbd>.",
]
},
"apihelp-delete-description": "Rûpelekê jê bibe.",
- "apihelp-expandtemplates-param-title": "Sernavê rûpelê."
+ "apihelp-expandtemplates-param-title": "Sernavê rûpelê.",
+ "apihelp-tag-param-reason": "Sedemê bo guherandinê."
}
protected $mLBInfo = array();
protected $mDefaultBigSelects = null;
protected $mSchemaVars = false;
+ /** @var array */
+ protected $mSessionVars = array();
protected $preparedArgs;
}
}
+ $this->mSessionVars = $params['variables'];
+
/** Get the default table prefix*/
if ( $tablePrefix == 'get from global' ) {
$this->mTablePrefix = $wgDBprefix;
$p['password'] = isset( $p['password'] ) ? $p['password'] : false;
$p['dbname'] = isset( $p['dbname'] ) ? $p['dbname'] : false;
$p['flags'] = isset( $p['flags'] ) ? $p['flags'] : 0;
+ $p['variables'] = isset( $p['variables'] ) ? $p['variables'] : array();
$p['tablePrefix'] = isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global';
$p['schema'] = isset( $p['schema'] ) ? $p['schema'] : $defaultSchemas[$dbType];
$p['foreign'] = isset( $p['foreign'] ) ? $p['foreign'] : false;
if ( is_string( $wgSQLMode ) ) {
$set[] = 'sql_mode = ' . $this->addQuotes( $wgSQLMode );
}
+ // Set any custom settings defined by site config
+ // (e.g. https://dev.mysql.com/doc/refman/4.1/en/innodb-parameters.html)
+ foreach ( $this->mSessionVars as $var => $val ) {
+ // Escape strings but not numbers to avoid MySQL complaining
+ if ( !is_int( $val ) && !is_float( $val ) ) {
+ $val = $this->addQuotes( $val );
+ }
+ $set[] = $this->addIdentifierQuotes( $var ) . ' = ' . $val;
+ }
if ( $set ) {
// Use doQuery() to avoid opening implicit transactions (DBO_TRX)
return $obj->flattenArrayReal( $vals, $type, $noHtml );
}
- /**
- * Flatten an array, using the user language for any messages.
- *
- * @param array $vals Array of values
- * @param string $type Type of array (either lang, ul, ol).
- * lang = language assoc array with keys being the lang code
- * ul = unordered list, ol = ordered list
- * type can also come from the '_type' member of $vals.
- * @param bool $noHtml If to avoid returning anything resembling HTML.
- * (Ugly hack for backwards compatibility with old MediaWiki).
- * @param bool|IContextSource $context
- * @return string Single value (in wiki-syntax).
- */
- public static function flattenArray( $vals, $type = 'ul', $noHtml = false, $context = false ) {
- $obj = new FormatMetadata;
- if ( $context ) {
- $obj->setContext( $context );
- }
-
- return $obj->flattenArrayReal( $vals, $type, $noHtml );
- }
-
/**
* A function to collapse multivalued tags into a single value.
* This turns an array of (for example) authors into a bulleted list.
"pool-queuefull": "Die poel se wagtou is vol",
"pool-errorunknown": "Onbekende fout",
"pool-servererror": "Die \"pool counter\"-diens is nie beskikbaar nie ($1).",
+ "poolcounter-usage-error": "Gebruiksfout: $1",
"aboutsite": "Inligting oor {{SITENAME}}",
"aboutpage": "Project:Omtrent",
"copyright": "Inhoud is onderhewig aan $1, tensy anders vermeld",
"disclaimers": "Voorbehoud",
"disclaimerpage": "Project:Voorwaardes",
"edithelp": "Wysigingshulp",
+ "helppage-top-gethelp": "Hulp",
"mainpage": "Tuisblad",
"mainpage-description": "Tuisblad",
"policy-url": "Project:Beleid",
"readonly_lag": "Die databasis is outomaties gesluit terwyl die slaafdatabasisse met die meester gesinchroniseer word",
"internalerror": "Interne fout",
"internalerror_info": "Interne fout: $1",
+ "internalerror-fatal-exception": "Fatale fout van tipe \"$1\"",
"filecopyerror": "Kon nie lêer van \"$1\" na \"$2\" kopieer nie.",
"filerenameerror": "Kon nie lêernaam van \"$1\" na \"$2\" wysig nie.",
"filedeleteerror": "Kon nie lêer \"$1\" skrap nie.",
"directorycreateerror": "Kon nie gids \"$1\" skep nie.",
+ "directoryreadonlyerror": "Gids \"$1\" is lees-alleen.",
+ "directorynotreadableerror": "Gids \"$1\" is nie leesbaar nie.",
"filenotfound": "Kon nie lêer \"$1\" vind nie.",
"unexpected": "Onverwagte waarde: \"$1\"=\"$2\".",
"formerror": "Fout: kon vorm nie stuur nie",
"content-model-javascript": "JavaScript",
"content-model-css": "CSS",
"content-json-empty-object": "Leë objek",
+ "content-json-empty-array": "Leë reeks",
"duplicate-args-category": "Bladsye met dubbele sjabloonparameters",
"expensive-parserfunction-warning": "Waarskuwing: Die bladsy gebruik te veel duur ontlederfunksies.\n\nDaar is {{PLURAL:$1|$1 funksie|$1 funksies}}, terwyl die bladsy minder as $2 moet hê.",
"expensive-parserfunction-category": "Bladsye wat te veel duur ontlederfunkies gebruik",
"notextmatches": "Geen artikelteks resultate nie",
"prevn": "vorige {{PLURAL:$1|$1}}",
"nextn": "volgende {{PLURAL:$1|$1}}",
+ "prev-page": "vorige bladsy",
+ "next-page": "volgende bladsy",
"prevn-title": "Vorige {{PLURAL:$1|resultaat|$1 resultate}}",
"nextn-title": "Volgende {{PLURAL:$1|resultaat|$1 resultate}}",
"shown-title": "$1 {{PLURAL:$1|resultaat|resultate}} per bladsy",
"prefs-personal": "Gebruikersdata",
"prefs-rc": "Onlangse wysigings",
"prefs-watchlist": "Dophoulys",
+ "prefs-editwatchlist": "Wysig dophoulys",
"prefs-watchlist-days": "Aantal dae om in dophoulys te wys:",
"prefs-watchlist-days-max": "Maksimum $1 {{PLURAL:$1|dag|dae}}",
"prefs-watchlist-edits": "Aantal wysigings om in uitgebreide dophoulys te wys:",
"right-sendemail": "адпраўка электронных лістоў іншым удзельнікам",
"right-passwordreset": "прагляд электронных лістоў з ачысткай паролю",
"right-managechangetags": "ствараць і выдаляць [[Special:Tags|меткі]] з базы зьвестак",
+ "right-applychangetags": "дадаваць [[Special:Tags|меткі]] пры рэдагаваньні",
"newuserlogpage": "Журнал стварэньня рахункаў",
"newuserlogpagetext": "Гэта журнал стварэньня рахункаў удзельнікаў і ўдзельніц.",
"rightslog": "Журнал правоў удзельнікаў",
"log-name-pagelang": "Журнал зьменаў мовы",
"log-description-pagelang": "Гэта журнал зьменаў мовы старонак.",
"logentry-pagelang-pagelang": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} мову старонкі $3 з $4 на $5.",
- "default-skin-not-found": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code dir=\"ltr\">$wgDefaultSkin</code> як <code>$1</code> недаступная.\n\nВашае ўсталяваньне, падобна, уключае наступныя тэмы афармленьня. Глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя:Наладка тэмаў афармленьня] дзеля інфармацыі, як падключыць іх і абраць тэму па змоўчаньні.\n\n$2\n\n; Калі вы толькі што ўсталявалі MediaWiki:\n: Напэўна вы ўсталявалі з git або наўпрост з крынічнага коду з ужываньнем іншага мэтаду. Гэта чакана. Паспрабуйце ўсталяваць некалькі тэмаў афармленьня з [https://www.mediawiki.org/wiki/Category:All_skins каталёгу тэмаў mediawiki.org]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code>skins/</code> зь яго.\n:* Спампуйце tarball-усталёўнікі для асобных тэмаў з [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Зрабіце клон аднаго з сховішчаў <code>mediawiki/skins/*</code> праз git у каталёг <code dir=\"ltr\">skins/</code> вашай усталёўкі MediaWiki.\n: Калі вы распрацоўнік MediaWiki, гэта не павінна ўплываць на вашае git-сховішча.\n\n; Калі вы толькі што абнавілі MediaWiki:\n: MediaWiki вэрсіі 1.24 і навейшыя больш не падключаюць тэмы афармленьня аўтаматычна (глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Інструкцыя:Аўтаматычнае выяўленьне тэмаў афармленьня]). Вы можаце дадаць наступныя радкі ў <code>LocalSettings.php</code>, каб падключыць усе ўсталяваныя тэмы афармленьня:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Калі вы толькі што зьмянілі <code>LocalSettings.php</code>:\n: Пераправерце назвы тэмаў афармленьня на наяўнасьць памылак.",
+ "default-skin-not-found": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code dir=\"ltr\">$wgDefaultSkin</code> як <code>$1</code> недаступная.\n\nВашае ўсталяваньне, падобна, уключае {{PLURAL:$4|наступную тэму афармленьне|наступныя тэмы афармленьня}}. Глядзіце старонку [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя:Наладка тэмаў афармленьня] дзеля інфармацыі, як падключыць {{PLURAL:$4|яе|іх і абраць тэму па змоўчаньні}}.\n\n$2\n\n; Калі вы толькі што ўсталявалі MediaWiki:\n: Напэўна вы ўсталявалі з git або наўпрост з крынічнага коду з ужываньнем іншага мэтаду. Гэта чакана. Паспрабуйце ўсталяваць некалькі тэмаў афармленьня з [https://www.mediawiki.org/wiki/Category:All_skins каталёгу тэмаў mediawiki.org]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code>skins/</code> зь яго.\n:* Спампуйце tarball-усталёўнікі для асобных тэмаў з [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Зрабіце клон аднаго з сховішчаў <code>mediawiki/skins/*</code> праз git у каталёг <code dir=\"ltr\">skins/</code> вашай усталёўкі MediaWiki.\n: Калі вы распрацоўнік MediaWiki, гэта не павінна ўплываць на вашае git-сховішча.\n\n; Калі вы толькі што абнавілі MediaWiki:\n: MediaWiki вэрсіі 1.24 і навейшыя больш не падключаюць тэмы афармленьня аўтаматычна (глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Інструкцыя:Аўтаматычнае выяўленьне тэмаў афармленьня]). Вы можаце дадаць {{PLURAL:$5|наступны радок у|наступныя радкі ў}} <code>LocalSettings.php</code>, каб падключыць {{PLURAL:$5|усталяваную тэму|усе ўсталяваныя тэмы}} афармленьня:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Калі вы толькі што зьмянілі <code>LocalSettings.php</code>:\n: Пераправерце назвы тэмаў афармленьня на наяўнасьць памылак.",
"default-skin-not-found-no-skins": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code>$wgDefaultSkin</code> як <code>$1</code>, недаступная.\n\nВы ня маеце ўсталяваных тэмаў афармленьня.\n\n; Калі вы толькі што ўсталявалі або абнавілі MediaWiki:\n: Напэўна вы ўсталявалі з git або наўпрост з крынічнага коду з ужываньнем іншага мэтаду. Гэта чакана. MediaWiki вэрсіі 1.24 і навейшыя ня ўтрымліваюць тэмы афармленьня ў галоўным сховішчы. Паспрабуйце ўсталяваць некалькі тэмаў афармленьня з [https://www.mediawiki.org/wiki/Category:All_skins каталёгу тэмаў mediawiki.org]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code dir=\"ltr\">skins/</code> зь яго.\n:* Спампуйце tarball-усталёўнікі для асобны тэмаў афармленьня з [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Зрабіце клон аднаго з сховішчаў <code>mediawiki/skins/*</code> праз git у каталёг <code>skins/</code> вашай усталёўкі MediaWiki.\n: Калі вы распрацоўнік MediaWiki, гэта не павінна ўплываць на вашае git-сховішча. Глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя:Наладка тэмаў афармленьня] дзеля інфармацыі, як падключыць іх і абраць тэму па змоўчаньні.",
"default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (уключана)",
"default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''адключана''')",
"version-license-not-found": "এই এক্সটেনশনের জন্য কোনো বিস্তারিত লাইসেন্স তথ্য পাওয়া যায়নি।",
"version-credits-title": "$1-এর জন্য কৃতিত্ব",
"version-credits-not-found": "এই এক্সটেনশনটির জন্য কোনো বিস্তারিত কৃতিত্ব তথ্য পাওয়া যায়নি।",
- "version-poweredby-credits": "এইক উইকিটি পরিচালিত হচ্ছে '''[https://www.mediawiki.org/ মিডিয়াউইকি]'''-এর মাধ্যমে, কপিরাইট © ২০০১-$1 $2।",
+ "version-poweredby-credits": "এই উইকিটি পরিচালিত হচ্ছে <strong>[https://www.mediawiki.org/ মিডিয়াউইকি]</strong> -এর মাধ্যমে, কপিরাইট © ২০০১-$1 $2।",
"version-poweredby-others": "অন্যান্য",
"version-poweredby-translators": "translatewiki.net অনুবাদকগণ",
"version-credits-summary": "[[Special:Version|মিডিয়াউইকি]] সফটওয়্যারে অবদানের জন্য আমরা এই ব্যক্তিকে স্বীকৃতি দিতে চাই।",
- "version-license-info": "মিডিয়াউইকি এ++++কটি ফ্রি সফটওয়্যার, আপনি এটি বিতরণ করতে পারবেন এবং/অথবা সম্পদানা করতে পারবেন, এক্ষেত্রে ফ্রি সফটওয়্যার ফাউন্ডেশনের প্রকাশিত গনু জেনারেল পাবলিক লাইসেন্সের ২য় অথবা সাম্প্রতিকতম কোনো সংস্করণ মেনে চলতে হবে। \n\nসকলের উপকারের লক্ষ্যে এটি বিতরণ করা হয়ে থাকে, কিন্তু এক্ষেত্রে কোনো ওয়ারেন্টি দেয়া হয় না, এমনকি বিশেষ কোনো কার্যক্ষেত্রে ব্যবহারের জন্যও তথাকথিত ওয়ারেন্টি দেয়া হয় না। বিস্তারিত জানতে দেখুন গনু জেনারেল পাবলিক লাইসেন্স। \n\nএই সফটওয়্যারের সাথে [{{SERVER}}{{SCRIPTPATH}}/COPYING গনু জেনারেল পাবলিক লাইসেন্সের একটি কপি] থাকার কথা; যদি আপনি না পেয়ে থাকেন তাহলে অনুগ্রহ করে ফ্রি সফটওয়্যার ফাউন্ডেশনকে জানান এই ঠিকানায়, Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA অথবা [//www.gnu.org/licenses/old-licenses/gpl-2.0.html অনলাইনে দেখুন]।",
+ "version-license-info": "মিডিয়াউইকি একটি ফ্রি সফটওয়্যার, আপনি এটি বিতরণ করতে পারবেন এবং/অথবা সম্পদানা করতে পারবেন, এক্ষেত্রে ফ্রি সফটওয়্যার ফাউন্ডেশনের প্রকাশিত গনু জেনারেল পাবলিক লাইসেন্সের ২য় অথবা সাম্প্রতিকতম কোনো সংস্করণ মেনে চলতে হবে। \n\nসকলের উপকারের লক্ষ্যে এটি বিতরণ করা হয়ে থাকে, কিন্তু এক্ষেত্রে কোনো ওয়ারেন্টি দেয়া হয় না, এমনকি বিশেষ কোনো কার্যক্ষেত্রে ব্যবহারের জন্যও তথাকথিত ওয়ারেন্টি দেয়া হয় না। বিস্তারিত জানতে দেখুন গনু জেনারেল পাবলিক লাইসেন্স। \n\nএই সফটওয়্যারের সাথে [{{SERVER}}{{SCRIPTPATH}}/COPYING গনু জেনারেল পাবলিক লাইসেন্সের একটি কপি] থাকার কথা; যদি আপনি না পেয়ে থাকেন তাহলে অনুগ্রহ করে ফ্রি সফটওয়্যার ফাউন্ডেশনকে জানান এই ঠিকানায়, Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA অথবা [//www.gnu.org/licenses/old-licenses/gpl-2.0.html অনলাইনে দেখুন]।",
"version-software": "ইনস্টলকৃত সফটওয়্যার",
"version-software-product": "পণ্য",
"version-software-version": "সংস্করণ",
"rcshowhideliu": "сайта кĕнисене $1",
"rcshowhideliu-show": "кăтартмалла",
"rcshowhideliu-hide": "кăтартмалла мар",
- "rcshowhideanons": "ячĕсене палăртманскерсене $1",
+ "rcshowhideanons": "Паллă маррисене $1",
"rcshowhideanons-show": "кăтартмалла",
"rcshowhideanons-hide": "кăтартмалла мар",
"rcshowhidepatr": "тĕрĕсленĕ тӳрлетӳсене $1",
"rcshowhidepatr-hide": "кăтартмалла мар",
"rcshowhidemine": "хăвăн тӳрлетнисене $1",
"rcshowhidemine-show": "кăтартмалла",
- "rcshowhidemine-hide": "кăтармалла мар",
+ "rcshowhidemine-hide": "кăтартмалла мар",
"rclinks": "Юлашки $2 кун хушшинче тунă $1 улшăнусене кăтартмалла<br />$3",
"diff": "танл.",
"hist": "ист",
"import-interwiki-history": "Kopioi sivun koko historia ja kaikki versiot",
"import-interwiki-templates": "Ota mukaan kaikki mallineet",
"import-interwiki-submit": "Tuo",
+ "import-mapping-default": "Tuonti vakiokohteisiin",
+ "import-mapping-namespace": "Tuonti nimiavaruuteen:",
+ "import-mapping-subpage": "Tuonti seuraavan sivun alasivuiksi:",
"import-upload-filename": "Tiedostonimi:",
"import-comment": "Kommentti:",
"importtext": "Vie sivuja lähdewikistä käyttäen [[Special:Export|vientityökalua]].\nTallenna tiedot koneellesi ja tuo ne tällä sivulla.",
"import-interwiki-history": "Copiar todas as versións que hai no historial desta páxina",
"import-interwiki-templates": "Incluír todos os modelos",
"import-interwiki-submit": "Importar",
+ "import-mapping-default": "Importar aos lugares predeterminados",
+ "import-mapping-namespace": "Importar a un espazo de nomes:",
+ "import-mapping-subpage": "Importar como subpáxinas da seguinte páxina:",
"import-upload-filename": "Nome do ficheiro:",
"import-comment": "Comentario:",
"importtext": "Por favor, exporte o ficheiro do wiki de orixe usando a [[Special:Export|ferramenta de exportación]].\nGárdeo no seu disco duro e cárgueo aquí.",
"tags-source-manual": "Aplicado manualmente por usuarios e bots",
"tags-source-none": "Xa non está en uso",
"tags-edit": "editar",
- "tags-delete": "Borrar",
+ "tags-delete": "borrar",
"tags-activate": "activar",
- "tags-deactivate": "Reactivar",
+ "tags-deactivate": "desactivar",
"tags-hitcount": "$1 {{PLURAL:$1|modificación|modificacións}}",
"tags-manage-no-permission": "Non ten os permisos necesarios para modificar etiquetas.",
"tags-create-heading": "Crear unha nova etiqueta",
"tags-create-explanation": "Por defecto, as etiquetas creadas recentemente poderán ser empregadas polos usuarios e os bots.",
- "tags-create-tag-name": "Nome da páxina:",
+ "tags-create-tag-name": "Nome da etiqueta:",
"tags-create-reason": "Motivo:",
"tags-create-submit": "Crear",
"tags-create-no-name": "Debe especificar unha páxina.",
"tags-create-already-exists": "A páxina \"$1\" xa existe.",
"tags-create-warnings-above": "{{PLURAL:$2|Atopouse o seguinte erro|Atopáronse os seguintes erros}} ao intentar crear a etiqueta \"$1\":",
"tags-create-warnings-below": "Desexa continuar creando a etiqueta?",
- "tags-delete-title": "Borrar etiqueta",
+ "tags-delete-title": "Borrar unha etiqueta",
"tags-delete-explanation-initial": "Está a piques de borrar a etiqueta \"$1\" da base de datos.",
"tags-delete-explanation-in-use": "Ha eliminarse {{PLURAL:$2|dunha revisión ou entrada|das $2 revisións e/ou entradas}} de rexistro {{PLURAL:$2|á|ás}} que actualmente se aplica.",
"tags-delete-explanation-warning": "Esta acción é <strong>irreversible</strong> e nin sequera os administradores da base de datos poderán desfacela. Asegúrese de que é esta a etiqueta que desexa borrar.",
"tags-delete-not-found": "A páxina \"$1\" non existe.",
"tags-delete-too-many-uses": "A etiqueta \"$1\" aplícase a máis de $2 {{PLURAL:$2|revisión|revisións}}; isto significa que non se pode borrar.",
"tags-delete-warnings-after-delete": "A etiqueta \"$1\" borrouse correctamente; con todo, {{PLURAL:$2|atopouse o seguinte erro|atopáronse os seguintes erros}}:",
- "tags-activate-title": "Activar etiqueta",
+ "tags-activate-title": "Activar unha etiqueta",
"tags-activate-question": "Está a piques de activar a etiqueta\"$1\".",
"tags-activate-reason": "Motivo:",
"tags-activate-not-allowed": "Non é posible activar a páxina \"$1\".",
"tags-activate-not-found": "A páxina \"$1\" non existe.",
"tags-activate-submit": "Activar",
- "tags-deactivate-title": "Desactivar etiqueta",
+ "tags-deactivate-title": "Desactivar unha etiqueta",
"tags-deactivate-question": "Está a piques de desactivar a etiqueta \"$1\".",
"tags-deactivate-reason": "Motivo:",
"tags-deactivate-not-allowed": "Non é posible reactivar a páxina \"$1\".",
- "tags-deactivate-submit": "Reactivar",
+ "tags-deactivate-submit": "Desactivar",
"tags-apply-no-permission": "Non ten permisos para aplicar etiquetas de cambios xunto cos seus tus cambios.",
"tags-apply-not-allowed-one": "A etiqueta \"$1\" non se puede aplicar manualmente.",
"tags-apply-not-allowed-multi": "{{PLURAL:$2|A seguinte etiqueta non se pode|As seguintes etiquetas non se poden}} aplicar manualmente: $1",
"rcshowhidebots": "Bot'an $1",
"rcshowhidebots-show": "nîşan bide",
"rcshowhidebots-hide": "veşêre",
- "rcshowhideliu": "Bikarhênerên tomarkirî $1",
+ "rcshowhideliu": "$1 bikarhênerên tomarkirî",
"rcshowhideliu-show": "nîşan bide",
"rcshowhideliu-hide": "veşêre",
"rcshowhideanons": "Bikarhênerên netomarkirî (IP) $1",
"file-info-size": "$1 × $2 pixel, mezinbûnê data: $3, MIME-typ: $4",
"file-nohires": "Versyonekî jê mezintir tune.",
"svg-long-desc": "Daneya SVG, mezinbûna rast: $1 × $2 pixel; mezinbûna daneyê: $3",
- "show-big-image": "Mezînbûn",
+ "show-big-image": "Dosyeya orjînal",
"newimages": "Pêşangeha wêneyên nû",
"imagelisttext": "Jêr lîsteyek ji $1 file'an heye, duxrekirin $2.",
"newimages-summary": "Ev rûpela taybet dosyeyên ku herî dawî hatine barkirin, nîşan dide.",
"tog-hideminor": "Celare recensiones minores in indice nuper mutatorum",
"tog-hidepatrolled": "Redactiones censae inter nuper mutatas celandae",
"tog-newpageshidepatrolled": "Paginae censae inter nouissime creatas celandae",
- "tog-extendwatchlist": "Indicem paginarum obseruandarum cunctas mutatas praeter nouissimas includere decet",
+ "tog-extendwatchlist": "Extendere indicem paginarum observatarum ut omnes emendationes monstrentur, non solum emendationes recentissimae",
"tog-usenewrc": "Indice nuper mutatarum excelsa uti",
"tog-numberheadings": "Subtituli numeris adornandi",
"tog-showtoolbar": "Affigere trabem redigentem",
"import": "Paginas importare",
"importinterwiki": "Adportatio transvici",
"import-interwiki-submit": "Importare",
- "import-interwiki-namespace": "Spatium nominale destinatum:",
"import-upload-filename": "Nomen fasciculi:",
"import-comment": "Sententia:",
"importstart": "Adportare paginas...",
"redirect-text": "Inside fieldset for [[Special:Redirect]]",
"redirect-summary": "Shown at top of [[Special:Redirect]]",
"redirect-submit": "Button label in [[Special:Redirect]].\n{{Identical|Go}}",
- "redirect-lookup": "First field label in [[Special:Redirect]].\n\nFollowed by the select box which has the following options:\n* {{msg-mw|Redirect-user}}\n* {{msg-mw|Redirect-page}}\n* {{msg-mw|Redirect-revision}}\n* {{msg-mw|Redirect-file}}",
+ "redirect-lookup": "First field label in [[Special:Redirect]].\n\nFollowed by the select box which has the following options:\n* {{msg-mw|Redirect-user}}\n* {{msg-mw|Redirect-page}}\n* {{msg-mw|Redirect-revision}}\n* {{msg-mw|Redirect-file}}\n{{Identical|Lookup}}",
"redirect-value": "Second field label in [[Special:Redirect]]\n{{Identical|Value}}",
"redirect-user": "Description of lookup type for [[Special:Redirect]].\n{{Identical|User ID}}",
"redirect-page": "Description of lookup type for [[Special:Redirect]].\n{{Identical|Page ID}}",
"pageinfo-protect-cascading-yes": "Да",
"pageinfo-protect-cascading-from": "Каскадная защита от",
"pageinfo-category-info": "Информация о категории",
+ "pageinfo-category-total": "Общее число членов",
"pageinfo-category-pages": "Количество страниц",
"pageinfo-category-subcats": "Количество подкатегорий",
"pageinfo-category-files": "Количество файлов",
"cannotchangeemail": "本wiki不允许对账户的电子邮件地址进行更改。",
"emaildisabled": "该网站无法发送电子邮件。",
"accountcreated": "已建立账户",
- "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]])的账户已创建。",
+ "accountcreatedtext": "[[{{ns:User}}:$1|$1]]([[{{ns:User talk}}:$1|对话]])的账户已创建。",
"createaccount-title": "在{{SITENAME}}创建新账户",
"createaccount-text": "有人在{{SITENAME}}中利用您的邮箱创建了一个名为 \"$2\" 的新帐户($4),密码是 \"$3\" 。您应该立即登录并更改密码。\n\n如果该账户创建错误的话,您可以忽略此信息。",
"login-throttled": "你最近尝试登录的次数过多。请等待$1后再试。",
'File with invalid date metadata (bug 29471)' );
}
- /**
- * @param string $filename
- * @param int $expected Total image area
- * @dataProvider provideFlattenArray
- * @covers FormatMetadata::flattenArray
- */
- public function testFlattenArray( $vals, $type, $noHtml, $ctx, $expected ) {
- $actual = FormatMetadata::flattenArray( $vals, $type, $noHtml, $ctx );
- $this->assertEquals( $expected, $actual );
- }
-
- public static function provideFlattenArray() {
- return array(
- array(
- array( 1, 2, 3 ), 'ul', false, false,
- "<ul><li>1</li>\n<li>2</li>\n<li>3</li></ul>",
- ),
- array(
- array( 1, 2, 3 ), 'ol', false, false,
- "<ol><li>1</li>\n<li>2</li>\n<li>3</li></ol>",
- ),
- array(
- array( 1, 2, 3 ), 'ul', true, false,
- "\n*1\n*2\n*3",
- ),
- array(
- array( 1, 2, 3 ), 'ol', true, false,
- "\n#1\n#2\n#3",
- ),
- // TODO: more test cases
- );
- }
-
/**
* @param mixed $input
* @param mixed $output
mwTester = new CompletenessTest( mw, mwTestIgnore );
}
- /**
- * Test environment recommended for all QUnit test modules
- *
- * Whether to log environment changes to the console
- */
- QUnit.config.urlConfig.push( 'mwlogenv' );
-
/**
* Reset mw.config and others to a fresh copy of the live config for each test(),
* and restore it back to the live one afterwards.
* </code>
*/
QUnit.newMwEnvironment = ( function () {
- var warn, error, log, liveConfig, liveMessages,
+ var warn, error, liveConfig, liveMessages,
ajaxRequests = [];
liveConfig = mw.config.values;
ajaxRequests.push( { xhr: jqXHR, options: ajaxOptions } );
}
- log = QUnit.urlParams.mwlogenv ? mw.log : function () {};
-
return function ( localEnv ) {
localEnv = $.extend( {
// QUnit
return {
setup: function () {
- log( 'MwEnvironment> SETUP for "' + QUnit.config.current.module
- + ': ' + QUnit.config.current.testName + '"' );
// Greetings, mock environment!
mw.config.values = freshConfigCopy( localEnv.config );
teardown: function () {
var timers, active;
- log( 'MwEnvironment> TEARDOWN for "' + QUnit.config.current.module
- + ': ' + QUnit.config.current.testName + '"' );
localEnv.teardown.call( this );