[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] [bridgedb/master 1/3] Towards l10n of BridgeDB: Add gettext facilities, make BridgeDB switch languages when asked.



Author: Christian Fromme <kaner@xxxxxxxxxx>
Date: Tue, 24 Aug 2010 20:46:05 +0200
Subject: Towards l10n of BridgeDB: Add gettext facilities, make BridgeDB switch languages
Commit: b0d15c4780543248ec71a3db85eb630211c11ab4

---
 bridgedb.conf               |    1 +
 i18n/de/bridgedb.po         |  163 +++++++++++++++++++++++++++++++++++++++++++
 i18n/en/bridgedb.po         |  114 ++++++++++++++++++++++++++++++
 i18n/templates/bridgedb.pot |  114 ++++++++++++++++++++++++++++++
 lib/bridgedb/I18n.py        |   83 ++++++++++++++++++++++
 lib/bridgedb/Main.py        |    7 ++
 lib/bridgedb/Server.py      |  106 +++++++++++++++-------------
 setup.cfg                   |    2 +
 setup.py                    |   60 ++++++++++++++++-
 9 files changed, 598 insertions(+), 52 deletions(-)
 create mode 100644 i18n/de/bridgedb.po
 create mode 100644 i18n/en/bridgedb.po
 create mode 100644 i18n/templates/bridgedb.pot
 create mode 100644 lib/bridgedb/I18n.py
 create mode 100644 setup.cfg

diff --git a/bridgedb.conf b/bridgedb.conf
index d28775a..625e53e 100644
--- a/bridgedb.conf
+++ b/bridgedb.conf
@@ -140,3 +140,4 @@ EMAIL_INCLUDE_FINGERPRINTS=False
 #   HTTPS_SHARE : EMAIL_SHARE : RESERVED_SHARE
 RESERVED_SHARE=2
 
