diff --git a/src/stacosys/i18n/messages.py b/src/stacosys/i18n/messages.py new file mode 100644 index 0000000..d64cbac --- /dev/null +++ b/src/stacosys/i18n/messages.py @@ -0,0 +1,17 @@ +import configparser +import os + + +class Messages: + def __init__(self): + self.property_dict = {} + + def load_messages(self, lang): + config = configparser.ConfigParser() + config.read(os.path.join(os.path.dirname(__file__), 'messages_' + lang + '.properties')) + + for key, value in config.items('messages'): + self.property_dict[key] = value + + def get(self, key): + return self.property_dict.get(key) diff --git a/src/stacosys/i18n/messages_en.properties b/src/stacosys/i18n/messages_en.properties new file mode 100644 index 0000000..85d02a7 --- /dev/null +++ b/src/stacosys/i18n/messages_en.properties @@ -0,0 +1,6 @@ +[messages] +login.failure.username=Username or password incorrect +logout.flash=You have been logged out. +admin.comment.notfound=Comment not found. +admin.comment.approved=Comment published. +admin.comment.deleted=Comment deleted. \ No newline at end of file diff --git a/src/stacosys/i18n/messages_fr.properties b/src/stacosys/i18n/messages_fr.properties new file mode 100644 index 0000000..9137863 --- /dev/null +++ b/src/stacosys/i18n/messages_fr.properties @@ -0,0 +1,6 @@ +[messages] +login.failure.username=Identifiant ou mot de passe incorrect +logout.flash=Vous avez été déconnecté. +admin.comment.notfound=Commentaire introuvable +admin.comment.approved=Commentaire publié +admin.comment.deleted=Commentaire supprimé \ No newline at end of file diff --git a/src/stacosys/interface/templates/admin_en.html b/src/stacosys/interface/templates/admin_en.html new file mode 100644 index 0000000..59c8f19 --- /dev/null +++ b/src/stacosys/interface/templates/admin_en.html @@ -0,0 +1,64 @@ + + + + + +Stacosys Comment Moderation + + + +
+

Comment Moderation

+ +
+
+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+ {% for message in messages %} +

{{ message }}

+ {% endfor %} +
+ {% endif %} + {% endwith %} + + + + + + + + + + + + {% for comment in comments %} + + + + + + + + {% endfor %} + +
DateAuthorCommentArticleActions
{{ comment.created }}{{ comment.author_name }}{{ comment.content }}{{ comment.url }} +
+ + + +
+
+ + + +
+
+
+ + + diff --git a/src/stacosys/interface/templates/login_en.html b/src/stacosys/interface/templates/login_en.html new file mode 100644 index 0000000..6d81754 --- /dev/null +++ b/src/stacosys/interface/templates/login_en.html @@ -0,0 +1,42 @@ + + + + + +Stacosys + + + + +
+

Comment Moderation Login

+
+
+ {% with messages = get_flashed_messages() %} + {% if messages %} +
+ {% for message in messages %} +

{{ message }}

+ {% endfor %} +
+ {% endif %} + {% endwith %} +
+

+

+

+

