Make sure we always expire cache unless user very explicitly turns it off by setting it to false
Make sure we always expire cache unless user very explicitly turns it off by setting it to false

file:a/README -> file:b/README
--- a/README
+++ b/README
@@ -79,3 +79,47 @@
 If you want to edit the text header that appears above the project list on the
 home page, edit templates/hometext.tpl.
 
+
+[Caching]
+
+To turn on caching, set the 'cache' config item to true.  Gitphp will cache
+every page's output, including plaintext output and binary output such as
+blobs and snapshots, for the number of seconds specified in the
+'cachelifetime' config key.
+The 'cacheexpire' key is recommended for most users.  With this option on,
+gitphp will attempt to keep the cache in sync by automatically expiring any
+cached pages that are older than the most recent commit, on any branch.
+It is a slight performance hit to make this check, but the performance hit
+is tiny compared to the gain you get from turning on caching.  It will
+avoid situations where users are getting a cached version of a page that
+isn't up to date and doesn't reflect the most recent commit, or worse,
+pages that have been cached at different times and show data from both
+before and after a commit (eg page 1 of the shortlog shows the most recent
+commit but page 1 of the log was cached a while ago and doesn't show the
+most recent commit).
+However, if your project is so active that commits are constantly coming in
+and invalidating the cache, rendering it useless, it would be better to
+turn cache expiration off and just set a really short cache lifetime of
+a few seconds.  In other words:
+
+Most users:
+* Set 'cacheexpire' to TRUE
+* Set 'cachelifetime' high, 3600 seconds (1 hour) or more.  -1 means
+  cache forever
+
+Extremely active projects, with commits every few seconds, or advanced
+users that know exactly how often commits come in and want to save
+the performance of the expiration check:
+* Set 'cacheexpire' to FALSE
+* Set 'cachelifetime' low, between 5-10 seconds.
+
+If you ever run into problems with your cache not syncing correctly, or
+showing out of date information, you can use the 'expire' action to force
+expiration of all cache.  This action is not linked anywhere because it
+is not supposed to be run by users, it's more of an administrative function.
+To use it, you want to set a=expire.  So, for example, you would visit this
+address in a browser (obviously with the correct path to your gitphp
+index.php):
+
+http://yourserver.com/gitphp/index.php?a=expire
+

file:b/cache/.gitignore (new)
--- /dev/null
+++ b/cache/.gitignore
@@ -1,1 +1,2 @@
+*
 

--- a/config/gitphp.conf.php.example
+++ b/config/gitphp.conf.php.example
@@ -176,11 +176,35 @@
 $gitphp_conf['debug'] = FALSE;
 
 /*
- * lang
- * Sets the language of the interface
- * Must be a valid translation in include/locale/
- */
-$gitphp_conf['lang'] = "en_US";
+ * cache
+ * Turns on smarty caching
+ * Be careful with this.  If in doubt, leave it off
+ */
+$gitphp_conf['cache'] = FALSE;
+
+/*
+ * cacheexpire
+ * Attempts to automatically expire cache when a new commit renders
+ * it out of date.
+ * This is a good option for most users because it ensures the cache
+ * is always up to date and users are seeing correct information,
+ * although it is a slight performance hit.
+ * However, if your commits are coming in so quickly that the cache
+ * is constantly being expired, turn this off.
+ */
+$gitphp_conf['cacheexpire'] = TRUE;
+
+/*
+ * cachelifetime
+ * Sets how long a page will be cached, in seconds
+ * If you are automatically expiring the cache
+ * (see the 'cacheexpire' option above), then this can be set
+ * relatively high - 3600 seconds (1 hour) or even longer.
+ * -1 means no timeout.
+ * If you have turned cacheexpire off because of too many
+ * cache expirations, set this low (5-10 seconds).
+ */
+$gitphp_conf['cachelifetime'] = 3600;
 
 /*
  * git_projects

--- /dev/null
+++ b/include/cache.cache_expire.php
@@ -1,1 +1,36 @@
+<?php
+/*
+ *  cache.cache_expire.pehe
+ *  gitphp: A PHP git repository browser
+ *  Component: Cache - cache expire
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ */
 
+require_once('gitutil.git_read_refs.php');
+
+function cache_expire($projectroot, $project, $projectlist, $expireall = false)
+{
+	global $tpl;
+
+	if ($expireall) {
+		$tpl->clear_all_cache();
+		return;
+	}
+
+	if ((!isset($projectroot)) || (!isset($project)))
+		return;
+
+	$headlist = git_read_refs($projectroot, $project, "refs/heads");
+
+	if (count($headlist) > 0) {
+		$age = $headlist[0]['age'];
+
+		$tpl->clear_cache(null, sha1($project), null, $age);
+
+		$tpl->clear_cache('projectlist.tpl', sha1(serialize($projectlist)), null, $age);
+	}
+}
+
+?>
+

--- a/include/defs.constants.php
+++ b/include/defs.constants.php
@@ -15,7 +15,5 @@
 define("GITPHP_COMPRESS_GZ", 2);
 define("GITPHP_COMPRESS_ZIP", 3);
 
-define("GITPHP_LOCALE_DIR", "include/locale/");
-
 ?>
 