+CONFIGURED_LOCALES = [ "en", "de" ]
diff --git a/i18n/de/bridgedb.po b/i18n/de/bridgedb.po
new file mode 100644
index 0000000..108cbec
--- /dev/null
+++ b/i18n/de/bridgedb.po
@@ -0,0 +1,163 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-14 13:28+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@xxxxxx>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/bridgedb/I18n.py:7
+msgid ""
+"\n"
+"    Here are your bridge relays:\n"
+"    "
+msgstr ""
+"\n"
+"   Hier sind deine Bridge Relays:\n"
+"    "
+
+#: lib/bridgedb/I18n.py:11
+msgid ""
+"\n"
+"    Bridge relays (or \"bridges\" for short) are Tor relays that aren't "
+"listed\n"
+"    in the main directory. Since there is no complete public list of them,\n"
+"    even if your ISP is filtering connections to all the known Tor relays,\n"
+"    they probably won't be able to block all the bridges.\n"
+"    "
+msgstr ""
+"\n"
+"    Sogenannte \"Bridge Relays\" (oder kurz \"Bridges\" ) sind Tor Relays, die"
+"    nicht in den oeffentlich publizierten Relay-Listen auftauchen."
+"    Dadurch, dass die Bridges der Oeffentlichkeit nicht bekannt ist, "
+"    sind ISPs nicht dazu in der Lage, alle Tor Relays zu filtern."
+"    "
+
+#: lib/bridgedb/I18n.py:18
+msgid ""
+"\n"
+"    To use the above lines, go to Vidalia's Network settings page, and "
+"click\n"
+"    \"My ISP blocks connections to the Tor network\". Then add each bridge\n"
+"    address one at a time.\n"
+"    "
+msgstr ""
+"\n"
+"    Um die oben genannten Zeilen zu nutzen, sollten Sie in Vidalia's   "
+"    Network Settings gehen und den Menuepunkt \"Mein ISP blockt Verbindungen "
+"    zum Tor Netzwerk\" anklicken. Anschliessend koennen sie die Bridge-Adressen"
+"    hinzufuegen."
+"    "
+
+#: lib/bridgedb/I18n.py:24
+msgid ""
+"\n"
+"    Configuring more than one bridge address will make your Tor connection\n"
+"    more stable, in case some of the bridges become unreachable.\n"
+"    "
+msgstr ""
+"\n"
+"    Mehr als eine Brigde-Adresse zu verwenden fuehrt zu einer stabileren\n"
+"    Verbindung. Es kann immer sein, dass mal eine Bridge kurzzeitig nicht "
+"    erreichbar ist.\n"
+"    "
+
+#: lib/bridgedb/I18n.py:29
+msgid ""
+"\n"
+"    Another way to find public bridge addresses is to send mail to\n"
+"    bridges@xxxxxxxxxxxxxx with the line \"get bridges\" by itself in the "
+"body\n"
+"    of the mail. However, so we can make it harder for an attacker to learn\n"
+"    lots of bridge addresses, you must send this request from a gmail or\n"
+"    yahoo account.\n"
+"    "
+msgstr ""
+"\n"
+"    Eine weitere Moeglichkeit Bridge-Adressen zu finden ist, eine Email\n"
+"    an bridges@xxxxxxxxxxxxxx mit der Zeile \"get bridges\" zu Schreiben.\n"
+"    Diesen Reqeuest muessen Sie allerdings von einem GMail oder Yahoo-Account"
+"    schicken.\n"
+"    "
+
+#: lib/bridgedb/I18n.py:48
+msgid ""
+"\n"
+"[This is an automated message; please do not reply.]\n"
+msgstr ""
+"\n"
+"[Diese Mail wurde elektronisch erstellt; Bitte nicht antworten.]\n"
+
+#: lib/bridgedb/I18n.py:52
+msgid ""
+"\n"
+"Here are your bridge relays:\n"
+msgstr ""
+"\n"
+"Hier sind Ihre Bridge Relays:\n"
+
+#: lib/bridgedb/I18n.py:56
+msgid ""
+"\n"
+"Bridge relays (or \"bridges\" for short) are Tor relays that aren't listed\n"
+"in the main directory. Since there is no complete public list of them,\n"
+"even if your ISP is filtering connections to all the known Tor relays,\n"
+"they probably won't be able to block all the bridges.\n"
+msgstr ""
+"\n"
+"    Sogenannte \"Bridge Relays\" (oder kurz \"Bridges\" ) sind Tor Relays, die"
+"    nicht in den oeffentlich publizierten Relay-Listen auftauchen."
+"    Dadurch, dass die Bridges der Oeffentlichkeit nicht bekannt ist, "
+"    sind ISPs nicht dazu in der Lage, alle Tor Relays zu filtern.\n"
+
+#: lib/bridgedb/I18n.py:63
+msgid ""
+"\n"
+"To use the above lines, go to Vidalia's Network settings page, and click\n"
+"\"My ISP blocks connections to the Tor network\". Then add each bridge\n"
+"address one at a time.\n"
+msgstr ""
+"\n"
+"    Um die oben genannten Zeilen zu nutzen, sollten Sie in Vidalia's   "
+"    Network Settings gehen und den Menuepunkt \"Mein ISP blockt Verbindungen "
+"    zum Tor Netzwerk\" anklicken. Anschliessend koennen sie die Bridge-Adressen"
+"    hinzufuegen.\n"
+
+#: lib/bridgedb/I18n.py:69
+msgid ""
+"\n"
+"Configuring more than one bridge address will make your Tor connection\n"
+"more stable, in case some of the bridges become unreachable.\n"
+msgstr ""
+"\n"
+"    Mehr als eine Brigde-Adresse zu verwenden fuehrt zu einer stabileren\n"
+"    Verbindung. Es kann immer sein, dass mal eine Bridge kurzzeitig nicht "
+"    erreichbar ist.\n"
+
+#: lib/bridgedb/I18n.py:74
+msgid ""
+"\n"
+"Another way to find public bridge addresses is to visit\n"
+"https://bridges.torproject.org/. The answers you get from that page\n"
+"will change every few days, so check back periodically if you need more\n"
+"bridge addresses.\n"
+msgstr ""
+"\n"
+"Ein anderer Weg, neue Bridge-Adressen zu finden, ist folgende Web-Adresse zu"
+" besuchen:\n"
+"https://bridges.torproject.org/. Sie koennen diese Adresse alle paar Tage\n"
+"besuchen, um neue Bridge-Adressen zu erhalten.\n"
+
+#: lib/bridgedb/I18n.py:89
+msgid "(no bridges currently available)"
+msgstr "(Zur Zeit sind keine Bridges verfuegbar)"
diff --git a/i18n/en/bridgedb.po b/i18n/en/bridgedb.po
new file mode 100644
index 0000000..0604f29
--- /dev/null
+++ b/i18n/en/bridgedb.po
@@ -0,0 +1,114 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-14 13:28+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@xxxxxx>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/bridgedb/I18n.py:7
+msgid ""
+"\n"
+"    Here are your bridge relays:\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/I18n.py:11
+msgid ""
+"\n"
+"    Bridge relays (or \"bridges\" for short) are Tor relays that aren't "
+"listed\n"
+"    in the main directory. Since there is no complete public list of them,\n"
+"    even if your ISP is filtering connections to all the known Tor relays,\n"
+"    they probably won't be able to block all the bridges.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/I18n.py:18
+msgid ""
+"\n"
+"    To use the above lines, go to Vidalia's Network settings page, and "
+"click\n"
+"    \"My ISP blocks connections to the Tor network\". Then add each bridge\n"
+"    address one at a time.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/I18n.py:24
+msgid ""
+"\n"
+"    Configuring more than one bridge address will make your Tor connection\n"
+"    more stable, in case some of the bridges become unreachable.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/I18n.py:29
+msgid ""
+"\n"
+"    Another way to find public bridge addresses is to send mail to\n"
+"    bridges@xxxxxxxxxxxxxx with the line \"get bridges\" by itself in the "
+"body\n"
+"    of the mail. However, so we can make it harder for an attacker to learn\n"
+"    lots of bridge addresses, you must send this request from a gmail or\n"
+"    yahoo account.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/I18n.py:48
+msgid ""
+"\n"
+"[This is an automated message; please do not reply.]\n"
+msgstr ""
+
+#: lib/bridgedb/I18n.py:52
+msgid ""
+"\n"
+"Here are your bridge relays:\n"
+msgstr ""
+
+#: lib/bridgedb/I18n.py:56
+msgid ""
+"\n"
+"Bridge relays (or \"bridges\" for short) are Tor relays that aren't listed\n"
+"in the main directory. Since there is no complete public list of them,\n"
+"even if your ISP is filtering connections to all the known Tor relays,\n"
+"they probably won't be able to block all the bridges.\n"
+msgstr ""
+
+#: lib/bridgedb/I18n.py:63
+msgid ""
+"\n"
+"To use the above lines, go to Vidalia's Network settings page, and click\n"
+"\"My ISP blocks connections to the Tor network\". Then add each bridge\n"
+"address one at a time.\n"
+msgstr ""
+
+#: lib/bridgedb/I18n.py:69
+msgid ""
+"\n"
+"Configuring more than one bridge address will make your Tor connection\n"
+"more stable, in case some of the bridges become unreachable.\n"
+msgstr ""
+
+#: lib/bridgedb/I18n.py:74
+msgid ""
+"\n"
+"Another way to find public bridge addresses is to visit\n"
+"https://bridges.torproject.org/. The answers you get from that page\n"
+"will change every few days, so check back periodically if you need more\n"
+"bridge addresses.\n"
+msgstr ""
+
+#: lib/bridgedb/I18n.py:89
+msgid "(no bridges currently available)"
+msgstr ""
diff --git a/i18n/templates/bridgedb.pot b/i18n/templates/bridgedb.pot
new file mode 100644
index 0000000..c88de86
--- /dev/null
+++ b/i18n/templates/bridgedb.pot
@@ -0,0 +1,114 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-14 13:28+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@xxxxxx>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/bridgedb/Strings.py:7
+msgid ""
+"\n"
+"    Here are your bridge relays:\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/Strings.py:11
+msgid ""
+"\n"
+"    Bridge relays (or \"bridges\" for short) are Tor relays that aren't "
+"listed\n"
+"    in the main directory. Since there is no complete public list of them,\n"
+"    even if your ISP is filtering connections to all the known Tor relays,\n"
+"    they probably won't be able to block all the bridges.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/Strings.py:18
+msgid ""
+"\n"
+"    To use the above lines, go to Vidalia's Network settings page, and "
+"click\n"
+"    \"My ISP blocks connections to the Tor network\". Then add each bridge\n"
+"    address one at a time.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/Strings.py:24
+msgid ""
+"\n"
+"    Configuring more than one bridge address will make your Tor connection\n"
+"    more stable, in case some of the bridges become unreachable.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/Strings.py:29
+msgid ""
+"\n"
+"    Another way to find public bridge addresses is to send mail to\n"
+"    bridges@xxxxxxxxxxxxxx with the line \"get bridges\" by itself in the "
+"body\n"
+"    of the mail. However, so we can make it harder for an attacker to learn\n"
+"    lots of bridge addresses, you must send this request from a gmail or\n"
+"    yahoo account.\n"
+"    "
+msgstr ""
+
+#: lib/bridgedb/Strings.py:48
+msgid ""
+"\n"
+"[This is an automated message; please do not reply.]\n"
+msgstr ""
+
+#: lib/bridgedb/Strings.py:52
+msgid ""
+"\n"
+"Here are your bridge relays:\n"
+msgstr ""
+
+#: lib/bridgedb/Strings.py:56
+msgid ""
+"\n"
+"Bridge relays (or \"bridges\" for short) are Tor relays that aren't listed\n"
+"in the main directory. Since there is no complete public list of them,\n"
+"even if your ISP is filtering connections to all the known Tor relays,\n"
+"they probably won't be able to block all the bridges.\n"
+msgstr ""
+
+#: lib/bridgedb/Strings.py:63
+msgid ""
+"\n"
+"To use the above lines, go to Vidalia's Network settings page, and click\n"
+"\"My ISP blocks connections to the Tor network\". Then add each bridge\n"
+"address one at a time.\n"
+msgstr ""
+
+#: lib/bridgedb/Strings.py:69
+msgid ""
+"\n"
+"Configuring more than one bridge address will make your Tor connection\n"
+"more stable, in case some of the bridges become unreachable.\n"
+msgstr ""
+
+#: lib/bridgedb/Strings.py:74
+msgid ""
+"\n"
+"Another way to find public bridge addresses is to visit\n"
+"https://bridges.torproject.org/. The answers you get from that page\n"
+"will change every few days, so check back periodically if you need more\n"
+"bridge addresses.\n"
+msgstr ""
+
+#: lib/bridgedb/Strings.py:89
+msgid "(no bridges currently available)"
+msgstr ""
diff --git a/lib/bridgedb/I18n.py b/lib/bridgedb/I18n.py
new file mode 100644
index 0000000..4999b5b
--- /dev/null
+++ b/lib/bridgedb/I18n.py
@@ -0,0 +1,83 @@
+# BridgeDB i18n strings & helper routines. The string should go into pootle
+
+import gettext
+
+languages = {}
+
+def setupLanguages(cfg):
+    """Set up all languages we support
+    """
+    for lang in cfg.CONFIGURED_LOCALES:
+        languages[lang] = gettext.translation("bridgedb", languages=[lang])
+
+def _(text):
+    """This is necessary because strings are translated when they're imported.
+       Otherwise this would make it impossible to switch languages more than 
+       once
+    """
+    return text
+
+HTML_1 = _("""
+    Here are your bridge relays:
+    """)
+
+HTML_2 = _("""
+    Bridge relays (or "bridges" for short) are Tor relays that aren't listed
+    in the main directory. Since there is no complete public list of them,
+    even if your ISP is filtering connections to all the known Tor relays,
+    they probably won't be able to block all the bridges.
+    """)
+
+HTML_3 = _("""
+    To use the above lines, go to Vidalia's Network settings page, and click
+    "My ISP blocks connections to the Tor network". Then add each bridge
+    address one at a time.
+    """)
+
+HTML_4 = _("""
+    Configuring more than one bridge address will make your Tor connection
+    more stable, in case some of the bridges become unreachable.
+    """)
+
+HTML_5 = _("""
+    Another way to find public bridge addresses is to send mail to
+    bridges@xxxxxxxxxxxxxx with the line "get bridges" by itself in the body
+    of the mail. However, so we can make it harder for an attacker to learn
+    lots of bridge addresses, you must send this request from a gmail or
+    yahoo account.
+    """)
+
+EMAIL_1 = _("""
+[This is an automated message; please do not reply.]
+""")
+
+EMAIL_2 = _("""
+Here are your bridge relays:
+""")
+
+EMAIL_3 = _("""
+Bridge relays (or "bridges" for short) are Tor relays that aren't listed
+in the main directory. Since there is no complete public list of them,
+even if your ISP is filtering connections to all the known Tor relays,
+they probably won't be able to block all the bridges.
+""")
+
+EMAIL_4 = _("""
+To use the above lines, go to Vidalia's Network settings page, and click
+"My ISP blocks connections to the Tor network". Then add each bridge
+address one at a time.
+""")
+
+EMAIL_5 = _("""
+Configuring more than one bridge address will make your Tor connection
+more stable, in case some of the bridges become unreachable.
+""")
+
+EMAIL_6 = _("""
+Another way to find public bridge addresses is to visit
+https://bridges.torproject.org/. The answers you get from that page
+will change every few days, so check back periodically if you need more
+bridge addresses.
+""")
+
+NO_BRIDGES = _("(no bridges currently available)")
diff --git a/lib/bridgedb/Main.py b/lib/bridgedb/Main.py
index b13710b..eebd55c 100644
--- a/lib/bridgedb/Main.py
+++ b/lib/bridgedb/Main.py
@@ -10,6 +10,7 @@ import os
 import signal
 import sys
 import logging
