diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | babel.map | 4 | ||||
-rw-r--r-- | de.po | 162 | ||||
-rwxr-xr-x | i18n-prepare | 5 | ||||
-rwxr-xr-x | i18n-update | 6 | ||||
-rwxr-xr-x | index.py | 8 | ||||
-rw-r--r-- | templates/8021x.html | 5 | ||||
-rw-r--r-- | templates/error.html | 11 | ||||
-rw-r--r-- | templates/login.html | 4 | ||||
-rw-r--r-- | templates/select.html | 9 | ||||
-rw-r--r-- | tmpl.py | 44 |
11 files changed, 242 insertions, 18 deletions
@@ -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 @@ -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 @@ -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> @@ -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') |