diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-10-11 13:29:45 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-10-11 13:29:45 +0200 |
commit | 1ae0306a3cf2ea27f60b2d205789994d260c2cce (patch) | |
tree | 53117a55c27601e92172ea82f1d8cd11d355c06c /talermerchantdemos/blog/blog.py | |
parent | 2e665813a44988bfd906c0fab773f82652047841 (diff) | |
download | taler-merchant-demos-1ae0306a3cf2ea27f60b2d205789994d260c2cce.tar.gz taler-merchant-demos-1ae0306a3cf2ea27f60b2d205789994d260c2cce.tar.bz2 taler-merchant-demos-1ae0306a3cf2ea27f60b2d205789994d260c2cce.zip |
add i18n FSFS
Diffstat (limited to 'talermerchantdemos/blog/blog.py')
-rw-r--r-- | talermerchantdemos/blog/blog.py | 151 |
1 files changed, 62 insertions, 89 deletions
diff --git a/talermerchantdemos/blog/blog.py b/talermerchantdemos/blog/blog.py index c8315e5..7112b33 100644 --- a/talermerchantdemos/blog/blog.py +++ b/talermerchantdemos/blog/blog.py @@ -34,22 +34,8 @@ import sys from urllib.parse import urljoin, urlencode, urlparse from taler.util.talerconfig import TalerConfig, ConfigurationError from ..blog.content import ARTICLES, get_article_file, get_image_file -from talermerchantdemos.httpcommon import backend_get, backend_post, fallback_404 -from datetime import datetime - -class Deadline: - def __init__(self, value): - self.value = value - def isExpired(self): - if self.value == "never": - return False - now = int(round(time.time()) * 1000) - now_dt = datetime.fromtimestamp(now / 1000) - deadline_dt = datetime.fromtimestamp(self.value / 1000) - print("debug: checking refund expiration, now: {}, deadline: {}".format( - now_dt.strftime("%c"), deadline_dt.strftime("%c") - )) - return now > self.value +from talermerchantdemos.httpcommon import backend_get, backend_post, self_localized, err_abort, Deadline + def refundable(pay_status): refunded = pay_status.get("refunded") @@ -99,24 +85,6 @@ translations.append('en') print("Operating with the following translations available:") print(translations) - -## -# Helper function used inside Jinja2 logic to create a links -# to the current page but in a different language. Used to -# implement the "Language" menu. -# -def self_localized(lang): - """ - Return URL for the current page in another locale. - """ - path = request.path - # path must have the form "/$LANG/$STUFF" - parts = path.split('/', 2) - if (2 >= len(parts)): - # Totally unexpected path format, do not localize - return path - return "/" + lang + "/" + parts[2] - app.jinja_env.globals.update(self_localized=self_localized) @@ -130,21 +98,10 @@ def utility_processor(): # These helpers will be available in templates def env(name, default=None): return os.environ.get(name, default) - return dict(env=env) ## -# Return a error response to the client. -# -# @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.j2", **params) - flask.abort(flask.make_response(t, abort_status_code)) - - -## # "Fallback" exception handler to capture all the unmanaged errors. # # @param e the Exception object, currently unused. @@ -153,7 +110,9 @@ def err_abort(abort_status_code, **params): @app.errorhandler(Exception) def internal_error(e): return flask.render_template( - "templates/error.html.j2", message=gettext("Internal error"), stack=traceback.format_exc() + "templates/error.html.j2", + message=gettext("Internal error"), + stack=traceback.format_exc() ) @@ -184,8 +143,15 @@ def get_locale(): # @return response object of the index page. @app.route("/<lang>/") def start(lang): + if lang in ARTICLES: + translated=ARTICLES[lang] + else: + translated={} return flask.render_template( - "templates/index.html.j2", lang=lang, merchant_currency=CURRENCY, articles=ARTICLES.values() + "templates/index.html.j2", + lang=lang, + merchant_currency=CURRENCY, + articles=translated.values() ) @@ -198,7 +164,7 @@ def confirm_refund(lang, order_id): order_status = pay_status.get("order_status") if order_status != "paid": err_abort( - 400, message="Cannot refund unpaid article", + 400, message=gettext("Cannot refund unpaid article"), ) article_name = pay_status["contract_terms"]["extra"]["article_name"] @@ -223,7 +189,7 @@ def confirm_refund(lang, order_id): # "refund URL" is returned; then the wallet will run # the refund protocol in a transparent way. @app.route("/refund/<order_id>", methods=["POST"]) -def refund(lang, order_id): +def refund(order_id): if not order_id: return flask.jsonify(dict(error="Aborting refund: order unknown")), 400 session_id = flask.session.get("session_id", "") @@ -234,11 +200,15 @@ def refund(lang, order_id): if order_status != "paid": err_abort( - 402, message="You did not pay for this article (nice try!)", json=pay_status + 402, + message=gettext("You did not pay for this article (nice try!)"), + json=pay_status ) if not refundable(pay_status): err_abort( - 403, message="Item not refundable (anymore)", json=pay_status + 403, + message=gettext("Item not refundable (anymore)"), + json=pay_status ) refund_spec = dict(reason="Demo reimbursement", refund=ARTICLE_AMOUNT) resp = backend_post(BACKEND_URL, f"private/orders/{order_id}/refund", refund_spec) @@ -249,6 +219,7 @@ def refund(lang, order_id): # Render the article after a successful purchase. # # @param article_name _slugged_ (= spaces converted to underscores) article title. +# @param lang language the article is to be in # @param data image filename to return along the article. # @param order_id the ID of the order where this article got purchased. # (Will be put in the refund-request form action, since any article @@ -258,15 +229,15 @@ def refund(lang, order_id): # - 404: supplemental @a data not found. # In the successful case, a response object carrying the # article in it will be returned. -def render_article(article_name, data, order_id, refundable): - article_info = ARTICLES.get(article_name) +def render_article(article_name, lang, data, order_id, refundable): + article_info = ARTICLES[lang].get(article_name) if article_info is None: - m = "Internal error: Files for article ({}) not found.".format(article_name) + m = gettext("Internal error: Files for article ({}) not found.").format(article_name) err_abort(500, message=m) if data is not None: if data in article_info.extra_files: return flask.send_file(get_image_file(data)) - m = "Supplemental file ({}) for article ({}) not found.".format( + m = gettext("Supplemental file ({}) for article ({}) not found.").format( data, article_name ) err_abort(404, message=m) @@ -276,6 +247,7 @@ def render_article(article_name, data, order_id, refundable): article_file=get_article_file(article_info), article_name=article_name, order_id=order_id, + lang=lang, refundable=refundable ) @@ -291,6 +263,7 @@ def post_order(article_name,lang): extra=dict(article_name=article_name,lang=lang), fulfillment_url=flask.request.base_url, summary="Essay: " + article_name.replace("_", " "), + # FIXME: add support for i18n of summary! # 10 minutes time for a refund wire_transfer_deadline=dict(t_ms=1000 * int(time.time() + 15 * 30)), ) @@ -300,25 +273,6 @@ def post_order(article_name,lang): dict(order=order, refund_delay=dict(d_ms=1000 * 120))) return order_resp -## -# Setup a fresh order with the backend. -# -# @param article_name which article the order is for -# @param lang which language to use -# -def post_order(article_name,lang): - order = dict( - amount=ARTICLE_AMOUNT, - extra=dict(article_name=article_name,lang=lang), - fulfillment_url=flask.request.base_url, - summary="Essay: " + article_name.replace("_", " "), - # 10 minutes time for a refund - refund_deadline=dict(t_ms=1000 * int(time.time() + 10 * 30)), - wire_transfer_deadline=dict(t_ms=1000 * int(time.time() + 15 * 30)), - ) - order_resp = backend_post(BACKEND_URL, "private/orders", dict(order=order)) - return order_resp - ## # Trigger a article purchase. The logic follows the main steps: @@ -356,23 +310,27 @@ def article(article_name, lang=None, data=None): # First-timer; generate order first. if not order_id: if not lang: - err_abort(403, message="Direct access forbidden") + err_abort(403, message=gettext("Direct access forbidden")) order_resp = post_order(article_name,lang) order_id = order_resp["order_id"] # Ask the backend for the status of the payment pay_status = backend_get( - BACKEND_URL, f"private/orders/{order_id}", params=dict(session_id=session_id) + BACKEND_URL, + f"private/orders/{order_id}", + params=dict(session_id=session_id) ) order_status = pay_status.get("order_status") if order_status == "claimed": if not lang: - err_abort(403, message="Direct access forbidden") + err_abort(403, message=gettext("Direct access forbidden")) # Order already claimed, must setup fresh order order_resp = post_order(article_name,lang) order_id = order_resp["order_id"] pay_status = backend_get( - BACKEND_URL, f"private/orders/{order_id}", params=dict(session_id=session_id) + BACKEND_URL, + f"private/orders/{order_id}", + params=dict(session_id=session_id) ) order_status = pay_status.get("order_status") # This really must be 'unpaid' now... @@ -385,12 +343,12 @@ def article(article_name, lang=None, data=None): article_name=article_name, order_id=order_id, ) - response = render_article(article_name, data, order_id, refundable(pay_status)) - response.set_cookie( - "order_id", order_id, path=urllib.parse.quote(f"/essay/{article_name}") - ) - response.set_cookie( - "order_id", order_id, path=urllib.parse.quote(f"/{lang}/essay/{article_name}") + response = render_article( + article_name, + lang, + data, + order_id, + refundable(pay_status) ) return response @@ -401,7 +359,14 @@ def article(article_name, lang=None, data=None): if ai is not None and au is not None: response = flask.redirect(au) response.set_cookie( - "order_id", ai, path=urllib.parse.quote(f"/essay/{article_name}") + "order_id", + ai, + path=urllib.parse.quote(f"/essay/{article_name}") + ) + response.set_cookie( + "order_id", + ai, + path=urllib.parse.quote(f"/{lang}/essay/{article_name}") ) return response @@ -409,19 +374,27 @@ def article(article_name, lang=None, data=None): # run the payment protocol. response = flask.redirect(pay_status["order_status_url"]) response.set_cookie( - "order_id", order_id, path=urllib.parse.quote(f"/essay/{article_name}") + "order_id", + order_id, + path=urllib.parse.quote(f"/essay/{article_name}") ) response.set_cookie( - "order_id", order_id, path=urllib.parse.quote(f"/{lang}/essay/{article_name}") + "order_id", + order_id, + path=urllib.parse.quote(f"/{lang}/essay/{article_name}") ) return response @app.errorhandler(500) def handler(e): return flask.render_template( - "templates/error.html.j2", message=gettext("Internal server error")) + "templates/error.html.j2", + message=gettext("Internal server error") + ) @app.errorhandler(404) def handler(e): return flask.render_template( - "templates/error.html.j2", message=gettext("Page not found")) + "templates/error.html.j2", + message=gettext("Page not found") + ) |