+import gettext
 
 from twisted.internet import reactor
 
@@ -18,6 +19,7 @@ import bridgedb.Dist as Dist
 import bridgedb.Time as Time
 import bridgedb.Server as Server
 import bridgedb.Storage
+import bridgedb.I18n as I18n
 
 class Conf:
     """A configuration object.  Holds unvalidated attributes.
@@ -88,6 +90,8 @@ CONFIG = Conf(
     EMAIL_INCLUDE_FINGERPRINTS = False,
 
     RESERVED_SHARE=2,
+
+    CONFIGURED_LOCALES = [ "en", "de" ]
   )
 
 def configureLogging(cfg):
@@ -224,6 +228,9 @@ def startup(cfg):
                                    cfg.DB_FILE)
     bridgedb.Storage.setGlobalDB(db)
 
+    # Setup languages
+    I18n.setupLanguages(cfg)
+
     # Get a proxy list.
     proxyList = ProxyCategory()
     proxyList.replaceProxyList(loadProxyList(cfg))
diff --git a/lib/bridgedb/Server.py b/lib/bridgedb/Server.py
index 61d3a01..dd5066d 100644
--- a/lib/bridgedb/Server.py
+++ b/lib/bridgedb/Server.py
@@ -11,6 +11,7 @@ import MimeWriter
 import rfc822
 import time
 import logging
+import gettext
 
 from zope.interface import implements
 
@@ -22,55 +23,7 @@ import twisted.web.server
 import twisted.mail.smtp
 
 import bridgedb.Dist
-
-HTML_MESSAGE_TEMPLATE = """
-<html><body>
-<p>Here are your bridge relays:
-<pre id="bridges">
-%s
-</pre>
-</p>
-<p>Bridge relays (or "bridges" for short) are Tor relays that aren't listed
-in the main directory. Since there is no complete public list of them,
-even if your ISP is filtering connections to all the known Tor relays,
-they probably won't be able to block all the bridges.</p>
-<p>To use the above lines, go to Vidalia's Network settings page, and click
-"My ISP blocks connections to the Tor network". Then add each bridge
-address one at a time.</p>
-<p>Configuring more than one bridge address will make your Tor connection
-more stable, in case some of the bridges become unreachable.</p>
-<p>Another way to find public bridge addresses is to send mail to
-bridges@xxxxxxxxxxxxxx with the line "get bridges" by itself in the body
-of the mail. However, so we can make it harder for an attacker to learn
-lots of bridge addresses, you must send this request from a gmail or
-yahoo account.</p>
-</body></html>
-""".strip()
-
-EMAIL_MESSAGE_TEMPLATE = """\
-[This is an automated message; please do not reply.]
-
-Here are your bridge relays:
-
-%s
-
-Bridge relays (or "bridges" for short) are Tor relays that aren't listed
-in the main directory. Since there is no complete public list of them,
-even if your ISP is filtering connections to all the known Tor relays,
-they probably won't be able to block all the bridges.
-
-To use the above lines, go to Vidalia's Network settings page, and click
-"My ISP blocks connections to the Tor network". Then add each bridge
-address one at a time.
-
-Configuring more than one bridge address will make your Tor connection
-more stable, in case some of the bridges become unreachable.
-
-Another way to find public bridge addresses is to visit
-https://bridges.torproject.org/. The answers you get from that page
-will change every few days, so check back periodically if you need more
-bridge addresses.
-"""
+import bridgedb.I18n as I18n
 
 class WebResource(twisted.web.resource.Resource):
     """This resource is used by Twisted Web to give a web page with some
