summaryrefslogtreecommitdiff
path: root/talermerchantdemos/donations/donations.py
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-10-11 16:15:15 +0200
committerChristian Grothoff <christian@grothoff.org>2020-10-11 16:15:15 +0200
commitaa06ddd3cf1de03922fc4e45e46ef3476a69e3f8 (patch)
treec1b72c6ac23d657b0ca0eddf7078813731333cef /talermerchantdemos/donations/donations.py
parent449f1d5765ffffcf2c708f4ccf6278e9c79081d0 (diff)
downloadtaler-merchant-demos-aa06ddd3cf1de03922fc4e45e46ef3476a69e3f8.tar.gz
taler-merchant-demos-aa06ddd3cf1de03922fc4e45e46ef3476a69e3f8.tar.bz2
taler-merchant-demos-aa06ddd3cf1de03922fc4e45e46ef3476a69e3f8.zip
add i18n and new menu structure to donations page
Diffstat (limited to 'talermerchantdemos/donations/donations.py')
-rw-r--r--talermerchantdemos/donations/donations.py115
1 files changed, 95 insertions, 20 deletions
diff --git a/talermerchantdemos/donations/donations.py b/talermerchantdemos/donations/donations.py
index 3f021f9..19fc235 100644
--- a/talermerchantdemos/donations/donations.py
+++ b/talermerchantdemos/donations/donations.py
@@ -1,6 +1,6 @@
##
# This file is part of GNU TALER.
-# Copyright (C) 2014-2016 INRIA
+# Copyright (C) 2014-2016, 2020 Taler Systems SA
#
# TALER is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
@@ -20,13 +20,18 @@
import base64
import logging
import flask
+from flask import request
+from flask_babel import Babel
+from flask_babel import refresh
+from flask_babel import force_locale
+from flask_babel import gettext
import os
import time
import traceback
import urllib
from taler.util.talerconfig import TalerConfig, ConfigurationError
from urllib.parse import urljoin
-from ..httpcommon import backend_post, backend_get, fallback_404
+from ..httpcommon import backend_post, backend_get, fallback_404, self_localized
import sys
if not sys.version_info.major == 3 and sys.version_info.minor >= 6:
@@ -52,6 +57,28 @@ except ConfigurationError as ce:
exit(1)
app.config.from_object(__name__)
+babel = Babel(app)
+
+
+LOGGER.info("Using translations from:" + ':'.join(list(babel.translation_directories)))
+translations = [str(translation) for translation in babel.list_translations()]
+if not 'en' in translations:
+ translations.append('en')
+LOGGER.info("Operating with the following translations available: " + ' '.join(translations))
+
+app.jinja_env.globals.update(self_localized=self_localized)
+
+
+@babel.localeselector
+def get_locale():
+ parts = request.path.split('/', 2)
+ if (2 >= len(parts)):
+ # Totally unexpected path format, do not localize
+ return "en"
+ lang = parts[1]
+ if lang in translations:
+ return lang
+ return "en"
##
@@ -73,7 +100,10 @@ def utility_processor():
# @param abort_status_code status code to return along the response.
# @param params _kw_ arguments to passed verbatim to the templating engine.
def err_abort(abort_status_code, **params):
- t = flask.render_template("templates/error.html", **params)
+ t = flask.render_template(
+ "templates/error.html.j2",
+ lang=get_locale(),
+ **params)
flask.abort(flask.make_response(t, abort_status_code))
@@ -110,7 +140,7 @@ def backend_instanced_post(instance, endpoint, json):
def expect_parameter(name):
val = flask.request.args.get(name)
if not val:
- return err_abort(400, message="parameter '{}' required".format(name))
+ return err_abort(400, message=gettext("parameter '{}' required").format(name))
return val
@@ -123,17 +153,47 @@ def expect_parameter(name):
@app.errorhandler(Exception)
def internal_error(e):
return flask.render_template(
- "templates/error.html", message="Internal error", stack=traceback.format_exc()
+ "templates/error.html.j2",
+ message=gettext("Internal error"),
+ lang=get_locale(),
+ stack=traceback.format_exc()
)
+##
+# Serve the /favicon.ico requests.
+#
+# @return the favicon.ico file.
+@app.route("/favicon.ico")
+def favicon():
+ LOGGER.info("will look into: " + os.path.join(app.root_path, 'static'))
+ return flask.send_from_directory(
+ os.path.join(app.root_path, 'static'),
+ "favicon.ico",
+ mimetype="image/vnd.microsoft.ico"
+ )
##
-# Serve the main index page.
+# Serve the main index page, redirecting to /<lang>/
#
# @return response object of the index page.
@app.route("/")
def index():
- return flask.render_template("templates/index.html", merchant_currency=CURRENCY)
+ default = 'en'
+ target = flask.request.accept_languages.best_match(translations, default)
+ return flask.redirect("/" + target + "/", code=302)
+
+
+##
+# Serve the main index page.
+#
+# @return response object of the index page.
+@app.route("/<lang>/")
+def start(lang):
+ return flask.render_template(
+ "templates/index.html.j2",
+ lang=lang,
+ merchant_currency=CURRENCY
+ )
##
@@ -151,16 +211,17 @@ def javascript_licensing():
# and finally confirm the donation.
#
# @return response object for the /checkout page.
-@app.route("/checkout", methods=["GET"])
-def checkout():
+@app.route("/<lang>/checkout", methods=["GET"])
+def checkout(lang):
amount = expect_parameter("donation_amount")
donation_receiver = expect_parameter("donation_receiver")
donation_donor = expect_parameter("donation_donor")
return flask.render_template(
- "templates/checkout.html",
+ "templates/checkout.html.j2",
donation_amount=amount,
donation_receiver=donation_receiver,
donation_donor=donation_donor,
+ lang=lang,
merchant_currency=CURRENCY,
)
@@ -170,9 +231,12 @@ def checkout():
# of further processing the payment method they chose.
#
# @return response object about the mentioned impossibility.
-@app.route("/provider-not-supported")
+@app.route("/<lang>/provider-not-supported")
def provider_not_supported():
- return flask.render_template("templates/provider-not-supported.html")
+ return flask.render_template(
+ "templates/provider-not-supported.html.j2",
+ lang=lang
+ )
##
@@ -182,17 +246,19 @@ def provider_not_supported():
# @return response object that will redirect the browser to
# the fulfillment URL, where all the pay-logic will
# happen.
-@app.route("/donate")
-def donate():
+@app.route("/<lang>/donate")
+def donate(lang):
donation_receiver = expect_parameter("donation_receiver")
donation_amount = expect_parameter("donation_amount")
donation_donor = expect_parameter("donation_donor")
payment_system = expect_parameter("payment_system")
if payment_system != "taler":
- return flask.redirect(flask.url_for("provider_not_supported"))
+ return flask.redirect(flask.url_for("provider_not_supported",
+ lang=lang))
fulfillment_url = flask.url_for(
"fulfillment",
timestamp=str(time.time()),
+ lang=lang,
receiver=donation_receiver,
_external=True,
)
@@ -200,7 +266,9 @@ def donate():
order = dict(
amount=donation_amount,
extra=dict(
- donor=donation_donor, receiver=donation_receiver, amount=donation_amount
+ donor=donation_donor,
+ receiver=donation_receiver,
+ amount=donation_amount
),
fulfillment_url=fulfillment_url,
summary="Donation to {}".format(donation_receiver),
@@ -211,7 +279,10 @@ def donate():
)
order_id = order_resp["order_id"]
return flask.redirect(
- flask.url_for("fulfillment", receiver=donation_receiver, order_id=order_id)
+ flask.url_for("fulfillment",
+ receiver=donation_receiver,
+ lang=lang,
+ order_id=order_id)
)
@@ -223,8 +294,8 @@ def donate():
# @return after the wallet sent the payment, the final HTML "congrats"
# page is returned; otherwise, the browser will be redirected
# to a page that accepts the payment.
-@app.route("/donation/<receiver>")
-def fulfillment(receiver):
+@app.route("/<lang>/donation/<receiver>")
+def fulfillment(lang,receiver):
order_id = expect_parameter("order_id")
pay_params = dict(order_id=order_id)
pay_status = backend_instanced_get(
@@ -239,6 +310,7 @@ def fulfillment(receiver):
donation_amount=extra["amount"],
donation_donor=extra["donor"],
order_id=order_id,
+ lang=lang,
currency=CURRENCY,
)
return flask.redirect(pay_status["order_status_url"])
@@ -246,4 +318,7 @@ def fulfillment(receiver):
@app.errorhandler(404)
def handler(e):
return flask.render_template(
- "templates/error.html", message="Page not found")
+ "templates/error.html.j2",
+ lang=get_locale(),
+ message=gettext("Page not found")
+ )