From 0e15d6812335ff0208bd603358b67b086ccb6685 Mon Sep 17 00:00:00 2001 From: ljf Date: Fri, 19 Feb 2021 00:14:04 +0100 Subject: [PATCH] i18n + custom settings --- README.md | 40 ++++++++++++------- assets/canceled.html | 10 ++--- assets/favicon.ico | Bin 7407 -> 0 bytes assets/index.html | 25 ++++++------ assets/index.js | 24 +++--------- assets/logo.png | Bin 14329 -> 0 bytes assets/success.html | 10 ++--- babel.cfg | 3 ++ locales/en/LC_MESSAGES/messages.po | 54 ++++++++++++++++++++++++++ locales/fr/LC_MESSAGES/messages.po | 54 ++++++++++++++++++++++++++ requirements.txt | 1 + server.py | 59 ++++++++++++++++------------- 12 files changed, 200 insertions(+), 80 deletions(-) delete mode 100644 assets/favicon.ico delete mode 100644 assets/logo.png create mode 100644 babel.cfg create mode 100644 locales/en/LC_MESSAGES/messages.po create mode 100644 locales/fr/LC_MESSAGES/messages.po diff --git a/README.md b/README.md index eccf0d7..d2107b7 100644 --- a/README.md +++ b/README.md @@ -22,25 +22,37 @@ source venv/bin/activate pip3 install requirements.txt ``` -Create a .env file with : +Create a settings.py file with : ``` -PORT=8000 -DEBUG=True -PROJECT_NAME=YunoHost -DOMAIN=http://localhost:8000 -STATIC_DIR=assets -SECRET_CSRF_KEY=TO_CHANGE +ENV = 'development' +PORT = 8000 +DOMAIN = 'http://localhost:8000' +SECRET_KEY = '712AZPOC87HXD5SQSb12rd' +SECRET_CSRF_KEY = '712AZPOC87HXD5SQSb12' +LANGUAGES = ['en', 'fr'] +BABEL_TRANSLATION_DIRECTORIES = 'locales' + +# Customization +CUSTOM = {} +CUSTOM['name'] = 'YunoHost' +CUSTOM['contact_url'] = 'mailto:donate-6521@yunohost.org' +CUSTOM['logo'] = 'https://yunohost.org/user/images/logo.png' +CUSTOM['favicon'] = 'https://yunohost.org/user/themes/yunohost-docs/images/favicon.png' +CUSTOM['currencies'] = [ + ('EUR', '€'), + ('USD', '$') +] # Stripe keys -STRIPE_PUBLISHABLE_KEY=pk_test_gOgGjacs9YfvDJY03BRZ576O -STRIPE_SECRET_KEY=TO_REPLACE_BY_THE_GOOD_VALUE +CUSTOM['stripe_publishable_key'] = 'pk_test_gOgGjacs9YfvDJY03BRZ576O' +STRIPE_SECRET_KEY = 'sk_test_' # Stripe subscription data -ONE_TIME_EUR_DONATION=price_1IKuPVE7vOmTpJBiYMq7ztLH -RECURING_EUR_DONATION=price_1IKumjE7vOmTpJBikyqS2NqD - -ONE_TIME_USD_DONATION=price_1IKuQfE7vOmTpJBi0A3nRGCJ -RECURING_USD_DONATION=price_1IKumAE7vOmTpJBiO4CEfa3Q +DONATION={'one_time':{}, 'recuring': {}} +DONATION['one_time']['EUR'] = 'price_1IKuPVE7vOmTpJBiYMq7ztLH' +DONATION['one_time']['USD'] = 'price_1IKuQfE7vOmTpJBi0A3nRGCJ' +DONATION['recuring']['EUR'] = 'price_1IKumjE7vOmTpJBikyqS2NqD' +DONATION['recuring']['USD'] = 'price_1IKumAE7vOmTpJBiO4CEfa3Q' ``` ``` diff --git a/assets/canceled.html b/assets/canceled.html index 4a6ebfb..4befef3 100644 --- a/assets/canceled.html +++ b/assets/canceled.html @@ -4,9 +4,9 @@ - Donate to YunoHost + {{ _('Donate to %(name)s', name=name) }} - + @@ -14,10 +14,10 @@
- -

Your payment was canceled

+ +

{{ _('Your payment was canceled') }}