@@ -84,6 +37,7 @@ class WebResource(twisted.web.resource.Resource):
              schedule -- an IntervalSchedule object
              N -- the number of bridges to hand out per query.
         """
+        gettext.install("bridgedb", unicode=True)
         twisted.web.resource.Resource.__init__(self)
         self.distributor = distributor
         self.schedule = schedule
@@ -105,6 +59,12 @@ class WebResource(twisted.web.resource.Resource):
         else:
             ip = request.getClientIP()
 
+        # See if we did get a request for a certain locale, otherwise fall back
+        # to 'en'
+        lang = request.args.get("lang", ['en'])
+        lang = lang[0]
+        I18n.languages[lang].install()
+
         format = request.args.get("format", None)
         if format and len(format): format = format[0] # choose the first arg
 
@@ -115,7 +75,7 @@ class WebResource(twisted.web.resource.Resource):
             answer = "".join("%s\n" % b.getConfigLine(self.includeFingerprints)
                              for b in bridges)
         else:
-            answer = "No bridges available."
+            answer = _(I18n.NO_BRIDGES)
 
         logging.info("Replying to web request from %s.  Parameters were %r", ip,
                      request.args)
@@ -123,8 +83,25 @@ class WebResource(twisted.web.resource.Resource):
             request.setHeader("Content-Type", "text/plain")
             return answer
         else:
+            HTML_MESSAGE_TEMPLATE = self.buildHTMLMessageTemplate()
             return HTML_MESSAGE_TEMPLATE % answer
 
+    def buildHTMLMessageTemplate(self):
+        """DOCDOC"""
+        template_string = "<html><body>" \
+                             + "<p>" + _(I18n.HTML_1) \
+                             + "<pre id=\"bridges\">" \
+                             + "%s" \
+                             + "</pre></p>" \
+                             + "<p>" + _(I18n.HTML_2) + "</p>" \
+                             + "<p>" + _(I18n.HTML_3) + "</p>" \
+                             + "<p>" + _(I18n.HTML_4) + "</p>" \
+                             + "<p>" + _(I18n.HTML_5) + "</p>" \
+                             + "</body></html>"
+
+        return template_string
+
+
 def addWebServer(cfg, dist, sched):
     """Set up a web server.
          cfg -- a configuration object from Main.  We use these options:
