add translation to german

This commit is contained in:
Franzi 2021-12-23 09:14:27 +01:00
parent fcb6a8f6ca
commit 8db179d07c
Signed by: kunsi
GPG Key ID: 12E3D2136B818350
12 changed files with 497 additions and 53 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
.venv/
*.mo
*.pyc
.venv/
config.json

View File

@ -2,8 +2,26 @@
Licenced under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/). See [LICENCE](LICENCE) file for full licence text.
## Development
All instructions assume you have the requirements already installed.
## Adding translations
Replace `<LANG>` with your intended language.
1. run `pybabel init -i messages.pot -d translations -l <LANG>`
2. edit `translations/<LANG>/LC_MESSAGES/messages.po`
3. For testing, run `pybabel compile -d translations`
If you changed the translation strings, make sure to run `pybabel extract -F babel.cfg -o messages.pot .` and
`pybabel update -i messages.pot -d translations` first.
## Setting it up
After deploying the repository, change to `ldap_frontend` directory, then
run `pybabel compile -d translations`.
### config.json
```json
{

View File

@ -2,7 +2,8 @@ from json import load
from os import environ
from flask import Flask, flash, redirect, request, session, url_for
from flask_wtf.csrf import CSRFProtect, CSRFError
from flask_babel import Babel, gettext
from flask_wtf.csrf import CSRFError, CSRFProtect
from ldap3 import ALL_ATTRIBUTES, MODIFY_ADD, MODIFY_DELETE
from ldap3.core.exceptions import LDAPException
from ldap3.utils.dn import escape_rdn
@ -19,16 +20,25 @@ from .helpers.ldap import (
app = Flask(__name__)
app.secret_key = environ.get("FLASK_SECRET_KEY", default="test")
app.config["LANGUAGES"] = {"en": "English", "de": "Deutsch"}
babel = Babel(app)
csrf = CSRFProtect(app)
with open(environ["APP_CONFIG"]) as f:
APP_CONFIG = load(f)
@babel.localeselector
def get_locale():
return request.accept_languages.best_match(app.config["LANGUAGES"].keys())
@app.errorhandler(CSRFError)
def handle_csrf_error(e):
flash("CRSF validation error. For your own safety, you have been logged out.")
flash(
gettext("CRSF validation error. For your own safety, you have been logged out.")
)
session["is_logged_in"] = False
session["username"] = ""
@ -39,7 +49,7 @@ def handle_csrf_error(e):
@app.route("/")
def slash():
if session.get('is_logged_in'):
if session.get("is_logged_in"):
return redirect(url_for("selfservice"))
return redirect(url_for("login"))
@ -57,11 +67,11 @@ def login():
session["username"] = escape_rdn(request.form["username"])
session["password"] = request.form["password"]
flash("logged in")
flash(gettext("logged in"))
return redirect(url_for("selfservice"))
else:
flash("username or password is wrong")
flash(gettext("username or password is wrong"))
return template(None, "login.html")
@ -72,7 +82,7 @@ def logout():
session["username"] = ""
session["password"] = ""
flash("logged out")
flash(gettext("you have been logged out"))
return redirect(url_for("login"))
@ -96,7 +106,7 @@ def selfservice(ldap):
"mail": request.form["mail"],
},
)
flash("data updated")
flash(gettext("user data was updated"))
except LDAPException as e:
app.logger.error(
"Updating {} failed: {}\n{}".format(
@ -113,15 +123,15 @@ def selfservice(ldap):
request.form["current"],
):
validated = False
flash("current password does not match")
flash(gettext("current password does not match the one stored"))
if request.form["new"] != request.form["repeat"]:
validated = False
flash("new passwords do not match")
flash(gettext("new passwords do not match"))
if len(request.form["new"]) < 12:
validated = False
flash("new password must be atleast 12 characters")
flash(gettext("new password must be atleast 12 characters long"))
if validated:
try:
@ -131,7 +141,7 @@ def selfservice(ldap):
request.form["new"],
)
session["password"] = request.form["new"]
flash("password changed")
flash(gettext("your password was changed"))
except LDAPException as e:
app.logger.error(
"Updating {} failed: {}".format(
@ -184,7 +194,13 @@ def group_edit(ldap, ou):
]
},
)
flash(f"{request.form['remove']} was removed from {ou}")
flash(
gettext(
"%(user)s was removed from %(ou)s",
user=request.form["remove"],
ou=ou,
)
)
elif request.form.get("add"):
ldap.modify(
APP_CONFIG["template"]["group_dn"].format(ou),
@ -199,7 +215,11 @@ def group_edit(ldap, ou):
]
},
)
flash(f"{request.form['add']} was added to {ou}")
flash(
gettext(
"%(user)s was added to %(ou)s", user=request.form["remove"], ou=ou
)
)
return redirect(url_for("group_edit", ou=ou))

3
ldap_frontend/babel.cfg Normal file
View File

@ -0,0 +1,3 @@
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

199
ldap_frontend/messages.pot Normal file
View File

@ -0,0 +1,199 @@
# Translations template for PROJECT.
# Copyright (C) 2021 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-12-23 09:11+0100\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: __init__.py:40
msgid "CRSF validation error. For your own safety, you have been logged out."
msgstr ""
#: __init__.py:69
msgid "logged in"
msgstr ""
#: __init__.py:73
msgid "username or password is wrong"
msgstr ""
#: __init__.py:84
msgid "you have been logged out"
msgstr ""
#: __init__.py:108
msgid "user data was updated"
msgstr ""
#: __init__.py:125
msgid "current password does not match the one stored"
msgstr ""
#: __init__.py:129
msgid "new passwords do not match"
msgstr ""
#: __init__.py:133
msgid "new password must be atleast 12 characters long"
msgstr ""
#: __init__.py:143
msgid "your password was changed"
msgstr ""
#: __init__.py:196
#, python-format
msgid "%(user)s was removed from %(ou)s"
msgstr ""
#: __init__.py:211
#, python-format
msgid "%(user)s was added to %(ou)s"
msgstr ""
#: templates/login.html:2 templates/login.html:7 templates/login.html:19
msgid "Login"
msgstr ""
#: templates/login.html:10
msgid "Username"
msgstr ""
#: templates/login.html:15
msgid "Password"
msgstr ""
#: templates/layout/default.html:23 templates/selfservice.html:2
msgid "self service"
msgstr ""
#: templates/selfservice.html:7
msgid "Edit User Data"
msgstr ""
#: templates/groups/members.html:7 templates/selfservice.html:10
msgid "uid"
msgstr ""
#: templates/selfservice.html:13
msgid "Contact an administrator if you want to change this."
msgstr ""
#: templates/selfservice.html:18
msgid "name"
msgstr ""
#: templates/selfservice.html:21
msgid "This field gets adjusted automatically based on the fields below."
msgstr ""
#: templates/selfservice.html:26
msgid "surname"
msgstr ""
#: templates/selfservice.html:33
msgid "given name"
msgstr ""
#: templates/selfservice.html:40
msgid "e-mail address"
msgstr ""
#: templates/selfservice.html:46
msgid "Update"
msgstr ""
#: templates/selfservice.html:53 templates/selfservice.html:77
msgid "change password"
msgstr ""
#: templates/selfservice.html:56
msgid "current password"
msgstr ""
#: templates/selfservice.html:63
msgid "new password"
msgstr ""
#: templates/selfservice.html:66
msgid "Your new password must be atleast 12 characters long."
msgstr ""
#: templates/selfservice.html:71
msgid "repeat new password"
msgstr ""
#: templates/groups/list.html:2
msgid "group list"
msgstr ""
#: templates/groups/list.html:7
msgid "group name"
msgstr ""
#: templates/groups/list.html:8
msgid "group description"
msgstr ""
#: templates/groups/list.html:9
msgid "member?"
msgstr ""
#: templates/groups/list.html:10
msgid "member count"
msgstr ""
#: templates/groups/members.html:2
#, python-format
msgid "group %(ou)s"
msgstr ""
#: templates/groups/members.html:8
msgid "cn"
msgstr ""
#: templates/groups/members.html:9
msgid "remove member"
msgstr ""
#: templates/groups/members.html:21
msgid "remove"
msgstr ""
#: templates/groups/members.html:31 templates/groups/members.html:45
msgid "add user to group"
msgstr ""
#: templates/groups/members.html:37
msgid "select user"
msgstr ""
#: templates/layout/default.html:26
msgid "groups"
msgstr ""
#: templates/layout/default.html:30
msgid "Other Sites"
msgstr ""
#: templates/layout/default.html:39
#, python-format
msgid "Signed in as <em>%(uid)s</em>"
msgstr ""
#: templates/layout/default.html:39
msgid "logout"
msgstr ""

View File

@ -1,13 +1,13 @@
{% extends "layout/default.html" %}
{% block title %}groups{% endblock %}
{% block title %}{% trans %}group list{% endtrans %}{% endblock %}
{% block content %}
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th scope="col">group name</th>
<th scope="col">group description</th>
<th scope="col">member?</th>
<th scope="col">member count</th>
<th scope="col">{% trans %}group name{% endtrans %}</th>
<th scope="col">{% trans %}group description{% endtrans %}</th>
<th scope="col">{% trans %}member?{% endtrans %}</th>
<th scope="col">{% trans %}member count{% endtrans %}</th>
</tr>
</thead>
<tbody>

View File

@ -1,12 +1,12 @@
{% extends "layout/default.html" %}
{% block title %}group {{ ou }}{% endblock %}
{% block title %}{% trans ou=ou %}group {{ ou }}{% endtrans %}{% endblock %}
{% block content %}
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th scope="col">uid</th>
<th scope="col">cn</th>
<th scope="col">remove</th>
<th scope="col">{% trans %}uid{% endtrans %}</th>
<th scope="col">{% trans %}cn{% endtrans %}</th>
<th scope="col">{% trans %}remove member{% endtrans %}</th>
</tr>
</thead>
<tbody>
@ -18,7 +18,7 @@
<form action="{{ url_for("group_edit", ou=ou) }}" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<input type="hidden" name="remove" value="{{ member["uid"] }}">
<input type="submit" value="remove" class="btn btn-danger">
<input type="submit" value="{% trans %}remove{% endtrans %}" class="btn btn-danger">
</form>
</td>
</tr>
@ -28,13 +28,13 @@
<form action="{{ url_for("group_edit", ou=ou) }}" method="post" class="row g-3 needs-validation">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<fieldset>
<legend>add user to group</legend>
<legend>{% trans %}add user to group{% endtrans %}</legend>
<div class="row mb-3">
<label for="add" class="form-label col-sm-2">user</label>
<div class="col-sm-10">
<select name="add" id="add" class="form-select">
<option value="" selected>select user ...</option>
<option value="" selected>{% trans %}select user{% endtrans %}</option>
{% for user in other_users|sort %}
<option value="{{ user["uid"] }}">{{ user["cn"] }} ({{ user["uid"] }})</option>
{% endfor %}
@ -42,7 +42,7 @@
</div>
</div>
<input type="submit" value="add user" class="btn btn-primary mb-3"><br>
<input type="submit" value="{% trans %}add user to group{% endtrans %}" class="btn btn-primary mb-3"><br>
</fieldset>
</form>
{% endblock %}

View File

@ -20,16 +20,14 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="{{ url_for("selfservice") }}">self service</a>
<a class="nav-link" href="{{ url_for("selfservice") }}">{% trans %}self service{% endtrans %}</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for("groups") }}">groups</a>
<a class="nav-link" href="{{ url_for("groups") }}">{% trans %}groups{% endtrans %}</a>
</li>
{% if APP_CONFIG.external_links %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Other Sites
</a>
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">{% trans %}Other Sites{% endtrans %}</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
{% for text, link in APP_CONFIG.external_links.items()|sort %}
<a class="dropdown-item" href="{{ link }}">{{ text }}</a>
@ -38,7 +36,7 @@
</li>
{% endif %}
</ul>
<span class="navbar-text navbar-right">Signed in as <em>{{ CURRENT_USER["uid"] }}</em> - <a href="{{ url_for("logout") }}">logout</a></span>
<span class="navbar-text navbar-right">{% trans uid=CURRENT_USER["uid"] %}Signed in as <em>{{ uid }}</em>{% endtrans %} - <a href="{{ url_for("logout") }}">{% trans %}logout{% endtrans %}</a></span>
</div>
</div>
</nav>

View File

@ -1,21 +1,22 @@
{% extends "layout/default.html" %}
{% block title %}{% trans %}Login{% endtrans %}{% endblock %}
{% block content %}
<form action="{{ url_for("login") }}" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<fieldset>
<legend>Login</legend>
<legend>{% trans %}Login{% endtrans %}</legend>
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<label for="username" class="form-label">{% trans %}Username{% endtrans %}</label>
<input type="text" name="username" id="username" required class="form-control">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<label for="password" class="form-label">{% trans %}Password{% endtrans %}</label>
<input type="password" name="password" id="password" required class="form-control">
</div>
<input type="submit" value="Login" class="btn btn-primary mb-3">
<input type="submit" value="{% trans %}Login{% endtrans %}" class="btn btn-primary mb-3">
</fieldset>
</form>
{% endblock %}

View File

@ -1,79 +1,80 @@
{% extends "layout/default.html" %}
{% block title %}self service{% endblock %}
{% block title %}{% trans %}self service{% endtrans %}{% endblock %}
{% block content %}
<form action="{{ url_for("selfservice") }}" method="post" class="row g-3 needs-validation">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<fieldset>
<legend>user data</legend>
<legend>{% trans %}Edit User Data{% endtrans %}</legend>
<div class="row mb-3">
<label for="uid" class="form-label col-sm-2">uid</label>
<label for="uid" class="form-label col-sm-2">{% trans %}uid{% endtrans %}</label>
<div class="col-sm-10">
<input type="text" name="uid" id="uid" value="{{ CURRENT_USER["uid"]|e }}" disabled readonly class="form-control" aria-describedby="uidHelp">
<div id="uidHelp" class="form-text">contact an administrator if you want to change this</div>
<div id="uidHelp" class="form-text">{% trans %}Contact an administrator if you want to change this.{% endtrans %}</div>
</div>
</div>
<div class="row mb-3">
<label for="cn" class="form-label col-sm-2">common name</label>
<label for="cn" class="form-label col-sm-2">{% trans commonName %}name{% endtrans %}</label>
<div class="col-sm-10">
<input type="text" name="cn" id="cn" value="{{ CURRENT_USER["cn"]|e }}" disabled readonly class="form-control" aria-describedby="cnHelp">
<div id="cnHelp" class="form-text">gets adjusted automatically</div>
<div id="cnHelp" class="form-text">{% trans %}This field gets adjusted automatically based on the fields below.{% endtrans %}</div>
</div>
</div>
<div class="row mb-3">
<label for="sn" class="form-label col-sm-2">surname</label>
<label for="sn" class="form-label col-sm-2">{% trans sn %}surname{% endtrans %}</label>
<div class="col-sm-10">
<input type="text" name="sn" id="sn" value="{{ CURRENT_USER["sn"]|e }}" required class="form-control">
</div>
</div>
<div class="row mb-3">
<label for="givenName" class="form-label col-sm-2">given name</label>
<label for="givenName" class="form-label col-sm-2">{% trans givenName %}given name{% endtrans %}</label>
<div class="col-sm-10">
<input type="text" name="givenName" id="givenName" value="{{ CURRENT_USER["givenName"]|e }}" required class="form-control">
</div>
</div>
<div class="row mb-3">
<label for="mail" class="form-label col-sm-2">email address</label>
<label for="mail" class="form-label col-sm-2">{% trans email %}e-mail address{% endtrans %}</label>
<div class="col-sm-10">
<input type="email" name="mail" id="mail" value="{{ CURRENT_USER["mail"]|e }}" required class="form-control">
</div>
</div>
<input type="submit" name="userdata" value="update" class="btn btn-primary mb-3"><br>
<input type="submit" name="userdata" value="{% trans %}Update{% endtrans %}" class="btn btn-primary mb-3"><br>
</fieldset>
</form>
<form action="{{ url_for("selfservice") }}" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<fieldset>
<legend>password</legend>
<legend>{% trans %}change password{% endtrans %}</legend>
<div class="row mb-3">
<label for="current" class="form-label col-sm-2">current password</label>
<label for="current" class="form-label col-sm-2">{% trans %}current password{% endtrans %}</label>
<div class="col-sm-10">
<input type="password" name="current" id="current" value="" class="form-control">
</div>
</div>
<div class="row mb-3">
<label for="new" class="form-label col-sm-2">new password</label>
<label for="new" class="form-label col-sm-2">{% trans %}new password{% endtrans %}</label>
<div class="col-sm-10">
<input type="password" name="new" id="new" value="" class="form-control">
<input type="password" name="new" id="new" value="" class="form-control" aria-describedby="newHelp">
<div id="newHelp" class="form-text">{% trans %}Your new password must be atleast 12 characters long.{% endtrans %}</div>
</div>
</div>
<div class="row mb-3">
<label for="repeat" class="form-label col-sm-2">repeat new password</label>
<label for="repeat" class="form-label col-sm-2">{% trans %}repeat new password{% endtrans %}</label>
<div class="col-sm-10">
<input type="password" name="repeat" id="repeat" value="" class="form-control">
</div>
</div>
<input type="submit" name="passwordchange" value="change password" class="btn btn-primary mb-3"><br>
<input type="submit" name="passwordchange" value="{% trans %}change password{% endtrans %}" class="btn btn-primary mb-3"><br>
</fieldset>
</form>
{% endblock %}

View File

@ -0,0 +1,200 @@
# German translations for qzwi-ldap-frontend.
# Copyright (C) 2021 Franziska Kunsmann
#
msgid ""
msgstr ""
"Project-Id-Version: qzwi-ldap-frontend\n"
"Report-Msgid-Bugs-To: qzwi@kunsmann.eu\n"
"POT-Creation-Date: 2021-12-23 09:11+0100\n"
"PO-Revision-Date: 2021-12-23 08:41+0100\n"
"Last-Translator: Franziska Kunsmann <qzwi@kunsmann.eu>\n"
"Language: de\n"
"Language-Team: de <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: __init__.py:40
msgid "CRSF validation error. For your own safety, you have been logged out."
msgstr ""
"Formularvalidierung fehlgeschlagen. Zu deiner Sicherheit wurdest du "
"abgemeldet."
#: __init__.py:69
msgid "logged in"
msgstr "Erfolgreich angemeldet"
#: __init__.py:73
msgid "username or password is wrong"
msgstr "Der eingegebene Benutzername existiert nicht oder das Passwort ist falsch."
#: __init__.py:84
msgid "you have been logged out"
msgstr "Du wurdest abgemeldet."
#: __init__.py:108
msgid "user data was updated"
msgstr "Die Benutzerdaten wurden geändert."
#: __init__.py:125
msgid "current password does not match the one stored"
msgstr "Das eingegebene Passwort stimmt nicht mit dem bisherigen überein."
#: __init__.py:129
msgid "new passwords do not match"
msgstr "Das neue Passwort stimmt nicht mit der Wiederholung überein."
#: __init__.py:133
msgid "new password must be atleast 12 characters long"
msgstr "Dein neues Passwort muss mindestens 12 Zeichen lang sein."
#: __init__.py:143
msgid "your password was changed"
msgstr "Dein Passwort wurde geändert."
#: __init__.py:196
#, python-format
msgid "%(user)s was removed from %(ou)s"
msgstr "%(user)s wurde aus %(ou)s entfernt."
#: __init__.py:211
#, python-format
msgid "%(user)s was added to %(ou)s"
msgstr "%(user)s wurde zu %(ou)s hinzugefügt."
#: templates/login.html:2 templates/login.html:7 templates/login.html:19
msgid "Login"
msgstr "Anmelden"
#: templates/login.html:10
msgid "Username"
msgstr "Benutzername"
#: templates/login.html:15
msgid "Password"
msgstr "Passwort"
#: templates/layout/default.html:23 templates/selfservice.html:2
msgid "self service"
msgstr "Daten ändern"
#: templates/selfservice.html:7
msgid "Edit User Data"
msgstr "Benutzer*innen-Daten ändern"
#: templates/groups/members.html:7 templates/selfservice.html:10
msgid "uid"
msgstr "Login-Name"
#: templates/selfservice.html:13
msgid "Contact an administrator if you want to change this."
msgstr "Kontaktiere einen Administrator, wenn du diesen Wert ändern möchtest."
#: templates/selfservice.html:18
msgid "name"
msgstr "Name"
#: templates/selfservice.html:21
msgid "This field gets adjusted automatically based on the fields below."
msgstr "Dieser Wert wird automatisch basierend auf den Feldern darunter geändert."
#: templates/selfservice.html:26
msgid "surname"
msgstr "Nachname"
#: templates/selfservice.html:33
msgid "given name"
msgstr "Vorname"
#: templates/selfservice.html:40
msgid "e-mail address"
msgstr "E-Mail-Adresse"
#: templates/selfservice.html:46
msgid "Update"
msgstr "Daten ändern"
#: templates/selfservice.html:53 templates/selfservice.html:77
msgid "change password"
msgstr "Passwort ändern"
#: templates/selfservice.html:56
msgid "current password"
msgstr "Aktuelles Passwort"
#: templates/selfservice.html:63
msgid "new password"
msgstr "Neues Passwort"
#: templates/selfservice.html:66
msgid "Your new password must be atleast 12 characters long."
msgstr "Dein neues Passwort muss mindestens 12 Zeichen lang sein."
#: templates/selfservice.html:71
msgid "repeat new password"
msgstr "Neues Passwort (Wiederholung)"
#: templates/groups/list.html:2
msgid "group list"
msgstr "Gruppen-Übersicht"
#: templates/groups/list.html:7
msgid "group name"
msgstr "Gruppen-Name"
#: templates/groups/list.html:8
msgid "group description"
msgstr "Gruppen-Beschreibung"
#: templates/groups/list.html:9
msgid "member?"
msgstr "Mitglied?"
#: templates/groups/list.html:10
msgid "member count"
msgstr "Anzahl der Mitglieder"
#: templates/groups/members.html:2
#, python-format
msgid "group %(ou)s"
msgstr "Gruppe %(ou)s"
#: templates/groups/members.html:8
msgid "cn"
msgstr "Name"
#: templates/groups/members.html:9
msgid "remove member"
msgstr "Mitglied entfernen"
#: templates/groups/members.html:21
msgid "remove"
msgstr "Entfernen"
#: templates/groups/members.html:31 templates/groups/members.html:45
msgid "add user to group"
msgstr "Mitglied zur Gruppe hinzufügen"
#: templates/groups/members.html:37
msgid "select user"
msgstr "Benutzer auswählen"
#: templates/layout/default.html:26
msgid "groups"
msgstr "Gruppen"
#: templates/layout/default.html:30
msgid "Other Sites"
msgstr "Links"
#: templates/layout/default.html:39
#, python-format
msgid "Signed in as <em>%(uid)s</em>"
msgstr "Angemeldet als <em>%(uid)s</em>\n"
#: templates/layout/default.html:39
msgid "logout"
msgstr "Abmelden"

View File

@ -1,5 +1,7 @@
Babel==2.9.1
click==8.0.3
Flask==2.0.2
Flask-Babel==2.0.0
Flask-WTF==1.0.0
gunicorn==20.1.0
itsdangerous==2.0.1
@ -7,5 +9,6 @@ Jinja2==3.0.3
ldap3==2.9.1
MarkupSafe==2.0.1
pyasn1==0.4.8
pytz==2021.3
Werkzeug==2.0.2
WTForms==3.0.0