- +
diff --git a/assets/favicon.ico b/assets/favicon.ico deleted file mode 100644 index 49ffcee49484cfd1ed1ec2fc47fcf8f2ea0d1d08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7407 zcmeHL2UJu?7yj%O`zk9I6e~7VEUQMbp&(s~fby0uJi1_4SnQ%wjH0ncv7oFyvA5qC zP3+NVG#V2lAa(^5ySX#F3mnYD_5AJp=Vv_Q%)I;E`)21o?)TjXltTs7sRJ6TVr(U# zCjet(%{sj*u$r!!nQ7Ox088ra2tzI)826)rO^TX!?(6ObhoOUT?9f3d-JIb~Ju)Z& zKb=2^Wywjn{>xQNjta-Z*)#DxKOgt+<>1}BcW@du1Rf5yhzS+p>+Xu|%uHOqcmb{> ztnlH(2c)O1MNW1$UcGz?+d%_hNB!F!+sQs0Cy)OFlOw|sKY1cj7R<-fCy(JX$`$rQ z214`}aOd`ITs(IcZ{NPf`}glLa`;eeTK6@4J=`!MECiW%{=}n)4`4g6KU}PbVe|TR z_~X_soICv^CPjqd%H>PQxqBDm!$ibRh=$!@3+&#$6@gx!xN!DN(HWG@%1+?_`~*z2 zO|H<*_*kwIieHddYg9#E4A8#3tWU9}qCz)W(^^Fr6m?t6x|fOY)1)Y%qE|gx z&5lI@n|G4QWK~;f0gBo^WQLvF$xO9?#(jIr>euNZ>#DWO&1=Yv(xqtm&pv*ZXN{>_P-pp>w~Cs9|F6xn8`iAGjqBGC zO!+N3BnYWVi3l9yfyI>nM%j(P(Srx@{CPfhsxxpmI}1_4fjINSDZDHwKwe%h+-$6H zFDHj$Tt`;s9mIqLBV*%wis1<#%D*q3KgZVeO+5FpJnm*=4JXQ*y4)G+=Z)oylac%E z85}JKW6Sz9%9+36>gCHk$3A`X1oPtKcn+R2E)utH-rzYnNI3@YC=VY$au|;vJ;I#0 z>6lAhm(xWbC2>G7ZvJ{5=g*wRo7b=5Zf^q*>N$6_v2F7v{Ce#d1S!1`O#LPCLBMEt z&I@j~);MxtKXznn;kn(9@;l>)!~6CkH}@I&reo#OFNqsmIQJab^DUgMED<+xJnm*? zLA_}sRxeA%l}kV2t{48|YpR;@r9b;cWS-n_w*MGH9Zc@p={iJeyLL6=R- zPC)tuO#j7AG%+bHV#q+5PbmPgXQ#G-)*(_6#43($g#q@Wqa?*O8O5-pzyThV4bs zyQ-nWt7*w26z$mdy4Ex|6&rbWF1b5XQzw5i3vGszMWlZvn>fyl*@rbNY0$1k_t9jo z+u>tR9UvySkF!$Boj^@0+cjt=>CU5+Zq?rCGY9F+@Sm|TokArdl++7#N;O*OnpUU$ z{@YD3UXGm*gZ%tF93n2>vLOwZE}X~fSFbqtGrnJyx&#j&JmB1}(;2Kj4E6JYr=uNa zOqm46xs3mnuFhPST&22<)sCzldru?d*o2w!*u8BlZd|)YTE!ASe18H#!Wg)c-eKGw zOFhI_iNy;OaB%M)jCQo=wJFmPthS6C8-VPrOe{}HhT!6a*~H0j-@f76foU72A5I)Q z3O|ogyq0yOx|P+gYgc@Q#JRJvch^p=U$YANd3gx+_2%5p>e7OO7f4M`q#8JpYYo9= zBz`8H!D>>S_F=k+X|MUDDNddE4lbl!n0{f}h3Ps^2Rn*WfQUeUuGyIWm_24?{0 zn&bYxdw4*7r+NzL zS`5Oh zU_Zoy>$=s;mhyU^Y2T5g-I#u3n)1x4Q%Iga7t^Ue-%nc2-OdK*NI!=8`{K@@w~f z-P>I@>Ujd{|CMGWmw(Py<>i(~C_cksvw5%W5qjT29@jJ=V@F48J#S#N`it5s)$W0M z$FJwAQmLHlr|K79-oF`Wpm>N>5bet5;;4h)~MrL|sod6(It46hoR zWTnp!khj=n$njB;`r+#g%i#FkF?!*xU21CZj#Ks7j#@roqXysKx3@kHa-St5_L@QS|E3z6E%%r??LLGItSaY?+YVzlH9#v=9*r!N27|mLw1+9u0 zKgnA&pJp!wSI1Xds=@R(SIg@z9>fB^cZ8CT - Donate to YunoHost + {{ _('Donate to %(name)s', name=name) }} - + @@ -16,22 +16,25 @@
- -

I want to give to YunoHost

+ +

{{ _('I want to give to %(name)s', name=name) }}

+ + - + {% for iso, symbol in currencies %} +
- - + +

{{ _('If you want to stop a monthly donation contact us') }}

diff --git a/assets/index.js b/assets/index.js index c97a962..710bef1 100644 --- a/assets/index.js +++ b/assets/index.js @@ -1,24 +1,12 @@ -// Fetch your Stripe publishable key to initialize Stripe.js -// In practice, you might just hard code the publishable API -// key here. -fetch('/config') - .then(function (result) { - return result.json(); - }) - .then(function (json) { - window.config = json; - window.stripe = Stripe(config.publicKey); - }); +window.stripe = Stripe(document.getElementById('public_key').value); // When the form is submitted... var submitBtn = document.querySelector('#submit'); submitBtn.addEventListener('click', function (evt) { - var inputEl = document.getElementById('quantity'); - var quantity = parseInt(inputEl.value); - inputEl = document.getElementById('currency'); - var currency = inputEl.value; - inputEl = document.getElementById('frequency'); - var frequency = inputEl.value; + var quantity = parseInt(document.getElementById('quantity').value); + var currency = document.getElementById('currency').value; + var frequency = document.getElementById('frequency').value; + var csrf = document.getElementById('csrf').value; // Create the checkout session. fetch('/create-checkout-session', { @@ -27,7 +15,7 @@ submitBtn.addEventListener('click', function (evt) { 'Content-Type': 'application/json', }, body: JSON.stringify({ - user_csrf: window.config.csrf, + user_csrf: csrf, quantity: quantity, currency: currency, frequency: frequency diff --git a/assets/logo.png b/assets/logo.png deleted file mode 100644 index ff113c971df40064910d1d51883f6b4125077d85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14329 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

!VcJm#xG7fv4jEpn$RN8E_-YUF`+1gag z;N63`$Xjo*04Z#jH>UL$q`~?zrvRUw zbDmsF{W71N33MiH4;1mjpEJEQDAz*dWO^xb2uzOdmywxOL!nQfZ|0j0*|}*R8D10a zTjonINDTrkBCDob(fcy?x~yCWdn2+x$UG{o4>Kt^ULPc7mU++XfcK5e`(;ee)lK!G zYGgYaF;TtN?mq0v=s7d7PoJ);0y&G7Gm+x(HN*`cyh*9d4ler^bnnEkeN*N|fa4Jt z{TO-j__Ca-3c<@Gi(l)T?Tq6P+6TM_{~!&|6t0!+c%%aUD$>t?1o!~5>OPepHThMN z)`BUMGQRF*zV`fK#LPG!F%Nb#y~)cA)5diH>G%&lGwvazPn-I&7Q|`RA(O$crH#dK z2r+e^iCq9RZ&poPQ)u_lw$izu=VpBCNZ)I)-j(oM@;n3Efp^m8 z(8FAKgz4?-QUaxFlLg?{80Nuz3aKSig(1aHd|d?2KxVo3;pqV47162A_v%yOhCRI_+zFw z{ju=RTQ-k|SI$ytF}_P}xnT0>HOt|;1?fkO(Zb!sw7WLf%H`gL_b)~U$!q!9TS2E) zx;~~)O^ad0mGIIb6P(|M%(=V~xE?W+--FC+JOimjye$}3n{1w0TN-$~6l@V-|s-?Ki(PfabX5;uArs(Po?#gIrnWUT~0|n+4OUckF_qF7ne$# zlFj?JvzV_f@U7+zzRsbUE9{n_7N05E77(Y+iOe3|EXE|0zY zn)ep{9E>Sj2`-C|8oC~iY^`E35XYZHn|XJaFq=8vPxXW;Ddd(MIeD#TUAyIIm(a5C z=lHPFYCIm);>@L6&9e1{R(M=w9rix!aoTtmz~_Mf*?^Y~3U9p6d}$5p%}(fycd0GS zQWcHGW6i9H_&cj0dHYD_WJ_(ct!ZdT$!2}$&CH0uTWzxGG$l%0+e&9E?OaosBNU!5 zX84Ap`XG1fhnDbH+ERJ%!%r^3lS-4TEK+&ywHhgUUJI^6t!ycI*Q#tK5LXadp3P$Li*Jr zTahvp^3uDK(oJLvSxK$+d%z!-5?2rom8fYkEEw`LbzDh7OZ9s^+*%gvo7ABY-m}K% z&1~1av->p0yxb%4udTr?KKcXRQt=*N)^qJQ9-r3x+&9)c z4~KPK?XuM>VM-@z{=Z4PWlbLA3TKCZ7+>)&s-Tg2&MDH6nzB#+ - Donate to YunoHost + {{ _('Donate to %(name)s', name=name) }} - + @@ -14,10 +14,10 @@

- -

Thanks for your donation 🙂

+ +

{{ _('Thanks for your donation 🙂') }}

- +
diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000..0d3d70b --- /dev/null +++ b/babel.cfg @@ -0,0 +1,3 @@ +[python: server.py] +[jinja2: assets/**.html] +extensions=jinja2.ext.autoescape,jinja2.ext.with_ diff --git a/locales/en/LC_MESSAGES/messages.po b/locales/en/LC_MESSAGES/messages.po new file mode 100644 index 0000000..fa9e4e0 --- /dev/null +++ b/locales/en/LC_MESSAGES/messages.po @@ -0,0 +1,54 @@ +# English translations for PROJECT. +# Copyright (C) 2021 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2021-02-18 23:32+0100\n" +"PO-Revision-Date: 2021-02-18 23:33+0100\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.0\n" + +#: assets/canceled.html:7 assets/index.html:7 assets/success.html:7 +#, python-format +msgid "Donate to %(name)s" +msgstr "" + +#: assets/canceled.html:18 +msgid "Your payment was canceled" +msgstr "" + +#: assets/canceled.html:20 assets/success.html:20 +msgid "Go back to the donate form" +msgstr "" + +#: assets/index.html:20 +#, python-format +msgid "I want to give to %(name)s" +msgstr "" + +#: assets/index.html:31 +msgid "/ month" +msgstr "" + +#: assets/index.html:32 +msgid "one time" +msgstr "" + +#: assets/index.html:36 +msgid "Donate" +msgstr "" + +#: assets/success.html:18 +msgid "Thanks for your donation 🙂" +msgstr "" + diff --git a/locales/fr/LC_MESSAGES/messages.po b/locales/fr/LC_MESSAGES/messages.po new file mode 100644 index 0000000..b316e6c --- /dev/null +++ b/locales/fr/LC_MESSAGES/messages.po @@ -0,0 +1,54 @@ +# French translations for PROJECT. +# Copyright (C) 2021 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2021-02-18 23:32+0100\n" +"PO-Revision-Date: 2021-02-18 23:33+0100\n" +"Last-Translator: FULL NAME \n" +"Language: fr\n" +"Language-Team: fr \n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.9.0\n" + +#: assets/canceled.html:7 assets/index.html:7 assets/success.html:7 +#, python-format +msgid "Donate to %(name)s" +msgstr "Donner à %(name)s" + +#: assets/canceled.html:18 +msgid "Your payment was canceled" +msgstr "Votre paiement a été annulé" + +#: assets/canceled.html:20 assets/success.html:20 +msgid "Go back to the donate form" +msgstr "Retourner au formulaire de don" + +#: assets/index.html:20 +#, python-format +msgid "I want to give to %(name)s" +msgstr "Je veux donner à %(name)s" + +#: assets/index.html:31 +msgid "/ month" +msgstr "/ mois" + +#: assets/index.html:32 +msgid "one time" +msgstr "une fois" + +#: assets/index.html:36 +msgid "Donate" +msgstr "Donner" + +#: assets/success.html:18 +msgid "Thanks for your donation 🙂" +msgstr "Merci pour votre don 🙂" + diff --git a/requirements.txt b/requirements.txt index 00bc321..1956d56 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,3 +12,4 @@ stripe==2.47.0 toml==0.9.6 urllib3==1.25.3 flask-simple-csrf +flask-babel diff --git a/server.py b/server.py index 85497c2..eeb8920 100644 --- a/server.py +++ b/server.py @@ -13,25 +13,21 @@ import random import string from flask import Flask, render_template, jsonify, request, send_from_directory, session +from flask_babel import Babel, _ from flask_simple_csrf import CSRF -from dotenv import load_dotenv, find_dotenv -# Setup Stripe python client library. -load_dotenv(find_dotenv()) - -stripe.api_key = os.getenv('STRIPE_SECRET_KEY') -stripe.api_version = os.getenv('STRIPE_API_VERSION') - static_dir = str(os.path.abspath(os.path.join( - __file__, "..", os.getenv("STATIC_DIR")))) + __file__, "..", 'assets'))) app = Flask(__name__, static_folder=static_dir, static_url_path="", template_folder=static_dir) -app.secret_key = os.getenv('SECRET_KEY') +app.config.from_pyfile('settings.py') +stripe.api_key = app.config['STRIPE_SECRET_KEY'] CSRF = CSRF(config={ - 'SECRET_CSRF_KEY':os.getenv('SECRET_CSRF_KEY') + 'SECRET_CSRF_KEY': app.config['SECRET_CSRF_KEY'] }) app = CSRF.init_app(app) +babel = Babel(app) @app.before_request def before_request(): @@ -39,43 +35,52 @@ def before_request(): session['USER_CSRF'] = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(64)) session['CSRF_TOKEN'] = CSRF.create(session['USER_CSRF']) +@babel.localeselector +def get_locale(): + return 'fr' #request.accept_languages.best_match(app.config['LANGUAGES']) + @app.route('/', methods=['GET']) def get_index(): - return render_template('index.html') + return render_template('index.html', **app.config['CUSTOM'], + csrf=session['USER_CSRF']) -@app.route('/config', methods=['GET']) -def get_publishable_key(): - return jsonify({ - 'publicKey': os.getenv('STRIPE_PUBLISHABLE_KEY'), - 'name': os.getenv('PROJECT_NAME'), - 'csrf': session['USER_CSRF'], - }) +@app.route('/success', methods=['GET']) +def get_success(): + return render_template('success.html', **app.config['CUSTOM']) + + +@app.route('/canceled', methods=['GET']) +def get_canceled(): + return render_template('canceled.html', **app.config['CUSTOM']) + @app.route('/create-checkout-session', methods=['POST']) def create_checkout_session(): data = json.loads(request.data) - domain_url = os.getenv('DOMAIN') + domain_url = app.config['DOMAIN'] try: + donation = app.config['DONATION'] + currencies = [iso for iso, symbol in app.config['CUSTOM']['currencies']] if CSRF.verify(data['user_csrf'], session['CSRF_TOKEN']) is False or \ - data['frequency'] not in ['RECURING', 'ONE_TIME'] or \ - data['currency'] not in ['EUR', 'USD'] or \ + data['frequency'] not in ['recuring', 'one_time'] or \ + data['currency'] not in currencies or \ int(data['quantity']) <= 0: return jsonify(error="Bad value"), 400 # Create new Checkout Session for the order - price = f"{data['frequency']}_{data['currency']}_DONATION" - mode = "payment" if data['frequency'] == 'ONE_TIME' else "subscription" + price = donation[data['frequency']][data['currency']] + mode = "payment" if data['frequency'] == 'one_time' else "subscription" checkout_session = stripe.checkout.Session.create( success_url=domain_url + - "/success.html?session_id={CHECKOUT_SESSION_ID}", - cancel_url=domain_url + "/canceled.html", + "/success?session_id={CHECKOUT_SESSION_ID}", + cancel_url=domain_url + "/canceled", payment_method_types= ["card"], mode=mode, line_items=[ { - "price": os.getenv(price), + "price": price, "quantity": data['quantity'] } ] @@ -87,4 +92,4 @@ def create_checkout_session(): if __name__ == '__main__': - app.run(port=os.getenv('PORT'), debug=os.getenv('DEBUG')) + app.run(port=app.config['PORT'], debug=app.debug)