diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-10-11 16:15:15 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-10-11 16:15:15 +0200 |
commit | aa06ddd3cf1de03922fc4e45e46ef3476a69e3f8 (patch) | |
tree | c1b72c6ac23d657b0ca0eddf7078813731333cef /talermerchantdemos/donations/donations.py | |
parent | 449f1d5765ffffcf2c708f4ccf6278e9c79081d0 (diff) | |
download | taler-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.py | 115 |
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") + ) |