diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java
index fc24856be97361274d930d32a90a3c6b87dd5141..7632dc4c0e62e4be8bfef6f420ef2a660024b7c1 100644
--- a/router/java/src/net/i2p/router/transport/TransportImpl.java
+++ b/router/java/src/net/i2p/router/transport/TransportImpl.java
@@ -43,6 +43,7 @@ import net.i2p.util.Log;
 import net.i2p.util.SimpleScheduler;
 import net.i2p.util.SimpleTimer;
 import net.i2p.util.SystemVersion;
+import net.i2p.util.Translate;
 
 /**
  * Defines a way to send a message to another peer and start listening for messages
@@ -654,4 +655,30 @@ public abstract class TransportImpl implements Transport {
             return false;
         }
     }
+
+    private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
+
+    /**
+     *  Translate
+     *  @since 0.9.8 moved from transports
+     */
+    protected String _(String s) {
+        return Translate.getString(s, _context, BUNDLE_NAME);
+    }
+
+    /**
+     *  Translate
+     *  @since 0.9.8 moved from transports
+     */
+    protected String _(String s, Object o) {
+        return Translate.getString(s, o, _context, BUNDLE_NAME);
+    }
+
+    /**
+     *  Translate
+     *  @since 0.9.8
+     */
+    protected String ngettext(String s, String p, int n) {
+        return Translate.getString(n, s, p, _context, BUNDLE_NAME);
+    }
 }
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
index 343ee5f0b0ef670ba3a23645a44a61946e912fd2..4ff5fc5099bf91f380fc108b02d5026bdfb10307 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
@@ -36,7 +36,6 @@ import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
 import net.i2p.util.Addresses;
 import net.i2p.util.ConcurrentHashSet;
 import net.i2p.util.Log;
-import net.i2p.util.Translate;
 
 /**
  *  The NIO TCP transport
@@ -843,7 +842,9 @@ public class NTCPTransport extends TransportImpl {
 
         if (!peers.isEmpty()) {
 //            buf.append("<tr> <td colspan=\"11\"><hr></td></tr>\n");
-            buf.append("<tr class=\"tablefooter\"><td align=\"center\"><b>").append(peers.size()).append(' ').append(_("peers")).append("</b></td><td>&nbsp;</td><td>&nbsp;");
+            buf.append("<tr class=\"tablefooter\"><td align=\"center\"><b>")
+               .append(ngettext("{0} peer", "{0} peers", peers.size()))
+               .append("</b></td><td>&nbsp;</td><td>&nbsp;");
             buf.append("</td><td align=\"center\"><b>").append(formatRate(bpsRecv/1024)).append(THINSP).append(formatRate(bpsSend/1024)).append("</b>");
             buf.append("</td><td align=\"center\"><b>").append(DataHelper.formatDuration2(totalUptime/peers.size()));
             buf.append("</b></td><td align=\"center\"><b>").append(DataHelper.formatDuration2(offsetTotal*1000/peers.size()));
@@ -888,15 +889,6 @@ public class NTCPTransport extends TransportImpl {
         }
     }
 
-    private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
-
-    /**
-     *  Translate
-     */
-    private final String _(String s) {
-        return Translate.getString(s, _context, BUNDLE_NAME);
-    }
-
     /**
      * Cache the bid to reduce object churn
      */
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
index bae48409b7d08d0f8e4d536ec5d71c184c0cf1dc..f9ea5662e638d60e3b2ab326bd87b0d7b926b575 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -44,7 +44,6 @@ import net.i2p.util.Log;
 import net.i2p.util.SimpleScheduler;
 import net.i2p.util.SimpleTimer;
 import net.i2p.util.SimpleTimer2;
-import net.i2p.util.Translate;
 
 /**
  *  The SSU transport
@@ -2414,7 +2413,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
         }
         
 //        buf.append("<tr><td colspan=\"16\"><hr></td></tr>\n");
-        buf.append("<tr class=\"tablefooter\"><td colspan=\"3\" align=\"left\"><b>").append(_("SUMMARY")).append("</b></td>" +
+        buf.append("<tr class=\"tablefooter\"><td colspan=\"3\" align=\"left\"><b>")
+           .append(ngettext("{0} peer", "{0} peers", peers.size()))
+           .append("</b></td>" +
                    "<td align=\"center\" nowrap><b>");
         buf.append(formatKBps(bpsIn)).append(THINSP).append(formatKBps(bpsOut));
         long x = numPeers > 0 ? uptimeMsTotal/numPeers : 0;
@@ -2474,21 +2475,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
         }
     }
     private static final DecimalFormat _pctFmt = new DecimalFormat("#0.0%");
-    private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
-
-    /**
-     *  Translate
-     */
-    private final String _(String s) {
-        return Translate.getString(s, _context, BUNDLE_NAME);
-    }
-
-    /**
-     *  Translate
-     */
-    private final String _(String s, Object o) {
-        return Translate.getString(s, o, _context, BUNDLE_NAME);
-    }
 
     /*
      * Cache the bid to reduce object churn