+ +
+
+ + + diff --git a/src/stacosys/interface/web/admin.py b/src/stacosys/interface/web/admin.py index 64aa3da..9b8c0ef 100644 --- a/src/stacosys/interface/web/admin.py +++ b/src/stacosys/interface/web/admin.py @@ -37,8 +37,7 @@ def login(): if is_login_ok(username, password): session["user"] = username return redirect("/web/admin") - # TODO localization - flash("Identifiant ou mot de passe incorrect") + flash(app.config["MESSAGES"].get("login.failure.username")) return redirect("/web/login") # GET return render_template( @@ -49,6 +48,7 @@ def login(): @app.route("/web/logout", methods=["GET"]) def logout(): session.pop("user") + flash(app.config["MESSAGES"].get("logout.flash")) return redirect("/web/admin") @@ -58,8 +58,6 @@ def admin_homepage(): "user" in session and session["user"] == app.config["CONFIG"].get(ConfigParameter.WEB_USERNAME) ): - # TODO localization - flash("Vous avez été déconnecté.") return redirect("/web/login") comments = dao.find_not_published_comments() @@ -74,15 +72,12 @@ def admin_homepage(): def admin_action(): comment = dao.find_comment_by_id(request.form.get("comment")) if comment is None: - # TODO localization - flash("Commentaire introuvable") + flash(app.config["MESSAGES"].get("admin.comment.notfound")) elif request.form.get("action") == "APPROVE": dao.publish_comment(comment) app.config["RSS"].generate() - # TODO localization - flash("Commentaire publié") + flash(app.config["MESSAGES"].get("admin.comment.approved")) else: dao.delete_comment(comment) - # TODO localization - flash("Commentaire supprimé") + flash(app.config["MESSAGES"].get("admin.comment.deleted")) return redirect("/web/admin") diff --git a/src/stacosys/run.py b/src/stacosys/run.py index 5634764..255c424 100644 --- a/src/stacosys/run.py +++ b/src/stacosys/run.py @@ -7,6 +7,7 @@ import os import sys from stacosys.db import database +from stacosys.i18n.messages import Messages from stacosys.interface import api, app, form from stacosys.interface.web import admin from stacosys.service.configuration import Config, ConfigParameter @@ -64,6 +65,12 @@ def configure_rss(config): return rss +def configure_localization(config): + messages = Messages() + messages.load_messages(config.get(ConfigParameter.LANG)) + return messages + + def main(config_pathname): logger = configure_logging() config = load_and_validate_config(config_pathname, logger) @@ -72,11 +79,13 @@ def main(config_pathname): logger.info("Start Stacosys application") rss = configure_rss(config) mailer = configure_and_validate_mailer(config, logger) + messages = configure_localization(config) logger.info("start interfaces %s %s %s", api, form, admin) app.config["CONFIG"] = config app.config["MAILER"] = mailer app.config["RSS"] = rss + app.config["MESSAGES"] = messages app.run( host=config.get(ConfigParameter.HTTP_HOST), port=config.get_int(ConfigParameter.HTTP_PORT), diff --git a/src/stacosys/service/mail.py b/src/stacosys/service/mail.py index 4e52228..6aa9470 100644 --- a/src/stacosys/service/mail.py +++ b/src/stacosys/service/mail.py @@ -38,21 +38,22 @@ class Mailer: def send(self, subject: str, message: str) -> bool: sender = self._smtp_login - receivers = [self._site_admin_email] - - msg = MIMEText(message) - msg["Subject"] = subject - msg["To"] = self._site_admin_email - msg["From"] = sender try: + msg = MIMEText(message) + msg["Subject"] = subject + msg["From"] = sender + msg["To"] = self._site_admin_email + with SMTP_SSL(self._smtp_host, self._smtp_port) as server: - server.login(self._smtp_login, self._smtp_password) - server.send_message(msg, sender, receivers) + try: + server.login(self._smtp_login, self._smtp_password) + except SMTPAuthenticationError: + logger.exception("Invalid credentials") + return False + + server.send_message(msg) return True - except SMTPAuthenticationError: - logger.exception("Invalid credentials") - return False - except Exception as e: - logger.exception(f"Error sending email: {e}") - return False + except Exception: + logger.error("Error sending email", exc_info=True) + return False diff --git a/src/stacosys/service/rssfeed.py b/src/stacosys/service/rssfeed.py index 069448f..9c9ebe0 100644 --- a/src/stacosys/service/rssfeed.py +++ b/src/stacosys/service/rssfeed.py @@ -52,5 +52,5 @@ class Rss: lastBuildDate=datetime.now(), items=items, ) - # pylint: disable=consider-using-with - rss.write_xml(open(self._rss_file, "w", encoding="utf-8"), encoding="utf-8") + with open(self._rss_file, "w", encoding="utf-8") as outfile: + rss.write_xml(outfile, encoding="utf-8")