diff --git a/i18n/de-DE.json b/i18n/de-DE.json new file mode 100644 index 0000000..619566d --- /dev/null +++ b/i18n/de-DE.json @@ -0,0 +1,50 @@ +{ + "html_language": "de", + "browser_language": "de-DE", + "ok": "ok", + "cancel": "abbrechen", + "dashboard": "dashboard", + "username": "benutzername", + "password": "passwort", + "login": "login", + "logout": "abmelden", + "comments": "kommentare", + "unpublished": "unveröffentlicht", + "published": "veröffentlicht", + "spam": "spam", + "edit": "editieren", + "manage": "verwalten", + "export": "export", + "delete": "löschen", + "new": "neu", + "project": "projekt", + "new_project": "neues projekt", + "statistics": "statistiken", + "address": "adresse", + "status": "status", + "manage_mail": "Mail Addressen verwalten", + "manage_comments": "Kommentare verwalten", + "manage_comments_delete_comment": "Diesen Kommentar löschen", + "manage_comments_delete_and_block": "Diesen Kommentar löschen und EMail Adresse blocken.", + "manage_comments_allow_comment": "Diesen Kommentar erlauben, aber Email Adresse nicht freischalten.", + "manage_comments_allow_and_approve": "Diesen Kommentar erlauben und Email Adresse freischalten.", + "manage_spam": "Spam verwalten", + "select_article": "Artikel auswählen", + "hooray_no_spam": "Hurra, kein Spam!", + "spam_score": "Spamerkennung", + "tooltip_spam_score": "Je höher der Spam Wert ist, desto höher die Chance, dass es sich um Spam handelt.", + "stats_label_regular_comments": "reguläre Kommentare", + "stats_label_unpublished_comments": "unveröffentlichte Kommentare", + "stats_last_7_days": "Aktivität der letzten 7 Tage", + "stats_total_percentage": "Verhältnis von Kommentaren zu Spam", + "select_project_to_manage": "Projekte:", + "tooltip_create_new_project": "Neues Projekt erzeugen", + "tooltip_delete_project": "Projekt und dazugehörige Daten löschen", + "tooltip_edit_project": "Einstellungen und Daten des Projekts ändern", + "tooltip_export_all_comments": "Alle Kommentare nach Hugo exportieren.
Wird normalerweise nicht benötigt.", + "tooltip_manage_this_project": "Dieses Projekt verwalten", + "placeholder_search_mail": "Mail Adressen durchsuchen", + "tooltip_email_blocked": "Email ist momentan gesperrt. Zum entsperren klicken.", + "tooltip_email_allowed": "Email darf momentan ohne Bestätigung posten. Zum Sperren klicken.", + "tooltip_delete_email": "Eintrag löschen. Email unterliegt wieder den normalen Regeln." +} diff --git a/i18n/en-US.json b/i18n/en-US.json new file mode 100644 index 0000000..bceb0fe --- /dev/null +++ b/i18n/en-US.json @@ -0,0 +1,49 @@ +{ + "html_language": "en", + "browser_language": "en-US", + "ok": "ok", + "cancel": "cancel", + "dashboard": "dashboard", + "username": "username", + "password": "password", + "login": "login", + "logout": "logout", + "comments": "comments", + "unpublished": "unpublished", + "published": "published", + "spam": "spam", + "edit": "edit", + "manage": "manage", + "export": "export", + "delete": "delete", + "new": "new", + "project": "project", + "new_project": "new project", + "statistics": "statistics", + "address": "address", + "status": "status", + "manage_mail": "manage mail addresses", + "stats_label_regular_comments": "regular comments", + "stats_label_unpublished_comments": "unpublished comments", + "stats_last_7_days": "Activity last 7 days", + "stats_total_percentage": "Total comment - spam ratio", + "manage_comments": "manage comments", + "manage_comments_delete_comment": "Delete this comment", + "manage_comments_delete_and_block": "Delete this comment and block mail address", + "manage_comments_allow_comment": "Approve this comment, don't approve mail", + "manage_comments_allow_and_approve": "Approve this comment and approve mail", + "select_article": "Select article", + "select_project_to_manage": "Projects", + "hooray_no_spam": "Hooray, no Spam!", + "spam_score": "score", + "tooltip_spam_score": "The higher the spam score is, the more likely it is spam", + "tooltip_create_new_project": "Create a new project", + "tooltip_delete_project": "Delete the project and all of its content", + "tooltip_edit_project": "Edit the name of the project and it's properties", + "tooltip_export_all_comments": "Export all comments to Hugo.
This is normally not needed.", + "tooltip_manage_this_project": "Manage this project", + "placeholder_search_mail": "Search mail", + "tooltip_email_blocked": "Email is currently blocked. Click to unblock.", + "tooltip_email_allowed": "Email is currently excempt from spam detection. Click to block.", + "tooltip_delete_email": "Delete entry, Email has to follow the regular rules." +} diff --git a/labertasche/__init__.py b/labertasche/__init__.py index 64d0aeb..af6d693 100644 --- a/labertasche/__init__.py +++ b/labertasche/__init__.py @@ -13,7 +13,8 @@ from labertasche import ( blueprints, helper, mail, - settings + settings, + language ) _all_ = [ @@ -22,5 +23,6 @@ _all_ = [ blueprints, helper, mail, - settings + settings, + language ] diff --git a/labertasche/language/__init__.py b/labertasche/language/__init__.py new file mode 100644 index 0000000..379c629 --- /dev/null +++ b/labertasche/language/__init__.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# /********************************************************************************** +# * _author : Domeniko Gentner +# * _mail : code@tuxstash.de +# * _repo : https://git.tuxstash.de/gothseidank/labertasche +# * _license : This project is under MIT License +# *********************************************************************************/ +from flask import Request +from pathlib import Path +from json import load + + +class Language: + + def __init__(self, request: Request): + # Define data + self.i18n = dict() + self.languages = list() + + # Directory where translations live + i18n_dir = Path('./i18n').absolute() + + # Looks for translations + for filename in i18n_dir.glob("*.json"): + if filename.is_file(): + self.languages.append(filename.stem) + + # Check the browser language in the headers + self.browser_language = request.accept_languages.best_match(self.languages, default="en-US") + + # Try to Load language accepted by browser + try: + file = i18n_dir / self.browser_language + with file.with_suffix(".json").absolute().open('r', encoding='utf-8') as fp: + foreign = load(fp) + except FileNotFoundError: + pass + + # Always load english + file = i18n_dir / "en-US" + with file.with_suffix(".json").absolute().open('r', encoding='utf-8') as fp: + self.i18n = load(fp) + + # Merge dicts, so missing keys are replaced with English + self.i18n.update(**foreign) + diff --git a/server.py b/server.py index de90ce4..4bcf344 100644 --- a/server.py +++ b/server.py @@ -9,11 +9,12 @@ # noinspection PyProtectedMember from sqlalchemy.engine import Engine from logging import getLogger, ERROR as LOGGING_ERROR -from flask import Flask, redirect, url_for +from flask import Flask, redirect, url_for, request from flask_cors import CORS from sqlalchemy import event, inspect from labertasche.settings import Settings, Secret from labertasche.database import labertasche_db +from labertasche.language import Language from labertasche.blueprints import bp_comments, bp_login, bp_dashboard, bp_jsconnector, bp_dbupgrades from labertasche.helper import User from flask_login import LoginManager @@ -36,15 +37,13 @@ laberflask.config.update(dict( SECRET_KEY=secret.key, TEMPLATES_AUTO_RELOAD=settings.debug, SQLALCHEMY_DATABASE_URI=settings.database_uri, - SQLALCHEMY_TRACK_MODIFICATIONS=False + SQLALCHEMY_TRACK_MODIFICATIONS=False, + JSON_AS_ASCII=False )) # Mark secret for deletion del secret -# CORS -cors = CORS(laberflask) - # Import blueprints laberflask.register_blueprint(bp_comments) laberflask.register_blueprint(bp_dashboard) @@ -70,6 +69,10 @@ with laberflask.app_context(): labertasche_db.create_all() +# CORS +cors = CORS(laberflask) + + # There is only one user @loginmgr.user_loader def user_loader(user_id): @@ -92,3 +95,10 @@ def set_sqlite_pragma(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("PRAGMA journal_mode=WAL;") cursor.close() + + +# Inject i18n dictionaries into all templates +@laberflask.context_processor +def inject_language(): + lang = Language(request) + return {"i18n": lang.i18n} diff --git a/templates/base.html b/templates/base.html index 303804a..63e9f68 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,5 +1,5 @@ - + @@ -8,33 +8,47 @@ - labertasche Dashboard + Labertasche {{ i18n['dashboard'] | capitalize }} - + @@ -55,6 +69,11 @@ if (urlParams.get("error") === "404"){ show_modal('modal-project-not-found'); } + + tippy('[data-tippy-content]', { + allowHTML: true, + delay: 500 + }); {% block javascript %} {% endblock %} }); diff --git a/templates/login.html b/templates/login.html index 1f60757..0f63287 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,5 +1,5 @@ - + @@ -7,29 +7,28 @@ - - labertasche Dashboard + Labertasche {{ i18n['dashboard'] | capitalize }}
+ class="button is-info is-inverted is-medium ml-1 mt-1 my-shadow-subtle"> - Download + Github
-

Labertasche Login

+

Labertasche {{ i18n['login'] | capitalize }}

@@ -39,7 +38,7 @@
@@ -52,6 +51,5 @@
- diff --git a/templates/manage-comments.html b/templates/manage-comments.html index 8514d48..0cf713b 100644 --- a/templates/manage-comments.html +++ b/templates/manage-comments.html @@ -1,14 +1,18 @@ {% extends "base.html" %} {% block main %}
-

{{ title }}

+ {% if action == "spam" %} +

{{ i18n['manage_spam'] }}

+ {% else %} +

{{ i18n['manage_comments'] }}

+ {% endif %}