Josh Cogliati wrote:
Timwi, Thanks for the version of the patch. I have
some questions though.
On Thu, Jul 08, 2004 at 12:07:08PM +0100, Timwi wrote:
* Change
it to a special page?
No, please not!... I don't like special pages because they make the tabs
disappear. :) I'd really rather prefer if Special:Movepage were
converted to a simple &action=move thingie.
Tim Starling made the argument that
special pages were easier to link to and did not involve adding more
UI stuff to Article.php.
In my mind, it makes sense to be able to link to pages that pertain to
the wiki as a whole (e.g. Special:Recentchanges) or to a user (e.g.
Special:Contributions), but I don't see the benefit in being able to
link to Special:Movepage. (Admittedly, there is an obvious benefit in
being able to link to the info page for an article... but quite frankly,
I think if we really need that so badly, we should come up with a new
syntax for it so that we can also link to edit, history, etc.
Suggestion: [[::history:Article title]]
Would it be quicker to turn this into two query? Where
the second query is
something like:
+ $sql = "SELECT COUNT(DISTINCT old_user_text) FROM old WH
ERE ".$old_clause . " AND old_user_text != " . $cur_author;
Ingenious! Brilliant! Thanks!
I've also made it so that the <title> now shows "Article title -
Information - Site name" as opposed to just "Article title - Site name",
so it is consistent with History.
While I was at it, I noticed missing or wrong <title>s when protect or
unprotect a page. I've fixed those too.
I'm attaching the entire patch again. I think it's committable like
this, although someone should still add an "info" tab to the skin or
else the info page is unreachable except by manually fiddling with the URL.
Timwi
? config/LocalSettings.php
? images/9
? images/archive
? math/html.cmi
? math/html.cmx
? math/lexer.cmi
? math/lexer.cmx
? math/mathml.cmi
? math/mathml.cmx
? math/parser.cmi
? math/parser.cmx
? math/parser.mli
? math/render.cmi
? math/render.cmx
? math/render_info.cmi
? math/tex.cmi
? math/texutil.cmi
? math/texutil.cmx
? math/texvc
? math/texvc.cmi
? math/texvc.cmx
? math/texvc_test
? math/texvc_test.cmi
? math/texvc_test.cmx
? math/texvc_tex
? math/texvc_tex.cmi
? math/texvc_tex.cmx
? math/util.cmi
? math/util.cmx
Index: index.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/index.php,v
retrieving revision 1.35
diff -u -r1.35 index.php
--- index.php 28 Jun 2004 17:46:49 -0000 1.35
+++ index.php 8 Jul 2004 14:33:17 -0000
@@ -108,6 +108,7 @@
case "rollback":
case "protect":
case "unprotect":
+ case "info":
$wgArticle->$action();
break;
case "print":
Index: includes/Article.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/includes/Article.php,v
retrieving revision 1.175
diff -u -r1.175 Article.php
--- includes/Article.php 28 Jun 2004 20:24:23 -0000 1.175
+++ includes/Article.php 8 Jul 2004 14:33:17 -0000
@@ -16,12 +16,12 @@
/* private */ var $mMinorEdit, $mRedirectedFrom;
/* private */ var $mTouched, $mFileCache, $mTitle;
/* private */ var $mId, $mTable;
-
+
function Article( &$title ) {
$this->mTitle =& $title;
$this->clear();
}
-
+
/* private */ function clear()
{
$this->mContentLoaded = false;
@@ -62,7 +62,7 @@
}
return $text;
}
-
+
/* static */ function compressRevisionText( &$text ) {
global $wgCompressRevisions;
if( !$wgCompressRevisions ) {
@@ -75,7 +75,7 @@
$text = gzdeflate( $text );
return 'gzip';
}
-
+
# Returns the text associated with a "link" type old table row
/* static */ function followLink( $link ) {
# Split the link into fields and values
@@ -119,7 +119,7 @@
global $wgLoadBalancer;
$fname = 'fetchFromLocation';
wfProfileIn( $fname );
-
+
$p = strpos( $location, ':' );
if ( $p === false ) {
wfProfileOut( $fname );
@@ -132,7 +132,7 @@
case 'mysql':
# MySQL locations are specified by
mysql://<machineID>/<dbname>/<tblname>/<index>
# Machine ID 0 is the current connection
- if ( preg_match(
'/^mysql:\/\/(\d+)\/([A-Za-z_]+)\/([A-Za-z_]+)\/([A-Za-z_]+)$/',
+ if ( preg_match(
'/^mysql:\/\/(\d+)\/([A-Za-z_]+)\/([A-Za-z_]+)\/([A-Za-z_]+)$/',
$location, $matches ) ) {
$machineID = $matches[1];
$dbName = $matches[2];
@@ -144,11 +144,11 @@
} else {
# Alternate connection
$db =& $wgLoadBalancer->getConnection( $machineID );
-
+
if ( array_key_exists( $machineId, $wgKnownMysqlServers ) ) {
# Try to open, return false on failure
$params = $wgKnownDBServers[$machineId];
- $db = Database::newFromParams( $params['server'], $params['user'],
$params['password'],
+ $db = Database::newFromParams( $params['server'], $params['user'],
$params['password'],
$dbName, 1, false, true, true );
}
}
@@ -244,15 +244,15 @@
}
}
}
-
+
# This function returns the text of a section, specified by a number ($section).
- # A section is text under a heading like == Heading == or <h1>Heading</h1>,
or
+ # A section is text under a heading like == Heading == or <h1>Heading</h1>,
or
# the first section before any such heading (section 0).
#
# If a section contains subsections, these are also returned.
#
function getSection($text,$section) {
-
+
# strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
# comments to be stripped as well)
$striparray=array();
@@ -273,23 +273,23 @@
$headline=$secs[$section*2-1];
preg_match( '/^(=+).*?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?'
. '>/mi',$headline,$matches);
$hlevel=$matches[1];
-
+
# translate wiki heading into level
if(strpos($hlevel,'=')!==false) {
- $hlevel=strlen($hlevel);
+ $hlevel=strlen($hlevel);
}
-
+
$rv=$headline. $secs[$section*2];
$count=$section+1;
-
+
$break=false;
while(!empty($secs[$count*2-1]) && !$break) {
-
+
$subheadline=$secs[$count*2-1];
preg_match( '/^(=+).*?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?'
. '>/mi',$subheadline,$matches);
$subhlevel=$matches[1];
if(strpos($subhlevel,'=')!==false) {
- $subhlevel=strlen($subhlevel);
+ $subhlevel=strlen($subhlevel);
}
if($subhlevel > $hlevel) {
$rv.=$subheadline.$secs[$count*2];
@@ -298,7 +298,7 @@
$break=true;
}
$count++;
-
+
}
}
# reinsert stripped tags
@@ -308,7 +308,7 @@
return $rv;
}
-
+
# Load the revision (including cur_text) into this object
function loadContent( $noredir = false )
@@ -321,21 +321,21 @@
if ( $this->mContentLoaded ) return;
$fname = 'Article::loadContent';
-
- # Pre-fill content with error message so that if something
+
+ # Pre-fill content with error message so that if something
# fails we'll have something telling us what we intended.
- $t = $this->mTitle->getPrefixedText();
- if ( isset( $oldid ) ) {
- $oldid = IntVal( $oldid );
+ $t = $this->mTitle->getPrefixedText();
+ if ( isset( $oldid ) ) {
+ $oldid = IntVal( $oldid );
$t .= ",oldid={$oldid}";
- }
- if ( isset( $redirect ) ) {
- $redirect = ($redirect == 'no') ? 'no' : 'yes';
- $t .= ",redirect={$redirect}";
- }
+ }
+ if ( isset( $redirect ) ) {
+ $redirect = ($redirect == 'no') ? 'no' : 'yes';
+ $t .= ",redirect={$redirect}";
+ }
$this->mContent = wfMsg( 'missingarticle', $t );
-
+
if ( ! $oldid ) { # Retrieve current version
$id = $this->getID();
if ( 0 == $id ) return;
@@ -345,8 +345,8 @@
"FROM cur WHERE cur_id={$id}";
wfDebug( "$sql\n" );
$res = wfQuery( $sql, DB_READ, $fname );
- if ( 0 == wfNumRows( $res ) ) {
- return;
+ if ( 0 == wfNumRows( $res ) ) {
+ return;
}
$s = wfFetchObject( $res );
@@ -361,7 +361,7 @@
# Gotta hand redirects to special pages differently:
# Fill the HTTP response "Location" header and ignore
# the rest of the page we're on.
-
+
if ( $rt->getInterwiki() != '' ) {
$wgOut->redirect( $rt->getFullURL() ) ;
return;
@@ -375,7 +375,7 @@
$sql = 'SELECT cur_text,cur_timestamp,cur_user,cur_user_text,cur_comment,'
.
"cur_counter,cur_restrictions,cur_touched FROM cur WHERE
cur_id={$rid}";
$res = wfQuery( $sql, DB_READ, $fname );
-
+
if ( 0 != wfNumRows( $res ) ) {
$this->mRedirectedFrom = $this->mTitle->getPrefixedText();
$this->mTitle = $rt;
@@ -434,9 +434,9 @@
return $this->mContent;
}
$this->mContent = false;
-
+
$fname = 'Article::loadContent';
-
+
if ( ! $oldid ) { # Retrieve current version
$id = $this->getID();
if ( 0 == $id ) {
@@ -447,8 +447,8 @@
'cur_text,cur_timestamp,cur_user,cur_counter,cur_restrictions,cur_touched '
.
"FROM cur WHERE cur_id={$id}";
$res = wfQuery( $sql, DB_READ, $fname );
- if ( 0 == wfNumRows( $res ) ) {
- return false;
+ if ( 0 == wfNumRows( $res ) ) {
+ return false;
}
$s = wfFetchObject( $res );
@@ -464,7 +464,7 @@
$sql = 'SELECT cur_text,cur_timestamp,cur_user,' .
"cur_counter,cur_restrictions,cur_touched FROM cur WHERE
cur_id={$rid}";
$res = wfQuery( $sql, DB_READ, $fname );
-
+
if ( 0 != wfNumRows( $res ) ) {
$this->mRedirectedFrom = $this->mTitle->getPrefixedText();
$this->mTitle = $rt;
@@ -488,8 +488,8 @@
$sql = "SELECT old_text,old_timestamp,old_user,old_flags FROM $oldtable " .
"WHERE old_id={$oldid}";
$res = wfQuery( $sql, DB_READ, $fname );
- if ( 0 == wfNumRows( $res ) ) {
- return false;
+ if ( 0 == wfNumRows( $res ) ) {
+ return false;
}
$s = wfFetchObject( $res );
@@ -526,7 +526,7 @@
function isCountable( $text )
{
global $wgUseCommaCount, $wgMwRedir;
-
+
if ( 0 != $this->mTitle->getNamespace() ) { return 0; }
if ( $wgMwRedir->matchStart( $text ) ) { return 0; }
$token = ($wgUseCommaCount ? ',' : '[[' );
@@ -592,7 +592,7 @@
$fname = 'Article::getContributors';
# XXX: this is expensive; cache this info somewhere.
-
+
$title = $this->mTitle;
$contribs = array();
@@ -602,8 +602,8 @@
' FROM old LEFT JOIN user ON old.old_user = user.user_id '
.
' WHERE old.old_namespace = ' . $title->getNamespace() .
' AND old.old_title = "' . $title->getDBkey() .
'"' .
- ' AND old.old_user != ' . $this->getUser() .
- ' GROUP BY old.old_user ' .
+ ' AND old.old_user != ' . $this->getUser() .
+ ' GROUP BY old.old_user ' .
' ORDER BY timestamp DESC ';
if ($limit > 0) {
@@ -611,16 +611,16 @@
}
$res = wfQuery($sql, DB_READ, $fname);
-
+
while ( $line = wfFetchObject( $res ) ) {
$contribs[] = array($line->old_user, $line->old_user_text,
$line->user_real_name);
}
-
+
wfFreeResult($res);
-
+
return $contribs;
}
-
+
# This is the default action of the script: just view the page of
# the given title.
@@ -628,7 +628,7 @@
{
global $wgUser, $wgOut, $wgLang, $wgRequest;
global $wgLinkCache, $IP, $wgEnableParserCache;
-
+
$fname = 'Article::view';
wfProfileIn( $fname );
@@ -660,14 +660,14 @@
return;
}
}
-
+
# Should the parser cache be used?
if ( $wgEnableParserCache && intval($wgUser->getOption(
'stubthreshold' )) == 0 && empty( $oldid ) ) {
$pcache = true;
} else {
$pcache = false;
}
-
+
$outputDone = false;
if ( $pcache ) {
if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
@@ -677,14 +677,14 @@
if ( !$outputDone ) {
$text = $this->getContent( false ); # May change mTitle by following a redirect
-
+
# Another whitelist check in case oldid or redirects are altering the title
if ( !$this->mTitle->userCanRead() ) {
$wgOut->loginToUse();
$wgOut->output();
exit;
}
-
+
# We're looking at an old revision
@@ -698,8 +698,8 @@
'redirect=no' );
$s = wfMsg( 'redirectedfrom', $redir );
$wgOut->setSubtitle( $s );
-
- # Can't cache redirects
+
+ # Can't cache redirects
$pcache = false;
}
@@ -707,8 +707,8 @@
# wrap user css and user js in pre and don't parse
# XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is
found
- if (
- $this->mTitle->getNamespace() == Namespace::getUser() &&
+ if (
+ $this->mTitle->getNamespace() == Namespace::getUser() &&
preg_match('/\\/[\\w]+\\.(css|js)$/', $this->mTitle->getDBkey())
) {
$wgOut->addWikiText( wfMsg('clearyourcache'));
@@ -720,7 +720,7 @@
}
}
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
-
+
# Add link titles as META keywords
$wgOut->addMetaTags() ;
@@ -737,7 +737,7 @@
{
global $wgOut, $wgUser, $wgLinkCache, $wgMwRedir;
global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer, $wgIsPg, $wgIsMySQL;
-
+
$fname = 'Article::insertNewArticle';
$this->mCountAdjustment = $this->isCountable( $text );
@@ -752,7 +752,7 @@
$won = wfInvertTimestamp( $now );
wfSeedRandom();
$rand = number_format( mt_rand() / mt_getrandmax(), 12, '.', '' );
-
+
if ($wgIsPg) {
$cur_id_column="cur_id,";
$cur_id=wfGetSQL(""," nextval('cur_cur_id_seq')");
@@ -780,20 +780,20 @@
Article::onArticleCreate( $this->mTitle );
RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary );
-
- if ($watchthis) {
- if(!$this->mTitle->userIsWatching()) $this->watch();
+
+ if ($watchthis) {
+ if(!$this->mTitle->userIsWatching()) $this->watch();
} else {
if ( $this->mTitle->userIsWatching() ) {
$this->unwatch();
}
}
-
+
# The talk page isn't in the regular link tables, so we need to update manually:
$talkns = $ns ^ 1; # talk -> normal; normal -> talk
$sql = "UPDATE cur set cur_touched='$now' WHERE cur_namespace=$talkns AND
cur_title='" . wfStrencode( $ttl ) . "'";
wfQuery( $sql, DB_WRITE );
-
+
# standard deferred updates
$this->editUpdates( $text );
@@ -804,7 +804,7 @@
/* Side effects: loads last edit */
function getTextOfLastEditWithSectionReplacedOrAdded($section, $text, $summary =
''){
$this->loadLastEdit();
- $oldtext = $this->getContent( true );
+ $oldtext = $this->getContent( true );
if ($section != '') {
if($section=='new') {
if($summary) $subject="== {$summary} ==\n\n";
@@ -825,10 +825,10 @@
$secs=preg_split('/(^=+.*?=+|^<h[1-6].*?' .
'>.*?<\/h[1-6].*?' . '>)/mi',
$oldtext,-1,PREG_SPLIT_DELIM_CAPTURE);
$secs[$section*2]=$text."\n\n"; // replace with edited
-
+
# section 0 is top (intro) section
- if($section!=0) {
-
+ if($section!=0) {
+
# headline of old section - we need to go through this section
# to determine if there are any subsections that now need to
# be erased, as the mother section has been replaced with
@@ -836,23 +836,23 @@
$headline=$secs[$section*2-1];
preg_match( '/^(=+).*?=+|^<h([1-6]).*?' .
'>.*?<\/h[1-6].*?' . '>/mi',$headline,$matches);
$hlevel=$matches[1];
-
+
# determine headline level for wikimarkup headings
if(strpos($hlevel,'=')!==false) {
- $hlevel=strlen($hlevel);
+ $hlevel=strlen($hlevel);
}
-
+
$secs[$section*2-1]=''; // erase old headline
$count=$section+1;
$break=false;
while(!empty($secs[$count*2-1]) && !$break) {
-
+
$subheadline=$secs[$count*2-1];
preg_match(
'/^(=+).*?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?' .
'>/mi',$subheadline,$matches);
$subhlevel=$matches[1];
if(strpos($subhlevel,'=')!==false) {
- $subhlevel=strlen($subhlevel);
+ $subhlevel=strlen($subhlevel);
}
if($subhlevel > $hlevel) {
// erase old subsections
@@ -863,16 +863,16 @@
$break=true;
}
$count++;
-
+
}
-
+
}
$text=join('',$secs);
# reinsert the stuff that we stripped out earlier
- $text=$parser->unstrip($text,$striparray);
- $text=$parser->unstripNoWiki($text,$striparray);
+ $text=$parser->unstrip($text,$striparray);
+ $text=$parser->unstripNoWiki($text,$striparray);
}
-
+
}
return $text;
}
@@ -886,7 +886,7 @@
$fname = 'Article::updateArticle';
if ( $this->mMinorEdit ) { $me1 = 1; } else { $me1 = 0; }
- if ( $minor && $wgUser->getID() ) { $me2 = 1; } else { $me2 = 0; }
+ if ( $minor && $wgUser->getID() ) { $me2 = 1; } else { $me2 = 0; }
if ( preg_match( "/^((" . $wgMwRedir->getBaseRegex() .
')[^\\n]+)/i', $text, $m ) ) {
$redir = 1;
$text = $m[1] . "\n"; # Remove all content but redirect
@@ -894,7 +894,7 @@
else { $redir = 0; }
$text = $this->preSaveTransform( $text );
-
+
# Update article, but only if changed.
if( $wgDBtransactions ) {
@@ -918,7 +918,7 @@
"WHERE cur_id=" . $this->getID() .
" AND cur_timestamp='" . $this->getTimestamp() .
"'";
$res = wfQuery( $sql, DB_WRITE, $fname );
-
+
if( wfAffectedRows() == 0 ) {
/* Belated edit conflict! Run away!! */
return false;
@@ -926,7 +926,7 @@
# This overwrites $oldtext if revision compression is on
$flags = Article::compressRevisionText( $oldtext );
-
+
$oldtable=$wgIsPg?'"old"':'old';
if ($wgIsPg) {
$oldtable='"old"';
@@ -956,7 +956,7 @@
$oldid = $wgIsPg?$old_id:wfInsertId( $res );
$bot = (int)($wgUser->isBot() || $forceBot);
- RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary,
+ RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary,
$oldid, $this->getTimestamp(), $bot );
Article::onArticleEdit( $this->mTitle );
}
@@ -965,9 +965,9 @@
$sql = 'COMMIT';
wfQuery( $sql, DB_WRITE );
}
-
- if ($watchthis) {
- if (!$this->mTitle->userIsWatching()) $this->watch();
+
+ if ($watchthis) {
+ if (!$this->mTitle->userIsWatching()) $this->watch();
} else {
if ( $this->mTitle->userIsWatching() ) {
$this->unwatch();
@@ -975,8 +975,8 @@
}
# standard deferred updates
$this->editUpdates( $text );
-
-
+
+
$urls = array();
# Template namespace
# Purge all articles linking here
@@ -989,7 +989,7 @@
}
}
}
-
+
# Squid updates
if ( $wgUseSquid ) {
$urls = array_merge( $urls, $this->mTitle->getSquidURLs() );
@@ -1015,7 +1015,7 @@
$wgLinkCache->preFill( $this->mTitle );
$wgLinkCache->clear();
- # Now update the link cache by parsing the text
+ # Now update the link cache by parsing the text
$wgOut = new OutputPage();
$wgOut->addWikiText( $text );
@@ -1092,17 +1092,17 @@
if ( $confirm ) {
- $sql = "UPDATE cur SET cur_touched='" . wfTimestampNow() .
"'," .
- "cur_restrictions='{$limit}' WHERE cur_id={$id}";
- wfQuery( $sql, DB_WRITE, 'Article::protect' );
-
- $log = new LogPage( wfMsg( 'protectlogpage' ), wfMsg( 'protectlogtext'
) );
- if ( $limit === "" ) {
- $log->addEntry( wfMsg( 'unprotectedarticle',
$this->mTitle->getPrefixedText() ), $reason );
- } else {
- $log->addEntry( wfMsg( 'protectedarticle',
$this->mTitle->getPrefixedText() ), $reason );
- }
- $wgOut->redirect( $this->mTitle->getFullURL() );
+ $sql = "UPDATE cur SET cur_touched='" . wfTimestampNow() .
"'," .
+ "cur_restrictions='{$limit}' WHERE cur_id={$id}";
+ wfQuery( $sql, DB_WRITE, 'Article::protect' );
+
+ $log = new LogPage( wfMsg( 'protectlogpage' ), wfMsg( 'protectlogtext'
) );
+ if ( $limit === "" ) {
+ $log->addEntry( wfMsg( 'unprotectedarticle',
$this->mTitle->getPrefixedText() ), $reason );
+ } else {
+ $log->addEntry( wfMsg( 'protectedarticle',
$this->mTitle->getPrefixedText() ), $reason );
+ }
+ $wgOut->redirect( $this->mTitle->getFullURL() );
return;
} else {
$reason = htmlspecialchars( wfMsg( 'protectreason' ) );
@@ -1124,12 +1124,14 @@
$protcom = '';
if ( $limit === '' ) {
+ $wgOut->setPageTitle( wfMsg( 'confirmunprotect' ) );
$wgOut->setSubtitle( wfMsg( 'unprotectsub', $sub ) );
$wgOut->addWikiText( wfMsg( 'confirmunprotecttext' ) );
$check = htmlspecialchars( wfMsg( 'confirmunprotect' ) );
$protcom = htmlspecialchars( wfMsg( 'unprotectcomment' ) );
$formaction = $this->mTitle->escapeLocalURL( 'action=unprotect' . $par
);
} else {
+ $wgOut->setPageTitle( wfMsg( 'confirmprotect' ) );
$wgOut->setSubtitle( wfMsg( 'protectsub', $sub ) );
$wgOut->addWikiText( wfMsg( 'confirmprotecttext' ) );
$check = htmlspecialchars( wfMsg( 'confirmprotect' ) );
@@ -1178,16 +1180,16 @@
return $this->protect( '' );
}
- # UI entry point for page deletion
+ # UI entry point for page deletion
function delete()
{
global $wgUser, $wgOut, $wgMessageCache, $wgRequest, $wgIsPg;
$fname = 'Article::delete';
$confirm = $wgRequest->getBool( 'wpConfirm' ) &&
$wgRequest->wasPosted();
$reason = $wgRequest->getText( 'wpReason' );
-
+
# This code desperately needs to be totally rewritten
-
+
# Check permissions
if ( ( ! $wgUser->isSysop() ) ) {
$wgOut->sysopRequired();
@@ -1241,19 +1243,19 @@
$text = Article::getRevisionText( $old );
$blanked = true;
}
-
+
}
-
- $length=strlen($text);
-
+
+ $length=strlen($text);
+
# this should not happen, since it is not possible to store an empty, new
# page. Let's insert a standard text in case it does, though
- if($length == 0 && $reason === '') {
+ if($length == 0 && $reason === '') {
$reason = wfMsg('exblank');
}
-
+
if($length < 500 && $reason === '') {
-
+
# comment field=255, let's grep the first 150 to have some user
# space left
$text=substr($text,0,150);
@@ -1268,27 +1270,27 @@
$reason=wfMsg('exbeforeblank') . " '".$text;
}
if($length>150) { $reason .= '...'; } # we've only pasted part of the
text
- $reason.="'";
+ $reason.="'";
}
}
return $this->confirmDelete( '', $reason );
}
-
+
# Output deletion confirmation dialog
function confirmDelete( $par, $reason )
{
global $wgOut;
wfDebug( "Article::confirmDelete\n" );
-
+
$sub = htmlspecialchars( $this->mTitle->getPrefixedText() );
$wgOut->setSubtitle( wfMsg( 'deletesub', $sub ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->addWikiText( wfMsg( 'confirmdeletetext' ) );
$formaction = $this->mTitle->escapeLocalURL( 'action=delete' . $par );
-
+
$confirm = htmlspecialchars( wfMsg( 'confirm' ) );
$check = htmlspecialchars( wfMsg( 'confirmcheck' ) );
$delcom = htmlspecialchars( wfMsg( 'deletecomment' ) );
@@ -1334,7 +1336,7 @@
$fname = 'Article::doDelete';
wfDebug( "$fname\n" );
- if ( $this->doDeleteArticle( $reason ) ) {
+ if ( $this->doDeleteArticle( $reason ) ) {
$deleted = $this->mTitle->getPrefixedText();
$wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
@@ -1375,14 +1377,14 @@
$u = new SiteStatsUpdate( 0, 1, -$this->isCountable( $this->getContent( true ) )
);
array_push( $wgDeferredUpdateList, $u );
-
+
$linksTo = $this->mTitle->getLinksTo();
# Squid purging
if ( $wgUseSquid ) {
- $urls = array(
+ $urls = array(
$this->mTitle->getInternalURL(),
- $this->mTitle->getInternalURL( 'history' )
+ $this->mTitle->getInternalURL( 'history' )
);
foreach ( $linksTo as $linkTo ) {
$urls[] = $linkTo->getInternalURL();
@@ -1420,7 +1422,7 @@
$sql = "DELETE FROM old WHERE old_namespace={$ns} AND " .
"old_title='{$t}'";
wfQuery( $sql, DB_WRITE, $fname );
-
+
$sql = "DELETE FROM recentchanges WHERE rc_namespace={$ns} AND " .
"rc_title='{$t}'";
wfQuery( $sql, DB_WRITE, $fname );
@@ -1429,7 +1431,7 @@
$t = wfStrencode( $this->mTitle->getPrefixedDBkey() );
Article::onArticleDelete( $this->mTitle );
-
+
$sql = 'INSERT INTO brokenlinks (bl_from,bl_to) VALUES ';
$first = true;
@@ -1437,7 +1439,7 @@
if ( ! $first ) { $sql .= ','; }
$first = false;
# Get article ID. Efficient because it was loaded into the cache by getLinksTo().
- $linkID = $titleObj->getArticleID();
+ $linkID = $titleObj->getArticleID();
$sql .= "({$linkID},'{$t}')";
}
if ( ! $first ) {
@@ -1455,10 +1457,10 @@
$sql = "DELETE FROM brokenlinks WHERE bl_from={$id}";
wfQuery( $sql, DB_WRITE, $fname );
-
+
$sql = "DELETE FROM categorylinks WHERE cl_from={$id}";
wfQuery( $sql, DB_WRITE, $fname );
-
+
$log = new LogPage( wfMsg( 'dellogpage' ), wfMsg( 'dellogpagetext' )
);
$art = $this->mTitle->getPrefixedText();
$log->addEntry( wfMsg( 'deletedarticle', $art ), $reason );
@@ -1481,14 +1483,14 @@
$wgOut->readOnlyPage( $this->getContent( true ) );
return;
}
-
+
# Enhanced rollback, marks edits rc_bot=1
$bot = $wgRequest->getBool( 'bot' );
-
+
# Replace all this user's current edits with the next one down
$tt = wfStrencode( $this->mTitle->getDBKey() );
$n = $this->mTitle->getNamespace();
-
+
# Get the last editor
$sql = 'SELECT cur_id,cur_user,cur_user_text,cur_comment ' .
"FROM cur WHERE cur_title='{$tt}' AND cur_namespace={$n}";
@@ -1502,7 +1504,7 @@
$ut = wfStrencode( $s->cur_user_text );
$uid = $s->cur_user;
$pid = $s->cur_id;
-
+
$from = str_replace( '_', ' ', $wgRequest->getVal( 'from' )
);
if( $from != $s->cur_user_text ) {
$wgOut->setPageTitle(wfmsg('rollbackfailed'));
@@ -1517,7 +1519,7 @@
}
return;
}
-
+
# Get the last edit not by this guy
$use_index=$wgIsMySQL?"USE INDEX (name_title_timestamp)":"";
@@ -1535,7 +1537,7 @@
return;
}
$s = wfFetchObject( $res );
-
+
if ( $bot ) {
# Mark all reverted edits as bot
$sql = 'UPDATE recentchanges SET rc_bot=1 WHERE ' .
@@ -1552,7 +1554,7 @@
Article::onArticleEdit( $this->mTitle );
$wgOut->returnToMain( false );
}
-
+
# Do standard deferred updates after page view
@@ -1589,7 +1591,7 @@
$id = $this->getID();
$title = $this->mTitle->getPrefixedDBkey();
$shortTitle = $this->mTitle->getDBkey();
-
+
$adj = $this->mCountAdjustment;
if ( 0 != $id ) {
@@ -1626,7 +1628,7 @@
global $wgParser, $wgUser;
return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser,
ParserOptions::newFromUser( $wgUser ) );
}
-
+
/* Caching functions */
# checkLastModified returns true if it has taken care of all
@@ -1653,7 +1655,7 @@
$cache->loadFromFileCache();
return true;
} else {
- wfDebug( " tryFileCache() - starting buffer\n" );
+ wfDebug( " tryFileCache() - starting buffer\n" );
ob_start( array(&$cache, 'saveToFileCache' ) );
}
} else {
@@ -1664,7 +1666,7 @@
function isFileCacheable() {
global $wgUser, $wgUseFileCache, $wgShowIPinHeader, $wgRequest;
extract( $wgRequest->getValues( 'action', 'oldid', 'diff',
'redirect', 'printable' ) );
-
+
return $wgUseFileCache
and (!$wgShowIPinHeader)
and ($this->getID() != 0)
@@ -1678,7 +1680,7 @@
and (!isset($printable))
and (!$this->mRedirectedFrom);
}
-
+
# Loads cur_touched and returns a value indicating if it should be used
function checkTouched() {
$id = $this->getID();
@@ -1702,14 +1704,14 @@
$dbkey = $this->mTitle->getDBkey();
$encDbKey = wfStrencode( $dbkey );
$timestamp = wfTimestampNow();
-
+
# Save to history
$oldtable=$wgIsPg?'"old"':'old';
$sql = "INSERT INTO $oldtable
(old_namespace,old_title,old_text,old_comment,old_user,old_user_text,old_timestamp,inverse_timestamp)
SELECT
cur_namespace,cur_title,cur_text,cur_comment,cur_user,cur_user_text,cur_timestamp,99999999999999-cur_timestamp
FROM cur WHERE cur_namespace=$ns AND cur_title='$encDbKey'";
wfQuery( $sql, DB_WRITE );
-
+
# Use the affected row count to determine if the article is new
$numRows = wfAffectedRows();
@@ -1746,14 +1748,14 @@
$id = intval( $id );
global $wgHitcounterUpdateFreq;
- if( $wgHitcounterUpdateFreq <= 1 ){ //
+ if( $wgHitcounterUpdateFreq <= 1 ){ //
wfQuery('UPDATE cur SET cur_counter = cur_counter + 1 ' .
'WHERE cur_id = '.$id, DB_WRITE);
return;
}
# Not important enough to warrant an error page in case of failure
- $oldignore = wfIgnoreSQLErrors( true );
+ $oldignore = wfIgnoreSQLErrors( true );
wfQuery("INSERT INTO hitcounter (hc_id) VALUES ({$id})", DB_WRITE);
@@ -1767,7 +1769,7 @@
$res = wfQuery('SELECT COUNT(*) as n FROM hitcounter', DB_WRITE);
$row = wfFetchObject( $res );
$rown = intval( $row->n );
- if( $rown >= $wgHitcounterUpdateFreq ){
+ if( $rown >= $wgHitcounterUpdateFreq ){
wfProfileIn( 'Article::incViewCount-collect' );
$old_user_abort = ignore_user_abort( true );
@@ -1788,18 +1790,18 @@
}
# The onArticle*() functions are supposed to be a kind of hooks
- # which should be called whenever any of the specified actions
- # are done.
+ # which should be called whenever any of the specified actions
+ # are done.
#
- # This is a good place to put code to clear caches, for instance.
+ # This is a good place to put code to clear caches, for instance.
- # This is called on page move and undelete, as well as edit
+ # This is called on page move and undelete, as well as edit
/* static */ function onArticleCreate($title_obj){
global $wgUseSquid, $wgDeferredUpdateList;
$titles = $title_obj->getBrokenLinksTo();
-
- # Purge squid
+
+ # Purge squid
if ( $wgUseSquid ) {
$urls = $title_obj->getSquidURLs();
foreach ( $titles as $linkTitle ) {
@@ -1820,6 +1822,76 @@
/* static */ function onArticleEdit($title_obj){
LinkCache::linksccClearPage( $title_obj->getArticleID() );
}
+
+ # Info about this page
+
+ function info()
+ {
+ global $wgUser, $wgTitle, $wgOut, $wgLang;
+
+ $basenamespace = $wgTitle->getNamespace() & (~1);
+ $cur_clause = "cur_title='".$wgTitle->getDBkey()."' AND
cur_namespace=".$basenamespace;
+ $old_clause = "old_title='".$wgTitle->getDBkey()."' AND
old_namespace=".$basenamespace;
+ $wl_clause = "wl_title='".$wgTitle->getDBkey()."' AND
wl_namespace=".$basenamespace;
+ $fullTitle = $wgTitle->makeName($basenamespace, $wgTitle->getDBKey());
+ $wgOut->setPagetitle( $fullTitle );
+ $wgOut->setSubtitle( wfMsg( "infosubtitle" ));
+
+ # first, see if the page exists at all.
+ $sql = "SELECT COUNT(*) FROM cur WHERE ".$cur_clause;
+ $exists = wfSingleQuery( $sql , DB_READ );
+ if ($exists < 1) {
+ $wgOut->addHTML( wfMsg("noarticletext") );
+ } else {
+ $sql = "SELECT COUNT(*) FROM watchlist WHERE ".$wl_clause;
+ $wgOut->addHTML( "<ul><li>" . wfMsg("numwatchers")
. wfSingleQuery( $sql, DB_READ ) . "</li>" );
+ $sql = "SELECT COUNT(*) FROM old WHERE ".$old_clause;
+ $old = wfSingleQuery( $sql, DB_READ );
+ $wgOut->addHTML( "<li>" . wfMsg("numedits") . ($old + 1)
. "</li>");
+
+ # to find number of distinct authors, we need to do some
+ # funny stuff because of the cur/old table split:
+ # - first, find the name of the 'cur' author
+ # - then, find the number of *other* authors in 'old'
+
+ # find 'cur' author
+ $sql = "SELECT cur_user_text FROM cur WHERE ".$cur_clause;
+ $cur_author = wfSingleQuery( $sql, DB_READ );
+
+ # find number of 'old' authors excluding 'cur' author
+ $sql = "SELECT COUNT(DISTINCT old_user_text) FROM old WHERE ".$old_clause
+ ." AND old_user_text<>'" . $cur_author . "'";
+ $authors = wfSingleQuery( $sql, DB_READ ) + 1;
+
+ # now for the Talk page ...
+ $cur_clause = "cur_title='".$wgTitle->getDBkey()."' AND
cur_namespace=".($basenamespace+1);
+ $old_clause = "old_title='".$wgTitle->getDBkey()."' AND
old_namespace=".($basenamespace+1);
+
+ # does it exist?
+ $sql = "SELECT COUNT(*) FROM cur WHERE ".$cur_clause;
+ $exists = wfSingleQuery( $sql , DB_READ );
+
+ # number of edits
+ if ($exists > 0) {
+ $sql = "SELECT COUNT(*) FROM old WHERE ".$old_clause;
+ $old = wfSingleQuery( $sql, DB_READ );
+ $wgOut->addHTML( "<li>" . wfMsg("numtalkedits") . ($old
+ 1) . "</li>");
+ }
+ $wgOut->addHTML( "<li>" . wfMsg("numauthors") . $authors
. "</li>" );
+
+ # number of authors
+ if ($exists > 0) {
+ $sql = "SELECT cur_user_text FROM cur WHERE ".$cur_clause;
+ $cur_author = wfSingleQuery( $sql, DB_READ );
+
+ $sql = "SELECT COUNT(DISTINCT old_user_text) FROM old WHERE "
+ .$old_clause." AND old_user_text<>'" . $cur_author .
"'";
+ $authors = wfSingleQuery( $sql, DB_READ ) + 1;
+
+ $wgOut->addHTML( "<li>" . wfMsg("numtalkauthors") .
$authors . "</li></ul>" );
+ }
+ }
+ }
}
?>
Index: includes/DatabaseFunctions.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/includes/DatabaseFunctions.php,v
retrieving revision 1.36
diff -u -r1.36 DatabaseFunctions.php
--- includes/DatabaseFunctions.php 22 Jun 2004 08:54:26 -0000 1.36
+++ includes/DatabaseFunctions.php 8 Jul 2004 14:33:17 -0000
@@ -39,6 +39,15 @@
}
}
+function wfSingleQuery( $sql, $db, $fname = "" )
+{
+ $res = wfQuery($sql, $db, $fname );
+ $row = wfFetchRow( $res );
+ $ret = $row[0];
+ wfFreeResult( $res );
+ return $ret;
+}
+
function &wfGetDB( $db = DB_LAST )
{
global $wgLoadBalancer;
Index: includes/OutputPage.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/includes/OutputPage.php,v
retrieving revision 1.152
diff -u -r1.152 OutputPage.php
--- includes/OutputPage.php 19 Jun 2004 06:46:54 -0000 1.152
+++ includes/OutputPage.php 8 Jul 2004 14:33:17 -0000
@@ -14,19 +14,19 @@
var $mSuppressQuickbar;
var $mOnloadHandler;
var $mDoNothing;
- var $mContainsOldMagic, $mContainsNewMagic;
+ var $mContainsOldMagic, $mContainsNewMagic;
var $mIsArticleRelated;
var $mParserOptions;
var $mShowFeedLinks = false;
var $mEnableClientCache = true;
-
+
function OutputPage()
{
$this->mHeaders = $this->mCookies = $this->mMetatags =
$this->mKeywords = $this->mLinktags = array();
$this->mHTMLtitle = $this->mPagetitle = $this->mBodytext =
$this->mRedirect = $this->mLastModified =
- $this->mSubtitle = $this->mDebugtext = $this->mRobotpolicy =
+ $this->mSubtitle = $this->mDebugtext = $this->mRobotpolicy =
$this->mOnloadHandler = "";
$this->mIsArticleRelated = $this->mIsarticle = $this->mPrintable = true;
$this->mSuppressQuickbar = $this->mPrintable = false;
@@ -48,7 +48,7 @@
function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
function addScript( $script ) { $this->mScripts .= $script; }
function getScript() { return $this->mScripts; }
-
+
function addLink( $linkarr ) {
# $linkarr should be an associative array of attributes. We'll escape on output.
array_push( $this->mLinktags, $linkarr );
@@ -65,7 +65,7 @@
# checkLastModified tells the client to use the client-cached page if
# possible. If sucessful, the OutputPage is disabled so that
# any future call to OutputPage->output() have no effect. The method
- # returns true iff cache-ok headers was sent.
+ # returns true iff cache-ok headers was sent.
function checkLastModified ( $timestamp )
{
global $wgLang, $wgCachePages, $wgUser;
@@ -92,7 +92,7 @@
$modsince = preg_replace( '/;.*$/', '',
$_SERVER["HTTP_IF_MODIFIED_SINCE"] );
$ismodsince = wfUnix2Timestamp( strtotime( $modsince ) );
wfDebug( "-- client send If-Modified-Since: " . $modsince . "\n",
false );
- wfDebug( "-- we might send Last-Modified : $lastmod\n", false );
+ wfDebug( "-- we might send Last-Modified : $lastmod\n", false );
if( ($ismodsince >= $timestamp ) and $wgUser->validateCache( $ismodsince ) ) {
# Make sure you're in a place you can leave when you call us!
@@ -116,11 +116,11 @@
global $action;
switch($action) {
case 'edit':
- return wfMsg('edit');
+ return wfMsg('edit');
case 'history':
return wfMsg('history_short');
case 'protect':
- return wfMsg('unprotect');
+ return wfMsg('protect');
case 'unprotect':
return wfMsg('unprotect');
case 'delete':
@@ -131,6 +131,8 @@
return wfMsg('unwatch');
case 'submit':
return wfMsg('preview');
+ case 'info':
+ return wfMsg('info_short');
default:
return '';
}
@@ -168,8 +170,8 @@
$this->mIsarticle = false;
}
}
- function setArticleFlag( $v ) {
- $this->mIsarticle = $v;
+ function setArticleFlag( $v ) {
+ $this->mIsarticle = $v;
if ( $v ) {
$this->mIsArticleRelated = $v;
}
@@ -179,7 +181,7 @@
{
return $this->mIsArticleRelated;
}
-
+
function getLanguageLinks() {
return $this->mLanguageLinks;
}
@@ -191,7 +193,7 @@
}
function getCategoryLinks() {
return $this->mCategoryLinks;
- }
+ }
function addCategoryLinks($newLinkArray) {
$this->mCategoryLinks += $newLinkArray;
}
@@ -218,12 +220,12 @@
function addWikiText( $text, $linestart = true, $cacheArticle = NULL )
{
global $wgParser, $wgParserCache, $wgUser, $wgTitle;
-
+
$parserOutput = $wgParser->parse( $text, $wgTitle, $this->mParserOptions,
$linestart );
if ( $cacheArticle ) {
$wgParserCache->save( $parserOutput, $cacheArticle, $wgUser );
}
-
+
$this->mLanguageLinks += $parserOutput->getLanguageLinks();
$this->mCategoryLinks += $parserOutput->getCategoryLinks();
$this->addHTML( $parserOutput->getText() );
@@ -241,24 +243,24 @@
return false;
}
}
-
+
# Set the maximum cache time on the Squid in seconds
function setSquidMaxage( $maxage ) {
$this->mSquidMaxage = $maxage;
}
-
+
# Use enableClientCache(false) to force it to send nocache headers
function enableClientCache( $state ) {
return wfSetVar( $this->mEnableClientCache, $state );
}
-
+
function sendCacheControl() {
global $wgUseSquid, $wgUseESI;
# FIXME: This header may cause trouble with some versions of Internet Explorer
header( "Vary: Accept-Encoding, Cookie" );
if( $this->mEnableClientCache ) {
- if( $wgUseSquid && ! isset( $_COOKIE[ini_get( "session.name") ] )
&&
- ! $this->isPrintable() && $this->mSquidMaxage != 0 )
+ if( $wgUseSquid && ! isset( $_COOKIE[ini_get( "session.name") ] )
&&
+ ! $this->isPrintable() && $this->mSquidMaxage != 0 )
{
if ( $wgUseESI ) {
# We'll purge the proxy cache explicitly, but require end user agents
@@ -272,7 +274,7 @@
} else {
# We'll purge the proxy cache for anons explicitly, but require end user agents
# to revalidate against the proxy on each visit.
- # IMPORTANT! The Squid needs to replace the Cache-Control header with
+ # IMPORTANT! The Squid needs to replace the Cache-Control header with
# Cache-Control: s-maxage=0, must-revalidate, max-age=0
wfDebug( "** local proxy caching; {$this->mLastModified} **\n", false
);
# start with a shorter timeout for initial testing
@@ -297,7 +299,7 @@
header( "Pragma: no-cache" );
}
}
-
+
# Finally, all the text has been munged and accumulated into
# the object, let's actually output it:
#
@@ -311,7 +313,7 @@
}
$fname = "OutputPage::output";
wfProfileIn( $fname );
-
+
$sk = $wgUser->getSkin();
if ( "" != $this->mRedirect ) {
@@ -326,9 +328,9 @@
}
$this->mLastModified = gmdate( "D, j M Y H:i:s" ) . " GMT";
}
-
+
$this->sendCacheControl();
-
+
if( $wgDebugRedirects ) {
$url = htmlspecialchars( $this->mRedirect );
print
"<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
@@ -339,10 +341,10 @@
}
return;
}
-
-
+
+
$this->sendCacheControl();
-
+
header( "Content-type: $wgMimeType; charset={$wgOutputEncoding}" );
header( "Content-language: {$wgLanguageCode}" );
@@ -350,7 +352,7 @@
foreach( $this->mCookies as $name => $val ) {
setcookie( $name, $val, $exp, "/" );
}
-
+
$sk->outputPage( $this );
# flush();
}
@@ -373,7 +375,7 @@
global $wgUser, $wgLang;
$wgInputEncoding = strtolower( $wgInputEncoding );
-
+
if( $wgUser->getOption( 'altencoding' ) ) {
$wgLang->setAltEncoding();
return;
@@ -383,11 +385,11 @@
$wgOutputEncoding = strtolower( $wgOutputEncoding );
return;
}
-
+
/*
# This code is unused anyway!
# Commenting out. --bv 2003-11-15
-
+
$a = explode( ",", $_SERVER['HTTP_ACCEPT_CHARSET'] );
$best = 0.0;
$bestset = "*";
@@ -415,7 +417,7 @@
$wgOutputEncoding = $wgInputEncoding;
}
- # Returns a HTML comment with the elapsed time since request.
+ # Returns a HTML comment with the elapsed time since request.
# This method has no side effects.
function reportTime()
{
@@ -425,7 +427,7 @@
list( $usec, $sec ) = explode( " ", $wgRequestTime );
$start = (float)$sec + (float)$usec;
$elapsed = $now - $start;
-
+
# Use real server name if available, so we know which machine
# in a server farm generated the current page.
if ( function_exists( "posix_uname" ) ) {
@@ -477,7 +479,7 @@
$this->mBodytext = "";
$sk = $wgUser->getSkin();
- $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
+ $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
$this->addHTML( wfMsg( "sysoptext", $ap ) );
$this->returnToMain();
}
@@ -493,7 +495,7 @@
$this->mBodytext = "";
$sk = $wgUser->getSkin();
- $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
+ $ap = $sk->makeKnownLink( wfMsg( "administrators" ), "" );
$this->addHTML( wfMsg( "developertext", $ap ) );
$this->returnToMain();
}
@@ -511,9 +513,9 @@
# We put a comment in the .html file so a Sysop can diagnose the page the
# user can't see.
- $this->addHTML( "\n<!--" .
- $wgLang->getNsText( $wgTitle->getNamespace() ) .
- ":" .
+ $this->addHTML( "\n<!--" .
+ $wgLang->getNsText( $wgTitle->getNamespace() ) .
+ ":" .
$wgTitle->getDBkey() . "-->" );
$this->returnToMain(); # Flip back to the main page after 10 seconds.
}
@@ -537,7 +539,7 @@
$msg = str_replace( "$2", htmlspecialchars( $fname ), $msg );
$msg = str_replace( "$3", $errno, $msg );
$msg = str_replace( "$4", htmlspecialchars( $error ), $msg );
-
+
if ( $wgCommandLineMode || !is_object( $wgUser )) {
print "$msg\n";
wfAbruptExit();
@@ -566,7 +568,7 @@
$reason = file_get_contents( $wgReadOnlyFile );
$this->addWikiText( wfMsg( "readonlytext", $reason ) );
}
-
+
if( is_string( $source ) ) {
if( strcmp( $source, "" ) == 0 ) {
$source = wfMsg( "noarticletext" );
@@ -577,7 +579,7 @@
htmlspecialchars( $source ) . "\n</textarea>";
$this->addHTML( $text );
}
-
+
$this->returnToMain( false );
}
@@ -624,7 +626,7 @@
function returnToMain( $auto = true, $returnto = NULL )
{
global $wgUser, $wgOut, $wgRequest;
-
+
if ( $returnto == NULL ) {
$returnto = $wgRequest->getText( 'returnto' );
}
@@ -658,7 +660,7 @@
"/[_]/" => ' '
);
$a = htmlspecialchars(preg_replace(array_keys($strip), array_values($strip),$a ));
-
+
$wgOut->addMeta ( "KEYWORDS" , $a ) ;
}
@@ -673,7 +675,7 @@
} else {
$ret = "";
}
-
+
$ret .= "<!DOCTYPE html PUBLIC \"$wgDocType\"\n
\"$wgDTD\">\n";
if ( "" == $this->mHTMLtitle ) {
@@ -688,7 +690,7 @@
$ret .= "<html $xmlbits lang=\"$wgLanguageCode\" $rtl>\n";
$ret .= "<head>\n<title>" . htmlspecialchars(
$this->mHTMLtitle ) . "</title>\n";
array_push( $this->mMetatags, array( "http:Content-type",
"$wgMimeType; charset={$wgOutputEncoding}" ) );
-
+
$ret .= $this->getHeadLinks();
global $wgStylePath;
if( $this->isPrintable() ) {
@@ -707,7 +709,7 @@
$ret .= "</head>\n";
return $ret;
}
-
+
function getHeadLinks() {
global $wgRequest, $wgStylePath;
$ret = "";
Index: languages/Language.php
===================================================================
RCS file: /cvsroot/wikipedia/phase3/languages/Language.php,v
retrieving revision 1.257
diff -u -r1.257 Language.php
--- languages/Language.php 5 Jul 2004 21:26:35 -0000 1.257
+++ languages/Language.php 8 Jul 2004 14:33:17 -0000
@@ -66,7 +66,7 @@
'davinci' => 'DaVinci',
'mono' => 'Mono',
'monobook' => 'MonoBook',
- 'myskin' => 'MySkin'
+ 'myskin' => 'MySkin'
);
define( "MW_MATH_PNG", 0 );
@@ -145,10 +145,10 @@
'Sep', 'Oct', 'Nov', 'Dec'
);
-# Note to translators:
-# Please include the English words as synonyms. This allows people
+# Note to translators:
+# Please include the English words as synonyms. This allows people
# from other wikis to contribute more easily.
-#
+#
/* private */ $wgMagicWordsEn = array(
# ID CASE SYNONYMS
MAG_REDIRECT => array( 0, '#redirect' ),
@@ -166,7 +166,7 @@
MAG_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES' ),
MAG_CURRENTMONTHNAMEGEN => array( 1, 'CURRENTMONTHNAMEGEN' ),
MAG_PAGENAME => array( 1, 'PAGENAME' ),
- MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
+ MAG_NAMESPACE => array( 1, 'NAMESPACE' ),
MAG_MSG => array( 0, 'MSG:' ),
MAG_SUBST => array( 0, 'SUBST:' ),
MAG_MSGNW => array( 0, 'MSGNW:' ),
@@ -260,6 +260,7 @@
'go' => 'Go',
"history" => 'Page history',
'history_short' => 'History',
+'info_short' => 'Information',
'printableversion' => 'Printable version',
'edit' => 'Edit',
'editthispage' => 'Edit this page',
@@ -441,10 +442,10 @@
'youremail' => 'Your email*',
'yourrealname' => 'Your real name*',
'yournick' => 'Your nickname (for signatures)',
-'emailforlost' => "Fields marked with a star (*) are optional. Storing
an email address enables people to contact you through the website without you having to
reveal your
+'emailforlost' => "Fields marked with a star (*) are optional. Storing
an email address enables people to contact you through the website without you having to
reveal your
email address to them, and it can be used to send you a new password if you forget
it.<br /><br />Your real name, if you choose to provide it, will be used for
giving you attribution for your work.",
'prefs-help-userdata' => '* <strong>Real name</strong>
(optional): if you choose to provide it this will be used for giving you attribution for
your work.<br/>
-* <strong>Email</strong> (optional): Enables people to contact you through
the website without you having to reveal your
+* <strong>Email</strong> (optional): Enables people to contact you through
the website without you having to reveal your
email address to them, and it can be used to send you a new password if you forget
it.',
'loginerror' => 'Login error',
'nocookiesnew' => "The user account was created, but you are not logged
in. {{SITENAME}} uses cookies to log in users. You have cookies disabled. Please enable
them, then log in with your new username and password.",
@@ -525,7 +526,7 @@
'newarticle' => '(New)',
'newarticletext' =>
"You've followed a link to a page that doesn't exist yet.
-To create the page, start typing in the box below
+To create the page, start typing in the box below
(see the [[{{ns:4}}:Help|help page]] for more info).
If you are here by mistake, just click your browser's
'''back''' button.",
'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
@@ -674,8 +675,8 @@
See [[{{ns:4}}:User preferences help]] for help deciphering the options.",
'prefsreset' => 'Preferences have been reset from storage.',
-'qbsettings' => 'Quickbar settings',
-'qbsettingsnote' => 'This preference only works in the
\'Standard\' and the \'CologneBlue\' skin.',
+'qbsettings' => 'Quickbar settings',
+'qbsettingsnote' => 'This preference only works in the
\'Standard\' and the \'CologneBlue\' skin.',
'changepassword' => 'Change password',
'skin' => 'Skin',
'math' => 'Rendering math',
@@ -816,7 +817,7 @@
'savefile' => 'Save file',
'uploadedimage' => "uploaded \"$1\"",
'uploaddisabled' => 'Sorry, uploading is disabled.',
-
+
# Image list
#
'imagelist' => 'Image list',
@@ -894,7 +895,7 @@
'randompage' => 'Random page',
'shortpages' => 'Short pages',
'longpages' => 'Long pages',
-'deadendpages' => 'Dead-end pages',
+'deadendpages' => 'Dead-end pages',
'listusers' => 'User list',
'listadmins' => 'Admins list',
'specialpages' => 'Special pages',
@@ -939,7 +940,7 @@
as the "From" address of the mail, so the recipient will be able
to reply.',
'usermailererror' => 'Mail object returned error: ',
-'defemailsubject' => "{{SITENAME}} e-mail",
+'defemailsubject' => "{{SITENAME}} e-mail",
'noemailtitle' => 'No e-mail address',
'noemailtext' => 'This user has not specified a valid e-mail address,
or has chosen not to receive e-mail from other users.',
@@ -1030,11 +1031,11 @@
'rollbackfailed' => 'Rollback failed',
'cantrollback' => 'Cannot revert edit; last contributor is only author of
this page.',
'alreadyrolled' => "Cannot rollback last edit of [[$1]]
-by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the
page already.
+by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the
page already.
Last edit was by [[User:$3|$3]] ([[User talk:$3|Talk]]). ",
# only shown if there is an edit comment
-'editcomment' => "The edit comment was:
\"<i>$1</i>\".",
+'editcomment' => "The edit comment was:
\"<i>$1</i>\".",
'revertpage' => "Reverted edit of $2, changed back to last version by
$1",
'protectlogpage' => 'Protection_log',
'protectlogtext' => "Below is a list of page locks/unlocks.
@@ -1120,7 +1121,7 @@
'autoblocker' => "Autoblocked because you share an IP address with
\"$1\". Reason \"$2\".",
'blocklogpage' => 'Block_log',
'blocklogentry' => 'blocked "$1" with an expiry time of
$2',
-'blocklogtext' => 'This is a log of user blocking and unblocking actions.
Automatically
+'blocklogtext' => 'This is a log of user blocking and unblocking actions.
Automatically
blocked IP addresses are not be listed. See the [[Special:Ipblocklist|IP block list]]
for
the list of currently operational bans and blocks.',
'unblocklogentry' => 'unblocked "$1"',
@@ -1171,7 +1172,7 @@
# Make sysop
'makesysoptitle' => 'Make a user into a sysop',
-'makesysoptext' => 'This form is used by bureaucrats to turn ordinary
users into administrators.
+'makesysoptext' => 'This form is used by bureaucrats to turn ordinary
users into administrators.
Type the name of the user in the box and press the button to make the user an
administrator',
'makesysopname' => 'Name of the user:',
'makesysopsubmit' => 'Make this user into a sysop',
@@ -1292,7 +1293,7 @@
'lastmodifiedby' => "This page was last modified $1 by $2.",
'and' => 'and',
'othercontribs' => "Based on work by $1.",
-'others' => 'others',
+'others' => 'others',
'siteusers' => "$wgSitename user(s) $1",
'creditspage' => 'Page credits',
'nocredits' => 'There is no credits info available for this page.',
@@ -1300,65 +1301,73 @@
# Spam protection
'spamprotectiontitle' => 'Spam protection filter',
-'spamprotectiontext' => 'The page you wanted to save was blocked by the
spam filter. This is probably caused by a link to an external site.
+'spamprotectiontext' => 'The page you wanted to save was blocked by the
spam filter. This is probably caused by a link to an external site.
You might want to check the following regular expression for patterns that are currently
blocked:',
'subcategorycount' => "There are $1 subcategories to this
category.",
'categoryarticlecount' => "There are $1 articles in this
category.",
'usenewcategorypage' => "1\n\nSet first character to \"0\" to
disable the new category page layout.",
+# Info page
+"infosubtitle" => "Information for page",
+"numedits" => "Number of edits (article): ",
+"numtalkedits" => "Number of edits (discussion page): ",
+"numwatchers" => "Number of watchers: ",
+"numauthors" => "Number of distinct authors (article): ",
+"numtalkauthors" => "Number of distinct authors (discussion page):
",
+
# Monobook.js: tooltips and access keys for monobook
'Monobook.js' => '/* tooltips and access keys */
ta = new Object();
-ta[\'pt-userpage\'] = new Array(\'.\',\'My user page\');
-ta[\'pt-anonuserpage\'] = new Array(\'.\',\'The user page for the ip
you\\\'re editing as\');
-ta[\'pt-mytalk\'] = new Array(\'n\',\'My talk page\');
-ta[\'pt-anontalk\'] = new Array(\'n\',\'Discussion about edits from
this ip address\');
-ta[\'pt-preferences\'] = new Array(\'\',\'My preferences\');
-ta[\'pt-watchlist\'] = new Array(\'l\',\'The list of pages
you\\\'re monitoring for changes.\');
-ta[\'pt-mycontris\'] = new Array(\'y\',\'List of my
contributions\');
-ta[\'pt-login\'] = new Array(\'o\',\'You are encouraged to log in, it
is not mandatory however.\');
-ta[\'pt-anonlogin\'] = new Array(\'o\',\'You are encouraged to log
in, it is not mandatory however.\');
-ta[\'pt-logout\'] = new Array(\'o\',\'Log out\');
-ta[\'ca-talk\'] = new Array(\'t\',\'Discussion about the content
page\');
-ta[\'ca-edit\'] = new Array(\'e\',\'You can edit this page. Please
use the preview button before saving.\');
-ta[\'ca-addsection\'] = new Array(\'+\',\'Add a comment to this
discussion.\');
-ta[\'ca-viewsource\'] = new Array(\'e\',\'This page is protected. You
can view its source.\');
-ta[\'ca-history\'] = new Array(\'h\',\'Past versions of this
page.\');
-ta[\'ca-protect\'] = new Array(\'=\',\'Protect this page\');
-ta[\'ca-delete\'] = new Array(\'d\',\'Delete this page\');
-ta[\'ca-undelete\'] = new Array(\'d\',\'Restore the edits done to
this page before it was deleted\');
-ta[\'ca-move\'] = new Array(\'m\',\'Move this page\');
-ta[\'ca-nomove\'] = new Array(\'\',\'You don\\\'t have the
permissions to move this page\');
-ta[\'ca-watch\'] = new Array(\'w\',\'Add this page to your
watchlist\');
-ta[\'ca-unwatch\'] = new Array(\'w\',\'Remove this page from your
watchlist\');
-ta[\'search\'] = new Array(\'f\',\'Search this wiki\');
-ta[\'p-logo\'] = new Array(\'\',\'Main Page\');
-ta[\'n-mainpage\'] = new Array(\'z\',\'Visit the Main Page\');
-ta[\'n-portal\'] = new Array(\'\',\'About the project, what you can
do, where to find things\');
-ta[\'n-currentevents\'] = new Array(\'\',\'Find background
information on current events\');
-ta[\'n-recentchanges\'] = new Array(\'r\',\'The list of recent
changes in the wiki.\');
-ta[\'n-randompage\'] = new Array(\'x\',\'Load a random page\');
-ta[\'n-help\'] = new Array(\'\',\'The place to find out.\');
-ta[\'n-sitesupport\'] = new Array(\'\',\'Support us\');
-ta[\'t-whatlinkshere\'] = new Array(\'j\',\'List of all wiki pages
that link here\');
-ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Recent changes in
pages linking to this page\');
-ta[\'feed-rss\'] = new Array(\'\',\'RSS feed for this page\');
-ta[\'feed-atom\'] = new Array(\'\',\'Atom feed for this page\');
-ta[\'t-contributions\'] = new Array(\'\',\'View the list of
contributions of this user\');
-ta[\'t-emailuser\'] = new Array(\'\',\'Send a mail to this
user\');
-ta[\'t-upload\'] = new Array(\'u\',\'Upload images or media
files\');
-ta[\'t-specialpages\'] = new Array(\'q\',\'List of all special
pages\');
-ta[\'ca-nstab-main\'] = new Array(\'c\',\'View the content
page\');
-ta[\'ca-nstab-user\'] = new Array(\'c\',\'View the user page\');
-ta[\'ca-nstab-media\'] = new Array(\'c\',\'View the media
page\');
-ta[\'ca-nstab-special\'] = new Array(\'\',\'This is a special page,
you can\\\'t edit the page itself.\');
-ta[\'ca-nstab-wp\'] = new Array(\'a\',\'View the project page\');
-ta[\'ca-nstab-image\'] = new Array(\'c\',\'View the image
page\');
-ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'View the system
message\');
-ta[\'ca-nstab-template\'] = new Array(\'c\',\'View the
template\');
-ta[\'ca-nstab-help\'] = new Array(\'c\',\'View the help page\');
-ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category
page\');
+ta[\'pt-userpage\'] = new Array(\'.\',\'My user page\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'The user page for the ip
you\\\'re editing as\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'My talk page\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Discussion about edits from
this ip address\');
+ta[\'pt-preferences\'] = new Array(\'\',\'My preferences\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'The list of pages
you\\\'re monitoring for changes.\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'List of my
contributions\');
+ta[\'pt-login\'] = new Array(\'o\',\'You are encouraged to log in, it
is not mandatory however.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'You are encouraged to log
in, it is not mandatory however.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Log out\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Discussion about the content
page\');
+ta[\'ca-edit\'] = new Array(\'e\',\'You can edit this page. Please
use the preview button before saving.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Add a comment to this
discussion.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'This page is protected. You
can view its source.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Past versions of this
page.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Protect this page\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Delete this page\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Restore the edits done to
this page before it was deleted\');
+ta[\'ca-move\'] = new Array(\'m\',\'Move this page\');
+ta[\'ca-nomove\'] = new Array(\'\',\'You don\\\'t have the
permissions to move this page\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Add this page to your
watchlist\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Remove this page from your
watchlist\');
+ta[\'search\'] = new Array(\'f\',\'Search this wiki\');
+ta[\'p-logo\'] = new Array(\'\',\'Main Page\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Visit the Main Page\');
+ta[\'n-portal\'] = new Array(\'\',\'About the project, what you can
do, where to find things\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Find background
information on current events\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'The list of recent
changes in the wiki.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Load a random page\');
+ta[\'n-help\'] = new Array(\'\',\'The place to find out.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Support us\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'List of all wiki pages
that link here\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Recent changes in
pages linking to this page\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS feed for this page\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom feed for this page\');
+ta[\'t-contributions\'] = new Array(\'\',\'View the list of
contributions of this user\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Send a mail to this
user\');
+ta[\'t-upload\'] = new Array(\'u\',\'Upload images or media
files\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'List of all special
pages\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'View the content
page\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'View the user page\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'View the media
page\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'This is a special page,
you can\\\'t edit the page itself.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'View the project
page\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'View the image
page\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'View the system
message\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'View the
template\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'View the help page\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category
page\');
'
@@ -1392,7 +1401,7 @@
global $wgDefaultUserOptionsEn ;
return $wgDefaultUserOptionsEn ;
}
-
+
function getBookstoreList () {
global $wgBookstoreListEn ;
return $wgBookstoreListEn ;
@@ -1435,7 +1444,7 @@
global $wgMathNamesEn;
return $wgMathNamesEn;
}
-
+
function getDateFormats() {
global $wgDateFormatsEn;
return $wgDateFormatsEn;
@@ -1445,7 +1454,7 @@
global $wgUserTogglesEn;
return $wgUserTogglesEn;
}
-
+
function getUserToggle( $tog ) {
$togs =& $this->getUserToggles();
return $togs[$tog];
@@ -1469,7 +1478,7 @@
global $wgMonthNamesEn;
return $wgMonthNamesEn[$key-1];
}
-
+
/* by default we just return base form */
function getMonthNameGen( $key )
{
@@ -1491,11 +1500,11 @@
function userAdjust( $ts )
{
global $wgUser, $wgLocalTZoffset;
-
+
$tz = $wgUser->getOption( 'timecorrection' );
if ( $tz === '' ) {
$hrDiff = isset( $wgLocalTZoffset ) ? $wgLocalTZoffset : 0;
- $minDiff = 0;
+ $minDiff = 0;
} elseif ( strpos( $tz, ":" ) !== false ) {
$tzArray = explode( ":", $tz );
$hrDiff = intval($tzArray[0]);
@@ -1505,7 +1514,7 @@
}
if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
- $t = mktime( (
+ $t = mktime( (
(int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
(int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
(int)substr( $ts, 12, 2 ), # Seconds
@@ -1514,26 +1523,26 @@
(int)substr( $ts, 0, 4 ) ); #Year
return date( 'YmdHis', $t );
}
-
+
function date( $ts, $adj = false )
{
global $wgAmericanDates, $wgUser, $wgUseDynamicDates;
if ( $adj ) { $ts = $this->userAdjust( $ts ); }
-
+
if ( $wgUseDynamicDates ) {
- $datePreference = $wgUser->getOption( 'date' );
+ $datePreference = $wgUser->getOption( 'date' );
if ( $datePreference == 0 ) {
$datePreference = $wgAmericanDates ? 1 : 2;
}
} else {
$datePreference = $wgAmericanDates ? 1 : 2;
}
-
+
$month = $this->getMonthAbbreviation( substr( $ts, 4, 2 ) );
$day = $this->formatNum( 0 + substr( $ts, 6, 2 ) );
$year = $this->formatNum( substr( $ts, 0, 4 ) );
-
+
switch( $datePreference ) {
case 1: return "$month $day, $year";
case 2: return "$day $month $year";
@@ -1546,7 +1555,7 @@
if ( $adj ) { $ts = $this->userAdjust( $ts ); }
$t = substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 );
- if ( $seconds ) {
+ if ( $seconds ) {
$t .= ':' . substr( $ts, 12, 2 );
}
return $this->formatNum( $t );
@@ -1585,7 +1594,7 @@
global $wgAllMessagesEn;
return @$wgAllMessagesEn[$key];
}
-
+
function getAllMessages()
{
global $wgAllMessagesEn;
@@ -1596,19 +1605,19 @@
# For most languages, this is a wrapper for iconv
return iconv( $in, $out, $string );
}
-
+
function ucfirst( $string ) {
# For most languages, this is a wrapper for ucfirst()
return ucfirst( $string );
}
-
+
function lcfirst( $s ) {
return strtolower( $s{0} ). substr( $s, 1 );
}
function checkTitleEncoding( $s ) {
global $wgInputEncoding;
-
+
# Check for UTF-8 URLs; Internet Explorer produces these if you
# type non-ASCII chars in the URL bar or follow unescaped links.
$ishigh = preg_match( '/[\x80-\xff]/', $s);
@@ -1617,15 +1626,15 @@
if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
return @iconv( 'UTF-8', $wgInputEncoding, $s );
-
+
if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
return utf8_encode( $s );
-
+
# Other languages can safely leave this function, or replace
# it with one to detect and convert another legacy encoding.
return $s;
}
-
+
function stripForSearch( $in ) {
# Some languages have special punctuation to strip out
# or characters which need to be converted for MySQL's
@@ -1635,7 +1644,7 @@
function firstChar( $s ) {
# Get the first character of a string. In ASCII, return
- # first byte of the string. UTF8 and others have to
+ # first byte of the string. UTF8 and others have to
# overload this.
return $s[0];
}
@@ -1686,7 +1695,7 @@
function linkPrefixExtension() { return false; }
- function &getMagicWords()
+ function &getMagicWords()
{
global $wgMagicWordsEn;
return $wgMagicWordsEn;
@@ -1695,7 +1704,7 @@
# Fill a MagicWord object with data from here
function getMagic( &$mw )
{
- $raw =& $this->getMagicWords();
+ $raw =& $this->getMagicWords();
if( !isset( $raw[$mw->mId] ) ) {
# Fall back to English if local list is incomplete
$raw =& Language::getMagicWords();
@@ -1711,7 +1720,7 @@
return '<em>'.$text.'</em>';
}
-
+
# Normally we use the plain ASCII digits. Some languages such as Arabic will
# want to output numbers using script-appropriate characters: override this
# function with a translator. See LanguageAr.php for an example.