diff --git a/apps/routerconsole/java/bundle-messages.sh b/apps/routerconsole/java/bundle-messages.sh
index 629fc95f05b294dc8abd9c3ee9f758055889ef65..3b80c80e9c586c86e91b22d256d1ced64ce6a8c8 100755
--- a/apps/routerconsole/java/bundle-messages.sh
+++ b/apps/routerconsole/java/bundle-messages.sh
@@ -26,6 +26,7 @@ do
 	# extract strings from java and jsp files, and update messages.po files
 	# translate calls must be one of the forms:
 	# _("foo")
+	# _x("foo")
 	# cssHelper._("foo")
 	# cssHelper.title("foo")
 	# handler._("foo")
@@ -35,7 +36,8 @@ do
 	# then ant distclean updater.
 	find src ../jsp/WEB-INF -name *.java > $TMPFILE
 	xgettext -f $TMPFILE -F -L java \
-                 --keyword=_ --keyword=cssHelper._ --keyword=cssHelper.title --keyword=handler._ --keyword=formhandler._ \
+                 --keyword=_ --keyword=_x --keyword=cssHelper._ --keyword=cssHelper.title \
+                 --keyword=handler._ --keyword=formhandler._ \
 	         -o ${i}t
 	if [ $? -ne 0 ]
 	then
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java
index 715c800931a7c1148ff248e76149a30bbc111ed7..d4f825a9a1acf400af350f2435f1239a9a1d1ed1 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java
@@ -29,6 +29,11 @@ public class CSSHelper extends HelperBase {
             _context.router().setConfigSetting(Messages.PROP_LANG, lang);
     }
 
