summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorequinox <equinox@diac24.net>2011-09-27 08:01:14 +0200
committerequinox <equinox@diac24.net>2011-09-27 08:01:14 +0200
commit2066915a49fa45aeb2bc3ed79b7c6e0484b8d0af (patch)
tree9c7028cf5b09f38023fade23a70f485a4d1eea19
parent2a13c8256b2b64c3c61e043a1d9268b75a4597a4 (diff)
i18n support
-rw-r--r--.gitignore2
-rw-r--r--babel.map4
-rw-r--r--de.po162
-rwxr-xr-xi18n-prepare5
-rwxr-xr-xi18n-update6
-rwxr-xr-xindex.py8
-rw-r--r--templates/8021x.html5
-rw-r--r--templates/error.html11
-rw-r--r--templates/login.html4
-rw-r--r--templates/select.html9
-rw-r--r--tmpl.py44
11 files changed, 242 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index 4e829e6..dc3eb23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
accountservice.py
cherrypy.config
+locale
*.pyc
*.pem
*.pub
@@ -7,3 +8,4 @@ cherrypy.config
*.key
*.svg
*.old
+*.pot
diff --git a/babel.map b/babel.map
new file mode 100644
index 0000000..df856f3
--- /dev/null
+++ b/babel.map
@@ -0,0 +1,4 @@
+[python:**.py]
+[genshi:**/templates/**.xi]
+[genshi:**/templates/**.html]
+include_attrs = title
diff --git a/de.po b/de.po
new file mode 100644
index 0000000..060ce90
--- /dev/null
+++ b/de.po
@@ -0,0 +1,162 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-09-27 07:17+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+#: templates/8021x.html:10 templates/login.html:9 templates/select.html:10
+msgid "login"
+msgstr "login"
+
+#: templates/8021x.html:14
+msgid "wpa_supplicant WPA-EAP template"
+msgstr "wpa_supplicant WPA-EAP Vorlage"
+
+#: templates/8021x.html:15
+#, python-format
+msgid ""
+"network={\n"
+"\tscan_ssid=1\n"
+"\tssid=\"crew.sublab.org\"\n"
+"\n"
+"\tkey_mgmt=WPA-EAP\n"
+"\teap=TTLS\n"
+"\tphase2=\"auth=PAP\"\n"
+"\n"
+"\tidentity=\"%(8021x)s\"\n"
+"\tpassword=\"[1:insert password here]\"\n"
+"\n"
+"\tanonymous_identity=\"bernd\"\n"
+"\tca_cert=\"[2:/etc/ssl/certs/cacert.org.pem]\"\n"
+"\taltsubject_match=\"DNS:taifun.local.sublab.org\"\n"
+"\tpriority=500\n"
+"}"
+msgstr ""
+"network={\n"
+"\tscan_ssid=1\n"
+"\tssid=\"crew.sublab.org\"\n"
+"\n"
+"\tkey_mgmt=WPA-EAP\n"
+"\teap=TTLS\n"
+"\tphase2=\"auth=PAP\"\n"
+"\n"
+"\tidentity=\"%(8021x)s\"\n"
+"\tpassword=\"[1:Passwort hier einsetzen]\"\n"
+"\n"
+"\tanonymous_identity=\"bernd\"\n"
+"\tca_cert=\"[2:/etc/ssl/certs/cacert.org.pem]\"\n"
+"\taltsubject_match=\"DNS:taifun.local.sublab.org\"\n"
+"\tpriority=500\n"
+"}"
+
+#: templates/create.html:9
+msgid "create"
+msgstr "anlegen"
+
+#: templates/create.html:13 templates/login.html:14 templates/pwchange.html:12
+msgid "uid:"
+msgstr "uid:"
+
+#: templates/create.html:15 templates/login.html:16 templates/pwchange.html:16
+msgid "password:"
+msgstr "passwort:"
+
+#: templates/create.html:17 templates/pwchange.html:18
+msgid "repeat:"
+msgstr "wiederholen:"
+
+#: templates/create.html:20
+msgid ""
+"The account creation process takes around 20 to 30 seconds. Please do not "
+"spam the button."
+msgstr ""
+"Es dauert ca. 20 bis 30 Sekunden, einen Account anzulegen. Bitte nicht "
+"mehrfach versuchen."
+
+#: templates/error.html:10
+msgid "exception"
+msgstr "exception"
+
+#: templates/error.html:14
+#, python-format
+msgid ""
+"[1:broken!]\n"
+" [2:[3:subdap.exe] has detected a problem and had to be terminated.\n"
+" Please send an error report to [4:equinox ! diac24 ! net].]\n"
+" [5:%(exception)s]"
+msgstr ""
+"[1:kaputt!]\n"
+" [2:[3:subdap.exe] hat ein Problem festgestellt und musste beendet werden.\n"
+" Bitte schicken sie einen Fehlerbericht an [4:equinox ! diac24 ! net].]\n"
+" [5:%(exception)s]"
+
+#: templates/layout.xi:11 templates/layout.xi:28 templates/layout.xi:37
+msgid "subdap"
+msgstr "subdap"
+
+#: templates/layout.xi:19
+msgid "info"
+msgstr "info"
+
+#: templates/login.html:13
+msgid "create account"
+msgstr "Account anlegen"
+
+#: templates/pwchange.html:8 templates/select.html:26
+msgid "change password"
+msgstr "Passwort ändern"
+
+#: templates/pwchange.html:14
+msgid "old password:"
+msgstr "altes Passwort:"
+
+#: templates/pwchange.html:21
+msgid ""
+"The password change process takes around 20 to 30 seconds. Please do not "
+"spam the button."
+msgstr ""
+"Es dauert ca. 20 bis 30 Sekunden, das Passwort zu ändern. Bitte nicht "
+"mehrfach versuchen."
+
+#: templates/select.html:12
+msgid ""
+"[1:Your password has been changed.][2:]\n"
+" — please note that it may take a few minutes for Kerberos to update\n"
+" its [3:three heads]. At any moment, either your old password or your new\n"
+" password will work."
+msgstr ""
+"[1:Passwort wurde geändert.][2:]\n"
+" — bitte beachten: Es kann einige Minuten dauern, bis Kerberos seine [3:drei\n"
+" Köpfe] synchronisiert hat. Es kann daher sowohl das alte als auch das neue\n"
+" Passwort funktionieren."
+
+#: templates/select.html:20
+#, python-format
+msgid "Hi %(hi)s!"
+msgstr "Hallo %(hi)s!"
+
+#: templates/select.html:22
+msgid "sublab.org wiki"
+msgstr "sublab.org Wiki"
+
+#: templates/select.html:24
+msgid "802.1X template"
+msgstr "802.1X Vorlage"
+
+#: templates/select.html:28
+msgid "administration"
+msgstr "administration"
diff --git a/i18n-prepare b/i18n-prepare
new file mode 100755
index 0000000..1470ea7
--- /dev/null
+++ b/i18n-prepare
@@ -0,0 +1,5 @@
+#!/bin/sh
+pybabel extract -F babel.map . -o subdap.pot
+for i in *.po
+do msgmerge -v "$i" subdap.pot > "${i}T"
+done
diff --git a/i18n-update b/i18n-update
new file mode 100755
index 0000000..5159100
--- /dev/null
+++ b/i18n-update
@@ -0,0 +1,6 @@
+#!/bin/sh
+for i in *.po
+do dir="locale/${i%.mo}/LC_MESSAGES"
+ [ -d "$dir" ] || mkdir -p "$dir"
+ msgfmt -v "$i" -o "$dir/subdap.mo"
+done
diff --git a/index.py b/index.py
index 9f78ea0..cc36806 100755
--- a/index.py
+++ b/index.py
@@ -171,15 +171,17 @@ config = {
'/': {
'tools.decode.on': True,
'tools.encode.on': True,
+ 'tools.encode.encoding': 'utf-8',
+ 'tools.encode.add_charset': True,
'tools.gzip.on': True,
'tools.proxy.on': True,
-# 'tools.caching.on': False,
-# 'tools.expires.secs': 0,
-# 'tools.expires.force': True,
},
'/static': {
'tools.staticdir.on': True,
'tools.staticdir.dir': 'static',
+ 'tools.caching.on': True,
+ 'tools.expires.secs': 3600,
+# 'tools.expires.force': True,
},
}
diff --git a/templates/8021x.html b/templates/8021x.html
index 3e3405a..a5361e2 100644
--- a/templates/8021x.html
+++ b/templates/8021x.html
@@ -2,6 +2,7 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
+ xmlns:i18n="http://genshi.edgewall.org/i18n"
xmlns:sub="http://local.sublab.org/subdap/xmlns-templates"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.xi"/>
@@ -11,7 +12,7 @@
<sub:bodylarge>
<div class="cont">
<h1>wpa_supplicant WPA-EAP template</h1>
- <pre>network={
+ <pre i18n:msg="8021x">network={
scan_ssid=1
ssid="crew.sublab.org"
@@ -20,7 +21,7 @@
phase2="auth=PAP"
identity="${username}"
- password="<i style="color:red;background-color:white">passwort hier einsetzen</i>"
+ password="<i style="color:red;background-color:white">insert password here</i>"
anonymous_identity="bernd"
ca_cert="<a href="${url('static/cacert.org.pem')}">/etc/ssl/certs/cacert.org.pem</a>"
diff --git a/templates/error.html b/templates/error.html
index 8c04a9b..f8bd2a4 100644
--- a/templates/error.html
+++ b/templates/error.html
@@ -2,18 +2,19 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
+ xmlns:i18n="http://genshi.edgewall.org/i18n"
xmlns:sub="http://local.sublab.org/subdap/xmlns-templates"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.xi"/>
<head>
- <title>login</title>
+ <title>exception</title>
</head>
<body id="error">
<img src="static/fire.png" alt="subdap"/>
- <div id="cont">
- <h1>kaputt!</h1>
- <p><code>subdap.exe</code> hat ein Problem festgestellt und musste beendet werden.<br/>
- Bitte schicken sie einen Fehlerbericht an <code>equinox ! diac24 ! net</code>.</p>
+ <div id="cont" i18n:msg="exception">
+ <h1>broken!</h1>
+ <p><code>subdap.exe</code> has detected a problem and had to be terminated.
+ Please send an error report to <code>equinox ! diac24 ! net</code>.</p>
<pre>${details}</pre>
</div>
</body>
diff --git a/templates/login.html b/templates/login.html
index ea0fe89..09b130c 100644
--- a/templates/login.html
+++ b/templates/login.html
@@ -10,10 +10,10 @@
</head>
<sub:bodyform>
<form action='login' method='POST'>
- <a href="create" id="create">Konto erstellen</a>
+ <a href="create" id="create">create account</a>
<div>uid: <input type='text' name='username' size="10"/></div>
<b class="error" py:if="'username' in errors">${errors.username}</b>
- <div>passwort: <input type='password' name='password' size="10"/></div>
+ <div>password: <input type='password' name='password' size="10"/></div>
<b class="error" py:if="'password' in errors">${errors.password}</b>
<input type='submit' value='login'/>
</form>
diff --git a/templates/select.html b/templates/select.html
index b25cd1c..5132cdc 100644
--- a/templates/select.html
+++ b/templates/select.html
@@ -2,13 +2,14 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
+ xmlns:i18n="http://genshi.edgewall.org/i18n"
xmlns:sub="http://local.sublab.org/subdap/xmlns-templates"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.xi"/>
<head>
<title>login</title>
</head>
- <sub:infobox py:if="message.has_key('pwchangeok')">
+ <sub:infobox py:if="message.has_key('pwchangeok')" i18n:msg="pwchangeok">
<b>Your password has been changed.</b><br />
— please note that it may take a few minutes for Kerberos to update
its <a href="http://en.wikipedia.org/wiki/File:RomanCerberus.JPG">three heads</a>. At any moment, either your old password or your new
@@ -16,13 +17,13 @@
</sub:infobox>
<sub:bodyform>
<div class="cont">
- Hallo ${user['cn']}!
+ <span i18n:msg="hi">Hi ${user['cn']}!</span>
<p class="app"><a href="https://wiki.sublab.org/auth_subdap.php?${tgts['wiki']}">
<img src="${url('static/app_wiki.png')}" alt="wiki" width="48" height="48"/> sublab.org wiki</a></p>
<p class="app"><a href="cfg8021x?username=${user['cn']}">
- <img src="${url('static/app_8021x.png')}" alt="wlan" width="24" height="24"/> 802.1X config</a></p>
+ <img src="${url('static/app_8021x.png')}" alt="wlan" width="24" height="24"/> 802.1X template</a></p>
<p class="app"><a href="pwchange?username=${user['cn']}">
- <img src="${url('static/app_password.png')}" alt="pwchange" width="24" height="24"/> Passwort ändern</a></p>
+ <img src="${url('static/app_password.png')}" alt="pwchange" width="24" height="24"/> change password</a></p>
</div>
</sub:bodyform>
</html>
diff --git a/tmpl.py b/tmpl.py
index 9748f2a..b729a2f 100644
--- a/tmpl.py
+++ b/tmpl.py
@@ -4,10 +4,43 @@ import cherrypy
from genshi.core import Stream
from genshi.output import encode, get_serializer
from genshi.template import Context, TemplateLoader
+from genshi.filters import Translator
+
+import gettext
+
+languages = {'en': None, 'de': None}
+for l in languages.keys():
+ languages[l] = gettext.translation('subdap',
+ os.path.join(os.path.dirname(__file__), 'locale'), [l],
+ fallback = True)
+ print l, '->', languages[l]
+
+def do_translate(text):
+ return cherrypy.thread_data.translations.gettext(text)
+def select_language():
+ if cherrypy.thread_data.lang != None:
+ lang = cherrypy.thread_data.lang
+ return languages[lang if languages.has_key(lang) else 'en']
+ accept = cherrypy.request.headers['Accept-Language']
+ if isinstance(accept, str):
+ for group in accept.split(';'):
+ for lang in group.split(','):
+ if lang.find('=') >= 0:
+ continue
+ if lang.find('-') >= 0:
+ lang = lang[:lang.find('-')]
+ if languages.has_key(lang):
+ return languages[lang]
+
+ return languages['en']
+
+def template_loaded(template):
+ Translator(do_translate).setup(template)
loader = TemplateLoader(
os.path.join(os.path.dirname(__file__), 'templates'),
- auto_reload=True
+ auto_reload = True,
+ callback = template_loaded
)
def render(*args, **kwargs):
@@ -16,8 +49,9 @@ def render(*args, **kwargs):
template = loader.load(args[0])
else:
template = cherrypy.thread_data.template
+
#ctxt = Context(url = cherrypy.url)
- ctxt = Context(url = myurl)
+ ctxt = Context(url = myurl, lang = cherrypy.thread_data.lang)
ctxt.push(kwargs)
return template.generate(ctxt)
@@ -30,6 +64,12 @@ def expose(filename, method='html', encoding='utf-8', **options):
def wrapper(*args, **kwargs):
cherrypy.thread_data.template = loader.load(filename)
cherrypy.thread_data.func = func
+ cherrypy.thread_data.lang = None
+ if kwargs.has_key('lang'):
+ cherrypy.thread_data.lang = kwargs['lang']
+ del kwargs['lang']
+ cherrypy.thread_data.translations = select_language()
+
opt = options.copy()
if method == 'html':
opt.setdefault('doctype', 'html')