You've already forked snikket-web-portal
Compare commits
5 Commits
fix/use-en
...
feature/up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b36fc0d5ac | ||
|
|
68f72743c5 | ||
|
|
8741efb2c4 | ||
|
|
a0e8933b64 | ||
|
|
edb3154127 |
@@ -1,7 +1,7 @@
|
||||
aiohttp~=3.6
|
||||
quart~=0.11,<0.15
|
||||
quart~=0.17
|
||||
flask-wtf~=0.14
|
||||
hsluv~=0.0.2
|
||||
hsluv~=5.0
|
||||
flask-babel~=1.0
|
||||
email-validator~=1.1
|
||||
environ-config~=20.0
|
||||
|
||||
@@ -18,6 +18,8 @@ from quart import (
|
||||
jsonify,
|
||||
)
|
||||
|
||||
import werkzeug.exceptions
|
||||
|
||||
import environ
|
||||
|
||||
from . import colour, infra
|
||||
@@ -40,7 +42,7 @@ async def proc() -> typing.Dict[str, typing.Any]:
|
||||
|
||||
try:
|
||||
user_info = await infra.client.get_user_info()
|
||||
except (aiohttp.ClientError, quart.exceptions.HTTPException):
|
||||
except (aiohttp.ClientError, werkzeug.exceptions.HTTPException):
|
||||
user_info = {}
|
||||
|
||||
return {
|
||||
@@ -105,16 +107,16 @@ async def backend_error_handler(exc: Exception) -> quart.Response:
|
||||
|
||||
|
||||
async def generic_http_error(
|
||||
exc: quart.exceptions.HTTPException,
|
||||
exc: werkzeug.exceptions.HTTPException,
|
||||
) -> quart.Response:
|
||||
return quart.Response(
|
||||
await render_template(
|
||||
"generic_http_error.html",
|
||||
status=exc.status_code,
|
||||
status=exc.code,
|
||||
description=exc.description,
|
||||
name=exc.name,
|
||||
),
|
||||
status=exc.status_code,
|
||||
status=exc.code,
|
||||
)
|
||||
|
||||
|
||||
@@ -200,19 +202,19 @@ def create_app() -> quart.Quart:
|
||||
app.context_processor(proc)
|
||||
app.register_error_handler(
|
||||
aiohttp.ClientConnectorError,
|
||||
backend_error_handler, # type:ignore
|
||||
backend_error_handler,
|
||||
)
|
||||
app.register_error_handler(
|
||||
quart.exceptions.HTTPException,
|
||||
werkzeug.exceptions.HTTPException,
|
||||
generic_http_error, # type:ignore
|
||||
)
|
||||
app.register_error_handler(
|
||||
Exception,
|
||||
generic_error_handler, # type:ignore
|
||||
generic_error_handler,
|
||||
)
|
||||
|
||||
@app.route("/")
|
||||
async def index() -> quart.Response:
|
||||
async def index() -> werkzeug.Response:
|
||||
if infra.client.has_session:
|
||||
return redirect(url_for('user.index'))
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ from datetime import datetime
|
||||
|
||||
import aiohttp
|
||||
|
||||
import werkzeug.exceptions
|
||||
|
||||
import quart.flask_patch
|
||||
|
||||
import wtforms
|
||||
@@ -92,7 +94,7 @@ class EditUserForm(BaseForm):
|
||||
|
||||
@bp.route("/user/<localpart>/", methods=["GET", "POST"])
|
||||
@client.require_admin_session()
|
||||
async def edit_user(localpart: str) -> typing.Union[quart.Response, str]:
|
||||
async def edit_user(localpart: str) -> typing.Union[werkzeug.Response, str]:
|
||||
target_user_info = await client.get_user_by_localpart(localpart)
|
||||
|
||||
form = EditUserForm()
|
||||
@@ -147,7 +149,7 @@ class DeleteUserForm(BaseForm):
|
||||
|
||||
@bp.route("/user/<localpart>/delete", methods=["GET", "POST"])
|
||||
@client.require_admin_session()
|
||||
async def delete_user(localpart: str) -> typing.Union[str, quart.Response]:
|
||||
async def delete_user(localpart: str) -> typing.Union[str, werkzeug.Response]:
|
||||
target_user_info = await client.get_user_by_localpart(localpart)
|
||||
form = DeleteUserForm()
|
||||
if form.validate_on_submit():
|
||||
@@ -186,7 +188,7 @@ async def debug_user(localpart: str) -> typing.Union[str, quart.Response]:
|
||||
@client.require_admin_session()
|
||||
async def user_password_reset_link(
|
||||
id_: str,
|
||||
) -> typing.Union[str, quart.Response]:
|
||||
) -> typing.Union[str, werkzeug.Response]:
|
||||
invite_info = await client.get_invite_by_id(
|
||||
id_,
|
||||
)
|
||||
@@ -278,7 +280,7 @@ class InvitePost(BaseForm):
|
||||
|
||||
@bp.route("/invitations", methods=["GET", "POST"])
|
||||
@client.require_admin_session()
|
||||
async def invitations() -> typing.Union[str, quart.Response]:
|
||||
async def invitations() -> typing.Union[str, werkzeug.Response]:
|
||||
invites = sorted(
|
||||
(
|
||||
invite
|
||||
@@ -324,7 +326,7 @@ class InviteForm(BaseForm):
|
||||
|
||||
@bp.route("/invitation/-/new", methods=["POST"])
|
||||
@client.require_admin_session()
|
||||
async def create_invite() -> typing.Union[str, quart.Response]:
|
||||
async def create_invite() -> typing.Union[str, werkzeug.Response]:
|
||||
form = InvitePost()
|
||||
circles = await client.list_groups()
|
||||
form.circles.choices = [
|
||||
@@ -352,7 +354,7 @@ async def create_invite() -> typing.Union[str, quart.Response]:
|
||||
|
||||
@bp.route("/invitation/<id_>", methods=["GET", "POST"])
|
||||
@client.require_admin_session()
|
||||
async def edit_invite(id_: str) -> typing.Union[str, quart.Response]:
|
||||
async def edit_invite(id_: str) -> typing.Union[str, werkzeug.Response]:
|
||||
try:
|
||||
invite_info = await client.get_invite_by_id(id_)
|
||||
except aiohttp.ClientResponseError as exc:
|
||||
@@ -418,7 +420,7 @@ async def circles() -> str:
|
||||
|
||||
@bp.route("/circle/-/new", methods=["POST"])
|
||||
@client.require_admin_session()
|
||||
async def create_circle() -> typing.Union[str, quart.Response]:
|
||||
async def create_circle() -> typing.Union[str, werkzeug.Response]:
|
||||
create_form = CirclePost()
|
||||
if create_form.validate_on_submit():
|
||||
circle = await client.create_group(
|
||||
@@ -464,7 +466,7 @@ class EditCircleForm(BaseForm):
|
||||
|
||||
@bp.route("/circle/<id_>", methods=["GET", "POST"])
|
||||
@client.require_admin_session()
|
||||
async def edit_circle(id_: str) -> typing.Union[str, quart.Response]:
|
||||
async def edit_circle(id_: str) -> typing.Union[str, werkzeug.Response]:
|
||||
async with client.authenticated_session() as session:
|
||||
try:
|
||||
circle = await client.get_group_by_id(
|
||||
@@ -626,7 +628,7 @@ class AnnouncementForm(BaseForm):
|
||||
|
||||
@bp.route("/system/", methods=["GET", "POST"])
|
||||
@client.require_admin_session()
|
||||
async def system() -> typing.Union[str, quart.Response]:
|
||||
async def system() -> typing.Union[str, werkzeug.Response]:
|
||||
form = AnnouncementForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
@@ -657,7 +659,7 @@ async def system() -> typing.Union[str, quart.Response]:
|
||||
now = time.time()
|
||||
try:
|
||||
prosody_metrics = await client.get_system_metrics()
|
||||
except quart.exceptions.NotFound:
|
||||
except werkzeug.exceptions.NotFound:
|
||||
# server does not offer the endpoint for whatever reason -- ignore
|
||||
prosody_metrics = {}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ from quart import (
|
||||
session as http_session,
|
||||
)
|
||||
|
||||
import werkzeug
|
||||
|
||||
import wtforms
|
||||
|
||||
from flask_babel import lazy_gettext as _l, gettext
|
||||
@@ -46,14 +48,14 @@ def apple_store_badge() -> str:
|
||||
|
||||
|
||||
@bp.context_processor
|
||||
def context() -> typing.Mapping[str, typing.Any]:
|
||||
def context() -> typing.Dict[str, typing.Any]:
|
||||
return {
|
||||
"apple_store_badge": apple_store_badge,
|
||||
}
|
||||
|
||||
|
||||
@bp.route("/<id_>")
|
||||
async def view_old(id_: str) -> quart.Response:
|
||||
async def view_old(id_: str) -> werkzeug.Response:
|
||||
return redirect(url_for(".view", id_=id_))
|
||||
|
||||
|
||||
@@ -131,7 +133,7 @@ class RegisterForm(BaseForm):
|
||||
|
||||
|
||||
@bp.route("/<id_>/register", methods=["GET", "POST"])
|
||||
async def register(id_: str) -> typing.Union[str, quart.Response]:
|
||||
async def register(id_: str) -> typing.Union[str, werkzeug.Response]:
|
||||
try:
|
||||
invite = await client.get_public_invite_by_id(id_)
|
||||
except aiohttp.ClientResponseError as exc:
|
||||
@@ -199,7 +201,7 @@ class ResetForm(BaseForm):
|
||||
|
||||
|
||||
@bp.route("/<id_>/reset", methods=["GET", "POST"])
|
||||
async def reset(id_: str) -> typing.Union[str, quart.Response]:
|
||||
async def reset(id_: str) -> typing.Union[str, werkzeug.Response]:
|
||||
try:
|
||||
invite = await client.get_public_invite_by_id(id_)
|
||||
except aiohttp.ClientResponseError as exc:
|
||||
@@ -300,5 +302,5 @@ async def reset_success() -> str:
|
||||
|
||||
|
||||
@bp.route("/-")
|
||||
async def index() -> quart.Response:
|
||||
async def index() -> werkzeug.Response:
|
||||
return redirect(url_for("index"))
|
||||
|
||||
@@ -18,6 +18,8 @@ from quart import (
|
||||
flash,
|
||||
)
|
||||
|
||||
import werkzeug.exceptions
|
||||
|
||||
import babel
|
||||
import wtforms
|
||||
|
||||
@@ -48,7 +50,7 @@ class LoginForm(BaseForm):
|
||||
|
||||
|
||||
@bp.route("/-")
|
||||
async def index() -> quart.Response:
|
||||
async def index() -> werkzeug.Response:
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
@@ -56,7 +58,7 @@ ERR_CREDENTIALS_INVALID = _l("Invalid username or password.")
|
||||
|
||||
|
||||
@bp.route("/login", methods=["GET", "POST"])
|
||||
async def login() -> typing.Union[str, quart.Response]:
|
||||
async def login() -> typing.Union[str, werkzeug.Response]:
|
||||
if client.has_session and (await client.test_session()):
|
||||
return redirect(url_for('user.index'))
|
||||
|
||||
@@ -76,7 +78,7 @@ async def login() -> typing.Union[str, quart.Response]:
|
||||
password = form.password.data
|
||||
try:
|
||||
await client.login(jid, password)
|
||||
except quart.exceptions.Unauthorized:
|
||||
except werkzeug.exceptions.Unauthorized:
|
||||
form.password.errors.append(ERR_CREDENTIALS_INVALID)
|
||||
else:
|
||||
await flash(
|
||||
@@ -95,14 +97,13 @@ async def about() -> str:
|
||||
|
||||
if current_app.debug or client.is_admin_session:
|
||||
version = _version.version
|
||||
extra_versions["Quart"] = quart.__version__
|
||||
extra_versions["aiohttp"] = aiohttp.__version__
|
||||
extra_versions["babel"] = babel.__version__
|
||||
extra_versions["wtforms"] = wtforms.__version__
|
||||
extra_versions["flask-wtf"] = flask_wtf.__version__
|
||||
try:
|
||||
extra_versions["Prosody"] = await client.get_server_version()
|
||||
except quart.exceptions.Unauthorized:
|
||||
except werkzeug.exceptions.Unauthorized:
|
||||
extra_versions["Prosody"] = "unknown"
|
||||
|
||||
return await render_template(
|
||||
|
||||
@@ -19,7 +19,9 @@ from quart import (
|
||||
current_app, _app_ctx_stack, session as http_session, abort, redirect,
|
||||
url_for,
|
||||
)
|
||||
import quart.exceptions
|
||||
import quart
|
||||
|
||||
import werkzeug.exceptions
|
||||
|
||||
from . import xmpputil
|
||||
from .xmpputil import split_jid
|
||||
@@ -386,16 +388,16 @@ class ProsodyClient:
|
||||
) -> typing.Callable[
|
||||
[typing.Callable[..., typing.Awaitable[T]]],
|
||||
typing.Callable[..., typing.Awaitable[
|
||||
typing.Union[T, quart.Response]]]]:
|
||||
typing.Union[T, quart.Response, werkzeug.Response]]]]:
|
||||
def decorator(
|
||||
f: typing.Callable[..., typing.Awaitable[T]],
|
||||
) -> typing.Callable[..., typing.Awaitable[
|
||||
typing.Union[T, quart.Response]]]:
|
||||
typing.Union[T, quart.Response, werkzeug.Response]]]:
|
||||
@functools.wraps(f)
|
||||
async def wrapped(
|
||||
*args: typing.Any,
|
||||
**kwargs: typing.Any,
|
||||
) -> typing.Union[T, quart.Response]:
|
||||
) -> typing.Union[T, quart.Response, werkzeug.Response]:
|
||||
if not self.has_session or not (await self.test_session()):
|
||||
redirect_to_value = redirect_to
|
||||
if redirect_to_value is not False:
|
||||
@@ -415,17 +417,17 @@ class ProsodyClient:
|
||||
) -> typing.Callable[
|
||||
[typing.Callable[..., typing.Awaitable[T]]],
|
||||
typing.Callable[..., typing.Awaitable[
|
||||
typing.Union[T, quart.Response]]]]:
|
||||
typing.Union[T, quart.Response, werkzeug.Response]]]]:
|
||||
def decorator(
|
||||
f: typing.Callable[..., typing.Awaitable[T]],
|
||||
) -> typing.Callable[..., typing.Awaitable[
|
||||
typing.Union[T, quart.Response]]]:
|
||||
typing.Union[T, quart.Response, werkzeug.Response]]]:
|
||||
@functools.wraps(f)
|
||||
@self.require_session(redirect_to=redirect_to)
|
||||
async def wrapped(
|
||||
*args: typing.Any,
|
||||
**kwargs: typing.Any,
|
||||
) -> typing.Union[T, quart.Response]:
|
||||
) -> typing.Union[T, quart.Response, werkzeug.Response]:
|
||||
if not self.is_admin_session:
|
||||
raise abort(403, "This is not for you.")
|
||||
|
||||
@@ -492,7 +494,7 @@ class ProsodyClient:
|
||||
session=session,
|
||||
)
|
||||
avatar_hash = avatar_info["sha1"]
|
||||
except quart.exceptions.HTTPException:
|
||||
except werkzeug.exceptions.HTTPException:
|
||||
avatar_hash = None
|
||||
|
||||
return {
|
||||
@@ -644,7 +646,7 @@ class ProsodyClient:
|
||||
new_access_model,
|
||||
)
|
||||
))
|
||||
except quart.exceptions.NotFound:
|
||||
except werkzeug.exceptions.NotFound:
|
||||
if ignore_not_found:
|
||||
return
|
||||
raise
|
||||
@@ -774,7 +776,7 @@ class ProsodyClient:
|
||||
session: aiohttp.ClientSession,
|
||||
) -> str:
|
||||
access_models = filter(
|
||||
lambda x: not isinstance(x, quart.exceptions.NotFound),
|
||||
lambda x: not isinstance(x, werkzeug.exceptions.NotFound),
|
||||
await asyncio.gather(
|
||||
self.get_avatar_access_model(session=session),
|
||||
self.get_nickname_access_model(session=session),
|
||||
|
||||
Binary file not shown.
@@ -6,18 +6,18 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"Report-Msgid-Bugs-To: translations@snikket.org\n"
|
||||
"POT-Creation-Date: 2022-01-17 17:27+0100\n"
|
||||
"PO-Revision-Date: 2021-04-02 19:01+0000\n"
|
||||
"Last-Translator: Daniel Holmgaard <annoncer@protonmail.com>\n"
|
||||
"Language-Team: Danish <https://i18n.sotecware.net/projects/snikket/web-"
|
||||
"portal/da/>\n"
|
||||
"PO-Revision-Date: 2022-05-30 14:01+0000\n"
|
||||
"Last-Translator: Daniel Holmgaard <fovatis@tutanota.com>\n"
|
||||
"Language-Team: Danish <http://i18n.sotecware.net/projects/snikket/web-portal/"
|
||||
"da/>\n"
|
||||
"Language: da\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.5.1\n"
|
||||
"X-Generator: Weblate 4.8.1\n"
|
||||
"Generated-By: Babel 2.9.0\n"
|
||||
|
||||
#: snikket_web/admin.py:68 snikket_web/templates/admin_delete_user.html:10
|
||||
@@ -194,23 +194,23 @@ msgstr "Bruger fjernet fra cirkel"
|
||||
|
||||
#: snikket_web/admin.py:609
|
||||
msgid "Message contents"
|
||||
msgstr ""
|
||||
msgstr "Meddelelsens indhold"
|
||||
|
||||
#: snikket_web/admin.py:615
|
||||
msgid "Only send to online users"
|
||||
msgstr ""
|
||||
msgstr "Send kun til online brugere"
|
||||
|
||||
#: snikket_web/admin.py:619
|
||||
msgid "Post to all users"
|
||||
msgstr ""
|
||||
msgstr "Send til alle brugere"
|
||||
|
||||
#: snikket_web/admin.py:623
|
||||
msgid "Send preview to yourself"
|
||||
msgstr ""
|
||||
msgstr "Send forhåndsvisning til dig selv"
|
||||
|
||||
#: snikket_web/admin.py:645
|
||||
msgid "Announcement sent!"
|
||||
msgstr ""
|
||||
msgstr "Bekendgørelse sendt!"
|
||||
|
||||
#: snikket_web/infra.py:51
|
||||
msgid "Main"
|
||||
@@ -221,6 +221,8 @@ msgid ""
|
||||
"The account data you tried to import is too large to upload. Please contact "
|
||||
"your Snikket operator."
|
||||
msgstr ""
|
||||
"De kontodata, du forsøgte at importere, er for store til at uploade. Kontakt "
|
||||
"din Snikket-operatør."
|
||||
|
||||
#: snikket_web/invite.py:112
|
||||
msgid "Username"
|
||||
@@ -261,11 +263,11 @@ msgstr "Ændr adgangskode"
|
||||
|
||||
#: snikket_web/invite.py:244
|
||||
msgid "Account data file"
|
||||
msgstr ""
|
||||
msgstr "Kontodatafil"
|
||||
|
||||
#: snikket_web/invite.py:248
|
||||
msgid "Import data"
|
||||
msgstr ""
|
||||
msgstr "Importer data"
|
||||
|
||||
#: snikket_web/invite.py:269
|
||||
#, python-format
|
||||
@@ -273,6 +275,8 @@ msgid ""
|
||||
"The account data you tried to import is in an unknown format. Please upload "
|
||||
"an XML file in XEP-0227 format (provided format: %(mimetype)s)."
|
||||
msgstr ""
|
||||
"De kontodata, du forsøgte at importere, er i et ukendt format. Upload en XML-"
|
||||
"fil i XEP-0227-format (forudsat format: %(mimetype)s)."
|
||||
|
||||
#: snikket_web/invite.py:289 snikket_web/templates/unauth.html:18
|
||||
#: snikket_web/user.py:178
|
||||
@@ -341,11 +345,11 @@ msgstr "Opdater profil"
|
||||
|
||||
#: snikket_web/user.py:82
|
||||
msgid "Account data"
|
||||
msgstr ""
|
||||
msgstr "Kontodata"
|
||||
|
||||
#: snikket_web/user.py:86
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
msgstr "Upload"
|
||||
|
||||
#: snikket_web/user.py:111
|
||||
msgid "Incorrect password."
|
||||
@@ -369,11 +373,11 @@ msgstr "Profil opdateret"
|
||||
|
||||
#: snikket_web/user.py:184
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
msgstr "Exporter"
|
||||
|
||||
#: snikket_web/user.py:202
|
||||
msgid "You currently have no account data to export."
|
||||
msgstr ""
|
||||
msgstr "Du har i øjeblikket ingen kontodata at eksportere."
|
||||
|
||||
#: snikket_web/templates/_footer.html:4
|
||||
#, python-format
|
||||
@@ -662,7 +666,7 @@ msgstr "Cirkel medlemmer"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
msgid "The user has been deleted from the server."
|
||||
msgstr ""
|
||||
msgstr "Brugeren er blevet slettet fra serveren."
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
#: snikket_web/templates/library.j2:108
|
||||
@@ -876,22 +880,20 @@ msgstr "Håndter invitationer"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:35
|
||||
msgid "System health"
|
||||
msgstr ""
|
||||
msgstr "Systemets sundhed"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:38
|
||||
msgid "View the server status or send a broadcast message to all users."
|
||||
msgstr ""
|
||||
msgstr "Vis serverstatus, eller send en udsendelsesmeddelelse til alle brugere."
|
||||
|
||||
#: snikket_web/templates/admin_home.html:40
|
||||
msgid "Send a broadcast message to all users."
|
||||
msgstr ""
|
||||
msgstr "Send en udsendelsesmeddelelse til alle brugere."
|
||||
|
||||
#: snikket_web/templates/admin_home.html:43
|
||||
#: snikket_web/templates/admin_system.html:4
|
||||
#, fuzzy
|
||||
#| msgid "Manage users"
|
||||
msgid "Manage system"
|
||||
msgstr "Håndter brugere"
|
||||
msgstr "Håndter system"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:48
|
||||
msgid "Go back to your user's web portal page."
|
||||
@@ -952,11 +954,11 @@ msgstr "Ødelæg link"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:6
|
||||
msgid "Overall system status"
|
||||
msgstr ""
|
||||
msgstr "Samlet systemstatus"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:9
|
||||
msgid "System load (5 minute average)"
|
||||
msgstr ""
|
||||
msgstr "Systembelastning (5 minutters gennemsnit)"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:14
|
||||
#: snikket_web/templates/admin_system.html:22
|
||||
@@ -967,11 +969,11 @@ msgstr ""
|
||||
#: snikket_web/templates/admin_system.html:76
|
||||
#: snikket_web/templates/admin_system.html:84
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
msgstr "ukendt"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:17
|
||||
msgid "Memory use"
|
||||
msgstr ""
|
||||
msgstr "Forbrug af hukommelse"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:20
|
||||
#, python-format
|
||||
@@ -979,54 +981,56 @@ msgid ""
|
||||
"%(percentage_global)s of %(mem_available)s. Of that, Snikket uses "
|
||||
"%(percentage_snikket)s."
|
||||
msgstr ""
|
||||
"%(percentage_global)s af %(mem_available)s. Der af bruger Snikket "
|
||||
"%(percentage_snikket)s."
|
||||
|
||||
#: snikket_web/templates/admin_system.html:27
|
||||
msgid "Web portal status"
|
||||
msgstr ""
|
||||
msgstr "Webportalens status"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:30
|
||||
#: snikket_web/templates/admin_system.html:53
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
msgstr "Version"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:31
|
||||
#: snikket_web/templates/admin_system.html:54
|
||||
msgid "View all versions"
|
||||
msgstr ""
|
||||
msgstr "Vis alle versioner"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:32
|
||||
#: snikket_web/templates/admin_system.html:55
|
||||
msgid "Average CPU use"
|
||||
msgstr ""
|
||||
msgstr "Gennemsnitlig CPU-forbrug"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:40
|
||||
#: snikket_web/templates/admin_system.html:63
|
||||
msgid "Current memory use"
|
||||
msgstr ""
|
||||
msgstr "Nuværende hukommelsesbrug"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:50
|
||||
#, fuzzy
|
||||
#| msgid "Snikket Web Portal"
|
||||
msgid "Snikket server status"
|
||||
msgstr "Snikket Webportal"
|
||||
msgstr "Snikket server status"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:71
|
||||
msgid "Storage used by shared files"
|
||||
msgstr ""
|
||||
msgstr "Lagerplads, der bruges af delte filer"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:79
|
||||
msgid "Connected devices"
|
||||
msgstr ""
|
||||
msgstr "Forbundet enheder"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:90
|
||||
msgid "Broadcast message"
|
||||
msgstr ""
|
||||
msgstr "Send besked"
|
||||
|
||||
#: snikket_web/templates/admin_system.html:92
|
||||
msgid ""
|
||||
"This form allows you to send a message to all users currently online on your "
|
||||
"Snikket server. Use it wisely."
|
||||
msgstr ""
|
||||
"Denne formular giver dig mulighed for at sende en besked til alle brugere, "
|
||||
"der i øjeblikket er online på din Snikket-server. Brug den med omtanke."
|
||||
|
||||
#: snikket_web/templates/admin_users.html:19
|
||||
msgid "The user is an administrator."
|
||||
@@ -1300,22 +1304,20 @@ msgid ""
|
||||
"You can now safely close this page, or log in to the web portal to <a href="
|
||||
"\"%(login_url)s\">manage your account</a>."
|
||||
msgstr ""
|
||||
"Du kan nu trygt lukke denne side eller logge ind på webportalen for at <a "
|
||||
"href=\"%(login_url)s\">administrere din konto</a>."
|
||||
|
||||
#: snikket_web/templates/invite_success.html:21
|
||||
#, fuzzy
|
||||
#| msgid "Operation successful"
|
||||
msgid "Import successful"
|
||||
msgstr "Operation lykkes"
|
||||
msgstr "Importering lykkes"
|
||||
|
||||
#: snikket_web/templates/invite_success.html:22
|
||||
msgid "Congratulations! Your account data has been successfully imported."
|
||||
msgstr ""
|
||||
msgstr "Tillykke! Dine kontodata er blevet importeret."
|
||||
|
||||
#: snikket_web/templates/invite_success.html:26
|
||||
#, fuzzy
|
||||
#| msgid "Using the Snikket app"
|
||||
msgid "Moving to Snikket?"
|
||||
msgstr "Bruger Snikket appen"
|
||||
msgstr "Flytte til Snikket?"
|
||||
|
||||
#: snikket_web/templates/invite_success.html:27
|
||||
msgid ""
|
||||
@@ -1324,10 +1326,14 @@ msgid ""
|
||||
"information, etc.) from your previous account. When you have exported the "
|
||||
"data from your previous account, upload it using the form below."
|
||||
msgstr ""
|
||||
"Hvis du flytter fra en anden Snikket-platform eller en anden XMPP-kompatibel "
|
||||
"tjeneste, kan du eventuelt importere dataene (kontakter, profiloplysninger "
|
||||
"osv.) fra din tidligere konto. Når du har eksporteret dataene fra din "
|
||||
"tidligere konto, skal du uploade dem ved hjælp af nedenstående formular."
|
||||
|
||||
#: snikket_web/templates/invite_success.html:30
|
||||
msgid "Upload account data"
|
||||
msgstr ""
|
||||
msgstr "Upload kontodata"
|
||||
|
||||
#: snikket_web/templates/invite_view.html:6
|
||||
#, python-format
|
||||
@@ -1558,10 +1564,8 @@ msgstr "Rediger profil"
|
||||
|
||||
#: snikket_web/templates/user_home.html:33
|
||||
#: snikket_web/templates/user_manage_data.html:4
|
||||
#, fuzzy
|
||||
#| msgid "Manage users"
|
||||
msgid "Manage your data"
|
||||
msgstr "Håndter brugere"
|
||||
msgstr "Håndter dine data"
|
||||
|
||||
#: snikket_web/templates/user_home.html:39
|
||||
msgid "Your Snikket"
|
||||
@@ -1588,16 +1592,16 @@ msgstr ""
|
||||
"af de forbundne enheder."
|
||||
|
||||
#: snikket_web/templates/user_manage_data.html:8
|
||||
#, fuzzy
|
||||
#| msgid "Your account"
|
||||
msgid "Export account"
|
||||
msgstr "Din konto"
|
||||
msgstr "Eksporter konto"
|
||||
|
||||
#: snikket_web/templates/user_manage_data.html:9
|
||||
msgid ""
|
||||
"Download your account data as a file for backup purposes or to move your "
|
||||
"account to another service."
|
||||
msgstr ""
|
||||
"Download dine kontodata som en fil til sikkerhedskopieringsformål eller for "
|
||||
"at flytte din konto til en anden tjeneste."
|
||||
|
||||
#: snikket_web/templates/user_passwd.html:5
|
||||
msgid "Change your password"
|
||||
|
||||
BIN
snikket_web/translations/zh_Hans_CN/LC_MESSAGES/messages.mo
Normal file
BIN
snikket_web/translations/zh_Hans_CN/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
@@ -6,18 +6,19 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"Report-Msgid-Bugs-To: translations@snikket.org\n"
|
||||
"POT-Creation-Date: 2022-01-17 17:27+0100\n"
|
||||
"PO-Revision-Date: 2022-05-14 14:42+0800\n"
|
||||
"Last-Translator: Raka <me@bihu.im>\n"
|
||||
"Language-Team: zh_Hans_CN <LL@li.org>\n"
|
||||
"Language: zh_CN\n"
|
||||
"PO-Revision-Date: 2022-05-20 00:01+0000\n"
|
||||
"Last-Translator: Zack Zhou <lnx@outlook.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <http://i18n.sotecware.net/projects/"
|
||||
"snikket/web-portal/zh_Hans/>\n"
|
||||
"Language: zh_Hans_CN\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.8.1\n"
|
||||
"Generated-By: Babel 2.10.1\n"
|
||||
"X-Generator: Poedit 3.0.1\n"
|
||||
|
||||
#: snikket_web/admin.py:68 snikket_web/templates/admin_delete_user.html:10
|
||||
#: snikket_web/templates/admin_edit_circle.html:59
|
||||
@@ -371,7 +372,7 @@ msgstr "导出"
|
||||
|
||||
#: snikket_web/user.py:202
|
||||
msgid "You currently have no account data to export."
|
||||
msgstr "目前没有需要导出的数据"
|
||||
msgstr "目前没有需要导出的数据。"
|
||||
|
||||
#: snikket_web/templates/_footer.html:4
|
||||
#, python-format
|
||||
@@ -415,13 +416,15 @@ msgid ""
|
||||
"\"%(agpl_url)s\">Affero GNU General Public License, version 3.0 or later</a>. "
|
||||
"The full terms of the license can be reviewed using the aforementioned link."
|
||||
msgstr ""
|
||||
"此Web门户软件许可遵循 <a href=\"%(agpl_url)s\">GNU Affero通用公共许可证(版本3."
|
||||
"0及之后版本)</a>中的条款。此许可证的完整条款请使用前文中的链接查看。"
|
||||
|
||||
#: snikket_web/templates/about.html:15
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The source code of the web portal can be downloaded and viewed in <a href="
|
||||
"\"%(source_url)s\">its GitHub repository</a>."
|
||||
msgstr ""
|
||||
msgstr "此Web门户的源代码可在<a href=\"%(source_url)s\">其GitHub repository</a>查看并下载。"
|
||||
|
||||
#: snikket_web/templates/about.html:16
|
||||
#, python-format
|
||||
@@ -430,6 +433,8 @@ msgid ""
|
||||
"Material Icons</a>, made available by Google under the terms of the <a href="
|
||||
"\"%(apache20_url)s\">Apache 2.0 License</a>."
|
||||
msgstr ""
|
||||
"Web门户中使用的图标为<a href=\"%(source_url)s\">Google’s Material Icons</a>,"
|
||||
"由Google制作分发并遵循<a href=\"%(apache20_url)s\">Apache 2.0 许可证</a>中的条款。"
|
||||
|
||||
#: snikket_web/templates/about.html:17
|
||||
msgid "Trademarks"
|
||||
@@ -442,6 +447,8 @@ msgid ""
|
||||
"Company. For more information about the trademarks, visit the <a href="
|
||||
"\"%(trademarks_url)s\">Snikket Trademarks information page</a>."
|
||||
msgstr ""
|
||||
"“Snikket”和鹦鹉logo是Snikket Community Interest Company的商标。关于商标的更多信息,请访问<a href="
|
||||
"\"%(trademarks_url)s\">Snikket商标信息页面</a>。"
|
||||
|
||||
#: snikket_web/templates/about.html:19
|
||||
msgid "Software Versions"
|
||||
@@ -544,12 +551,11 @@ msgstr "警告"
|
||||
|
||||
#: snikket_web/templates/admin_debug_user.html:12
|
||||
msgid "The below dump may contain sensitive information."
|
||||
msgstr "Dump可能包括敏感信息"
|
||||
msgstr "调试信息中可能包括敏感信息。"
|
||||
|
||||
#: snikket_web/templates/admin_debug_user.html:15
|
||||
#, fuzzy
|
||||
msgid "Raw debug dump"
|
||||
msgstr "Debug信息"
|
||||
msgstr "原始调试信息"
|
||||
|
||||
#: snikket_web/templates/admin_debug_user.html:17
|
||||
msgid "Copy complete output"
|
||||
@@ -596,7 +602,7 @@ msgstr "这是你的主圈子"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:15
|
||||
msgid "This circle is managed automatically and cannot be removed or renamed."
|
||||
msgstr "此圈子由系统自动生成,无法被修改或删除"
|
||||
msgstr "此圈子由系统自动生成,无法被修改或删除。"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:17
|
||||
#: snikket_web/templates/admin_edit_circle.html:33
|
||||
@@ -636,7 +642,7 @@ msgstr "圈子成员"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
msgid "The user has been deleted from the server."
|
||||
msgstr "用户已从实例删除"
|
||||
msgstr "用户已从实例删除。"
|
||||
|
||||
#: snikket_web/templates/admin_edit_circle.html:71
|
||||
#: snikket_web/templates/library.j2:108
|
||||
@@ -698,7 +704,7 @@ msgstr "圈子"
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:35
|
||||
msgid "The user will not be added to any circle and will have no contacts."
|
||||
msgstr "此用户将不会有圈子和联系人"
|
||||
msgstr "此用户将不会有任何圈子和联系人。"
|
||||
|
||||
#: snikket_web/templates/admin_edit_invite.html:40
|
||||
msgid "Contact"
|
||||
@@ -744,7 +750,7 @@ msgstr "编辑用户"
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:26
|
||||
msgid "The login name cannot be changed."
|
||||
msgstr "账号无法修改"
|
||||
msgstr "登录账号无法被修改。"
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:33
|
||||
msgid ""
|
||||
@@ -755,7 +761,7 @@ msgstr "权限级别控制此Sknikket实例的用户能发起交流的范围。"
|
||||
#: snikket_web/templates/admin_edit_user.html:40
|
||||
#, python-format
|
||||
msgid "<strong>%(title)s%(icon)s</strong><p>%(description)s</p>"
|
||||
msgstr ""
|
||||
msgstr "<strong>%(title)s%(icon)s</strong><p>%(description)s</p>"
|
||||
|
||||
#: snikket_web/templates/admin_edit_user.html:50
|
||||
msgid "Return to user list"
|
||||
@@ -807,7 +813,7 @@ msgstr "用户"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:11
|
||||
msgid "Create password reset links or delete users."
|
||||
msgstr "创建密码重置链接或删除用户"
|
||||
msgstr "创建密码重置链接或删除用户。"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:15
|
||||
#: snikket_web/templates/admin_users.html:4
|
||||
@@ -837,7 +843,7 @@ msgstr "系统健康状况"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:38
|
||||
msgid "View the server status or send a broadcast message to all users."
|
||||
msgstr "查看服务器状态或向所有用户发布广播消息"
|
||||
msgstr "查看服务器状态或向所有用户发布广播消息。"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:40
|
||||
msgid "Send a broadcast message to all users."
|
||||
@@ -850,7 +856,7 @@ msgstr "系统管理"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:48
|
||||
msgid "Go back to your user's web portal page."
|
||||
msgstr "返回用户门户页面"
|
||||
msgstr "返回用户门户页面。"
|
||||
|
||||
#: snikket_web/templates/admin_home.html:50
|
||||
msgid "Exit admin panel"
|
||||
@@ -882,7 +888,7 @@ msgstr "删除邀请"
|
||||
|
||||
#: snikket_web/templates/admin_invites.html:57
|
||||
msgid "Currently, there are no pending invitations."
|
||||
msgstr "当前没有待定邀请"
|
||||
msgstr "当前没有待定邀请。"
|
||||
|
||||
#: snikket_web/templates/admin_reset_user_password.html:8
|
||||
msgid "Password reset"
|
||||
@@ -987,7 +993,7 @@ msgstr "此用户是管理员。"
|
||||
|
||||
#: snikket_web/templates/admin_users.html:19
|
||||
msgid " (Administrator)"
|
||||
msgstr "(管理员)"
|
||||
msgstr " (管理员)"
|
||||
|
||||
#: snikket_web/templates/admin_users.html:22
|
||||
msgid "The user is restricted."
|
||||
@@ -995,7 +1001,7 @@ msgstr "此用户受到限制。"
|
||||
|
||||
#: snikket_web/templates/admin_users.html:22
|
||||
msgid " (Restricted)"
|
||||
msgstr "(受限)"
|
||||
msgstr " (受限)"
|
||||
|
||||
#: snikket_web/templates/app.html:4
|
||||
msgid "Snikket Web Portal"
|
||||
@@ -1040,7 +1046,7 @@ msgstr "邀请到 %(site_name)s"
|
||||
#: snikket_web/templates/invite_view.html:14
|
||||
#, python-format
|
||||
msgid "Powered by <img src=\"%(logo_url)s\" alt=\"Snikket\">"
|
||||
msgstr ""
|
||||
msgstr "由<img alt=\"Snikket\" src=\"%(logo_url)s\">强力驱动"
|
||||
|
||||
#: snikket_web/templates/invite_invalid.html:8
|
||||
msgid "Invite expired"
|
||||
@@ -1131,7 +1137,7 @@ msgstr "在线重置密码"
|
||||
msgid ""
|
||||
"To reset your password online, fill out the fields below and confirm using the "
|
||||
"button."
|
||||
msgstr "填写信息并提交来重置密码"
|
||||
msgstr "填写信息并使用下面的按钮提交来在线重置密码。"
|
||||
|
||||
#: snikket_web/templates/invite_reset_success.html:5
|
||||
msgid "Password reset successful | Snikket"
|
||||
@@ -1300,6 +1306,8 @@ msgid ""
|
||||
"Install the Snikket App on your Android device (<a href=\"%(ios_info_url)s\" "
|
||||
"rel=\"noopener noreferrer\" target=\"_blank\">iOS coming soon!</a>)."
|
||||
msgstr ""
|
||||
"在你的Android设备上安装Snikket App(<a href=\"%(ios_info_url)s\" rel=\"noopener "
|
||||
"noreferrer\" target=\"_blank\">iOS 版本即将到来!</a>)。"
|
||||
|
||||
#: snikket_web/templates/invite_view.html:28
|
||||
msgid "Get it on Google Play"
|
||||
|
||||
@@ -13,7 +13,7 @@ from quart import (
|
||||
flash,
|
||||
current_app,
|
||||
)
|
||||
import quart.exceptions
|
||||
import werkzeug.exceptions
|
||||
|
||||
import wtforms
|
||||
|
||||
@@ -96,7 +96,7 @@ async def index() -> str:
|
||||
|
||||
@bp.route('/passwd', methods=["GET", "POST"])
|
||||
@client.require_session()
|
||||
async def change_pw() -> typing.Union[str, quart.Response]:
|
||||
async def change_pw() -> typing.Union[str, werkzeug.Response]:
|
||||
form = ChangePasswordForm()
|
||||
if form.validate_on_submit():
|
||||
try:
|
||||
@@ -104,8 +104,8 @@ async def change_pw() -> typing.Union[str, quart.Response]:
|
||||
form.current_password.data,
|
||||
form.new_password.data,
|
||||
)
|
||||
except (quart.exceptions.Unauthorized,
|
||||
quart.exceptions.Forbidden):
|
||||
except (werkzeug.exceptions.Unauthorized,
|
||||
werkzeug.exceptions.Forbidden):
|
||||
# server refused current password, set an appropriate error
|
||||
form.current_password.errors.append(
|
||||
_("Incorrect password."),
|
||||
@@ -128,7 +128,7 @@ EAVATARTOOBIG = _l(
|
||||
|
||||
@bp.route("/profile", methods=["GET", "POST"])
|
||||
@client.require_session()
|
||||
async def profile() -> typing.Union[str, quart.Response]:
|
||||
async def profile() -> typing.Union[str, werkzeug.Response]:
|
||||
max_avatar_size = current_app.config["MAX_AVATAR_SIZE"]
|
||||
|
||||
form = ProfileForm()
|
||||
@@ -221,7 +221,7 @@ async def manage_data() -> typing.Union[str, quart.Response]:
|
||||
|
||||
@bp.route("/logout", methods=["GET", "POST"])
|
||||
@client.require_session()
|
||||
async def logout() -> typing.Union[quart.Response, str]:
|
||||
async def logout() -> typing.Union[werkzeug.Response, str]:
|
||||
form = LogoutForm()
|
||||
if form.validate_on_submit():
|
||||
await client.logout()
|
||||
|
||||
@@ -4,7 +4,7 @@ import typing
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from quart import abort
|
||||
import quart.exceptions
|
||||
import werkzeug.exceptions
|
||||
|
||||
|
||||
TAG_XMPP_ERROR = "error"
|
||||
@@ -239,7 +239,7 @@ def extract_pubsub_item_get_reply(
|
||||
) -> typing.Optional[ET.Element]:
|
||||
try:
|
||||
pubsub = extract_iq_reply(iq_tree, TAG_PUBSUB)
|
||||
except quart.exceptions.NotFound:
|
||||
except werkzeug.exceptions.NotFound:
|
||||
return None
|
||||
|
||||
if pubsub is None:
|
||||
|
||||
Reference in New Issue
Block a user