@@ -187,6 +164,7 @@ def getMailResponse(lines, ctx):
     if not subject: subject = "[no subject]"
     clientFromAddr = msg.getaddr("From")
     clientSenderAddr = msg.getaddr("Sender")
+    clientToaddr = msg.getaddr("To")
     msgID = msg.getheader("Message-ID", None)
     if clientSenderAddr and clientSenderAddr[1]:
         clientAddr = clientSenderAddr[1]
@@ -196,6 +174,11 @@ def getMailResponse(lines, ctx):
         logging.info("No From or Sender header on incoming mail.")
         return None,None
 
+    # Look up the locale part in the 'To:' address, if there is one and install
+    # it
+    lang = getLocaleFromPlusAddr(clientToaddr)
+    I18n.languages[lang].install()
+
     try:
         _, addrdomain = bridgedb.Dist.extractAddrSpec(clientAddr.lower())
     except bridgedb.Dist.BadEmail:
@@ -257,7 +240,15 @@ def getMailResponse(lines, ctx):
         answer = "".join("  %s\n" % b.getConfigLine(with_fp) for b in bridges)
     else:
         answer = "(no bridges currently available)"
-    body.write(EMAIL_MESSAGE_TEMPLATE % answer)
+
+    EMAIL_MESSAGE_TEMPLATE =   _(EMAIL_1) \
+                             + _(EMAIL_2) \
+                             + "%s" \
+                             + _(EMAIL_3) \
+                             + _(EMAIL_4) \
+                             + _(EMAIL_5) \
+                             + _(EMAIL_6)
+    body.write(_(EMAIL_MESSAGE_TEMPLATE) % answer)
 
     f.seek(0)
     logging.info("Email looks good; we should send an answer.")