--- a/include/display.git_blob.php
+++ b/include/display.git_blob.php
@@ -18,72 +18,77 @@
 function git_blob($projectroot, $project, $hash, $file, $hashbase)
 {
 	global $gitphp_conf,$tpl;
-	$head = git_read_head($projectroot . $project);
-	if (!isset($hashbase))
-		$hashbase = $head;
-	if (!isset($hash) && isset($file))
-		$hash = git_get_hash_by_path($projectroot . $project, $hashbase,$file,"blob");
-	$catout = git_cat_file($projectroot . $project, $hash);
-	$tpl->assign("hash",$hash);
-	$tpl->assign("hashbase",$hashbase);
-	$tpl->assign("head", $head);
-	if ($co = git_read_commit($projectroot . $project, $hashbase)) {
-		$tpl->assign("fullnav",TRUE);
-		$refs = read_info_ref($projectroot . $project);
-		$tpl->assign("tree",$co['tree']);
-		$tpl->assign("title",$co['title']);
-		if (isset($file))
-			$tpl->assign("file",$file);
-		if ($hashbase == "HEAD") {
-			if (isset($refs[$head]))
-				$tpl->assign("hashbaseref",$refs[$head]);
+
+	$cachekey = sha1($project) . "|" . $hashbase . "|" . $hash . "|" . sha1($file);
+
+	if (!$tpl->is_cached('blob.tpl',$cachekey)) {
+		$head = git_read_head($projectroot . $project);
+		if (!isset($hashbase))
+			$hashbase = $head;
+		if (!isset($hash) && isset($file))
+			$hash = git_get_hash_by_path($projectroot . $project, $hashbase,$file,"blob");
+		$catout = git_cat_file($projectroot . $project, $hash);
+		$tpl->assign("hash",$hash);
+		$tpl->assign("hashbase",$hashbase);
+		$tpl->assign("head", $head);
+		if ($co = git_read_commit($projectroot . $project, $hashbase)) {
+			$tpl->assign("fullnav",TRUE);
+			$refs = read_info_ref($projectroot . $project);
+			$tpl->assign("tree",$co['tree']);
+			$tpl->assign("title",$co['title']);
+			if (isset($file))
+				$tpl->assign("file",$file);
+			if ($hashbase == "HEAD") {
+				if (isset($refs[$head]))
+					$tpl->assign("hashbaseref",$refs[$head]);
+			} else {
+				if (isset($refs[$hashbase]))
+					$tpl->assign("hashbaseref",$refs[$hashbase]);
+			}
+		}
+		$paths = git_path_trees($projectroot . $project, $hashbase, $file);
+		$tpl->assign("paths",$paths);
+
+		if ($gitphp_conf['filemimetype']) {
+			$mime = file_mime($catout,$file);
+			if ($mime)
+				$mimetype = strtok($mime, "/");
+		}
+
+		if ($mimetype == "image") {
+			$tpl->assign("mime", $mime);
+			$tpl->assign("data", base64_encode($catout));
 		} else {
-			if (isset($refs[$hashbase]))
-				$tpl->assign("hashbaseref", $refs[$hashbase]);
-		}
-	}
-	$paths = git_path_trees($projectroot . $project, $hashbase, $file);
-	$tpl->assign("paths",$paths);
-
-	if ($gitphp_conf['filemimetype']) {
-		$mime = file_mime($catout,$file);
-		if ($mime)
-			$mimetype = strtok($mime, "/");
-	}
-
-	if ($mimetype == "image") {
-		$tpl->assign("mime", $mime);
-		$tpl->assign("data", base64_encode($catout));
-	} else {
-		$usedgeshi = $gitphp_conf['geshi'];
-		if ($usedgeshi) {
-			$usedgeshi = FALSE;
-			include_once($gitphp_conf['geshiroot'] . "geshi.php");
-			if (class_exists("GeSHi")) {
-				$geshi = new GeSHi("",'php');
-				if ($geshi) {
-					$lang = "";
-					if (isset($file))
-						$lang = $geshi->get_language_name_from_extension(substr(strrchr($file,'.'),1));
-					if (isset($lang) && (strlen($lang) > 0)) {
-						$geshi->set_source($catout);
-						$geshi->set_language($lang);
-						$geshi->set_header_type(GESHI_HEADER_DIV);
-						$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS);
-						$tpl->assign("geshiout",$geshi->parse_code());
-						$usedgeshi = TRUE;
+			$usedgeshi = $gitphp_conf['geshi'];
+			if ($usedgeshi) {
+				$usedgeshi = FALSE;
+				include_once($gitphp_conf['geshiroot'] . "geshi.php");
+				if (class_exists("GeSHi")) {
+					$geshi = new GeSHi("",'php');
+					if ($geshi) {
+						$lang = "";
+						if (isset($file))
+							$lang = $geshi->get_language_name_from_extension(substr(strrchr($file,'.'),1));
+						if (isset($lang) && (strlen($lang) > 0)) {
+							$geshi->set_source($catout);
+							$geshi->set_language($lang);
+							$geshi->set_header_type(GESHI_HEADER_DIV);
+							$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS);
+							$tpl->assign("geshiout",$geshi->parse_code());
+							$usedgeshi = TRUE;
+						}
 					}
 				}
 			}
-		}
 
-		if (!$usedgeshi) {
-			$lines = explode("\n",$catout);
-			$tpl->assign("lines",$lines);
+			if (!$usedgeshi) {
+				$lines = explode("\n",$catout);
+				$tpl->assign("lines",$lines);
+			}
 		}
 	}
 
-	$tpl->display("blob.tpl");
+	$tpl->display('blob.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_blob_plain.php
+++ b/include/display.git_blob_plain.php
@@ -12,26 +12,49 @@
 
 function git_blob_plain($projectroot,$project,$hash,$file)
 {
-	global $gitphp_conf;
+	global $gitphp_conf, $tpl;
 
-	if ($file)
-		$saveas = $file;
-	else
-		$saveas = $hash . ".txt";
+	$cachekey = sha1($project) . "|" . $hash . "|" . sha1($file);
 
-	$buffer = git_cat_file($projectroot . $project, $hash);
+	$buffer = null;
 
-	if ($gitphp_conf['filemimetype'])
-		$mime = file_mime($buffer, $file);
+	// XXX: Nasty hack to cache headers
+	if (!$tpl->is_cached('blobheaders.tpl', $cachekey)) {
+		if ($file)
+			$saveas = $file;
+		else
+			$saveas = $hash . ".txt";
 
-	if ($mime)
-		header("Content-type: " . $mime);
-	else
-		header("Content-type: text/plain; charset=UTF-8");
+		$buffer = git_cat_file($projectroot . $project, $hash);
 
-	header("Content-disposition: inline; filename=\"" . $saveas . "\"");
+		if ($gitphp_conf['filemimetype'])
+			$mime = file_mime($buffer, $file);
 
-	echo $buffer;
+		$headers = array();
+
+		if ($mime)
+			$headers[] = "Content-type: " . $mime;
+		else
+			$headers[] = "Content-type: text/plain; charset=UTF-8";
+
+		$headers[] = "Content-disposition: inline; filename=\"" . $saveas . "\"";
+
+		$tpl->assign("blobheaders", serialize($headers));
+	}
+	$out = $tpl->fetch('blobheaders.tpl', $cachekey);
+
+	$returnedheaders = unserialize($out);
+
+	foreach ($returnedheaders as $i => $header)
+		header($header);
+
+
+	if (!$tpl->is_cached('blobplain.tpl', $cachekey)) {
+		if (!$buffer)
+			$buffer = git_cat_file($projectroot . $project, $hash);
+		$tpl->assign("blob", $buffer);
+	}
+	$tpl->display('blobplain.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_blobdiff.php
+++ b/include/display.git_blobdiff.php
@@ -16,29 +16,34 @@
 function git_blobdiff($projectroot,$project,$hash,$hashbase,$hashparent,$file)
 {
 	global $tpl;
-	$ret = prep_tmpdir();
-	if ($ret !== TRUE) {
-		echo $ret;
-		return;
+
+	$cachekey = sha1($project) . "|" . $hashbase . "|" . $hash . "|" . $hashparent . "|" . sha1($file);
+
+	if (!$tpl->is_cached('blobdiff.tpl', $cachekey)) {
+		$ret = prep_tmpdir();
+		if ($ret !== TRUE) {
+			echo $ret;
+			return;
+		}
+		$tpl->assign("hash",$hash);
+		$tpl->assign("hashparent",$hashparent);
+		$tpl->assign("hashbase",$hashbase);
+		if (isset($file))
+			$tpl->assign("file",$file);
+		if ($co = git_read_commit($projectroot . $project, $hashbase)) {
+			$tpl->assign("fullnav",TRUE);
+			$tpl->assign("tree",$co['tree']);
+			$tpl->assign("title",$co['title']);
+			$refs = read_info_ref($projectroot . $project);
+			if (isset($refs[$hashbase]))
+				$tpl->assign("hashbaseref",$refs[$hashbase]);
+		}
+		$paths = git_path_trees($projectroot . $project, $hashbase, $file);
+		$tpl->assign("paths",$paths);
+		$diffout = explode("\n",git_diff($projectroot . $project, $hashparent,($file?$file:$hashparent),$hash,($file?$file:$hash)));
+		$tpl->assign("diff",$diffout);
 	}
-	$tpl->assign("hash",$hash);
-	$tpl->assign("hashparent",$hashparent);
-	$tpl->assign("hashbase",$hashbase);
-	if (isset($file))
-		$tpl->assign("file",$file);
-	if ($co = git_read_commit($projectroot . $project, $hashbase)) {
-		$tpl->assign("fullnav",TRUE);
-		$tpl->assign("tree",$co['tree']);
-		$tpl->assign("title",$co['title']);
-		$refs = read_info_ref($projectroot . $project);
-		if (isset($refs[$hashbase]))
-			$tpl->assign("hashbaseref",$refs[$hashbase]);
-	}
-	$paths = git_path_trees($projectroot . $project, $hashbase, $file);
-	$tpl->assign("paths",$paths);
-	$diffout = explode("\n",git_diff($projectroot . $project, $hashparent,($file?$file:$hashparent),$hash,($file?$file:$hash)));
-	$tpl->assign("diff",$diffout);
-	$tpl->display("blobdiff.tpl");
+	$tpl->display('blobdiff.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_blobdiff_plain.php
+++ b/include/display.git_blobdiff_plain.php
@@ -12,13 +12,21 @@
 
 function git_blobdiff_plain($projectroot,$project,$hash,$hashbase,$hashparent,$file)
 {
-	$ret = prep_tmpdir();
-	if ($ret !== TRUE) {
-		echo $ret;
-		return;
+	global $tpl;
+
+	header("Content-type: text/plain; charset=UTF-8");
+
+	$cachekey = sha1($project) . "|" . $hashbase . "|" . $hash . "|" . $hashparent . "|" . sha1($file);
+
+	if (!$tpl->is_cached('blobdiffplain.tpl', $cachekey)) {
+		$ret = prep_tmpdir();
+		if ($ret !== TRUE) {
+			echo $ret;
+			return;
+		}
+		$tpl->assign("blobdiff",git_diff($projectroot . $project, $hashparent,($file?"a/".$file:$hashparent),$hash,($file?"b/".$file:$hash)));
 	}
-	header("Content-type: text/plain; charset=UTF-8");
-	echo git_diff($projectroot . $project, $hashparent,($file?"a/".$file:$hashparent),$hash,($file?"b/".$file:$hash));
+	$tpl->display('blobdiffplain.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_commit.php
+++ b/include/display.git_commit.php
@@ -16,77 +16,83 @@
 function git_commit($projectroot,$project,$hash)
 {
 	global $tpl;
-	$co = git_read_commit($projectroot . $project, $hash);
-	$ad = date_str($co['author_epoch'],$co['author_tz']);
-	$cd = date_str($co['committer_epoch'],$co['committer_tz']);
-	if (isset($co['parent'])) {
-		$root = "";
-		$parent = $co['parent'];
-	} else {
-		$root = "--root";
-		$parent = "";
+
+	$cachekey = sha1($project) . "|" . $hash;
+
+	if (!$tpl->is_cached('commit.tpl', $cachekey)) {
+		$co = git_read_commit($projectroot . $project, $hash);
+		$ad = date_str($co['author_epoch'],$co['author_tz']);
+		$cd = date_str($co['committer_epoch'],$co['committer_tz']);
+		if (isset($co['parent'])) {
+			$root = "";
+			$parent = $co['parent'];
+		} else {
+			$root = "--root";
+			$parent = "";
+		}
+		$diffout = git_diff_tree($projectroot . $project, $root . " " . $parent . " " . $hash, TRUE);
+		$difftree = explode("\n",$diffout);
+		$tpl->assign("hash",$hash);
+		$tpl->assign("tree",$co['tree']);
+		if (isset($co['parent']))
+			$tpl->assign("parent",$co['parent']);
+		$tpl->assign("title",$co['title']);
+		$refs = read_info_ref($projectroot . $project);
+		if (isset($refs[$co['id']]))
+			$tpl->assign("commitref",$refs[$co['id']]);
+		$tpl->assign("author",$co['author']);
+		$tpl->assign("adrfc2822",$ad['rfc2822']);
+		$tpl->assign("adhourlocal",$ad['hour_local']);
+		$tpl->assign("adminutelocal",$ad['minute_local']);
+		$tpl->assign("adtzlocal",$ad['tz_local']);
+		$tpl->assign("committer",$co['committer']);
+		$tpl->assign("cdrfc2822",$cd['rfc2822']);
+		$tpl->assign("cdhourlocal",$cd['hour_local']);
+		$tpl->assign("cdminutelocal",$cd['minute_local']);
+		$tpl->assign("cdtzlocal",$cd['tz_local']);
+		$tpl->assign("id",$co['id']);
+		$tpl->assign("parents",$co['parents']);
+		$tpl->assign("comment",$co['comment']);
+		$tpl->assign("difftreesize",count($difftree)+1);
+		$difftreelines = array();
+		foreach ($difftree as $i => $line) {
+			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$line,$regs)) {
+				$difftreeline = array();
+				$difftreeline["from_mode"] = $regs[1];
+				$difftreeline["to_mode"] = $regs[2];
+				$difftreeline["from_mode_cut"] = substr($regs[1],-4);
+				$difftreeline["to_mode_cut"] = substr($regs[2],-4);
+				$difftreeline["from_id"] = $regs[3];
+				$difftreeline["to_id"] = $regs[4];
+				$difftreeline["status"] = $regs[5];
+				$difftreeline["similarity"] = ltrim($regs[6],"0");
+				$difftreeline["file"] = $regs[7];
+				$difftreeline["from_file"] = strtok($regs[7],"\t");
+				$difftreeline["from_filetype"] = file_type($regs[1]);
+				$difftreeline["to_file"] = strtok("\t");
+				$difftreeline["to_filetype"] = file_type($regs[2]);
+				if ((octdec($regs[2]) & 0x8000) == 0x8000)
+					$difftreeline["isreg"] = TRUE;
+				$modestr = "";
+				if ((octdec($regs[1]) & 0x17000) != (octdec($regs[2]) & 0x17000))
+					$modestr .= " from " . file_type($regs[1]) . " to " . file_type($regs[2]);
+				if ((octdec($regs[1]) & 0777) != (octdec($regs[2]) & 0777)) {
+					if ((octdec($regs[1]) & 0x8000) && (octdec($regs[2]) & 0x8000))
+						$modestr .= " mode: " . (octdec($regs[1]) & 0777) . "->" . (octdec($regs[2]) & 0777);
+					else if (octdec($regs[2]) & 0x8000)
+						$modestr .= " mode: " . (octdec($regs[2]) & 0777);
+				}
+				$difftreeline["modechange"] = $modestr;
+				$simmodechg = "";
+				if ($regs[1] != $regs[2])
+					$simmodechg .= ", mode: " . (octdec($regs[2]) & 0777);
+				$difftreeline["simmodechg"] = $simmodechg;
+				$difftreelines[] = $difftreeline;
+			}
+		}
+		$tpl->assign("difftreelines",$difftreelines);
 	}
-	$diffout = git_diff_tree($projectroot . $project, $root . " " . $parent . " " . $hash, TRUE);
-	$difftree = explode("\n",$diffout);
-	$tpl->assign("hash",$hash);
-	$tpl->assign("tree",$co['tree']);
-	if (isset($co['parent']))
-		$tpl->assign("parent",$co['parent']);
-	$tpl->assign("title",$co['title']);
-	$refs = read_info_ref($projectroot . $project);
-	if (isset($refs[$co['id']]))
-		$tpl->assign("commitref",$refs[$co['id']]);
-	$tpl->assign("author",$co['author']);
-	$tpl->assign("adrfc2822",$ad['rfc2822']);
-	$tpl->assign("adhourlocal",$ad['hour_local']);
-	$tpl->assign("adminutelocal",$ad['minute_local']);
-	$tpl->assign("adtzlocal",$ad['tz_local']);
-	$tpl->assign("committer",$co['committer']);
-	$tpl->assign("cdrfc2822",$cd['rfc2822']);
-	$tpl->assign("cdhourlocal",$cd['hour_local']);
-	$tpl->assign("cdminutelocal",$cd['minute_local']);
-	$tpl->assign("cdtzlocal",$cd['tz_local']);
-	$tpl->assign("id",$co['id']);
-	$tpl->assign("parents",$co['parents']);
-	$tpl->assign("comment",$co['comment']);
-	$tpl->assign("difftreesize",count($difftree)+1);
-	$difftreelines = array();
-	foreach ($difftree as $i => $line) {
-		if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$line,$regs)) {
-			$difftreeline = array();
-			$difftreeline["from_mode"] = $regs[1];
-			$difftreeline["to_mode"] = $regs[2];
-			$difftreeline["from_mode_cut"] = substr($regs[1],-4);
-			$difftreeline["to_mode_cut"] = substr($regs[2],-4);
-			$difftreeline["from_id"] = $regs[3];
-			$difftreeline["to_id"] = $regs[4];
-			$difftreeline["status"] = $regs[5];
-			$difftreeline["similarity"] = ltrim($regs[6],"0");
-			$difftreeline["file"] = $regs[7];
-			$difftreeline["from_file"] = strtok($regs[7],"\t");
-			$difftreeline["from_filetype"] = file_type($regs[1]);
-			$difftreeline["from_filetype_localized"] = lookupstring($difftreeline["from_filetype"]);
-			$difftreeline["to_file"] = strtok("\t");
-			$difftreeline["to_filetype"] = file_type($regs[2]);
-			$difftreeline["to_filetype_localized"] = lookupstring($difftreeline["to_filetype"]);
-			if ((octdec($regs[2]) & 0x8000) == 0x8000)
-				$difftreeline["isreg"] = TRUE;
-			$modestr = "";
-			if ((octdec($regs[1]) & 0x17000) != (octdec($regs[2]) & 0x17000))
-				$difftreeline["typechange"] = TRUE;
-			if ((octdec($regs[1]) & 0777) != (octdec($regs[2]) & 0777)) {
-				if ((octdec($regs[1]) & 0x8000) && (octdec($regs[2]) & 0x8000))
-					$difftreeline["modechange"] = (octdec($regs[1]) & 0777) . "->" . (octdec($regs[2]) & 0777);
-				else if (octdec($regs[2]) & 0x8000)
-					$difftreeline["modechange"] = (octdec($regs[2]) & 0777);
-			}
-			if ($regs[1] != $regs[2])
-				$difftreeline["simmodechg"] = (octdec($regs[2]) & 0777);
-			$difftreelines[] = $difftreeline;
-		}
-	}
-	$tpl->assign("difftreelines",$difftreelines);
-	$tpl->display("commit.tpl");
+	$tpl->display('commit.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_commitdiff.php
+++ b/include/display.git_commitdiff.php
@@ -13,54 +13,56 @@
  require_once('gitutil.git_diff_tree.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_diff.php');
- require_once('i18n.lookupstring.php');
 
 function git_commitdiff($projectroot,$project,$hash,$hash_parent)
 {
 	global $tpl;
-	$ret = prep_tmpdir();
-	if ($ret !== TRUE) {
-		echo $ret;
-		return;
+
+	$cachekey = sha1($project) . "|" . $hash . "|" . $hash_parent;
+
+	if (!$tpl->is_cached('commitdiff.tpl', $cachekey)) {
+		$ret = prep_tmpdir();
+		if ($ret !== TRUE) {
+			echo $ret;
+			return;
+		}
+		$co = git_read_commit($projectroot . $project, $hash);
+		if (!isset($hash_parent))
+			$hash_parent = $co['parent'];
+		$diffout = git_diff_tree($projectroot . $project, $hash_parent . " " . $hash);
+		$difftree = explode("\n",$diffout);
+		$refs = read_info_ref($projectroot . $project);
+		$tpl->assign("hash",$hash);
+		$tpl->assign("tree",$co['tree']);
+		$tpl->assign("hashparent",$hash_parent);
+		$tpl->assign("title",$co['title']);
+		if (isset($refs[$co['id']]))
+			$tpl->assign("commitref",$refs[$co['id']]);
+		$tpl->assign("comment",$co['comment']);
+		$difftreelines = array();
+		foreach ($difftree as $i => $line) {
+			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
+				$difftreeline = array();
+				$difftreeline["from_mode"] = $regs[1];
+				$difftreeline["to_mode"] = $regs[2];
+				$difftreeline["from_id"] = $regs[3];
+				$difftreeline["to_id"] = $regs[4];
+				$difftreeline["status"] = $regs[5];
+				$difftreeline["file"] = $regs[6];
+				$difftreeline["from_type"] = file_type($regs[1]);
+				$difftreeline["to_type"] = file_type($regs[2]);
+				if ($regs[5] == "A")
+					$difftreeline['diffout'] = explode("\n",git_diff($projectroot . $project, null,"/dev/null",$regs[4],"b/" . $regs[6]));
+				else if ($regs[5] == "D")
+					$difftreeline['diffout'] = explode("\n",git_diff($projectroot . $project, $regs[3],"a/" . $regs[6],null,"/dev/null"));
+				else if (($regs[5] == "M") && ($regs[3] != $regs[4]))
+					$difftreeline['diffout'] = explode("\n",git_diff($projectroot . $project, $regs[3],"a/" . $regs[6],$regs[4],"b/" . $regs[6]));
+				$difftreelines[] = $difftreeline;
+			}
+		}
+		$tpl->assign("difftreelines",$difftreelines);
 	}
-	$co = git_read_commit($projectroot . $project, $hash);
-	if (!isset($hash_parent))
-		$hash_parent = $co['parent'];
-	$diffout = git_diff_tree($projectroot . $project, $hash_parent . " " . $hash);
-	$difftree = explode("\n",$diffout);
-	$refs = read_info_ref($projectroot . $project);
-	$tpl->assign("hash",$hash);
-	$tpl->assign("tree",$co['tree']);
-	$tpl->assign("hashparent",$hash_parent);
-	$tpl->assign("title",$co['title']);
-	if (isset($refs[$co['id']]))
-		$tpl->assign("commitref",$refs[$co['id']]);
-	$tpl->assign("comment",$co['comment']);
-	$difftreelines = array();
-	foreach ($difftree as $i => $line) {
-		if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
-			$difftreeline = array();
-			$difftreeline["from_mode"] = $regs[1];
-			$difftreeline["to_mode"] = $regs[2];
-			$difftreeline["from_id"] = $regs[3];
-			$difftreeline["to_id"] = $regs[4];
-			$difftreeline["status"] = $regs[5];
-			$difftreeline["file"] = $regs[6];
-			$difftreeline["from_type"] = file_type($regs[1]);
-			$difftreeline["to_type"] = file_type($regs[2]);
-			$difftreeline["from_type_localized"] = lookupstring($difftreeline["from_type"]);
-			$difftreeline["to_type_localized"] = lookupstring($difftreeline["to_type"]);
-			if ($regs[5] == "A")
-				$difftreeline['diffout'] = explode("\n",git_diff($projectroot . $project, null,"/dev/null",$regs[4],"b/" . $regs[6]));
-			else if ($regs[5] == "D")
-				$difftreeline['diffout'] = explode("\n",git_diff($projectroot . $project, $regs[3],"a/" . $regs[6],null,"/dev/null"));
-			else if (($regs[5] == "M") && ($regs[3] != $regs[4]))
-				$difftreeline['diffout'] = explode("\n",git_diff($projectroot . $project, $regs[3],"a/" . $regs[6],$regs[4],"b/" . $regs[6]));
-			$difftreelines[] = $difftreeline;
-		}
-	}
-	$tpl->assign("difftreelines",$difftreelines);
-	$tpl->display("commitdiff.tpl");
+	$tpl->display('commitdiff.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_commitdiff_plain.php
+++ b/include/display.git_commitdiff_plain.php
@@ -12,56 +12,60 @@
  require_once('util.script_url.php');
  require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_diff_tree.php');
- require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_read_revlist.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_diff.php');
 
 function git_commitdiff_plain($projectroot,$project,$hash,$hash_parent)
 {
 	global $tpl;
-	$ret = prep_tmpdir();
-	if ($ret !== TRUE) {
-		echo $ret;
-		return;
-	}
-	$co = git_read_commit($projectroot . $project, $hash);
-	if (!isset($hash_parent))
-		$hash_parent = $co['parent'];
-	$diffout = git_diff_tree($projectroot . $project, $hash_parent . " " . $hash);
-	$difftree = explode("\n",$diffout);
-	$refs = read_info_ref($projectroot . $project,"tags");
-	$listout = git_rev_list($projectroot . $project, "HEAD");
-	$tok = strtok($listout,"\n");
-	while ($tok !== false) {
-		if (isset($refs[$tok]))
-			$tagname = $refs[$tok];
-		if ($tok == $hash)
-			break;
-		$tok = strtok("\n");
-	}
+
+	$cachekey = sha1($project) . "|" . $hash . "|" . $hash_parent;
+
 	header("Content-type: text/plain; charset=UTF-8");
 	header("Content-disposition: inline; filename=\"git-" . $hash . ".patch\"");
-	$ad = date_str($co['author_epoch'],$co['author_tz']);
-	$tpl->assign("from",$co['author']);
-	$tpl->assign("date",$ad['rfc2822']);
-	$tpl->assign("subject",$co['title']);
-	if (isset($tagname))
-		$tpl->assign("tagname",$tagname);
-	$tpl->assign("url",script_url() . "?p=" . $project . "&a=commitdiff&h=" . $hash);
-	$tpl->assign("comment",$co['comment']);
-	$diffs = array();
-	foreach ($difftree as $i => $line) {
-		if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
-			if ($regs[5] == "A")
-				$diffs[] = git_diff($projectroot . $project, null, "/dev/null", $regs[4], "b/" . $regs[6]);
-			else if ($regs[5] == "D")
-				$diffs[] = git_diff($projectroot . $project, $regs[3], "a/" . $regs[6], null, "/dev/null");
-			else if ($regs[5] == "M")
-				$diffs[] = git_diff($projectroot . $project, $regs[3], "a/" . $regs[6], $regs[4], "b/" . $regs[6]);
+
+	if (!$tpl->is_cached('diff_plaintext.tpl', $cachekey)) {
+		$ret = prep_tmpdir();
+		if ($ret !== TRUE) {
+			echo $ret;
+			return;
 		}
+		$co = git_read_commit($projectroot . $project, $hash);
+		if (!isset($hash_parent))
+			$hash_parent = $co['parent'];
+		$diffout = git_diff_tree($projectroot . $project, $hash_parent . " " . $hash);
+		$difftree = explode("\n",$diffout);
+		$refs = read_info_ref($projectroot . $project,"tags");
+		$listout = git_read_revlist($projectroot . $project, "HEAD");
+		foreach ($listout as $i => $rev) {
+			if (isset($refs[$rev]))
+				$tagname = $refs[$rev];
+			if ($rev == $hash)
+				break;
+		}
+		$ad = date_str($co['author_epoch'],$co['author_tz']);
+		$tpl->assign("from",$co['author']);
+		$tpl->assign("date",$ad['rfc2822']);
+		$tpl->assign("subject",$co['title']);
+		if (isset($tagname))
+			$tpl->assign("tagname",$tagname);
+		$tpl->assign("url",script_url() . "?p=" . $project . "&a=commitdiff&h=" . $hash);
+		$tpl->assign("comment",$co['comment']);
+		$diffs = array();
+		foreach ($difftree as $i => $line) {
+			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
+				if ($regs[5] == "A")
+					$diffs[] = git_diff($projectroot . $project, null, "/dev/null", $regs[4], "b/" . $regs[6]);
+				else if ($regs[5] == "D")
+					$diffs[] = git_diff($projectroot . $project, $regs[3], "a/" . $regs[6], null, "/dev/null");
+				else if ($regs[5] == "M")
+					$diffs[] = git_diff($projectroot . $project, $regs[3], "a/" . $regs[6], $regs[4], "b/" . $regs[6]);
+			}
+		}
+		$tpl->assign("diffs",$diffs);
 	}
-	$tpl->assign("diffs",$diffs);
-	$tpl->display("diff_plaintext.tpl");
+	$tpl->display('diff_plaintext.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_heads.php
+++ b/include/display.git_heads.php
@@ -13,11 +13,16 @@
 function git_heads($projectroot,$project)
 {
 	global $tpl;
-	$head = git_read_head($projectroot . $project);
-	$tpl->assign("head",$head);
-	$headlist = git_read_refs($projectroot, $project, "refs/heads");
-	$tpl->assign("headlist",$headlist);
-	$tpl->display("heads.tpl");
+
+	$cachekey = sha1($project);
+
+	if (!$tpl->is_cached('heads.tpl', $cachekey)) {
+		$head = git_read_head($projectroot . $project);
+		$tpl->assign("head",$head);
+		$headlist = git_read_refs($projectroot, $project, "refs/heads");
+		$tpl->assign("headlist",$headlist);
+	}
+	$tpl->display('heads.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_history.php
+++ b/include/display.git_history.php
@@ -17,46 +17,51 @@
 function git_history($projectroot,$project,$hash,$file)
 {
 	global $tpl;
-	if (!isset($hash))
-		$hash = git_read_head($projectroot . $project);
-	$co = git_read_commit($projectroot . $project, $hash);
-	$refs = read_info_ref($projectroot . $project);
-	$tpl->assign("hash",$hash);
-	if (isset($refs[$hash]))
-		$tpl->assign("hashbaseref",$refs[$hash]);
-	$tpl->assign("tree",$co['tree']);
-	$tpl->assign("title",$co['title']);
-	$paths = git_path_trees($projectroot . $project, $hash, $file);
-	$tpl->assign("paths",$paths);
-	$cmdout = git_history_list($projectroot . $project, $hash, $file);
-	$lines = explode("\n", $cmdout);
-	$historylines = array();
-	foreach ($lines as $i => $line) {
-		if (ereg("^([0-9a-fA-F]{40})",$line,$regs))
-			$commit = $regs[1];
-		else if (ereg(":([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs) && isset($commit)) {
-				$historyline = array();
-				$co = git_read_commit($projectroot . $project, $commit);
-				$historyline["agestringage"] = $co['age_string_age'];
-				$historyline["agestringdate"] = $co['age_string_date'];
-				$historyline["authorname"] = $co['author_name'];
-				$historyline["commit"] = $commit;
-				$historyline["file"] = $file;
-				$historyline["title"] = $co['title_short'];
-				if (isset($refs[$commit]))
-					$historyline["commitref"] = $refs[$commit];
-				$blob = git_get_hash_by_path($projectroot . $project, $hash,$file);
-				$blob_parent = git_get_hash_by_path($projectroot . $project, $commit,$file);
-				if ($blob && $blob_parent && ($blob != $blob_parent)) {
-					$historyline["blob"] = $blob;
-					$historyline["blobparent"] = $blob_parent;
-				}
-				$historylines[] = $historyline;
-				unset($commit);
+
+	$cachekey = sha1($project) . "|" . $hash . "|" . sha1($file);
+
+	if (!$tpl->is_cached('history.tpl', $cachekey)) {
+		if (!isset($hash))
+			$hash = git_read_head($projectroot . $project);
+		$co = git_read_commit($projectroot . $project, $hash);
+		$refs = read_info_ref($projectroot . $project);
+		$tpl->assign("hash",$hash);
+		if (isset($refs[$hash]))
+			$tpl->assign("hashbaseref",$refs[$hash]);
+		$tpl->assign("tree",$co['tree']);
+		$tpl->assign("title",$co['title']);
+		$paths = git_path_trees($projectroot . $project, $hash, $file);
+		$tpl->assign("paths",$paths);
+		$cmdout = git_history_list($projectroot . $project, $hash, $file);
+		$lines = explode("\n", $cmdout);
+		$historylines = array();
+		foreach ($lines as $i => $line) {
+			if (ereg("^([0-9a-fA-F]{40})",$line,$regs))
+				$commit = $regs[1];
+			else if (ereg(":([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs) && isset($commit)) {
+					$historyline = array();
+					$co = git_read_commit($projectroot . $project, $commit);
+					$historyline["agestringage"] = $co['age_string_age'];
+					$historyline["agestringdate"] = $co['age_string_date'];
+					$historyline["authorname"] = $co['author_name'];
+					$historyline["commit"] = $commit;
+					$historyline["file"] = $file;
+					$historyline["title"] = $co['title_short'];
+					if (isset($refs[$commit]))
+						$historyline["commitref"] = $refs[$commit];
+					$blob = git_get_hash_by_path($projectroot . $project, $hash,$file);
+					$blob_parent = git_get_hash_by_path($projectroot . $project, $commit,$file);
+					if ($blob && $blob_parent && ($blob != $blob_parent)) {
+						$historyline["blob"] = $blob;
+						$historyline["blobparent"] = $blob_parent;
+					}
+					$historylines[] = $historyline;
+					unset($commit);
+			}
 		}
+		$tpl->assign("historylines",$historylines);
 	}
-	$tpl->assign("historylines",$historylines);
-	$tpl->display("history.tpl");
+	$tpl->display('history.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_log.php
+++ b/include/display.git_log.php
@@ -16,51 +16,56 @@
 function git_log($projectroot,$project,$hash,$page)
 {
 	global $tpl;
-	$head = git_read_head($projectroot . $project);
-	if (!isset($hash))
-		$hash = $head;
-	if (!isset($page))
-		$page = 0;
-	$refs = read_info_ref($projectroot . $project);
-	$tpl->assign("hash",$hash);
-	$tpl->assign("head",$head);
 
-	if ($page)
-		$tpl->assign("page",$page);
+	$cachekey = sha1($project) . "|" . $hash . "|" . (isset($page) ? $page : 0);
 
-	$revlist = git_read_revlist($projectroot . $project, $hash, 101, ($page * 100));
+	if (!$tpl->is_cached('log.tpl', $cachekey)) {
+		$head = git_read_head($projectroot . $project);
+		if (!isset($hash))
+			$hash = $head;
+		if (!isset($page))
+			$page = 0;
+		$refs = read_info_ref($projectroot . $project);
+		$tpl->assign("hash",$hash);
+		$tpl->assign("head",$head);
 
-	$revlistcount = count($revlist);
-	$tpl->assign("revlistcount",$revlistcount);
+		if ($page)
+			$tpl->assign("page",$page);
 
-	if (!$revlist) {
-		$tpl->assign("norevlist",TRUE);
-		$co = git_read_commit($hash);
-		$tpl->assign("lastchange",$co['age_string']);
+		$revlist = git_read_revlist($projectroot . $project, $hash, 101, ($page * 100));
+
+		$revlistcount = count($revlist);
+		$tpl->assign("revlistcount",$revlistcount);
+
+		if (!$revlist) {
+			$tpl->assign("norevlist",TRUE);
+			$co = git_read_commit($hash);
+			$tpl->assign("lastchange",$co['age_string']);
+		}
+
+		$commitlines = array();
+		$commitcount = min(100,$revlistcount);
+		for ($i = 0; $i < $commitcount; $i++) {
+			$commit = $revlist[$i];
+			if (isset($commit) && strlen($commit) > 1) {
+				$commitline = array();
+				$co = git_read_commit($projectroot . $project, $commit);
+				$ad = date_str($co['author_epoch']);
+				$commitline["project"] = $project;
+				$commitline["commit"] = $commit;
+				if (isset($refs[$commit]))
+					$commitline["commitref"] = $refs[$commit];
+				$commitline["agestring"] = $co['age_string'];
+				$commitline["title"] = $co['title'];
+				$commitline["authorname"] = $co['author_name'];
+				$commitline["rfc2822"] = $ad['rfc2822'];
+				$commitline["comment"] = $co['comment'];
+				$commitlines[] = $commitline;
+			}
+		}
+		$tpl->assign("commitlines",$commitlines);
 	}
-
-	$commitlines = array();
-	$commitcount = min(100,$revlistcount);
-	for ($i = 0; $i < $commitcount; $i++) {
-		$commit = $revlist[$i];
-		if (isset($commit) && strlen($commit) > 1) {
-			$commitline = array();
-			$co = git_read_commit($projectroot . $project, $commit);
-			$ad = date_str($co['author_epoch']);
-			$commitline["project"] = $project;
-			$commitline["commit"] = $commit;
-			if (isset($refs[$commit]))
-				$commitline["commitref"] = $refs[$commit];
-			$commitline["agestring"] = $co['age_string'];
-			$commitline["title"] = $co['title'];
-			$commitline["authorname"] = $co['author_name'];
-			$commitline["rfc2822"] = $ad['rfc2822'];
-			$commitline["comment"] = $co['comment'];
-			$commitlines[] = $commitline;
-		}
-	}
-	$tpl->assign("commitlines",$commitlines);
-	$tpl->display("log.tpl");
+	$tpl->display('log.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_message.php
+++ b/include/display.git_message.php
@@ -10,12 +10,17 @@
 function git_message($message, $error = FALSE, $standalone = TRUE)
 {
 	global $tpl;
-	$tpl->assign("message",$message);
-	if ($error)
-		$tpl->assign("error", TRUE);
-	if ($standalone)
-		$tpl->assign("standalone", TRUE);
-	$tpl->display("message.tpl");
+
+	$cachekey = sha1($message) . "|" . ($error ? "1" : "0") . "|" . ($standalone ? "1" : "0");
+
+	if (!$tpl->is_cached('message.tpl', $cachekey)) {
+		$tpl->assign("message",$message);
+		if ($error)
+			$tpl->assign("error", TRUE);
+		if ($standalone)
+			$tpl->assign("standalone", TRUE);
+	}
+	$tpl->display('message.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_opml.php
+++ b/include/display.git_opml.php
@@ -13,22 +13,27 @@
 function git_opml($projectroot,$projectlist)
 {
 	global $tpl,$gitphp_conf;
-	$projlist = git_read_projects($projectroot,$projectlist);
-	header("Content-type: text/xml; charset=UTF-8");
-	$tpl->assign("title",$gitphp_conf['title']);
-	$tpl->assign("self",script_url());
-	$opmllist = array();
-	foreach ($projlist as $cat => $plist) {
-		if (is_array($plist)) {
-			foreach ($plist as $i => $proj) {
-				$opmllist[] = $proj;
+
+	$cachekey = sha1(serialize($projectlist));
+
+	if (!$tpl->is_cached('opml.tpl', $cachekey)) {
+		header("Content-type: text/xml; charset=UTF-8");
+		$projlist = git_read_projects($projectroot,$projectlist);
+		$tpl->assign("title",$gitphp_conf['title']);
+		$tpl->assign("self",script_url());
+		$opmllist = array();
+		foreach ($projlist as $cat => $plist) {
+			if (is_array($plist)) {
+				foreach ($plist as $i => $proj) {
+					$opmllist[] = $proj;
+				}
+			} else {
+				$opmllist[] = $plist;
 			}
-		} else {
-			$opmllist[] = $plist;
 		}
+		$tpl->assign("opmllist",$opmllist);
 	}
-	$tpl->assign("opmllist",$opmllist);
-	$tpl->display("opml.tpl");
+	$tpl->display('opml.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_project_index.php
+++ b/include/display.git_project_index.php
@@ -11,16 +11,20 @@
 
 function git_project_index($projectroot, $projectlist)
 {
-	$projlist = git_read_projects($projectroot, $projectlist);
+	global $tpl, $git_projects;
+
 	header("Content-type: text/plain; charset=utf-8");
 	header("Content-Disposition: inline; filename=\"index.aux\"");
-	foreach ($projlist as $cat => $plist) {
-		if (is_array($plist)) {
-			foreach ($plist as $i => $proj)
-				echo $proj . "\n";
-		} else
-			echo $plist . "\n";
+
+	$cachekey = sha1(serialize($projectlist));
+
+	if (!$tpl->is_cached('projectindex.tpl', $cachekey)) {
+		if (isset($git_projects))
+			$tpl->assign("categorized", TRUE);
+		$projlist = git_read_projects($projectroot, $projectlist);
+		$tpl->assign("projlist", $projlist);
 	}
+	$tpl->display('projectindex.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_project_list.php
+++ b/include/display.git_project_list.php
@@ -11,61 +11,65 @@
  require_once('util.descrcmp.php');
  require_once('util.ownercmp.php');
  require_once('util.agecmp.php');
- require_once('i18n.lookupstring.php');
  require_once('gitutil.git_read_projects.php');
 
 function git_project_list($projectroot,$projectlist,$order = "project")
 {
 	global $tpl,$git_projects;
-	$projects = git_read_projects($projectroot,$projectlist, TRUE);
-	if (is_array($projects)) {
-		if (count($projects) > 0) {
-			if ($order)
-				$tpl->assign("order",$order);
-			if (!isset($git_projects)) {
-				switch ($order) {
-					case "project":
-						usort($projects,"projectcmp");
-						break;
-					case "descr":
-						usort($projects,"descrcmp");
-						break;
-					case "owner":
-						usort($projects,"ownercmp");
-						break;
-					case "age":
-						usort($projects,"agecmp");
-						break;
-				}
-				$tpl->assign("projects",$projects);
-			} else {
-				foreach ($projects as $cat => $plist) {
+
+	$cachekey = sha1(serialize($projectlist)) . "|" . sha1($order);
+
+	if (!$tpl->is_cached('projectlist.tpl', $cachekey)) {
+		$projects = git_read_projects($projectroot,$projectlist, TRUE);
+		if (is_array($projects)) {
+			if (count($projects) > 0) {
+				if ($order)
+					$tpl->assign("order",$order);
+				if (!isset($git_projects)) {
 					switch ($order) {
 						case "project":
-							usort($projects[$cat],"projectcmp");
+							usort($projects,"projectcmp");
 							break;
 						case "descr":
-							usort($projects[$cat],"descrcmp");
+							usort($projects,"descrcmp");
 							break;
 						case "owner":
-							usort($projects[$cat],"ownercmp");
+							usort($projects,"ownercmp");
 							break;
 						case "age":
-							usort($projects[$cat],"agecmp");
+							usort($projects,"agecmp");
 							break;
 					}
+					$tpl->assign("projects",$projects);
+				} else {
+					foreach ($projects as $cat => $plist) {
+						switch ($order) {
+							case "project":
+								usort($projects[$cat],"projectcmp");
+								break;
+							case "descr":
+								usort($projects[$cat],"descrcmp");
+								break;
+							case "owner":
+								usort($projects[$cat],"ownercmp");
+								break;
+							case "age":
+								usort($projects[$cat],"agecmp");
+								break;
+						}
+					}
+					$tpl->assign("categorizedprojects",$projects);
 				}
-				$tpl->assign("categorizedprojects",$projects);
+			} else {
+				$tpl->assign("message","No projects found");
+				$tpl->assign("error",TRUE);
 			}
 		} else {
-			$tpl->assign("message",lookupstring("No projects found"));
+			$tpl->assign("message",$projects);
 			$tpl->assign("error",TRUE);
 		}
-	} else {
-		$tpl->assign("message",$projects);
-		$tpl->assign("error",TRUE);
 	}
-	$tpl->display("projectlist.tpl");
+	$tpl->display('projectlist.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_rss.php
+++ b/include/display.git_rss.php
@@ -18,41 +18,46 @@
 function git_rss($projectroot,$project)
 {
 	global $tpl;
-	$head = git_read_head($projectroot . $project);
-	$revlist = git_read_revlist($projectroot . $project, $head, GITPHP_RSS_ITEMS);
 	header("Content-type: text/xml; charset=UTF-8");
-	$tpl->assign("self",script_url());
 
-	$commitlines = array();
-	for ($i = 0; $i <= count($revlist); $i++) {
-		$commit = $revlist[$i];
-		$co = git_read_commit($projectroot . $project, $commit);
-		if (($i >= 20) && ((time() - $co['committer_epoch']) > 48*60*60))
-			break;
-		$cd = date_str($co['committer_epoch']);
-		$difftree = array();
-		$diffout = git_diff_tree($projectroot . $project, $co['parent'] . " " . $co['id']);
-		$tok = strtok($diffout,"\n");
-		while ($tok !== false) {
-			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$tok,$regs))
-				$difftree[] = $regs[7];
-			$tok = strtok("\n");
+	$cachekey = sha1($project);
+
+	if (!$tpl->is_cached('rss.tpl', $cachekey)) {
+		$head = git_read_head($projectroot . $project);
+		$revlist = git_read_revlist($projectroot . $project, $head, GITPHP_RSS_ITEMS);
+		$tpl->assign("self",script_url());
+
+		$commitlines = array();
+		for ($i = 0; $i < count($revlist); $i++) {
+			$commit = $revlist[$i];
+			$co = git_read_commit($projectroot . $project, $commit);
+			if (($i >= 20) && ((time() - $co['committer_epoch']) > 48*60*60))
+				break;
+			$cd = date_str($co['committer_epoch']);
+			$difftree = array();
+			$diffout = git_diff_tree($projectroot . $project, $co['parent'] . " " . $co['id']);
+			$tok = strtok($diffout,"\n");
+			while ($tok !== false) {
+				if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$tok,$regs))
+					$difftree[] = $regs[7];
+				$tok = strtok("\n");
+			}
+			$commitline = array();
+			$commitline["cdmday"] = $cd['mday'];
+			$commitline["cdmonth"] = $cd['month'];
+			$commitline["cdhour"] = $cd['hour'];
+			$commitline["cdminute"] = $cd['minute'];
+			$commitline["title"] = $co['title'];
+			$commitline["author"] = $co['author'];
+			$commitline["cdrfc2822"] = $cd['rfc2822'];
+			$commitline["commit"] = $commit;
+			$commitline["comment"] = $co['comment'];
+			$commitline["difftree"] = $difftree;
+			$commitlines[] = $commitline;
 		}
-		$commitline = array();
-		$commitline["cdmday"] = $cd['mday'];
-		$commitline["cdmonth"] = $cd['month'];
-		$commitline["cdhour"] = $cd['hour'];
-		$commitline["cdminute"] = $cd['minute'];
-		$commitline["title"] = $co['title'];
-		$commitline["author"] = $co['author'];
-		$commitline["cdrfc2822"] = $cd['rfc2822'];
-		$commitline["commit"] = $commit;
-		$commitline["comment"] = $co['comment'];
-		$commitline["difftree"] = $difftree;
-		$commitlines[] = $commitline;
+		$tpl->assign("commitlines",$commitlines);
 	}
-	$tpl->assign("commitlines",$commitlines);
-	$tpl->display("rss.tpl");
+	$tpl->display('rss.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_search.php
+++ b/include/display.git_search.php
@@ -9,76 +9,80 @@
 
 require_once('defs.constants.php');
 require_once('util.highlight.php');
-require_once('i18n.lookupstring.php');
 require_once('gitutil.git_read_commit.php');
-require_once('gitutil.git_rev_list.php');
+require_once('gitutil.git_read_revlist.php');
 require_once('display.git_message.php');
 
 function git_search($projectroot, $project, $hash, $search, $searchtype, $page = 0)
 {
 	global $tpl,$gitphp_conf;
 
-	if (!$gitphp_conf['search']) {
-		git_message(lookupstring('Search has been disabled'), TRUE, TRUE);
-		return;
+	$cachekey = sha1($project) . "|" . $hash . "|" . sha1($searchtype) . "|" . sha1($search) . "|" . (isset($page) ? $page : 0);
+
+	if (!$tpl->is_cached('search.tpl', $cachekey)) {
+
+		if (!$gitphp_conf['search']) {
+			git_message("Search has been disabled", TRUE, TRUE);
+			return;
+		}
+
+		if (!isset($search) || (strlen($search) < 2)) {
+			git_message("You must enter search text of at least 2 characters", TRUE, TRUE);
+			return;
+		}
+		if (!isset($hash)) {
+			//$hash = git_read_head($projectroot . $project);
+			$hash = "HEAD";
+		}
+
+		$co = git_read_commit($projectroot . $project, $hash);
+
+		$revlist = git_read_revlist($projectroot . $project, $hash, 101, ($page * 100), FALSE, FALSE, $searchtype, $search);
+		if (count($revlist) < 1 || (strlen($revlist[0]) < 1)) {
+			git_message("No matches for '" . $search . "'.", FALSE, TRUE);
+			return;
+		}
+
+		$tpl->assign("hash",$hash);
+		$tpl->assign("treehash",$co['tree']);
+
+		$tpl->assign("search",$search);
+		$tpl->assign("searchtype",$searchtype);
+		$tpl->assign("page",$page);
+		$revlistcount = count($revlist);
+		$tpl->assign("revlistcount",$revlistcount);
+
+		$tpl->assign("title",$co['title']);
+
+		$commitlines = array();
+		$commitcount = min(100,$revlistcount);
+		for ($i = 0; $i < $commitcount; $i++) {
+			$commit = $revlist[$i];
+			if (strlen(trim($commit)) > 0) {
+				$commitline = array();
+				$co2 = git_read_commit($projectroot . $project, $commit);
+				$commitline["commit"] = $commit;
+				$commitline["agestringage"] = $co2['age_string_age'];
+				$commitline["agestringdate"] = $co2['age_string_date'];
+				$commitline["authorname"] = $co2['author_name'];
+				$commitline["title_short"] = $co2['title_short'];
+				if (strlen($co2['title_short']) < strlen($co2['title']))
+					$commitline["title"] = $co2['title'];
+				$commitline["committree"] = $co2['tree'];
+				$matches = array();
+				foreach ($co2['comment'] as $comline) {
+					$hl = highlight($comline, $search, "searchmatch", GITPHP_TRIM_LENGTH);
+					if ($hl && (strlen($hl) > 0))
+						$matches[] = $hl;
+				}
+				$commitline["matches"] = $matches;
+				$commitlines[] = $commitline;
+			}
+		}
+		
+		$tpl->assign("commitlines",$commitlines);
 	}
-
-	if (!isset($search) || (strlen($search) < 2)) {
-		git_message(lookupstring('You must enter search text of at least 2 characters'), TRUE, TRUE);
-		return;
-	}
-	if (!isset($hash)) {
-		//$hash = git_read_head($projectroot . $project);
-		$hash = "HEAD";
-	}
-
-	$co = git_read_commit($projectroot . $project, $hash);
-
-	$revlist = explode("\n",trim(git_rev_list($projectroot . $project, $hash, 101, ($page * 100), FALSE, FALSE, $searchtype, $search)));
-	if (count($revlist) < 1 || (strlen($revlist[0]) < 1)) {
-		git_message(sprintf(lookupstring('No matches for \'%1$s\'.'), $search), FALSE, TRUE);
-		return;
-	}
-
-	$tpl->assign("hash",$hash);
-	$tpl->assign("treehash",$co['tree']);
-
-	$tpl->assign("search",$search);
-	$tpl->assign("searchtype",$searchtype);
-	$tpl->assign("page",$page);
-	$revlistcount = count($revlist);
-	$tpl->assign("revlistcount",$revlistcount);
-
-	$tpl->assign("title",$co['title']);
-
-	$commitlines = array();
-	$commitcount = min(100,$revlistcount);
-	for ($i = 0; $i < $commitcount; $i++) {
-		$commit = $revlist[$i];
-		if (strlen(trim($commit)) > 0) {
-			$commitline = array();
-			$co2 = git_read_commit($projectroot . $project, $commit);
-			$commitline["commit"] = $commit;
-			$commitline["agestringage"] = $co2['age_string_age'];
-			$commitline["agestringdate"] = $co2['age_string_date'];
-			$commitline["authorname"] = $co2['author_name'];
-			$commitline["title_short"] = $co2['title_short'];
-			if (strlen($co2['title_short']) < strlen($co2['title']))
-				$commitline["title"] = $co2['title'];
-			$commitline["committree"] = $co2['tree'];
-			$matches = array();
-			foreach ($co2['comment'] as $comline) {
-				$hl = highlight($comline, $search, "searchmatch", GITPHP_TRIM_LENGTH);
-				if ($hl && (strlen($hl) > 0))
-					$matches[] = $hl;
-			}
-			$commitline["matches"] = $matches;
-			$commitlines[] = $commitline;
-		}
-	}
-	
-	$tpl->assign("commitlines",$commitlines);
-	$tpl->display("search.tpl");
+	$tpl->display('search.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_search_files.php
+++ b/include/display.git_search_files.php
@@ -9,7 +9,6 @@
 
 require_once('defs.constants.php');
 require_once('util.highlight.php');
-require_once('i18n.lookupstring.php');
 require_once('gitutil.git_filesearch.php');
 require_once('gitutil.git_read_commit.php');
 require_once('display.git_message.php');
@@ -18,79 +17,84 @@
 {
 	global $tpl,$gitphp_conf;
 
-	if (!($gitphp_conf['search'] && $gitphp_conf['filesearch'])) {
-		git_message(lookupstring('File search has been disabled'), TRUE, TRUE);
-		return;
+	$cachekey = sha1($project) . "|" . $hash . "|" . "filesearch" . "|" . sha1($search) . "|" . (isset($page) ? $page : 0);
+
+	if (!$tpl->is_cached('searchfiles.tpl', $cachekey)) {
+
+		if (!($gitphp_conf['search'] && $gitphp_conf['filesearch'])) {
+			git_message("File search has been disabled", TRUE, TRUE);
+			return;
+		}
+
+		if (!isset($search) || (strlen($search) < 2)) {
+			git_message("You must enter search text of at least 2 characters", TRUE, TRUE);
+			return;
+		}
+		if (!isset($hash)) {
+			//$hash = git_read_head($projectroot . $project);
+			$hash = "HEAD";
+		}
+
+		$co = git_read_commit($projectroot . $project, $hash);
+
+		$filesearch = git_filesearch($projectroot . $project, $hash, $search, false, ($page * 100), 101);
+
+		if (count($filesearch) < 1) {
+			git_message("No matches for '" . $search . "'.", FALSE, TRUE);
+			return;
+		}
+
+		$tpl->assign("hash",$hash);
+		$tpl->assign("treehash",$co['tree']);
+
+		$tpl->assign("search",$search);
+		$tpl->assign("searchtype","file");
+		$tpl->assign("page",$page);
+		$filesearchcount = count($filesearch);
+		$tpl->assign("filesearchcount",$filesearchcount);
+
+		$tpl->assign("title",$co['title']);
+
+		$filesearchlines = array();
+		$i = 0;
+		foreach ($filesearch as $file => $data) {
+			$filesearchline = array();
+			$filesearchline["file"] = $file;
+			if (strpos($file,"/") !== false) {
+				$f = basename($file);
+				$d = dirname($file);
+				if ($d == "/")
+					$d = "";
+				$hlt = highlight($f, $search, "searchmatch");
+				if ($hlt)
+					$hlt = $d . "/" . $hlt;
+			} else
+				$hlt = highlight($file, $search, "searchmatch");
+			if ($hlt)
+				$filesearchline["filename"] = $hlt;
+			else
+				$filesearchline["filename"] = $file;
+			$filesearchline["hash"] = $data['hash'];
+			if ($data['type'] == "tree")
+				$filesearchline["tree"] = TRUE;
+			if (isset($data['lines'])) {
+				$matches = array();
+				foreach ($data['lines'] as $line) {
+					$hlt = highlight($line,$search,"searchmatch",floor(GITPHP_TRIM_LENGTH*1.5),true);
+					if ($hlt)
+						$matches[] = $hlt;
+				}
+				if (count($matches) > 0)
+					$filesearchline["matches"] = $matches;
+			}
+			$filesearchlines[] = $filesearchline;
+			$i++;
+			if ($i >= 100)
+				break;
+		}
+		$tpl->assign("filesearchlines",$filesearchlines);
 	}
-
-	if (!isset($search) || (strlen($search) < 2)) {
-		git_message(lookupstring('You must enter search text of at least 2 characters'), TRUE, TRUE);
-		return;
-	}
-	if (!isset($hash)) {
-		//$hash = git_read_head($projectroot . $project);
-		$hash = "HEAD";
-	}
-
-	$co = git_read_commit($projectroot . $project, $hash);
-
-	$filesearch = git_filesearch($projectroot . $project, $hash, $search, false, ($page * 100), 101);
-
-	if (count($filesearch) < 1) {
-		git_message(sprintf(lookupstring('No matches for \'%1$s\'.'), $search), FALSE, TRUE);
-		return;
-	}
-
-	$tpl->assign("hash",$hash);
-	$tpl->assign("treehash",$co['tree']);
-
-	$tpl->assign("search",$search);
-	$tpl->assign("searchtype","file");
-	$tpl->assign("page",$page);
-	$filesearchcount = count($filesearch);
-	$tpl->assign("filesearchcount",$filesearchcount);
-
-	$tpl->assign("title",$co['title']);
-
-	$filesearchlines = array();
-	$i = 0;
-	foreach ($filesearch as $file => $data) {
-		$filesearchline = array();
-		$filesearchline["file"] = $file;
-		if (strpos($file,"/") !== false) {
-			$f = basename($file);
-			$d = dirname($file);
-			if ($d == "/")
-				$d = "";
-			$hlt = highlight($f, $search, "searchmatch");
-			if ($hlt)
-				$hlt = $d . "/" . $hlt;
-		} else
-			$hlt = highlight($file, $search, "searchmatch");
-		if ($hlt)
-			$filesearchline["filename"] = $hlt;
-		else
-			$filesearchline["filename"] = $file;
-		$filesearchline["hash"] = $data['hash'];
-		if ($data['type'] == "tree")
-			$filesearchline["tree"] = TRUE;
-		if (isset($data['lines'])) {
-			$matches = array();
-			foreach ($data['lines'] as $line) {
-				$hlt = highlight($line,$search,"searchmatch",floor(GITPHP_TRIM_LENGTH*1.5),true);
-				if ($hlt)
-					$matches[] = $hlt;
-			}
-			if (count($matches) > 0)
-				$filesearchline["matches"] = $matches;
-		}
-		$filesearchlines[] = $filesearchline;
-		$i++;
-		if ($i >= 100)
-			break;
-	}
-	$tpl->assign("filesearchlines",$filesearchlines);
-	$tpl->display("searchfiles.tpl");
+	$tpl->display('searchfiles.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_shortlog.php
+++ b/include/display.git_shortlog.php
@@ -16,45 +16,50 @@
 function git_shortlog($projectroot,$project,$hash,$page)
 {
 	global $tpl;
-	$head = git_read_head($projectroot . $project);
-	if (!isset($hash))
-		$hash = $head;
-	if (!isset($page))
-		$page = 0;
-	$refs = read_info_ref($projectroot . $project);
-	$tpl->assign("hash",$hash);
-	$tpl->assign("head",$head);
 
-	if ($page)
-		$tpl->assign("page",$page);
+	$cachekey = sha1($project) . "|" . $hash . "|" . (isset($page) ? $page : 0);
 
-	$revlist = git_read_revlist($projectroot . $project, $hash, 101, ($page * 100));
+	if (!$tpl->is_cached('shortlog.tpl', $cachekey)) {
+		$head = git_read_head($projectroot . $project);
+		if (!isset($hash))
+			$hash = $head;
+		if (!isset($page))
+			$page = 0;
+		$refs = read_info_ref($projectroot . $project);
+		$tpl->assign("hash",$hash);
+		$tpl->assign("head",$head);
 
-	$revlistcount = count($revlist);
-	$tpl->assign("revlistcount",$revlistcount);
+		if ($page)
+			$tpl->assign("page",$page);
 
-	$commitlines = array();
-	$commitcount = min(100,count($revlist));
-	for ($i = 0; $i < $commitcount; $i++) {
-		$commit = $revlist[$i];
-		if (strlen(trim($commit)) > 0) {
-			$commitline = array();
-			if (isset($refs[$commit]))
-				$commitline["commitref"] = $refs[$commit];
-			$co = git_read_commit($projectroot . $project, $commit);
-			$ad = date_str($co['author_epoch']);
-			$commitline["commit"] = $commit;
-			$commitline["agestringage"] = $co['age_string_age'];
-			$commitline["agestringdate"] = $co['age_string_date'];
-			$commitline["authorname"] = $co['author_name'];
-			$commitline["title_short"] = $co['title_short'];
-			if (strlen($co['title_short']) < strlen($co['title']))
-				$commitline["title"] = $co['title'];
-			$commitlines[] = $commitline;
+		$revlist = git_read_revlist($projectroot . $project, $hash, 101, ($page * 100));
+
+		$revlistcount = count($revlist);
+		$tpl->assign("revlistcount",$revlistcount);
+
+		$commitlines = array();
+		$commitcount = min(100,count($revlist));
+		for ($i = 0; $i < $commitcount; $i++) {
+			$commit = $revlist[$i];
+			if (strlen(trim($commit)) > 0) {
+				$commitline = array();
+				if (isset($refs[$commit]))
+					$commitline["commitref"] = $refs[$commit];
+				$co = git_read_commit($projectroot . $project, $commit);
+				$ad = date_str($co['author_epoch']);
+				$commitline["commit"] = $commit;
+				$commitline["agestringage"] = $co['age_string_age'];
+				$commitline["agestringdate"] = $co['age_string_date'];
+				$commitline["authorname"] = $co['author_name'];
+				$commitline["title_short"] = $co['title_short'];
+				if (strlen($co['title_short']) < strlen($co['title']))
+					$commitline["title"] = $co['title'];
+				$commitlines[] = $commitline;
+			}
 		}
+		$tpl->assign("commitlines",$commitlines);
 	}
-	$tpl->assign("commitlines",$commitlines);
-	$tpl->display("shortlog.tpl");
+	$tpl->display('shortlog.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_snapshot.php
+++ b/include/display.git_snapshot.php
@@ -12,33 +12,46 @@
 
 function git_snapshot($projectroot,$project,$hash)
 {
-	global $gitphp_conf;
+	global $gitphp_conf, $tpl;
+
 	if (!isset($hash))
 		$hash = "HEAD";
+
+	$cachekey = sha1($project) . "|" . $hash;
+
+	$bzcompress = false;
+	$gzencode = false;
+
 	$rname = str_replace(array("/",".git"),array("-",""),$project);
-	$arc = git_archive($projectroot . $project, $hash, $rname,
-		(($gitphp_conf['compressformat'] == GITPHP_COMPRESS_ZIP) ? "zip" : "tar"));
-
 	if ($gitphp_conf['compressformat'] == GITPHP_COMPRESS_ZIP) {
 		header("Content-Type: application/x-zip");
 		header("Content-Disposition: attachment; filename=" . $rname . ".zip");
-		echo $arc;
-		return;
 	} else if (($gitphp_conf['compressformat'] == GITPHP_COMPRESS_BZ2) && function_exists("bzcompress")) {
+		$bzcompress = true;
 		header("Content-Type: application/x-bzip2");
 		header("Content-Disposition: attachment; filename=" . $rname . ".tar.bz2");
-		echo bzcompress($arc,(isset($gitphp_conf['compresslevel'])?$gitphp_conf['compresslevel']:4));
-		return;
 	} else if (($gitphp_conf['compressformat'] == GITPHP_COMPRESS_GZ) && function_exists("gzencode")) {
+		$gzencode = true;
 		header("Content-Type: application/x-gzip");
 		header("Content-Disposition: attachment; filename=" . $rname . ".tar.gz");
-		echo gzencode($arc,(isset($gitphp_conf['compresslevel'])?$gitphp_conf['compresslevel']:-1));
-		return;
+	} else {
+		header("Content-Type: application/x-tar");
+		header("Content-Disposition: attachment; filename=" . $rname . ".tar");
 	}
 
-	header("Content-Type: application/x-tar");
-	header("Content-Disposition: attachment; filename=" . $rname . ".tar");
-	echo $arc;
+	if (!$tpl->is_cached('snapshot.tpl', $cachekey)) {
+
+		$arc = git_archive($projectroot . $project, $hash, $rname,
+			(($gitphp_conf['compressformat'] == GITPHP_COMPRESS_ZIP) ? "zip" : "tar"));
+
+		if (($gitphp_conf['compressformat'] == GITPHP_COMPRESS_BZ2) && $bzcompress) {
+			$arc = bzcompress($arc,(isset($gitphp_conf['compresslevel'])?$gitphp_conf['compresslevel']:4));
+		} else if (($gitphp_conf['compressformat'] == GITPHP_COMPRESS_GZ) && $gzencode) {
+			$arc = gzencode($arc,(isset($gitphp_conf['compresslevel'])?$gitphp_conf['compresslevel']:-1));
+		}
+		$tpl->assign("archive",$arc);
+	}
+	$tpl->display('snapshot.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_summary.php
+++ b/include/display.git_summary.php
@@ -19,53 +19,58 @@
 function git_summary($projectroot,$project)
 {
 	global $tpl;
-	$descr = git_project_descr($projectroot,$project);
-	$head = git_read_head($projectroot . $project);
-	$commit = git_read_commit($projectroot . $project, $head);
-	$commitdate = date_str($commit['committer_epoch'],$commit['committer_tz']);
-	$owner = git_project_owner($projectroot,$project);
-	$refs = read_info_ref($projectroot . $project);
-	$tpl->assign("head",$head);
-	$tpl->assign("description",$descr);
-	$tpl->assign("owner",$owner);
-	$tpl->assign("lastchange",$commitdate['rfc2822']);
-	$revlist = git_read_revlist($projectroot . $project, $head, 17);
-	foreach ($revlist as $i => $rev) {
-		$revdata = array();
-		$revco = git_read_commit($projectroot . $project, $rev);
-		$authordate = date_str($revco['author_epoch']);
-		$revdata["commit"] = $rev;
-		if (isset($refs[$rev]))
-			$revdata["commitref"] = $refs[$rev];
-		$revdata["commitage"] = $revco['age_string'];
-		$revdata["commitauthor"] = $revco['author_name'];
-		if (strlen($revco['title_short']) < strlen($revco['title'])) {
-			$revdata["title"] = $revco['title'];
-			$revdata["title_short"] = $revco['title_short'];
-		} else
-			$revdata["title_short"] = $revco['title'];
-		$revlist[$i] = $revdata;
+
+	$cachekey = sha1($project);
+
+	if (!$tpl->is_cached('project.tpl', $cachekey)) {
+		$descr = git_project_descr($projectroot,$project);
+		$head = git_read_head($projectroot . $project);
+		$commit = git_read_commit($projectroot . $project, $head);
+		$commitdate = date_str($commit['committer_epoch'],$commit['committer_tz']);
+		$owner = git_project_owner($projectroot,$project);
+		$refs = read_info_ref($projectroot . $project);
+		$tpl->assign("head",$head);
+		$tpl->assign("description",$descr);
+		$tpl->assign("owner",$owner);
+		$tpl->assign("lastchange",$commitdate['rfc2822']);
+		$revlist = git_read_revlist($projectroot . $project, $head, 17);
+		foreach ($revlist as $i => $rev) {
+			$revdata = array();
+			$revco = git_read_commit($projectroot . $project, $rev);
+			$authordate = date_str($revco['author_epoch']);
+			$revdata["commit"] = $rev;
+			if (isset($refs[$rev]))
+				$revdata["commitref"] = $refs[$rev];
+			$revdata["commitage"] = $revco['age_string'];
+			$revdata["commitauthor"] = $revco['author_name'];
+			if (strlen($revco['title_short']) < strlen($revco['title'])) {
+				$revdata["title"] = $revco['title'];
+				$revdata["title_short"] = $revco['title_short'];
+			} else
+				$revdata["title_short"] = $revco['title'];
+			$revlist[$i] = $revdata;
+		}
+		$tpl->assign("revlist",$revlist);
+
+		$taglist = git_read_refs($projectroot,$project,"refs/tags");
+		if (isset($taglist) && (count($taglist) > 0)) {
+			foreach ($taglist as $i => $tag) {
+				if (isset($tag['comment'])) {
+					$com = trim($tag['comment'][0]);
+					if (strlen($com) > GITPHP_TRIM_LENGTH)
+						$com = substr($trimmed,0,GITPHP_TRIM_LENGTH) . "...";
+					$taglist[$i]['comment'] = $com;
+				}
+			}
+			$tpl->assign("taglist",$taglist);
+		}
+
+		$headlist = git_read_refs($projectroot,$project,"refs/heads");
+		if (isset($headlist) && (count($headlist) > 0)) {
+			$tpl->assign("headlist",$headlist);
+		}
 	}
-	$tpl->assign("revlist",$revlist);
-
-	$taglist = git_read_refs($projectroot,$project,"refs/tags");
-	if (isset($taglist) && (count($taglist) > 0)) {
-		foreach ($taglist as $i => $tag) {
-			if (isset($tag['comment'])) {
-				$com = trim($tag['comment'][0]);
-				if (strlen($com) > GITPHP_TRIM_LENGTH)
-					$com = substr($trimmed,0,GITPHP_TRIM_LENGTH) . "...";
-				$taglist[$i]['comment'] = $com;
-			}
-		}
-		$tpl->assign("taglist",$taglist);
-	}
-
-	$headlist = git_read_refs($projectroot,$project,"refs/heads");
-	if (isset($headlist) && (count($headlist) > 0)) {
-		$tpl->assign("headlist",$headlist);
-	}
-	$tpl->display("project.tpl");
+	$tpl->display('project.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_tag.php
+++ b/include/display.git_tag.php
@@ -15,18 +15,23 @@
 {
 	global $tpl;
 
-	$head = git_read_head($projectroot . $project);
-	$tpl->assign("head",$head);
-	$tpl->assign("hash", $hash);
+	$cachekey = sha1($project) . "|" . $hash;
 
-	$tag = git_read_tag($projectroot . $project, $hash);
+	if (!$tpl->is_cached('tag.tpl', $cachekey)) {
 
-	$tpl->assign("tag",$tag);
-	if (isset($tag['author'])) {
-		$ad = date_str($tag['epoch'],$tag['tz']);
-		$tpl->assign("datedata",$ad);
+		$head = git_read_head($projectroot . $project);
+		$tpl->assign("head",$head);
+		$tpl->assign("hash", $hash);
+
+		$tag = git_read_tag($projectroot . $project, $hash);
+
+		$tpl->assign("tag",$tag);
+		if (isset($tag['author'])) {
+			$ad = date_str($tag['epoch'],$tag['tz']);
+			$tpl->assign("datedata",$ad);
+		}
 	}
-	$tpl->display("tag.tpl");
+	$tpl->display('tag.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_tags.php
+++ b/include/display.git_tags.php
@@ -13,13 +13,18 @@
 function git_tags($projectroot,$project)
 {
 	global $tpl;
-	$head = git_read_head($projectroot . $project);
-	$tpl->assign("head",$head);
-	$taglist = git_read_refs($projectroot, $project, "refs/tags");
-	if (isset($taglist) && (count($taglist) > 0)) {
-		$tpl->assign("taglist",$taglist);
+
+	$cachekey = sha1($project);
+
+	if (!$tpl->is_cached('tags.tpl', $cachekey)) {
+		$head = git_read_head($projectroot . $project);
+		$tpl->assign("head",$head);
+		$taglist = git_read_refs($projectroot, $project, "refs/tags");
+		if (isset($taglist) && (count($taglist) > 0)) {
+			$tpl->assign("taglist",$taglist);
+		}
 	}
-	$tpl->display("tags.tpl");
+	$tpl->display('tags.tpl', $cachekey);
 }
 
 ?>

--- a/include/display.git_tree.php
+++ b/include/display.git_tree.php
@@ -18,46 +18,51 @@
 function git_tree($projectroot,$project,$hash,$file,$hashbase)
 {
 	global $tpl;
-	if (!isset($hash)) {
-		$hash = git_read_head($projectroot . $project);
+
+	$cachekey = sha1($project) . "|" . $hashbase . "|" . $hash . "|" . sha1($file);
+
+	if (!$tpl->is_cached('tree.tpl', $cachekey)) {
+		if (!isset($hash)) {
+			$hash = git_read_head($projectroot . $project);
+			if (isset($file))
+				$hash = git_get_hash_by_path($projectroot . $project, ($hashbase?$hashbase:$hash),$file,"tree");
+				if (!isset($hashbase))
+					$hashbase = $hash;
+		}
+		$lsout = git_ls_tree($projectroot . $project, $hash, TRUE);
+		$refs = read_info_ref($projectroot . $project);
+		$tpl->assign("hash",$hash);
+		if (isset($hashbase))
+			$tpl->assign("hashbase",$hashbase);
+		if (isset($hashbase) && ($co = git_read_commit($projectroot . $project, $hashbase))) {
+			$basekey = $hashbase;
+			$tpl->assign("fullnav",TRUE);
+			$tpl->assign("title",$co['title']);
+			if (isset($refs[$hashbase]))
+				$tpl->assign("hashbaseref",$refs[$hashbase]);
+		}
+		$paths = git_path_trees($projectroot . $project, $hashbase, $file);
+		$tpl->assign("paths",$paths);
+
 		if (isset($file))
-			$hash = git_get_hash_by_path($projectroot . $project, ($hashbase?$hashbase:$hash),$file,"tree");
-			if (!isset($hashbase))
-				$hashbase = $hash;
+			$tpl->assign("base",$file . "/");
+
+		$treelines = array();
+		$tok = strtok($lsout,"\0");
+		while ($tok !== false) {
+			if (ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$",$tok,$regs)) {
+				$treeline = array();
+				$treeline["filemode"] = mode_str($regs[1]);
+				$treeline["type"] = $regs[2];
+				$treeline["hash"] = $regs[3];
+				$treeline["name"] = $regs[4];
+				$treelines[] = $treeline;
+			}
+			$tok = strtok("\0");
+		}
+		$tpl->assign("treelines",$treelines);
 	}
-	$lsout = git_ls_tree($projectroot . $project, $hash, TRUE);
-	$refs = read_info_ref($projectroot . $project);
-	$tpl->assign("hash",$hash);
-	if (isset($hashbase))
-		$tpl->assign("hashbase",$hashbase);
-	if (isset($hashbase) && ($co = git_read_commit($projectroot . $project, $hashbase))) {
-		$basekey = $hashbase;
-		$tpl->assign("fullnav",TRUE);
-		$tpl->assign("title",$co['title']);
-		if (isset($refs[$hashbase]))
-			$tpl->assign("hashbaseref",$refs[$hashbase]);
-	}
-	$paths = git_path_trees($projectroot . $project, $hashbase, $file);
-	$tpl->assign("paths",$paths);
-
-	if (isset($file))
-		$tpl->assign("base",$file . "/");
-
-	$treelines = array();
-	$tok = strtok($lsout,"\0");
-	while ($tok !== false) {
-		if (ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$",$tok,$regs)) {
-			$treeline = array();
-			$treeline["filemode"] = mode_str($regs[1]);
-			$treeline["type"] = $regs[2];
-			$treeline["hash"] = $regs[3];
-			$treeline["name"] = $regs[4];
-			$treelines[] = $treeline;
-		}
-		$tok = strtok("\0");
-	}
-	$tpl->assign("treelines",$treelines);
-	$tpl->display("tree.tpl");
+	$tpl->display('tree.tpl', $cachekey);
 }
 
 ?>

--- a/include/gitutil.git_exec_nix.php
+++ b/include/gitutil.git_exec_nix.php
@@ -10,7 +10,10 @@
  function git_exec_nix($project, $command)
  {
  	global $gitphp_conf;
-	$cmd = $gitphp_conf['gitbin'] . " --git-dir=" . $project . " " . $command;
+	$cmd = $gitphp_conf['gitbin'];
+	if (isset($project) && (strlen($project) > 0))
+		$cmd .= " --git-dir=" . $project;
+	$cmd .= " " . $command;
 	return shell_exec($cmd);
  }
 

--- a/include/gitutil.git_exec_win.php
+++ b/include/gitutil.git_exec_win.php
@@ -10,7 +10,10 @@
 function git_exec_win($project, $command)
 {
 	global $gitphp_conf;
-	$cmd = $gitphp_conf['gitbin'] . " --git-dir=" . $project . " " . $command;
+	$cmd = $gitphp_conf['gitbin'];
+	if (isset($project) && (strlen($project) > 0))
+		$cmd .= " --git-dir=" . $project;
+	$cmd .= " " . $command;
 	return shell_exec($cmd);
 }
 

--- a/include/gitutil.git_read_commit.php
+++ b/include/gitutil.git_read_commit.php
@@ -9,12 +9,11 @@
 
  require_once('defs.constants.php');
  require_once('util.age_string.php');
- require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_read_revlist.php');
 
 function git_read_commit($proj,$head)
 {
-	$revlist = git_rev_list($proj,$head,1,NULL,TRUE,TRUE);
-	$lines = explode("\n",$revlist);
+	$lines = git_read_revlist($proj,$head,1,NULL,TRUE,TRUE);
 	if (!($lines[0]) || !ereg("^[0-9a-fA-F]{40}",$lines[0]))
 		return null;
 	$commit = array();

--- a/include/gitutil.git_read_projects.php
+++ b/include/gitutil.git_read_projects.php
@@ -7,7 +7,6 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- require_once('i18n.lookupstring.php');
  require_once('gitutil.git_recurse_projects.php');
  require_once('gitutil.git_project_info.php');
 
@@ -47,9 +46,9 @@
 				}
 			}
 		} else
-			return lookupstring("Projectroot is not a directory");
+			return "Projectroot is not a directory";
 	} else
-		return lookupstring("No projectroot set");
+		return "No projectroot set";
 	return $projects;
 }
 

--- a/include/gitutil.git_read_refs.php
+++ b/include/gitutil.git_read_refs.php
@@ -13,7 +13,6 @@
  require_once('gitutil.git_read_hash.php');
  require_once('gitutil.git_read_tag.php');
  require_once('gitutil.git_read_commit.php');
- require_once('i18n.lookupstring.php');
 
 function git_read_refs($projectroot,$project,$refdir)
 {
@@ -45,10 +44,9 @@
 		if ($type) {
 			$ref_item = array();
 			$ref_item['type'] = $type;
-			$ref_item['type_localized'] = lookupstring($type);
 			$ref_item['id'] = $ref_id;
 			$ref_item['epoch'] = 0;
-			$ref_item['age'] = "unknown";
+			$ref_item['age_string'] = "unknown";
 
 			if ($type == "tag") {
 				$tag = git_read_tag($projectroot . $project, $ref_id);
@@ -56,11 +54,13 @@
 				if ($tag['type'] == "commit") {
 					$co = git_read_commit($projectroot . $project, $tag['object']);
 					$ref_item['epoch'] = $co['committer_epoch'];
-					$ref_item['age'] = $co['age_string'];
+					$ref_item['age_string'] = $co['age_string'];
+					$ref_item['age'] = $co['age'];
 				} else if (isset($tag['epoch'])) {
 					$age = time() - $tag['epoch'];
 					$ref_item['epoch'] = $tag['epoch'];
-					$ref_item['age'] = age_string($age);
+					$ref_item['age_string'] = age_string($age);
+					$ref_item['age'] = $age;
 				}
 				$ref_item['reftype'] = $tag['type'];
 				$ref_item['name'] = $tag['name'];
@@ -72,9 +72,9 @@
 				$ref_item['title'] = $co['title'];
 				$ref_item['refid'] = $ref_id;
 				$ref_item['epoch'] = $co['committer_epoch'];
-				$ref_item['age'] = $co['age_string'];
+				$ref_item['age_string'] = $co['age_string'];
+				$ref_item['age'] = $co['age'];
 			}
-			$ref_item['reftype_localized'] = lookupstring($ref_item['reftype']);
 			$reflist[] = $ref_item;
 		}
 	}

--- a/include/gitutil.git_read_revlist.php
+++ b/include/gitutil.git_read_revlist.php
@@ -8,11 +8,39 @@
  */
 
  require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_version.php');
 
-function git_read_revlist($proj,$head,$count,$skip = NULL)
+function git_read_revlist($proj,$head,$count = NULL,$skip = NULL,$header = FALSE,$parents = FALSE,$greptype = NULL, $search = NULL)
 {
-	$revs = trim(git_rev_list($proj,$head,$count, $skip));
+	$passedskip = $skip;
+	$passedcount = $count;
+	$canskip = true;
+
+	if (isset($skip) && ($skip > 0)) {
+		$version = git_version();
+		if (isset($version) && (strlen($version) > 0)) {
+			$splitver = explode(".",$version);
+
+			/* Skip only appears in git >= 1.5.0 */
+			if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5))) {
+				$canskip = false;
+				$passedskip = null;
+				$passedcount += $skip;
+			}
+		}
+	}
+
+	$revs = trim(git_rev_list($proj,$head, $passedcount, $passedskip, $header, $parents, $greptype, $search));
 	$revlist = explode("\n",$revs);
+
+	if ((!$canskip) && ($skip > 0)) {
+		$tmp = array();
+		$revcount = count($revlist);
+		for ($i = $skip; $i < $revcount; $i++)
+			$tmp[] = $revlist[$i];
+		return $tmp;
+	}
+
 	return $revlist;
 }
 

--- a/include/gitutil.git_read_tag.php
+++ b/include/gitutil.git_read_tag.php
@@ -8,7 +8,6 @@
  */
 
  require_once('gitutil.git_cat_file.php');
- require_once('i18n.lookupstring.php');
 
 function git_read_tag($project, $tag_id)
 {
@@ -20,10 +19,9 @@
 	while ($tok !== false) {
 		if (ereg("^object ([0-9a-fA-F]{40})$",$tok,$regs))
 			$tag['object'] = $regs[1];
-		else if (ereg("^type (.+)$",$tok,$regs)) {
+		else if (ereg("^type (.+)$",$tok,$regs))
 			$tag['type'] = $regs[1];
-			$tag['type_localized'] = lookupstring($tag['type']);
-		} else if (ereg("^tag (.+)$",$tok,$regs))
+		else if (ereg("^tag (.+)$",$tok,$regs))
 			$tag['name'] = $regs[1];
 		else if (ereg("^tagger (.*) ([0-9]+) (.*)$",$tok,$regs)) {
 			$tag['author'] = $regs[1];

--- /dev/null
+++ b/include/gitutil.git_version.php
@@ -1,1 +1,21 @@
+<?php
+/*
+ *  gitutil.git_version.php
+ *  gitphp: A PHP git repository browser
+ *  Component: Git utility - version
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ */
 
+ require_once('gitutil.git_exec.php');
+
+ function git_version()
+ {
+ 	$verstr = explode(" ",git_exec(null, "--version"));
+	if (($verstr[0] == "git") && ($verstr[1] == "version"))
+		return $verstr[2];
+	return null;
+ }
+
+?>
+

--- a/include/i18n.initlocale.php
+++ /dev/null
@@ -1,27 +1,1 @@
-<?php
-/*
- *  i18n.initlocale.php
- *  gitphp: A PHP git repository browser
- *  Component: i18n - load locale
- *
- *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
- */
 
-require_once('i18n.lookupstring.php');
-
-function initlocale($locale = "en_US")
-{
-	global $tpl;
-
-	if (!include(GITPHP_LOCALE_DIR . $locale . ".php"))
-		include(GITPHP_LOCALE_DIR . "en_US.php");
-
-	if (isset($strings)) {
-		$tpl->assign("localize",$strings);
-	}
-
-	return $strings;
-}
-
-?>
-

--- a/include/i18n.lookupstring.php
+++ /dev/null
@@ -1,29 +1,1 @@
-<?php
-/*
- *  i18n.lookupstring.php
- *  gitphp: A PHP git repository browser
- *  Component: i18n - look up a string
- *
- *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
- */
 
-function lookupstring($str, $strings = null)
-{
-	global $localestrings;
-
-	if (!$str)
-		return null;
-
-	if (isset($strings) && (count($strings) > 0)) {
-		if (isset($strings[$str]))
-			return $strings[$str];
-	} else {
-		if (isset($localestrings[$str]))
-			return $localestrings[$str];
-	}
-
-	return $str;
-}
-
-?>
-

 Binary files a/include/locale/._zz_DEBUG.php and /dev/null differ
--- a/include/locale/en_US.php
+++ /dev/null
@@ -1,366 +1,1 @@
-<?php
-/*
- *  en_US.php
- *  gitphp: A PHP git repository browser
- *  Component: i18n - en_US
- */
 
-$strings = array(
-	/*
-	 * Error message that tells the user that
-	 * there were no projects found in the projectroot
-	 */
-	'No projects found' => 'No projects found',
-
-	/*
-	 * Error message that tells the user that the projectroot
-	 * they have set up is not a directory
-	 */
-	'Projectroot is not a directory' => 'Projectroot is not a directory',
-
-	/*
-	 * Error message that tells the user that they have not set
-	 * a projectroot
-	 */
-	'No projectroot set' => 'No projectroot set',
-
-	/*
-	 * Tells the user that all searching has been disabled
-	 */
-	'Search has been disabled' => 'Search has been disabled',
-
-	/*
-	 * Tells the user that searching with files has been disabled
-	 */
-	'File search has been disabled' => 'File search has been disabled',
-
-	/*
-	 * Tells the user that their search string must be a minimum of 2 characters
-	 */
-	'You must enter search text of at least 2 characters' => 'You must enter search text of at least 2 characters',
-
-	/*
-	 * Tells the user that no matches were found for their search, where
-	 * %1$s is the search string
-	 */
-	'No matches for \'%1$s\'.' => 'No matches for \'%1$s\'.',
-
-	/*
-	 * Used to indicate multiple projects - links back to the project
-	 * listing page
-	 */
-	'projects' => 'projects',
-
-	/*
-	 * Used as the header for the project name column on the project list
-	 */
-	'headerproject' => 'Project',
-
-	/*
-	 * Used as the header for the description column on the project list
-	 */
-	'headerdescription' => 'Description',
-
-	/*
-	 * Used as the header for the owner column on the project list
-	 */
-	'headerowner' => 'Owner',
-
-	/*
-	 * Used as the header for the age (last time project was changed) column in the
-	 * project list
-	 */
-	'headerlastchange' => 'Last Change',
-
-	/*
-	 * Used as the header for the actions column (links to various other pages for
-	 * that project)
-	 */
-	'headeractions' => 'Actions',
-
-	/*
-	 * Used as the name for the main project summary page
-	 */
-	'summary' => 'summary',
-
-	/*
-	 * Used as the name for the shortlog (abbreviated commit log) page
-	 */
-	'shortlog' => 'shortlog',
-
-	/*
-	 * Used as the name for the log (full commit log) page
-	 */
-	'log' => 'log',
-
-	/*
-	 * Used as the name for a single "commit" to the repository - 
-	 * for the commit page, as well as on other pages when referencing
-	 * a single commit object
-	 */
-	'commit' => 'commit',
-
-	/*
-	 * Used as the name for the commitdiff page, which shows all changes
-	 * in a single commit
-	 */
-	'commitdiff' => 'commitdiff',
-
-	/*
-	 * Used as the name for the tree page and to reference tree objects - 
-	 * "trees" being a particular project's directory of files (or subdirectory)
-	 * at a given revision
-	 */
-	'tree' => 'tree',
-
-	/*
-	 * Used as the name for the snapshot action, which sends a tarball of the
-	 * project at a given revision
-	 */
-	'snapshot' => 'snapshot',
-
-	/*
-	 * Used as the name for the tags page/section, which lists all tags for a project
-	 */
-	'tags' => 'tags',
-
-	/*
-	 * Used as the name for the single tag page, which shows all info on a single
-	 * tag object
-	 */
-	'tag' => 'tag',
-
-	/*
-	 * Used as the name for the heads page/section, which lists all heads for a project
-	 */
-	'heads' => 'heads',
-
-	/*
-	 * Used as the name for the history page, which lists all commits where a particular
-	 * file was changed
-	 */
-	'history' => 'history',
-
-	/*
-	 * Used as the name for the blob page, which shows the content of a file at a given
-	 * revision (its 'blob' data)
-	 */
-	'blob' => 'blob',
-
-	/*
-	 * Used as a link to show the differences in a file for a commit
-	 */
-	'diff' => 'diff',
-
-	/*
-	 * Used as a link to diff a particular revision of a file to the current version
-	 */
-	'difftocurrent' => 'diff to current',
-
-	/*
-	 * Used as the name for the search action, and to caption the search box
-	 */
-	'search' => 'search',
-
-	/*
-	 * Used as the caption on the 'RSS' button, which gets a feed of the most recent
-	 * commits to a project
-	 */
-	'RSS' => 'RSS',
-
-	/*
-	 * Used as the caption for the 'OPML' button, which gets a list of projects in OPML format
-	 */
-	'OPML' => 'OPML',
-
-	/*
-	 * Used as the caption for the 'TXT' button, which gets a list of projects in plaintext
-	 */
-	'TXT' => 'TXT',
-
-	/*
-	 * Used as a link on various actions (blob, blobdiff, commitdiff, etc) to get the plaintext
-	 * version of it
-	 */
-	'plain' => 'plain',
-
-	/*
-	 * Used as an indicator that something was added
-	 */
-	'new' => 'new',
-
-	/*
-	 * Used as an indicator that something was deleted
-	 */
-	'deleted' => 'deleted',
-
-	/*
-	 * Used as an indicator that something is a file - for example, that we are diffing a
-	 * file or searching within files
-	 */
-	'file' => 'file',
-
-	/*
-	 * Used to denote the author of a particular commit, or that we want to search
-	 * authors
-	 */
-	'author' => 'author',
-
-	/*
-	 * Used to denote the committer of a particular commit, or that we want to search
-	 * committers
-	 */
-	'committer' => 'committer',
-
-	/*
-	 * Used as the link to the previous page, when paginating through log entries
-	 * or search results
-	 */
-	'prev' => 'prev',
-
-	/*
-	 * Used as the link to the next page, when paginating through log entries
-	 * or search results
-	 */
-	'next' => 'next',
-
-	/*
-	 * Used as the link to the first page, when paginating through search results
-	 */
-	'first' => 'first',
-
-	/*
-	 * Used as the link to the HEAD, when paginating through log entries
-	 */
-	'HEAD' => 'HEAD',
-
-	/*
-	 * Used to indicate the description of the project, on the project summary page
-	 */
-	'description' => 'description',
-
-	/*
-	 * Used to indicate the owner of the project, on the project summary page
-	 */
-	'owner' => 'owner',
-
-	/*
-	 * Used to indicate the age (last change) of the project, on the project summary page
-	 */
-	'lastchange' => 'last change',
-
-	/*
-	 * Used to indicate the object that is the parent of this one (eg the commit that
-	 * came right before this one)
-	 */
-	'parent' => 'parent',
-
-	/*
-	 * Used to indicate the object (commit, etc) that is attached to a tag
-	 */
-	'object' => 'object',
-
-	/*
-	 * Used to indicate a new object was added, where
-	 * %1$s is the type of object (file or tree)
-	 */
-	'newobject' => 'new %1$s',
-
-	/*
-	 * Used to indicate a new object was added, where
-	 * %1$s is the type of object (file or tree) and
-	 * %2$s is the new mode
-	 */
-	'newobjectwithmode' => 'new %1$s with mode: %2$s',
-
-	/*
-	 * Used to indicate an object was deleted, where
-	 * %1$s is the type of object (file or tree)
-	 */
-	'deletedobject' => 'deleted %1$s',
-
-	/*
-	 * Used to indicate an object's type was changed, where
-	 * %1$s is the old type and %2$s is the new type
-	 */
-	'changedobjecttype' => 'changed from %1$s to %2$s',
-
-	/*
-	 * Used to indicate an object's mode was changed, where
-	 * %1$s is the mode change (either just one mode or
-	 * mode1->mode2)
-	 */
-	'changedobjectmode' => 'changed mode: %1$s',
-
-	/*
-	 * Used to indicate that an object was moved/renamed,
-	 * where %1$s is the original name, and
-	 * %2$d is the percentage similarity
-	 */
-	'movedobjectwithsimilarity' => 'moved from %1$s with %2$d%% similarity',
-
-	/*
-	 * Used to indicate that an object was moved/renamed,
-	 * where %1$s is the original name,
-	 * %2$d is the percentage similarity, and
-	 * %3$s is the mode
-	 */
-	'movedobjectwithsimilaritymodechange' => 'moved from %1$s with %2$d%% similarity, mode: $3$s',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * years ago, where %1$d is the number of years
-	 */
-	'ageyearsago' => '%1$d years ago',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * years ago, where %1$d is the number of years
-	 */
-	'agemonthsago' => '%1$d months ago',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * weeks ago, where %1$d is the number of weeks
-	 */
-	'ageweeksago' => '%1$d weeks ago',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * days ago, where %1$d is the number of days
-	 */
-	'agedaysago' => '%1$d days ago',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * hours ago, where %1$d is the number of hours
-	 */
-	'agehoursago' => '%1$d hours ago',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * minutes ago, where %1$d is the number of minutes
-	 */
-	'ageminago' => '%1$d min ago',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * seconds ago, where %1$d is the number of seconds
-	 */
-	'agesecago' => '%1$d sec ago',
-
-	/*
-	 * Used to indicate something is happening right now
-	 * (less than 3 seconds ago)
-	 */
-	'agerightnow' => 'right now',
-
-	/*
-	 * Used to indicate a certain number of files were changed in a commit
-	 * where %1$d is the numebr of files changed
-	 */
-	'fileschanged' => '%1$d files changed',
-);
-
-?>
-

--- a/include/locale/zz_DEBUG.php
+++ /dev/null
@@ -1,366 +1,1 @@
-<?php
-/*
- *  zz_DEBUG.php
- *  gitphp: A PHP git repository browser
- *  Component: i18n - zz_DEBUG
- */
 
-$strings = array(
-	/*
-	 * Error message that tells the user that
-	 * there were no projects found in the projectroot
-	 */
-	'No projects found' => 'No projects found',
-
-	/*
-	 * Error message that tells the user that the projectroot
-	 * they have set up is not a directory
-	 */
-	'Projectroot is not a directory' => 'Projectroot is not a directory',
-
-	/*
-	 * Error message that tells the user that they have not set
-	 * a projectroot
-	 */
-	'No projectroot set' => 'No projectroot set',
-
-	/*
-	 * Tells the user that all searching has been disabled
-	 */
-	'Search has been disabled' => 'Search has been disabled',
-
-	/*
-	 * Tells the user that searching with files has been disabled
-	 */
-	'File search has been disabled' => 'File search has been disabled',
-
-	/*
-	 * Tells the user that their search string must be a minimum of 2 characters
-	 */
-	'You must enter search text of at least 2 characters' => 'You must enter search text of at least 2 characters',
-
-	/*
-	 * Tells the user that no matches were found for their search, where
-	 * %1$s is the search string
-	 */
-	'No matches for \'%1$s\'.' => 'No matches for \'%1$s\'.',
-
-	/*
-	 * Used to indicate multiple projects - links back to the project
-	 * listing page
-	 */
-	'projects' => '{prőjėčts••}',
-
-	/*
-	 * Used as the header for the project name column on the project list
-	 */
-	'headerproject' => '{Pröjèct••}',
-
-	/*
-	 * Used as the header for the description column on the project list
-	 */
-	'headerdescription' => '{Dèscrîptîön•••}',
-
-	/*
-	 * Used as the header for the owner column on the project list
-	 */
-	'headerowner' => '{Öwnèr•}',
-
-	/*
-	 * Used as the header for the age (last time project was changed) column in the
-	 * project list
-	 */
-	'headerlastchange' => '{Låst Chångè•••}',
-
-	/*
-	 * Used as the header for the actions column (links to various other pages for
-	 * that project)
-	 */
-	'headeractions' => '{Åctîöns••}',
-
-	/*
-	 * Used as the name for the main project summary page
-	 */
-	'summary' => '{sûmmäry••}',
-
-	/*
-	 * Used as the name for the shortlog (abbreviated commit log) page
-	 */
-	'shortlog' => '{shõrtlög••}',
-
-	/*
-	 * Used as the name for the log (full commit log) page
-	 */
-	'log' => '{lõg•}',
-
-	/*
-	 * Used as the name for a single "commit" to the repository - 
-	 * for the commit page, as well as on other pages when referencing
-	 * a single commit object
-	 */
-	'commit' => '{cömmït•}',
-
-	/*
-	 * Used as the name for the commitdiff page, which shows all changes
-	 * in a single commit
-	 */
-	'commitdiff' => '{cõmmïtdîff•••}',
-
-	/*
-	 * Used as the name for the tree page and to reference tree objects - 
-	 * "trees" being a particular project's directory of files (or subdirectory)
-	 * at a given revision
-	 */
-	'tree' => '{tréè•}',
-
-	/*
-	 * Used as the name for the snapshot action, which sends a tarball of the
-	 * project at a given revision
-	 */
-	'snapshot' => '{snãpshöt••}',
-
-	/*
-	 * Used as the name for the tags page/section, which lists all tags for a project
-	 */
-	'tags' => '{tágs•}',
-
-	/*
-	 * Used as the name for the single tag page, which shows all info on a single
-	 * tag object
-	 */
-	'tag' => '{tàg•}',
-
-	/*
-	 * Used as the name for the heads page/section, which lists all heads for a project
-	 */
-	'heads' => '{hèáds•}',
-
-	/*
-	 * Used as the name for the history page, which lists all commits where a particular
-	 * file was changed
-	 */
-	'history' => '{hîstöry••}',
-
-	/*
-	 * Used as the name for the blob page, which shows the content of a file at a given
-	 * revision (its 'blob' data)
-	 */
-	'blob' => '{blôb•}',
-	
-	/*
-	 * Used as a link to show the differences in a file for a commit
-	 */
-	'diff' => '{dîff•}',
-
-	/*
-	 * Used as a link to diff a particular revision of a file to the current version
-	 */
-	'difftocurrent' => '{dîff tò cürrênt••••}',
-
-	/*
-	 * Used as the name for the search action, and to caption the search box
-	 */
-	'search' => '{sêàrch••}',
-
-	/*
-	 * Used as the caption on the 'RSS' button, which gets a feed of the most recent
-	 * commits to a project
-	 */
-	'RSS' => '{RSS•}',
-
-	/*
-	 * Used as the caption for the 'OPML' button, which gets a list of projects in OPML format
-	 */
-	'OPML' => '{ÖPML•}',
-
-	/*
-	 * Used as the caption for the 'TXT' button, which gets a list of projects in plaintext
-	 */
-	'TXT' => '{TXT•}',
-
-	/*
-	 * Used as a link on various actions (blob, blobdiff, commitdiff, etc) to get the plaintext
-	 * version of it
-	 */
-	'plain' => '{plåïn•}',
-
-    /*
-     * Used as an indicator that something was added
-     */
-    'new' => '{ñêw•}',
-
-	/*
-	 * Used as an indicator that something was deleted
-	 */
-	'deleted' => '{délètëd••}',
-
-	/*
-	 * Used as an indicator that something is a file - for example, that we are diffing a
-	 * file or searching within files
-	 */
-	'file' => '{fílĕ•}',
-
-	/*
-	 * Used to denote the author of a particular commit, or that we want to search
-	 * authors
-	 */
-	'author' => '{åûthōr••}',
-
-	/*
-	 * Used to denote the committer of a particular commit, or that we want to search
-	 * committers
-	 */
-	'committer' => '{cōmmĩttęr••}',
-
-	/*
-	 * Used as the link to the previous page, when paginating through log entries
-	 * or search results
-	 */
-	'prev' => '{prěv•}',
-
-	/*
-	 * Used as the link to the next page, when paginating through log entries
-	 * or search results
-	 */
-	'next' => '{ńėxt•}',
-
-	/*
-	 * Used as the link to the first page, when paginating through search results
-	 */
-	'first' => '{fĩrst•}',
-
-	/*
-	 * Used as the link to the HEAD, when paginating through log entries
-	 */
-	'HEAD' => '{HĚĂD•}',
-	
-	/*
-     * Used to indicate the description of the project, on the project summary page
-     */
-    'description' => '{dêscrïptìõn•••}',
-
-    /*
-     * Used to indicate the owner of the project, on the project summary page
-     */
-    'owner' => '{öwnêr•}',
-
-    /*
-     * Used to indicate the age (last change) of the project, on the project summary page
-     */
-    'lastchange' => '{låst chãngë•••}',
-
-	/*
-	 * Used to indicate the object that is the parent of this one (eg the commit that
-	 * came right before this one)
-	 */
-	'parent' => '{pārėnt••}',
-
-	/*
-	 * Used to indicate the object (commit, etc) that is attached to a tag
-	 */
-	'object' => '{őbjěct••}',
-
-	/*
-	 * Used to indicate a new object was added, where
-	 * %1$s is the type of object (file or tree)
-	 */
-	'newobject' => '{‹%1$s› ñėw•}',
-
-	/*
-	 * Used to indicate a new object was added, where
-	 * %1$s is the type of object (file or tree) and
-	 * %2$s is the new mode
-	 */
-	'newobjectwithmode' => '{mõdę ‹%2$s› ñėw ‹%1$s›•••••}',
-
-	/*
-	 * Used to indicate an object was deleted, where
-	 * %1$s is the type of object (file or tree)
-	 */
-	'deletedobject' => '{‹%1$s› dėlětē••}',
-	
-	/*
-	 * Used to indicate an object's type was changed, where
-	 * %1$s is the old type and %2$s is the new type
-	 */
-	'changedobjecttype' => '{‹%1$s› tö ‹%2$s› chăngěd•••••}',
-	
-	/*
-	 * Used to indicate an object's mode was changed, where
-	 * %1$s is the mode change (either just one mode or
-	 * mode1->mode2)
-	 */
-    'changedobjectmode' => '{‹%1$s› mõdêchångè••••}',
-
-	/*
-	 * Used to indicate that an object was moved/renamed,
-	 * where %1$s is the original name, ande
-	 * %2$d is the percentage similarity,
-	 */
-	'movedobjectwithsimilarity' => '{%%‹%2$d› sĩmīląrĭtŷ, mővɛd frŏm ‹%1$s›•••••••••}',
-	
-    /*
-     * Used to indicate that an object was moved/renamed,
-     * where %1$s is the original name,
-     * %2$d is the percentage similarity, and
-     * %3$s is the mode
-     */
-    'movedobjectwithsimilaritymodechange' => '{%%‹%2$d› sĩmīląrĭtŷ, mővɛd frŏm ‹%1$s› mode ‹%3$s›•••••••••}',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * years ago, where %1$d is the number of years
-	 */
-	'ageyearsago' => '{ŷrs ‹%1$d› ăgő•••}',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * years ago, where %1$d is the number of years
-	 */
-	'agemonthsago' => '{mős ‹%1$d› ăgő•••}',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * weeks ago, where %1$d is the number of weeks
-	 */
-	'ageweeksago' => '{wks ‹%1$d› ăgő•••}',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * days ago, where %1$d is the number of days
-	 */
-	'agedaysago' => '{dŷs ‹%1$d› ăgő•••}',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * hours ago, where %1$d is the number of hours
-	 */
-	'agehoursago' => '{hrs ‹%1$d› ăgő•••}',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * minutes ago, where %1$d is the number of minutes
-	 */
-	'ageminago' => '{mñs ‹%1$d› ăgő••}',
-
-	/*
-	 * Used to indicate something happened a certain number of
-	 * seconds ago, where %1$d is the number of seconds
-	 */
-	'agesecago' => '{scs ‹%1$d› ăgő••}',
-
-	/*
-	 * Used to indicate something is happening right now
-	 * (less than 3 seconds ago)
-	 */
-	'agerightnow' => '{rĩght nøw•••}',
-	
-     /*
-      * Used to indicate a certain number of files were changed in a commit
-      * where %1$d is the numebr of files changed
-      */
-     'fileschanged' => '{chângëd ‹%1$d› fĭlēs••••}',
-);
-
-?>
-

--- a/include/util.age_string.php
+++ b/include/util.age_string.php
@@ -7,34 +7,23 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
-include('i18n.lookupstring.php');
-
 function age_string($age)
 {
-	if ($age > 60*60*24*365*2) {
-		return sprintf(lookupstring('ageyearsago'), (int)($age/60/60/24/365));
-		//i18n: return sprintf(lookupstring('%1$d years ago'), (int)($age/60/60/24/365));
-	} else if ($age > 60*60*24*(365/12)*2) {
-		return sprintf(lookupstring('agemonthsago'), (int)($age/60/60/24/(365/12)));
-		//i18n: return sprintf(lookupstring('%1$d months ago'), (int)($age/60/60/24/(365/12)));
-	} else if ($age > 60*60*24*7*2) {
-		return sprintf(lookupstring('ageweeksago'), (int)($age/60/60/24/7));
-		//i18n: return sprintf(lookupstring('%1$d weeks ago'), (int)($age/60/60/24/7));
-	} else if ($age > 60*60*24*2) {
-		return sprintf(lookupstring('agedaysago'), (int)($age/60/60/24));
-		//i18n: return sprintf(lookupstring('%1$d days ago'), (int)($age/60/60/24));
-	} else if ($age > 60*60*2) {
-		return sprintf(lookupstring('agehoursago'), (int)($age/60/60));
-		//i18n: return sprintf(lookupstring('%1$d hours ago'), (int)($age/60/60));
-	} else if ($age > 60*2) {
-		return sprintf(lookupstring('ageminago'), (int)($age/60));
-		//i18n: return sprintf(lookupstring('%1$d min ago'), (int)($age/60));
-	} else if ($age > 2) {
-		return sprintf(lookupstring('agesecago'), (int)$age);
-		//i18n: return sprintf(lookupstring('%1$d sec ago'), (int)$age);
-	}
-	return lookupstring('agerightnow');
-	//i18n: return lookupstring("right now");
+	if ($age > 60*60*24*365*2)
+		return (int)($age/60/60/24/365) . " years ago";
+	else if ($age > 60*60*24*(365/12)*2)
+		return (int)($age/60/60/24/(365/12)) . " months ago";
+	else if ($age > 60*60*24*7*2)
+		return (int)($age/60/60/24/7) . " weeks ago";
+	else if ($age > 60*60*24*2)
+		return (int)($age/60/60/24) . " days ago";
+	else if ($age > 60*60*2)
+		return (int)($age/60/60) . " hours ago";
+	else if ($age > 60*2)
+		return (int)($age/60) . " min ago";
+	else if ($age > 2)
+		return (int)$age . " sec ago";
+	return "right now";
 }
 
 ?>

--- a/include/version.php
+++ b/include/version.php
@@ -7,7 +7,7 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- $gitphp_version = "0.0.7";
+ $gitphp_version = "0.0.8";
  $gitphp_appstring = "gitphp $gitphp_version";
 
 ?>

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -22,33 +22,45 @@
   */
  require_once('config/gitphp.conf.php');
 
- /*
-  * Debug
-  */
- if ($gitphp_conf['debug']) {
- 	define('GITPHP_START_TIME', microtime(true));
-	error_reporting(E_ALL|E_STRICT);
- }
+ $extraoutput = FALSE;
 
  /*
   * Instantiate Smarty
   */
  require_once($gitphp_conf['smarty_prefix'] . "Smarty.class.php");
  $tpl =& new Smarty;
- if (isset($_GET['a']) &&
-     ($_GET['a'] != "commitdiff_plain") &&
-     ($_GET['a'] != "blob_plain") &&
-     ($_GET['a'] != "blobdiff_plain") &&
-     ($_GET['a'] != "rss") &&
-     ($_GET['a'] != "opml")) {
+ if ((!isset($_GET['a'])) || (
+     	($_GET['a'] != "commitdiff_plain") &&
+     	($_GET['a'] != "blob_plain") &&
+     	($_GET['a'] != "blobdiff_plain") &&
+     	($_GET['a'] != "rss") &&
+     	($_GET['a'] != "opml") &&
+	($_GET['a'] != "snapshot"))) {
 	$tpl->load_filter('output','trimwhitespace');
+	$extraoutput = TRUE;
 }
 
  /*
-  * Init i18n
-  */
- require_once('include/i18n.initlocale.php');
- $localestrings = initlocale($gitphp_conf['lang']);
+  * Debug
+  */
+ if ($gitphp_conf['debug']) {
+ 	if ($extraoutput) {
+		define('GITPHP_START_TIME', microtime(true));
+		error_reporting(E_ALL|E_STRICT);
+	}
+ }
+
+/*
+ * Caching
+ */
+ if ($gitphp_conf['cache']) {
+ 	$tpl->caching = 2;
+	$tpl->cache_lifetime = $gitphp_conf['cachelifetime'];
+	if (!(isset($gitphp_conf['cacheexpire']) && ($gitphp_conf['cacheexpire'] === FALSE))) {
+		require_once('include/cache.cache_expire.php');
+		cache_expire($gitphp_conf['projectroot'], (isset($_GET['p']) ? $_GET['p'] : null), $git_projects);
+	}
+ }
 
 /*
  * Setup global assigns used everywhere (such as header/footer)
@@ -82,7 +94,12 @@
 	$tpl->assign("filesearch",TRUE);
 
 
- if (isset($_GET['a']) && $_GET['a'] == "opml") {
+ if (isset($_GET['a']) && $_GET['a'] == "expire") {
+ 	require_once('include/cache.cache_expire.php');
+	require_once('include/display.git_message.php');
+	cache_expire(null, null, null, true);
+	git_message("Cache expired");
+ } else if (isset($_GET['a']) && $_GET['a'] == "opml") {
 	require_once('include/display.git_opml.php');
 	git_opml($gitphp_conf['projectroot'],$git_projects);
  } else if (isset($_GET['a']) && $_GET['a'] == "project_index") {
@@ -193,7 +210,7 @@
  	git_project_list($gitphp_conf['projectroot'],$git_projects,(isset($_GET['o']) ? $_GET['o'] : "project"));
  }
 
- if ($gitphp_conf['debug'])
+ if ($gitphp_conf['debug'] && $extraoutput)
  	echo "Execution time: " . round(microtime(true) - GITPHP_START_TIME, 8) . " sec";
 
 ?>

--- a/templates/blob.tpl
+++ b/templates/blob.tpl
@@ -11,25 +11,17 @@
  {* If we managed to look up commit info, we have enough info to display the full header - othewise just use a simple header *}
  <div class="page_nav">
    {if $fullnav}
-     {* i18n: summary = summary *}
-     {* i18n: shortlog = shortlog *}
-     {* i18n: log = log *}
-     {* i18n: commit = commit *}
-     {* i18n: comitdiff = commitdiff *}
-     {* i18n: tree = tree *}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hashbase}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hashbase}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hashbase}">{$localize.tree}</a><br />
-     {* i18n: plain = plain *}
+     <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hashbase}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hashbase}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hashbase}">tree</a><br />
      {if $file}
-       <a href="{$SCRIPT_NAME}?p={$project}&a=blob_plain&h={$hash}&f={$file}">{$localize.plain}</a> | 
-       {* i18n: HEAD = HEAD *}
+       <a href="{$SCRIPT_NAME}?p={$project}&a=blob_plain&h={$hash}&f={$file}">plain</a> | 
        {if ($hashbase != "HEAD") && ($hashbase != $head)}
-         <a href="{$SCRIPT_NAME}?p={$project}&a=blob&hb=HEAD&f={$file}">{$localize.HEAD}</a>
+         <a href="{$SCRIPT_NAME}?p={$project}&a=blob&hb=HEAD&f={$file}">HEAD</a>
        {else}
-         {$localize.HEAD}
+         HEAD
        {/if}
        <br />
      {else}
-       <a href="{$SCRIPT_NAME}?p={$project}&a=blob_plain&h={$hash}">{$localize.plain}</a><br />
+       <a href="{$SCRIPT_NAME}?p={$project}&a=blob_plain&h={$hash}">plain</a><br />
      {/if}
    {else}
      <br /><br />

--- a/templates/blobdiff.tpl
+++ b/templates/blobdiff.tpl
@@ -11,16 +11,9 @@
  {* If we managed to look up commit info, we have enough info to display the full header - othewise just use a simple header *}
  <div class="page_nav">
    {if $fullnav}
-     {* i18n: summary = summary *}
-     {* i18n: shortlog = shortlog *}
-     {* i18n: log = log *}
-     {* i18n: commit = commit *}
-     {* i18n: commitdiff = commitdiff *}
-     {* i18n: tree = tree *}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hashbase}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hashbase}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hashbase}">{$localize.tree}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hashbase}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hashbase}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hashbase}">tree</a>
      <br />
-     {* i18n: plain = plain *}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff_plain&h={$hash}&hp={$hashparent}&f={$file}">{$localize.plain}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff_plain&h={$hash}&hp={$hashparent}&f={$file}">plain</a>
    {else}
      <br /><br />
    {/if}
@@ -52,8 +45,7 @@
  <div class="page_body">
    <div class="diff_info">
      {* Display the from -> to diff header *}
-     {* i18n: blob = blob *}
-     {$localize.blob}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$hashparent}&hb={$hashbase}&f={$file}">{if $file}a/{$file}{else}{$hashparent}{/if}</a> -&gt; {$localize.blob}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$hash}&hb={$hashbase}&f={$file}">{if $file}b/{$file}{else}{$hash}{/if}</a>
+     blob:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$hashparent}&hb={$hashbase}&f={$file}">{if $file}a/{$file}{else}{$hashparent}{/if}</a> -&gt; blob:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$hash}&hb={$hashbase}&f={$file}">{if $file}b/{$file}{else}{$hash}{/if}</a>
    </div>
    {* Display the diff *}
    {include file='filediff.tpl'}

--- /dev/null
+++ b/templates/blobdiffplain.tpl
@@ -1,1 +1,9 @@
+{*
+ *  blobdiffplain.tpl
+ *  gitphp: A PHP git repository browser
+ *  Component: Blobdiff plain template
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ *}
+{$blobdiff}
 

--- /dev/null
+++ b/templates/blobheaders.tpl
@@ -1,1 +1,9 @@
+{*
+ *  blobheaders.tpl
+ *  gitphp: A PHP git repository browser
+ *  Component: Blob header dummy template
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ *}
+{$blobheaders}
 

--- /dev/null
+++ b/templates/blobplain.tpl
@@ -1,1 +1,9 @@
+{*
+ *  blobplain.tpl
+ *  gitphp: A PHP git repository browser
+ *  Component: Blob plain template
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ *}
+{$blob}
 

--- a/templates/commit.tpl
+++ b/templates/commit.tpl
@@ -10,13 +10,7 @@
 
  <div class="page_nav">
    {* Nav *}
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">{$localize.log}</a> | {$localize.commit} | {if $parent}<a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">{$localize.commitdiff}</a> | {/if}<a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">{$localize.tree}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">log</a> | commit | {if $parent}<a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">commitdiff</a> | {/if}<a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">tree</a>
    <br /><br />
  </div>
  <div>
@@ -35,8 +29,7 @@
    {* Commit data *}
    <table cellspacing="0">
      <tr>
-       {* i18n: author = author *}
-       <td>{$localize.author}</td>
+       <td>author</td>
        <td>{$author}</td>
      </tr>
      <tr>
@@ -44,8 +37,7 @@
        <td> {$adrfc2822} ({if $adhourlocal < 6}<span class="latenight">{/if}{$adhourlocal}:{$adminutelocal}{if $adhourlocal < 6}</span>{/if} {$adtzlocal})</td>
      </tr>
      <tr>
-       {* i18n: committer = committer *}
-       <td>{$localize.committer}</td>
+       <td>committer</td>
        <td>{$committer}</td>
      </tr>
      <tr>
@@ -53,26 +45,19 @@
        <td> {$cdrfc2822} ({$cdhourlocal}:{$cdminutelocal} {$cdtzlocal})</td>
      </tr>
      <tr>
-       {* i18n: commit = commit *}
-       <td>{$localize.commit}</td>
+       <td>commit</td>
        <td class="monospace">{$id}</td>
      <tr>
      <tr>
-       {* i18n: tree = tree *}
-       <td>{$localize.tree}</td>
+       <td>tree</td>
        <td class="monospace"><a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}" class="list">{$tree}</a></td>
-       {* i18n: snapshot = snapshot *}
-       {* i18n: tree = tree *}
-       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">{$localize.tree}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$hash}">{$localize.snapshot}</a></td>
+       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">tree</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$hash}">snapshot</a></td>
      </tr>
      {foreach from=$parents item=par}
        <tr>
-         {* i18n: parent = parent *}
-         <td>{$localize.parent}</td>
+         <td>parent</td>
 	 <td class="monospace"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$par}" class="list">{$par}</a></td>
-	 {* i18n: commit = commit *}
-	 {* i18n: commitdiff = commitdiff *}
-         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$par}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}&hp={$par}">{$localize.commitdiff}</a></td>
+         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$par}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}&hp={$par}">commitdiff</a></td>
        </tr>
      {/foreach}
    </table>
@@ -84,8 +69,7 @@
  </div>
  <div class="list_head">
    {if $difftreesize > 11}
-     {* i18n: fileschanged = %1$d files changed *}
-     {$localize.fileschanged|sprintf:$difftreesize}:
+     {$difftreesize} files changed:
    {/if}
  </div>
  <table cellspacing="0">
@@ -95,22 +79,12 @@
 	 
        {if $difftreelines[difftree].status == "A"}
          <td><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}" class="list">{$difftreelines[difftree].file}</a></td>
-	 {if $difftreelines[difftree].isreg}
-	   {* i18n: newobjectwithmode = new %1$s with mode: %2$s *}
-           <td><span class="newfile">[{$localize.newobjectwithmode|sprintf:$difftreelines[difftree].to_filetype_localized:$difftreelines[difftree].to_mode_cut}]</span></td>
-	 {else}
-	   {* i18n: newobject = new %1$s *}
-           <td><span class="newfile">[{$localize.newobject|sprintf:$difftreelines[difftree].to_filetype_localized}]</span></td>
-	 {/if}
-	 {* i18n: blob = blob *}
-         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">{$localize.blob}</a></td>
+         <td><span class="newfile">[new {$difftreelines[difftree].to_filetype}{if $difftreelines[difftree].isreg} with mode: {$difftreelines[difftree].to_mode_cut}{/if}]</span></td>
+         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">blob</a></td>
        {elseif $difftreelines[difftree].status == "D"}
          <td><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}" class="list">{$difftreelines[difftree].file}</a></td>
-	 {* i18n: deletedobject = deleted %1$s *}
-         <td><span class="deletedfile">[{$localize.deletedobject|sprintf:$difftreelines[difftree].from_filetype_localized}]</span></td>
-	 {* i18n: blob = blob *}
-	 {* i18n: history = history *}
-         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">{$localize.blob}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hash}&f={$difftreelines[difftree].file}">{$localize.history}</a></td>
+         <td><span class="deletedfile">[deleted {$difftreelines[difftree].from_filetype}]</span></td>
+         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">blob</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hash}&f={$difftreelines[difftree].file}">history</a></td>
        {elseif $difftreelines[difftree].status == "M" || $difftreelines[difftree].status == "T"}
          <td>
            {if $difftreelines[difftree].to_id != $difftreelines[difftree].from_id}
@@ -119,38 +93,13 @@
              <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}" class="list">{$difftreelines[difftree].file}</a>
            {/if}
          </td>
-         <td>
-	   {if $difftreelines[difftree].from_mode != $difftreelines[difftree].to_mode}
-	     <span class="changedfile">
-	       {if $difftreelines[difftree].typechange}
-	         {* i18n: changedobjecttype = changed from %1$s to %2$s *}
-	         [{$localize.changedobjecttype|sprintf:$difftreelines[difftree].from_filetype_localized:$difftreelines[difftree].to_filetype_localized}]
-	       {/if}
-	       {if $difftreelines[difftree].modechange}
-	         {* i18n: changedobjectmode = changed mode: %1$s *}
-	         [{$localize.changedobjectmode|sprintf:$difftreelines[difftree].modechange}]
-	       {/if}
-	     </span>
-	   {/if}
-	 </td>
+         <td>{if $difftreelines[difftree].from_mode != $difftreelines[difftree].to_mode} <span class="changedfile">[changed{$difftreelines[difftree].modechange}]</span>{/if}</td>
          <td class="link">
-	   {* i18n: blob = blob *}
-	   {* i18n: diff = diff *}
-	   {* i18n: history = history *}
-           <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">{$localize.blob}</a>{if $difftreelines[difftree].to_id != $difftreelines[difftree].from_id} | <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff&h={$difftreelines[difftree].to_id}&hp={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">{$localize.diff}</a>{/if} | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hash}&f={$difftreelines[difftree].file}">{$localize.history}</a></td>
+           <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">blob</a>{if $difftreelines[difftree].to_id != $difftreelines[difftree].from_id} | <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff&h={$difftreelines[difftree].to_id}&hp={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">diff</a>{/if} | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hash}&f={$difftreelines[difftree].file}">history</a></td>
        {elseif $difftreelines[difftree].status == "R"}
          <td><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].to_file}" class="list">{$difftreelines[difftree].to_file}</a></td>
-	 {capture name='oldfile' assign='oldfile'}<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].from_file}" class="list">{$difftreelines[difftree].from_file}</a>{/capture}
-         {if $difftreelines[difftree].simmodechg}
-           {* i18n: movedobjectwithsimilaritymodechange = moved from %1$s with %2$d%% similarity, mode: %3$s *}
-           <td><span class="movedfile">[{$localize.movedobjectwithsimilaritymodechange|sprintf:$oldfile:$difftreelines[difftree].similarity:$difftreelines[difftree].simmodechg}]</span></td>
-	 {else}
-           {* i18n: movedobjectwithsimilarity = moved from %1$s with %2$d%% similarity *}
-           <td><span class="movedfile">[{$localize.movedobjectwithsimilarity|sprintf:$oldfile:$difftreelines[difftree].similarity}]</span></td>
-	 {/if}
-	 {* i18n: blob = blob *}
-	 {* i18n: diff = diff *}
-         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].to_file}">{$localize.blob}</a>{if $difftreelines[difftree].to_id != $difftreelines[difftree].from_id} | <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff&h={$difftreelines[difftree].to_id}&hp={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].to_file}">{$localize.diff}</a>{/if}</td>
+         <td><span class="movedfile">[moved from <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].from_file}" class="list">{$difftreelines[difftree].from_file}</a> with {$difftreelines[difftree].similarity}% similarity{$difftreelines[difftree].simmodechg}]</span></td>
+         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].to_file}">blob</a>{if $difftreelines[difftree].to_id != $difftreelines[difftree].from_id} | <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff&h={$difftreelines[difftree].to_id}&hp={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].to_file}">diff</a>{/if}</td>
        {/if}
 
      </tr>

--- a/templates/commitdiff.tpl
+++ b/templates/commitdiff.tpl
@@ -10,14 +10,7 @@
 
  {* Nav *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: plain = plain *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">{$localize.commit}</a> | {$localize.commitdiff} | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">{$localize.tree}</a><br /><a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff_plain&h={$hash}&hp={$hashparent}">{$localize.plain}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">commit</a> | commitdiff | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">tree</a><br /><a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff_plain&h={$hash}&hp={$hashparent}">plain</a>
  </div>
  <div>
    <br /><br />
@@ -34,18 +27,16 @@
    {section name=difftree loop=$difftreelines}
      {if $difftreelines[difftree].status == "A"}
        <div class="diff_info">
-         {* i18n: deleted = deleted *}
-         {$difftreelines[difftree].to_type_localized}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}{$difftreelines[difftree].file}{else}{$difftreelines[difftree].to_id}{/if}</a>({$localize.new})
+         {$difftreelines[difftree].to_type}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}{$difftreelines[difftree].file}{else}{$difftreelines[difftree].to_id}{/if}</a>(new)
        </div>
      {elseif $difftreelines[difftree].status == "D"}
        <div class="diff_info">
-         {* i18n: deleted = deleted *}
-         {$difftreelines[difftree].from_type_localized}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}{$difftreelines[difftree].file}{else}{$difftreelines[difftree].from_id}{/if}</a>({$localize.deleted})
+         {$difftreelines[difftree].from_type}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}{$difftreelines[difftree].file}{else}{$difftreelines[difftree].from_id}{/if}</a>(deleted)
        </div>
      {elseif $difftreelines[difftree].status == "M"}
        {if $difftreelines[difftree].from_id != $difftreelines[difftree].to_id}
          <div class="diff_info">
-	   {$difftreelines[difftree].from_type_localized}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}a/{$difftreelines[difftree].file}{else}{$difftreelines[difftree].from_id}{/if}</a> -&gt; {$difftreelines[difftree].to_type_localized}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}b/{$difftreelines[difftree].file}{else}{$difftreelines[difftree].to_id}{/if}</a>
+	   {$difftreelines[difftree].from_type}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].from_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}a/{$difftreelines[difftree].file}{else}{$difftreelines[difftree].from_id}{/if}</a> -&gt; {$difftreelines[difftree].to_type}:<a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$difftreelines[difftree].to_id}&hb={$hash}&f={$difftreelines[difftree].file}">{if $difftreelines[difftree].file}b/{$difftreelines[difftree].file}{else}{$difftreelines[difftree].to_id}{/if}</a>
 	 </div>
        {/if}
      {/if}

--- a/templates/footer.tpl
+++ b/templates/footer.tpl
@@ -11,14 +11,11 @@
           <div class="page_footer_text">{$projectdescription}</div>
         {/if}
 	{if $validproject}
-	  {* i18n: RSS = RSS *}
-          <a href="{$SCRIPT_NAME}?p={$project}&a=rss" class="rss_logo">{$localize.RSS}</a>
+          <a href="{$SCRIPT_NAME}?p={$project}&a=rss" class="rss_logo">RSS</a>
 	{/if}
       {else}
-        {* i18n: OPML = OPML *}
-        <a href="{$SCRIPT_NAME}?a=opml" class="rss_logo">{$localize.OPML}</a>
-	{* i18n: TXT = TXT *}
-        <a href="{$SCRIPT_NAME}?a=project_index" class="rss_logo">{$localize.TXT}</a>
+        <a href="{$SCRIPT_NAME}?a=opml" class="rss_logo">OPML</a>
+        <a href="{$SCRIPT_NAME}?a=project_index" class="rss_logo">TXT</a>
       {/if}
     </div>
   </body>

--- a/templates/header.tpl
+++ b/templates/header.tpl
@@ -5,14 +5,13 @@
  *
  *  Copyright (C) 2006 Christopher Han <xiphux@gmail.com>
  *}
-{* $contentType = strpos($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') === false ? 'text/html' : 'application/xhtml+xml';
-header("Content-Type: $contentType; charset=utf-8"); *}
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
   <!-- gitphp web interface {$version}, (C) 2006 Christopher Han <xiphux@gmail.com> -->
   <head>
-    <title>{$pagetitle}{if $project && $validproject} :: {$project}{if $action && $validaction}/{$localize.$action}{/if}{/if}</title>
+    <title>{$pagetitle}{if $project && $validproject} :: {$project}{if $action && $validaction}/{$action}{/if}{/if}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     {if $validproject}
       <link rel="alternate" title="{$project} log" href="{$SCRIPT_NAME}?p={$project}&a=rss" type="application/rss+xml" />
     {/if}
@@ -24,12 +23,11 @@
       <a href="http://www.kernel.org/pub/software/scm/git/docs/" title="git documentation">
         <img src="git-logo.png" width="72" height="27" alt="git" class="logo" />
       </a>
-      {* i18n: projects = projects *}
-      <a href="index.php">{$localize.projects}</a> / 
+      <a href="index.php">projects</a> / 
       {if $project && $validproject}
         <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$project}</a>
         {if $action && $validaction}
-           / {$localize.$action}
+           / {$action}
         {/if}
         {if $enablesearch}
           <form method="get" action="index.php" enctype="application/x-www-form-urlencoded">
@@ -38,18 +36,13 @@
               <input type="hidden" name="a" value="search" />
               <input type ="hidden" name="h" value="{if $currentsearchhash}{$currentsearchhash}{else}HEAD{/if}" />
               <select name="st">
-	        {* i18n: commit = commit *}
-                <option {if $currentsearchtype == 'commit'}selected="selected"{/if} value="commit">{$localize.commit}</option>
-                {* i18n: author = author *}
-                <option {if $currentsearchtype == 'author'}selected="selected"{/if} value="author">{$localize.author}</option>
-                {* i18n: committer = committer *}
-                <option {if $currentsearchtype == 'committer'}selected="selected"{/if} value="committer">{$localize.committer}</option>
+                <option {if $currentsearchtype == 'commit'}selected="selected"{/if} value="commit">commit</option>
+                <option {if $currentsearchtype == 'author'}selected="selected"{/if} value="author">author</option>
+                <option {if $currentsearchtype == 'committer'}selected="selected"{/if} value="committer">committer</option>
                 {if $filesearch}
-		  {* i18n: file = file *}
-                  <option {if $currentsearchtype == 'file'}selected="selected"{/if} value="file">{$localize.file}</option>
+                  <option {if $currentsearchtype == 'file'}selected="selected"{/if} value="file">file</option>
                 {/if}
-		{* i18n: search = search *}
-              </select> {$localize.search}: <input type="text" name="s" {if $currentsearch}value="{$currentsearch}"{/if} />
+              </select> search: <input type="text" name="s" {if $currentsearch}value="{$currentsearch}"{/if} />
             </div>
           </form>
         {/if}

--- a/templates/heads.tpl
+++ b/templates/heads.tpl
@@ -1,5 +1,5 @@
 {*
- *  heads.tpl
+ *  heads_nav.tpl
  *  gitphp: A PHP git repository browser
  *  Component: Head view template
  *
@@ -10,13 +10,7 @@
 
  {* Nav *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&hb={$head}">{$localize.tree}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&hb={$head}">tree</a>
    <br /><br />
  </div>
  <div>
@@ -26,12 +20,9 @@
    {* Loop and display each head *}
    {foreach from=$headlist item=head}
      <tr class="{cycle values="light,dark"}">
-       <td><i>{$head.age}</i></td>
+       <td><i>{$head.age_string}</i></td>
        <td><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$head.name}" class="list"><b>{$head.name}</b></a></td>
-       {* i18n: shortlog = shortlog *}
-       {* i18n: log = log *}
-       {* i18n: tree = tree *}
-       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$head.name}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/heads/{$head.name}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h=refs/heads/{$head.name}&hb={$head.name}">{$localize.tree}</a></td>
+       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$head.name}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/heads/{$head.name}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h=refs/heads/{$head.name}&hb={$head.name}">tree</a></td>
      </tr>
    {/foreach}
  </table>

--- a/templates/history.tpl
+++ b/templates/history.tpl
@@ -10,13 +10,7 @@
 
  {* Page header *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">{$localize.tree}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$tree}&hb={$hash}">tree</a>
    <br /><br />
  </div>
  <div>
@@ -46,11 +40,7 @@
        <td title="{$historylines[history].agestringage}"><i>{$historylines[history].agestringdate}</i></td>
        <td><i>{$historylines[history].authorname}</i></td>
        <td><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$historylines[history].commit}" class="list"><b>{$historylines[history].title}{if $historylines[history].commitref} <span class="tag">{$historylines[history].commitref}</span>{/if}</b></a></td>
-       {* i18n: difftocurrent = diff to current *}
-       {* i18n: blob = blob *}
-       {* i18n: commit = commit *}
-       {* i18n: commitdiff = commitdiff *}
-       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$historylines[history].commit}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$historylines[history].commit}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=blob&hb={$historylines[history].commit}&f={$historylines[history].file}">{$localize.blob}</a>{if $historylines[history].blob && $historylines[history].blobparent} | <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff&h={$historylines[history].blob}&hp={$historylines[history].blobparent}&hb={$historylines[history].commit}&f={$historylines[history].file}">{$localize.difftocurrent}</a>{/if}
+       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$historylines[history].commit}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$historylines[history].commit}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=blob&hb={$historylines[history].commit}&f={$historylines[history].file}">blob</a>{if $historylines[history].blob && $historylines[history].blobparent} | <a href="{$SCRIPT_NAME}?p={$project}&a=blobdiff&h={$historylines[history].blob}&hp={$historylines[history].blobparent}&hb={$historylines[history].commit}&f={$historylines[history].file}">diff to current</a>{/if}
        </td>
      </tr>
    {/section}

--- a/templates/log.tpl
+++ b/templates/log.tpl
@@ -10,33 +10,24 @@
 
  {* Nav *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">{$localize.shortlog}</a> | {$localize.log} | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$hash}&hb={$hash}">{$localize.tree}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">shortlog</a> | log | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$hash}&hb={$hash}">tree</a>
    <br />
-   {* i18n: HEAD = HEAD *}
    {if ($hash != $head) || $page}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.HEAD}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=log">HEAD</a>
    {else}
-     {$localize.HEAD}
+     HEAD
    {/if}
    &sdot; 
-   {* i18n: prev = prev *}
    {if $page > 0}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}&pg={$page-1}" accesskey="p" title="Alt-p">{$localize.prev}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}&pg={$page-1}" accesskey="p" title="Alt-p">prev</a>
    {else}
-     {$localize.prev}
+     prev
    {/if}
    &sdot; 
-   {* i18n: next = next *}
    {if $revlistcount > 100}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}&pg={$page+1}" accesskey="n" title="Alt-n">{$localize.next}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}&pg={$page+1}" accesskey="n" title="Alt-n">next</a>
    {else}
-     {$localize.next}
+     next
    {/if}
    <br />
  </div>
@@ -60,10 +51,7 @@
    </div>
    <div class="title_text">
      <div class="log_link">
-       {* i18n: tree = tree *}
-       {* i18n: commit = commit *}
-       {* i18n: commitdiff = commitdiff *}
-       <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[log].commit}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$commitlines[log].commit}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$commitlines[log].commit}&hb={$commitlines[log].commit}">{$localize.tree}</a>
+       <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[log].commit}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$commitlines[log].commit}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$commitlines[log].commit}&hb={$commitlines[log].commit}">tree</a>
        <br />
      </div>
      <i>{$commitlines[log].authorname} [{$commitlines[log].rfc2822}]</i><br />

--- a/templates/project.tpl
+++ b/templates/project.tpl
@@ -10,28 +10,18 @@
 
  {* Nav *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   {$localize.summary} | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree">{$localize.tree}</a>
+   summary | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree">tree</a>
    <br /><br />
  </div>
  <div class="title">&nbsp;</div>
  {* Project brief *}
  <table cellspacing="0">
-   {* i18n: description = description *}
-   {* i18n: owner = owner *}
-   {* i18n: lastchange = last change *}
-   <tr><td>{$localize.description}</td><td>{$description}</td></tr>
-   <tr><td>{$localize.owner}</td><td>{$owner}</td></tr>
-   <tr><td>{$localize.lastchange}</td><td>{$lastchange}</td></tr>
+   <tr><td>description</td><td>{$description}</td></tr>
+   <tr><td>owner</td><td>{$owner}</td></tr>
+   <tr><td>last change</td><td>{$lastchange}</td></tr>
  </table>
  <div>
-   {* i18n: shortlog = shortlog *}
-   <a class="title" href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a>
+   <a class="title" href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a>
  </div>
  <table cellspacing="0">
    {* Recent revisions *}
@@ -49,13 +39,9 @@
              {if $revlist[rev].commitref}
                <span class="tag">{$revlist[rev].commitref}</span>
              {/if}
-           </b></a>
+           </b>
          </td>
-	 {* i18n: snapshot = snapshot *}
-	 {* i18n: tree = tree *}
-	 {* i18n: commit = commit *}
-	 {* i18n: commitdiff = commitdiff *}
-         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$revlist[rev].commit}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$revlist[rev].commit}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$revlist[rev].commit}&hb={$revlist[rev].commit}">{$localize.tree}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$revlist[rev].commit}">{$localize.snapshot}</a></td>
+         <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$revlist[rev].commit}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$revlist[rev].commit}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$revlist[rev].commit}&hb={$revlist[rev].commit}">tree</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$revlist[rev].commit}">snapshot</a></td>
        </tr>
      {/if}
    {/section}
@@ -63,8 +49,7 @@
  {if $taglist}
    {* Tags *}
    <div>
-     {* i18n: tags = tags *}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=tags" class="title">{$localize.tags}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=tags" class="title">tags</a>
    </div>
    <table cellspacing="0">
      {section name=tag max=17 loop=$taglist}
@@ -72,7 +57,7 @@
          {if $smarty.section.tag.index == 16}
            <td><a href="{$SCRIPT_NAME}?p={$project}&a=tags">...</a></td>
          {else}
-           <td><i>{$taglist[tag].age}</i></td>
+           <td><i>{$taglist[tag].age_string}</i></td>
            <td><a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}" class="list"><b>{$taglist[tag].name}</b></a></td>
            <td>
              {if $taglist[tag].comment}
@@ -81,13 +66,9 @@
            </td>
            <td class="link">
              {if $taglist[tag].type == "tag"}
-	       {* i18n: tag = tag *}
-   	       <a href="{$SCRIPT_NAME}?p={$project}&a=tag&h={$taglist[tag].id}">{$localize.tag}</a> | 
+   	       <a href="{$SCRIPT_NAME}?p={$project}&a=tag&h={$taglist[tag].id}">tag</a> | 
              {/if}
-	     {* i18n: shortlog = shortlog *}
-	     {* i18n: log = log *}
-	     {* i18n: snapshot = snapshot *}
-             <a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}">{$taglist[tag].reftype_localized}</a>{if $taglist[tag].reftype == "commit"} | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/tags/{$taglist[tag].name}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/tags/{$taglist[tag].name}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$taglist[tag].refid}">{$localize.snapshot}</a>{/if}
+             <a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}">{$taglist[tag].reftype}</a>{if $taglist[tag].reftype == "commit"} | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/tags/{$taglist[tag].name}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/tags/{$taglist[tag].name}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$taglist[tag].refid}">snapshot</a>{/if}
            </td>
          {/if}
        </tr>
@@ -97,8 +78,7 @@
  {if $headlist}
    {* Heads *}
    <div>
-     {* i18n: heads = heads *}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=heads" class="title">{$localize.heads}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=heads" class="title">heads</a>
    </div>
    <table cellspacing="0">
      {section name=head max=17 loop=$headlist}
@@ -106,12 +86,9 @@
          {if $smarty.section.head.index == 16}
            <td><a href="{$SCRIPT_NAME}?p={$project}&a=heads">...</a></td>
          {else}
-           <td><i>{$headlist[head].age}</i></td>
+           <td><i>{$headlist[head].age_string}</i></td>
            <td><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$headlist[head].name}" class="list"><b>{$headlist[head].name}</b></td>
-	   {* i18n: shortlog = shortlog *}
-	   {* i18n: log = log *}
-	   {* i18n: tree = tree *}
-           <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$headlist[head].name}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/heads/{$headlist[head].name}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h=refs/heads/{$headlist[head].name}&hb={$headlist[head].name}">{$localize.tree}</a></td>
+           <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/heads/{$headlist[head].name}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/heads/{$headlist[head].name}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h=refs/heads/{$headlist[head].name}&hb={$headlist[head].name}">tree</a></td>
          {/if}
        </tr>
      {/section}

--- /dev/null
+++ b/templates/projectindex.tpl
@@ -1,1 +1,19 @@
+{*
+ *  projectindex.tpl
+ *  gitphp: A PHP git repository browser
+ *  Component: Project index template
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ *}
+{if $categorized}
+{foreach from=$projlist item=plist}
+{foreach from=$plist item=proj}
+{$proj}
+{/foreach}
+{/foreach}
+{else}
+{foreach from=$projlist item=proj}
+{$proj}
+{/foreach}
+{/if}
 

--- a/templates/projectlist.tpl
+++ b/templates/projectlist.tpl
@@ -17,32 +17,27 @@
   <table cellspacing="0">
     {* Header *}
     <tr>
-      {* i18n: headerproject = Project *}
       {if $order == "project"}
-        <th>{$localize.headerproject}</th>
+        <th>Project</th>
       {else}
-        <th><a class="header" href="{$SCRIPT_NAME}?o=project">{$localize.headerproject}</a></th>
+        <th><a class="header" href="{$SCRIPT_NAME}?o=project">Project</a></th>
       {/if}
-      {* i18n: headerdescription = Description *}
       {if $order == "descr"}
-        <th>{$localize.headerdescription}</th>
+        <th>Description</th>
       {else}
-        <th><a class="header" href="{$SCRIPT_NAME}?o=descr">{$localize.headerdescription}</a></th>
+        <th><a class="header" href="{$SCRIPT_NAME}?o=descr">Description</a></th>
       {/if}
-      {* i18n: headerowner = Owner *}
       {if $order == "owner"}
-        <th>{$localize.headerowner}</th>
+        <th>Owner</th>
       {else}
-        <th><a class="header" href="{$SCRIPT_NAME}?o=owner">{$localize.headerowner}</a></th>
+        <th><a class="header" href="{$SCRIPT_NAME}?o=owner">Owner</a></th>
       {/if}
-      {* i18n: headerlastchange = Last Change *}
       {if $order == "age"}
-        <th>{$localize.headerlastchange}</th>
+        <th>Last Change</th>
       {else}
-        <th><a class="header" href="{$SCRIPT_NAME}?o=age">{$localize.headerlastchange}</a></th>
+        <th><a class="header" href="{$SCRIPT_NAME}?o=age">Last Change</a></th>
       {/if}
-      {* i18n: headeractions = Actions *}
-      <th>{$localize.headeractions}</th>
+      <th>Actions</th>
     </tr>
 
     {if $categorizedprojects}
@@ -74,12 +69,7 @@
                 <i>{$plist[proj].age_string}</i>
               {/if}
             </td>
-	    {* i18n: summary = summary *}
-	    {* i18n: shortlog = shortlog *}
-	    {* i18n: log = log *}
-	    {* i18n: snapshot = snapshot *}
-	    {* i18n: tree = tree *}
-            <td class="link"><a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=tree">{$localize.tree}</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=snapshot&h=HEAD">{$localize.snapshot}</a></td>
+            <td class="link"><a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=tree">tree</a> | <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=snapshot&h=HEAD">snapshot</a></td>
           </tr>
         {/section}
       {/foreach}
@@ -103,12 +93,7 @@
               <i>{$projects[proj].age_string}</i>
             {/if}
           </td>
-	  {* i18n: summary = summary *}
-	  {* i18n: shortlog = shortlog *}
-	  {* i18n: log = log *}
-	  {* i18n: snapshot = snapshot *}
-	  {* i18n: tree = tree *}
-          <td class="link"><a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=tree">{$localize.tree}</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=snapshot&h=HEAD">{$localize.snapshot}</a></td>
+          <td class="link"><a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=tree">tree</a> | <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=snapshot&h=HEAD">snapshot</a></td>
         </tr>
       {/section}
 

--- a/templates/search.tpl
+++ b/templates/search.tpl
@@ -10,33 +10,24 @@
 
 {* Nav *}
 <div class="page_nav">
-  {* i18n: summary = summary *}
-  {* i18n: shortlog = shortlog *}
-  {* i18n: log = log *}
-  {* i18n: commit = commit *}
-  {* i18n: commitdiff = commitdiff *}
-  {* i18n: tree = tree *}
-  <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$treehash}&hb={$hash}">{$localize.tree}</a>
+  <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$treehash}&hb={$hash}">tree</a>
   <br />
-  {* i18n: first = first *}
   {if $page > 0}
-    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}">{$localize.first}</a>
+    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}">first</a>
   {else}
-    {$localize.first}
+    first
   {/if}
     &sdot; 
-  {* i18n: prev = prev *}
   {if $page > 0}
-    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}{if $page > 1}&pg={$page-1}{/if}" accesskey="p" title="Alt-p">{$localize.prev}</a>
+    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}{if $page > 1}&pg={$page-1}{/if}" accesskey="p" title="Alt-p">prev</a>
   {else}
-    {$localize.prev}
+    prev
   {/if}
     &sdot; 
-  {* i18n: next = next *}
   {if $revlistcount > 100}
-    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" accesskey="n" title="Alt-n">{$localize.next}</a>
+    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" accesskey="n" title="Alt-n">next</a>
   {else}
-    {$localize.next}
+    next
   {/if}
   <br />
 </div>
@@ -49,24 +40,19 @@
     <tr class="{cycle values="light,dark"}">
       <td title="{$commitlines[match].agestringage}"><i>{$commitlines[match].agestringdate}</i></td>
       <td><i>{$commitlines[match].authorname}</i></td>
-      <td><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[match].commit}" class="list" {if $title}title="{$commitlines[match].title}"{/if}><b>{$commitlines[match].title_short}</b></a>
+      <td><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[match].commit}" class="list" {if $title}title="{$commitlines[match].title}"{/if}><b>{$commitlines[match].title_short}</b>
         {foreach from=$commitlines[match].matches item=line name=match}
           {if $smarty.foreach.match.first}<br />{/if}{$line}<br />
         {/foreach}
       </td>
-      {* i18n: snapshot = snapshot *}
-      {* i18n: tree = tree *}
-      {* i18n: commit = commit *}
-      {* i18n: commitdiff = commitdiff *}
-      <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[match].commit}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$commitlines[match].commit}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$commitlines[match].committree}&hb={$commitlines[match].commit}">{$localize.tree}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$commitlines[match].commit}">{$localize.snapshot}</a>
+      <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[match].commit}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$commitlines[match].commit}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$commitlines[match].committree}&hb={$commitlines[match].commit}">tree</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$commitlines[match].commit}">snapshot</a>
       </td>
     </tr>
   {/section}
 
   {if $revlistcount > 100}
     <tr>
-      {* i18n: next = next *}
-      <td><a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" title="Alt-n">{$localize.next}</a></td>
+      <td><a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" title="Alt-n">next</a></td>
     </tr>
   {/if}
 </table>

--- a/templates/searchfiles.tpl
+++ b/templates/searchfiles.tpl
@@ -10,33 +10,24 @@
 
 {* Nav *}
 <div class="page_nav">
-  {* i18n: summary = summary *}
-  {* i18n: shortlog = shortlog *}
-  {* i18n: log = log *}
-  {* i18n: commit = commit *}
-  {* i18n: commitdiff = commitdiff *}
-  {* i18n: tree = tree *}
-  <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$treehash}&hb={$hash}">{$localize.tree}</a>
+  <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$treehash}&hb={$hash}">tree</a>
   <br />
-  {* i18n: first = first *}
   {if $page > 0}
-    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}">{$localize.first}</a>
+    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}">first</a>
   {else}
-    {$localize.first}
+    first
   {/if}
     &sdot; 
-  {* i18n: prev = prev *}
   {if $page > 0}
-    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}{if $page > 1}&pg={$page-1}{/if}" accesskey="p" title="Alt-p">{$localize.prev}</a>
+    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}{if $page > 1}&pg={$page-1}{/if}" accesskey="p" title="Alt-p">prev</a>
   {else}
-    {$localize.prev}
+    prev
   {/if}
     &sdot; 
-  {* i18n: next = next *}
   {if $filesearchcount > 100}
-    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" accesskey="n" title="Alt-n">{$localize.next}</a>
+    <a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" accesskey="n" title="Alt-n">next</a>
   {else}
-    {$localize.next}
+    next
   {/if}
   <br />
 </div>
@@ -59,12 +50,9 @@
       </td>
       <td class="link">
         {if $filesearchlines[match].tree}
-	  {* i18n: tree = tree *}
-          <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$filesearchlines[match].hash}&hb={$hash}&f={$filesearchlines[match].file}">{$localize.tree}</a>
+          <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$filesearchlines[match].hash}&hb={$hash}&f={$filesearchlines[match].file}">tree</a>
         {else}
-	  {* i18n: blob = blob *}
-	  {* i18n: history = history *}
-          <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$filesearchlines[match].hash}&hb={$hash}&f={$filesearchlines[match].file}">{$localize.blob}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hash}&f={$filesearchlines[match].file}">{$localize.history}</a>
+          <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$filesearchlines[match].hash}&hb={$hash}&f={$filesearchlines[match].file}">blob</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hash}&f={$filesearchlines[match].file}">history</a>
         {/if}
       </td>
     </tr>
@@ -72,8 +60,7 @@
 
   {if $filesearchcount > 100}
     <tr>
-      {* i18n: next = next *}
-      <td><a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" title="Alt-n">{$localize.next}</a></td>
+      <td><a href="{$SCRIPT_NAME}?p={$project}&a=search&h={$hash}&s={$search}&st={$searchtype}&pg={$page+1}" title="Alt-n">next</a></td>
     </tr>
   {/if}
 </table>

--- a/templates/shortlog.tpl
+++ b/templates/shortlog.tpl
@@ -10,33 +10,24 @@
 
  {* Nav *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | {$localize.shortlog} | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$hash}&hb={$hash}">{$localize.tree}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | shortlog | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hash}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hash}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hash}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$hash}&hb={$hash}">tree</a>
    <br />
-   {* i18n: HEAD = HEAD *}
    {if ($hash != $head) || $page}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.HEAD}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">HEAD</a>
    {else}
-     {$localize.HEAD}
+     HEAD
    {/if}
      &sdot; 
-   {* i18n: prev = prev *}
    {if $page > 0}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}&pg={$page-1}" accesskey="p" title="Alt-p">{$localize.prev}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}&pg={$page-1}" accesskey="p" title="Alt-p">prev</a>
    {else}
-     {$localize.prev}
+     prev
    {/if}
      &sdot; 
-   {* i18n: next = next *}
    {if $revlistcount > 100}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}&pg={$page+1}" accesskey="n" title="Alt-n">{$localize.next}</a>
+     <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}&pg={$page+1}" accesskey="n" title="Alt-n">next</a>
    {else}
-     {$localize.next}
+     next
    {/if}
    <br />
  </div>
@@ -54,21 +45,16 @@
          {if $commitlines[log].commitref}
            <span class="tag">{$commitlines[log].commitref}</span>
          {/if}
-         </b></a>
+         </b>
        </td>
-       {* i18n: snapshot = snapshot *}
-       {* i18n: commit = commit *}
-       {* i18n: commitdiff = commitdiff *}
-       {* i18n: tree = tree *}
-       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[log].commit}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$commitlines[log].commit}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$commitlines[log].commit}&hb={$commitlines[log].commit}">{$localize.tree}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$commitlines[log].commit}">{$localize.snapshot}</a>
+       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$commitlines[log].commit}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$commitlines[log].commit}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$commitlines[log].commit}&hb={$commitlines[log].commit}">tree</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$commitlines[log].commit}">snapshot</a>
        </td>
      </tr>
    {/section}
 
    {if $revlistcount > 100}
      <tr>
-       {* i18n: next = next *}
-       <td><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}&pg={$page+1}" title="Alt-n">{$localize.next}</a></td>
+       <td><a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hash}&pg={$page+1}" title="Alt-n">next</a></td>
      </tr>
    {/if}
  </table>

--- /dev/null
+++ b/templates/snapshot.tpl
@@ -1,1 +1,9 @@
+{*
+ *  snapshots.tpl
+ *  gitphp: A PHP git repository browser
+ *  Component: Snapshot template
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ *}
+{$archive}
 

--- a/templates/tag.tpl
+++ b/templates/tag.tpl
@@ -10,13 +10,7 @@
 
  {* Nav *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&hb={$head}">{$localize.tree}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&hb={$head}">tree</a>
    <br /><br />
  </div>
  {* Tag data *}
@@ -26,15 +20,13 @@
  <div class="title_text">
    <table cellspacing="0">
      <tr>
-       {* i18n: object = object *}
-       <td>{$localize.object}</td>
+       <td>object</td>
        <td class="monospace"><a href="{$SCRIPT_NAME}?p={$project}&a={$tag.type}&h={$tag.object}" class="list">{$tag.object}</a></td>
-       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a={$tag.type}&h={$tag.object}">{$tag.type_localized}</a></td>
+       <td class="link"><a href="{$SCRIPT_NAME}?p={$project}&a={$tag.type}&h={$tag.object}">{$tag.type}</a></td>
      </tr>
      {if $tag.author}
        <tr>
-         {* i18n: author = author *}
-         <td>{$localize.author}</td>
+         <td>author</td>
 	 <td>{$tag.author}</td>
        </tr>
        <tr>

--- a/templates/tags.tpl
+++ b/templates/tags.tpl
@@ -10,13 +10,7 @@
 
  {* Nav *}
  <div class="page_nav">
-   {* i18n: summary = summary *}
-   {* i18n: shortlog = shortlog *}
-   {* i18n: log = log *}
-   {* i18n: commit = commit *}
-   {* i18n: commitdiff = commitdiff *}
-   {* i18n: tree = tree *}
-   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">{$localize.commitdiff}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&hb={$head}">{$localize.tree}</a>
+   <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$head}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$head}">commitdiff</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=tree&hb={$head}">tree</a>
    <br /><br />
  </div>
  <div>
@@ -26,7 +20,7 @@
  <table cellspacing="0">
    {section name=tag loop=$taglist}
      <tr class="{cycle values="light,dark"}">
-       <td><i>{$taglist[tag].age}</i></td>
+       <td><i>{$taglist[tag].age_string}</i></td>
        <td><a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}" class="list"><b>{$taglist[tag].name}</b></a></td>
        <td>
          {if count($taglist[tag].comment) > 0}
@@ -35,15 +29,11 @@
        </td>
        <td class="link">
          {if $taglist[tag].type == "tag"}
-	   {* i18n: tag = tag *}
-	   <a href="{$SCRIPT_NAME}?p={$project}&a=tag&h={$taglist[tag].id}">{$localize.tag}</a> | 
+	   <a href="{$SCRIPT_NAME}?p={$project}&a=tag&h={$taglist[tag].id}">tag</a> | 
 	 {/if}
-	 <a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}">{$taglist[tag].reftype_localized}</a>
+	 <a href="{$SCRIPT_NAME}?p={$project}&a={$taglist[tag].reftype}&h={$taglist[tag].refid}">{$taglist[tag].reftype}</a>
 	 {if $taglist[tag].reftype == "commit"}
-	   {* i18n: shortlog = shortlog *}
-	   {* i18n: log = log *}
-	   {* i18n: snapshot = snapshot *}
-	   | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/tags/{$taglist[tag].name}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/tags/{$taglist[tag].name}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$taglist[tag].refid}">{$localize.snapshot}</a>
+	   | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h=refs/tags/{$taglist[tag].name}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h=refs/tags/{$taglist[tag].name}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=snapshot&h={$taglist[tag].refid}">snapshot</a>
 	 {/if}
        </td>
      </tr>

--- a/templates/tree.tpl
+++ b/templates/tree.tpl
@@ -11,13 +11,7 @@
  {* Nav *}
  {if $fullnav}
    <div class="page_nav">
-     {* i18n: summary = summary *}
-     {* i18n: shortlog = shortlog *}
-     {* i18n: log = log *}
-     {* i18n: commit = commit *}
-     {* i18n: commitdiff = commitdiff *}
-     {* i18n: tree = tree *}
-     <a href="{$SCRIPT_NAME}?p={$project}&a=summary">{$localize.summary}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hashbase}">{$localize.shortlog}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hashbase}">{$localize.log}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hashbase}">{$localize.commit}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hashbase}">{$localize.commitdiff}</a> | {$localize.tree}<br /><br />
+     <a href="{$SCRIPT_NAME}?p={$project}&a=summary">summary</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=shortlog&h={$hashbase}">shortlog</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=log&h={$hashbase}">log</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hashbase}">commit</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=commitdiff&h={$hashbase}">commitdiff</a> | tree<br /><br />
    </div>
    <div>
      <a href="{$SCRIPT_NAME}?p={$project}&a=commit&h={$hashbase}" class="title">{$title}
@@ -50,17 +44,14 @@
              <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$treelines[tree].hash}{if $hashbase}&hb={$hashbase}{/if}&f={if $base}{$base}{/if}{$treelines[tree].name}" class="list">{$treelines[tree].name}</a>
 	   </td>
            <td class="link">
-	     {* i18n: blob = blob *}
-	     {* i18n: history = history *}
-	     <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$treelines[tree].hash}{if $hashbase}&hb={$hashbase}{/if}&f={if $base}{$base}{/if}{$treelines[tree].name}">{$localize.blob}</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hashbase}&f={if $base}{$base}{/if}{$treelines[tree].name}">{$localize.history}</a>
+	     <a href="{$SCRIPT_NAME}?p={$project}&a=blob&h={$treelines[tree].hash}{if $hashbase}&hb={$hashbase}{/if}&f={if $base}{$base}{/if}{$treelines[tree].name}">blob</a> | <a href="{$SCRIPT_NAME}?p={$project}&a=history&h={$hashbase}&f={if $base}{$base}{/if}{$treelines[tree].name}">history</a>
 	   </td>
          {elseif $treelines[tree].type == "tree"}
            <td class="list">
              <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$treelines[tree].hash}{if $hashbase}&hb={$hashbase}{/if}&f={if $base}{$base}{/if}{$treelines[tree].name}">{$treelines[tree].name}</a>
 	   </td>
            <td class="link">
-	     {* i18n: tree = tree *}
-	     <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$treelines[tree].hash}{if $hashbase}&hb={$hashbase}{/if}&f={if $base}{$base}{/if}{$treelines[tree].name}">{$localize.tree}</a>
+	     <a href="{$SCRIPT_NAME}?p={$project}&a=tree&h={$treelines[tree].hash}{if $hashbase}&hb={$hashbase}{/if}&f={if $base}{$base}{/if}{$treelines[tree].name}">tree</a>
 	   </td>
          {/if}
        </tr>

comments