+    /** needed for conditional css loads for zh */
+    public String getLang() {
+        return Messages.getLanguage(_context);
+    }
+
     /** translate the title and display consistently */
     public String title(String s) {
          StringBuilder buf = new StringBuilder(128);
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHelper.java
index 7815f5cba1e08b2f286156a2475b04357fc3d84f..96556b418af5a8f423baf10805545ad21254199e 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHelper.java
@@ -3,7 +3,7 @@ package net.i2p.router.web;
 public class ConfigUIHelper extends HelperBase {
     public ConfigUIHelper() {}
     
-    private static final String themes[] = {"classic", "dark", "light"};
+    private static final String themes[] = {_x("classic"), _x("dark"), _x("light")};
 
     public String getSettings() {
         StringBuilder buf = new StringBuilder(512);
@@ -12,7 +12,24 @@ public class ConfigUIHelper extends HelperBase {
             buf.append("<input type=\"radio\" class=\"optbox\" name=\"theme\" ");
             if (theme.equals(current))
                 buf.append("checked=\"true\" ");
-            buf.append("value=\"").append(theme).append("\"/>").append(theme).append("<br>\n");
+            buf.append("value=\"").append(theme).append("\">").append(_(theme)).append("<br>\n");
+        }
+        return buf.toString();
+    }
+
+    private static final String langs[] = {"de", "en", "fr", "nl", "se", "zh"};
+    private static final String xlangs[] = {_x("German"), _x("English"), _x("French"),
+                                            _x("Dutch"), _x("Swedish"), _x("Chinese")};
+
+    public String getLangSettings() {
+        StringBuilder buf = new StringBuilder(512);
+        String current = Messages.getLanguage(_context);
+        for (int i = 0; i < langs.length; i++) {
+            // we use "lang" so it is set automagically in CSSHelper
+            buf.append("<input type=\"radio\" class=\"optbox\" name=\"lang\" ");
+            if (langs[i].equals(current))
+                buf.append("checked=\"true\" ");
+            buf.append("value=\"").append(langs[i]).append("\">").append(_(xlangs[i])).append("<br>\n");
         }
         return buf.toString();
     }
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java b/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java
index 63762ec14d8f1651db5c8f09e07cf8ac98c3002c..e5e640957d7fdbc2966ea15dc9c77d904c16fa51 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java
@@ -34,4 +34,14 @@ public abstract class HelperBase {
     public String _(String s) {
         return Messages.getString(s, _context);
     }
+
+    /**
+     *  Mark a string for extraction by xgettext and translation.
+     *  Use this only in static initializers.
+     *  It does not translate!
+     *  @return s
+     */
+    public static String _x(String s) {
+        return s;
+    }
 }
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/Messages.java b/apps/routerconsole/java/src/net/i2p/router/web/Messages.java
index df7c5319f3fb0dc3fd090fa09c3bb8924d7242f5..a251f7e12466722918b5e8703c98a6bec70fc360 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/Messages.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/Messages.java
@@ -54,7 +54,7 @@ public class Messages {
         }
     }
 
-    private static String getLanguage(I2PAppContext ctx) {
+    public static String getLanguage(I2PAppContext ctx) {
         String lang = ctx.getProperty(PROP_LANG);
         if (lang == null || lang.length() <= 0)
             lang = _localeLang;
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java
index e7d6ee4126a09fce625028a2508f633d063d2276..7a9d91d5bdd14ac5c770de1df86598e32c555c16 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java
@@ -202,9 +202,9 @@ public class SummaryBarRenderer {
                     buf.append("<button type=\"submit\" name=\"updateAction\" value=\"Unsigned\" >")
                        .append(_("Download Unsigned"))
                        .append("<br>")
-                       .append(_helper.getUnsignedUpdateVersion())
-                       .append(' ')
                        .append(_("Update"))
+                       .append(' ')
+                       .append(_helper.getUnsignedUpdateVersion())
                        .append("</button>\n");
                 }
                 buf.append("</form>\n");
diff --git a/apps/routerconsole/jsp/confignav.jsp b/apps/routerconsole/jsp/confignav.jsp
index bba31052ec868fa567b9f44acc172a61d91f5931..699a57237181967018b1ede5ee445362b03d9153 100644
--- a/apps/routerconsole/jsp/confignav.jsp
+++ b/apps/routerconsole/jsp/confignav.jsp
@@ -2,11 +2,8 @@
 <center>
 <% if (request.getRequestURI().indexOf("config.jsp") != -1) {
  %>Network | <% } else { %><a href="config.jsp">Network</a> | <% }
- String userAgent = request.getHeader("User-Agent");
- if (userAgent == null || !userAgent.contains("MSIE")) {
      if (request.getRequestURI().indexOf("configui.jsp") != -1) {
      %>UI | <% } else { %><a href="configui.jsp">UI</a> | <% }
- }
  if (request.getRequestURI().indexOf("configservice.jsp") != -1) {
  %>Service | <% } else { %><a href="configservice.jsp">Service</a> | <% }
  if (request.getRequestURI().indexOf("configupdate.jsp") != -1) {
diff --git a/apps/routerconsole/jsp/configui.jsp b/apps/routerconsole/jsp/configui.jsp
index 89f7d7c2bf1d5c0101620009a8195855bc851d6e..1bf276237c2a5b6e9816fb8991e72f4577f13d75 100644
--- a/apps/routerconsole/jsp/configui.jsp
+++ b/apps/routerconsole/jsp/configui.jsp
@@ -2,8 +2,9 @@
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
-<html><head><title>I2P Router Console - config UI</title>
+<html><head>
 <%@include file="css.jsp" %>
+<%=cssHelper.title("config UI")%>
 </head><body>
 
 <%@include file="summary.jsp" %>
@@ -11,7 +12,7 @@
 <jsp:useBean class="net.i2p.router.web.ConfigUIHelper" id="uihelper" scope="request" />
 <jsp:setProperty name="uihelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
 
-<h1>I2P UI Configuration</h1>
+<h1><%=uihelper._("I2P UI Configuration")%></h1>
 <div class="main" id="main">
 
  <%@include file="confignav.jsp" %>
@@ -20,23 +21,27 @@
  <jsp:setProperty name="formhandler" property="*" />
  <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
-<div class="configure"><h3>Router Console Theme</h3>
-<%
- // userAgent defined in confignav
- if (userAgent == null || !userAgent.contains("MSIE")) {
-%>
+<div class="configure"><h3><%=uihelper._("Router Console Theme")%></h3>
  <form action="configui.jsp" method="POST">
  <% String prev = System.getProperty("net.i2p.router.web.ConfigUIHandler.nonce");
     if (prev != null) System.setProperty("net.i2p.router.web.ConfigUIHandler.noncePrev", prev);
     System.setProperty("net.i2p.router.web.ConfigUIHandler.nonce", new java.util.Random().nextLong()+""); %>
- <input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigUIHandler.nonce")%>" />
- <input type="hidden" name="action" value="blah" />
+ <input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigUIHandler.nonce")%>" >
+ <input type="hidden" name="action" value="blah" >
+<%
+ String userAgent = request.getHeader("User-Agent");
+ if (userAgent == null || !userAgent.contains("MSIE")) {
+%>
  <jsp:getProperty name="uihelper" property="settings" />
-<hr><div class="formaction">
-<input type="submit" name="shouldsave" value="Apply" /> <input type="reset" value="Cancel" />
-</div></form></div>
 <% } else { %>
-Theme selection disabled for Internet Explorer, sorry.<hr>If you're not using IE, it's likely that
-your browser is pretending to be IE; please configure your browser (or proxy) to use a different User Agent string if you'd like to access the console themes.
+<%=uihelper._("Theme selection disabled for Internet Explorer, sorry.")%>
+<hr>
+<%=uihelper._("If you're not using IE, it's likely that your browser is pretending to be IE; please configure your browser (or proxy) to use a different User Agent string if you'd like to access the console themes.")%>
 <% } %>
+<h3><%=uihelper._("Router Console Language")%></h3>
+<jsp:getProperty name="uihelper" property="langSettings" />
+<%=uihelper._("Please contribute to the router console translation project! Contact the developers on IRC #i2p to help.")%>
+<hr><div class="formaction">
+<input type="submit" name="shouldsave" value="Apply" > <input type="reset" value="Cancel" >
+</div></form></div>
 </div></body></html>
diff --git a/apps/routerconsole/jsp/css.jsp b/apps/routerconsole/jsp/css.jsp
index 865e907235f5565ec35b8b0aef506d0c8a36a283..62aceaa93f44046e2945230d27da0f7b7929fbdf 100644
--- a/apps/routerconsole/jsp/css.jsp
+++ b/apps/routerconsole/jsp/css.jsp
@@ -29,4 +29,12 @@
    cssHelper.setLang(request.getParameter("lang"));
 %>
 <link href="<%=cssHelper.getTheme(request.getHeader("User-Agent"))%>console.css" rel="stylesheet" type="text/css">
+<%
+   // make the fonts bigger for chinese
+   if (cssHelper.getLang().equals("zh")) {
+%>
+<link href="<%=cssHelper.getTheme(request.getHeader("User-Agent"))%>console_big.css" rel="stylesheet" type="text/css">
+<%
+   }
+%>
 <!--[if IE]><link href="/themes/console/classic/ieshim.css" rel="stylesheet" type="text/css" /><![endif]-->