@@ -283,6 +274,19 @@ def replyToMail(lines, ctx):
     logging.info("Sending reply to %r", sendToUser)
     return d
 
+def getLocaleFromPlusAddr(self, address):
+    """See whether the user sent his email to a 'plus' address, for 
+       instance to bridgedb+fa@tpo. Plus addresses are the current 
+       mechanism to set the reply language
+    """
+    replyLocale = "en"
+    r = '.*(<)?(\w+\+(\w+)@\w+(?:\.\w+)+)(?(1)>)'
+    match = re.match(r, address)
+    if match:
+        replyLocale = match.group(3)
+
+    return replyLocale
+
 class MailContext:
     """Helper object that holds information used by email subsystem."""
     def __init__(self, cfg, dist, sched):
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..e91c159
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,2 @@
+[install]
+install-data=/usr
diff --git a/setup.py b/setup.py
index 0ff72c1..9e7d17b 100644
--- a/setup.py
+++ b/setup.py
@@ -4,10 +4,66 @@
 # See LICENSE for licensing information
 
 import distutils
+import subprocess
+from distutils.command.install_data import install_data as _install_data
+import os
 import sys
 
 from distutils.core import setup, Command
 
+class createTrans(Command):
+    # Based on setup.py from 
+    # http://wiki.maemo.org/Internationalize_a_Python_application
+    description = "Install necessary translation files"
+    user_options = []
+    def initialize_options(self):
+        pass
+ 
+    def finalize_options(self):
+        pass
+ 
+    def run(self):
+        po_dir = os.path.join(os.path.dirname(os.curdir), 'i18n')
+        for path, dirnames, filenames in os.walk(po_dir):
+            for d in dirnames:
+                if d.endswith("templates"):
+                    continue
+                src = os.path.join('i18n', d, "bridgedb.po")
+                lang = d
+                dest_path = os.path.join('build', 'locale', lang, 'LC_MESSAGES')
+                dest = os.path.join(dest_path, 'bridgedb.mo')
+                if not os.path.exists(dest_path):
+                    os.makedirs(dest_path)
+                if not os.path.exists(dest):
+                    print 'Compiling %s' % src
+                    self.msgfmt(src, dest)
+                else:
+                    src_mtime = os.stat(src)[8]
+                    dest_mtime = os.stat(dest)[8]
+                    if src_mtime > dest_mtime:
+                        print 'Compiling %s' % src
+                        self.msgfmt(src, dest)
+    def msgfmt(self, src, dest):
+        args = src + " -o " + dest
+        try:
+            ret = subprocess.call("msgfmt" + " " + args, shell=True)
+            if ret < 0:
+                print 'Error in msgfmt execution: %s' % ret
+        except OSError, e:
+            print 'Comilation failed: ' % e
+
+class installData(_install_data):
+    def run(self):
+        self.data_files = []
+        for lang in os.listdir('build/locale/'):
+            if lang.endswith('templates'):
+                continue
+            lang_dir = os.path.join('share', 'locale', lang, 'LC_MESSAGES')
+            lang_file = os.path.join('build', 'locale', lang, 'LC_MESSAGES', 
+                                     'bridgedb.mo')
+            self.data_files.append( (lang_dir, [lang_file]) )
+        _install_data.run(self)
+
 class runTests(Command):
     # Based on setup.py from mixminion, which is based on setup.py
     # from Zooko's pyutil package, which is in turn based on
@@ -42,7 +98,9 @@ setup(name='BridgeDB',
       package_dir= {'' : 'lib'},
       packages=['bridgedb'],
       py_modules=['TorBridgeDB'],
-      cmdclass={'test' : runTests}
+      cmdclass={'test' : runTests,
+                'trans': createTrans,
+                'install_data': installData}
       )
 
 
-- 
1.7.1