From 3b2e11ab6369dfa853383840dc28915b60c2d062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Fri, 5 Jan 2018 22:06:11 +0100 Subject: Include all .j2 files in the packaged version. I've also renamed the templates to *.j2 in order to make things clearer to others. Having extensions with the name of the locale doesn't seem to be a good practice, and would need us to add the locales in the MANIFEST file each time we add one. Fix #305 --- ihatemoney/templates/invitation_mail.en | 12 ------------ ihatemoney/templates/invitation_mail.en.j2 | 12 ++++++++++++ ihatemoney/templates/invitation_mail.fr | 11 ----------- ihatemoney/templates/invitation_mail.fr.j2 | 11 +++++++++++ ihatemoney/templates/password_reminder.en | 8 -------- ihatemoney/templates/password_reminder.en.j2 | 8 ++++++++ ihatemoney/templates/password_reminder.fr | 7 ------- ihatemoney/templates/password_reminder.fr.j2 | 7 +++++++ ihatemoney/templates/reminder_mail.en | 10 ---------- ihatemoney/templates/reminder_mail.en.j2 | 10 ++++++++++ ihatemoney/templates/reminder_mail.fr | 9 --------- ihatemoney/templates/reminder_mail.fr.j2 | 9 +++++++++ ihatemoney/web.py | 6 +++--- 13 files changed, 60 insertions(+), 60 deletions(-) delete mode 100644 ihatemoney/templates/invitation_mail.en create mode 100644 ihatemoney/templates/invitation_mail.en.j2 delete mode 100644 ihatemoney/templates/invitation_mail.fr create mode 100644 ihatemoney/templates/invitation_mail.fr.j2 delete mode 100644 ihatemoney/templates/password_reminder.en create mode 100644 ihatemoney/templates/password_reminder.en.j2 delete mode 100644 ihatemoney/templates/password_reminder.fr create mode 100644 ihatemoney/templates/password_reminder.fr.j2 delete mode 100644 ihatemoney/templates/reminder_mail.en create mode 100644 ihatemoney/templates/reminder_mail.en.j2 delete mode 100644 ihatemoney/templates/reminder_mail.fr create mode 100644 ihatemoney/templates/reminder_mail.fr.j2 (limited to 'ihatemoney') diff --git a/ihatemoney/templates/invitation_mail.en b/ihatemoney/templates/invitation_mail.en deleted file mode 100644 index eeaafdb..0000000 --- a/ihatemoney/templates/invitation_mail.en +++ /dev/null @@ -1,12 +0,0 @@ -Hi, - -Someone using the email address {{ g.project.contact_email }} invited you to share your expenses for "{{ g.project.name }}". - -It's as simple as saying what did you paid for, for who, and how much did it cost you, we are caring about the rest. - -You can log in using this link: {{ url_for(".authenticate", _external=True, token=g.project.generate_token()) }}. -Once logged in you can use the following link which is easier to remember: {{ url_for(".list_bills", _external=True) }} -If your cookie gets deleted or if you log out, you will need to log back in using the first link. - -Enjoy, -Some weird guys (with beards) diff --git a/ihatemoney/templates/invitation_mail.en.j2 b/ihatemoney/templates/invitation_mail.en.j2 new file mode 100644 index 0000000..42be0d2 --- /dev/null +++ b/ihatemoney/templates/invitation_mail.en.j2 @@ -0,0 +1,12 @@ +Hi, + +Someone using the email address {{ g.project.contact_email }} invited you to share your expenses for "{{ g.project.name }}". + +It's as simple as saying what did you pay for, for whom, and how much did it cost you, we are caring about the rest. + +You can log in using this link: {{ url_for(".authenticate", _external=True, token=g.project.generate_token()) }}. +Once logged-in, you can use the following link which is easier to remember: {{ url_for(".list_bills", _external=True) }} +If your cookie gets deleted or if you log out, you will need to log back in using the first link. + +Enjoy, +Some weird guys (with beards) diff --git a/ihatemoney/templates/invitation_mail.fr b/ihatemoney/templates/invitation_mail.fr deleted file mode 100644 index a95f9e9..0000000 --- a/ihatemoney/templates/invitation_mail.fr +++ /dev/null @@ -1,11 +0,0 @@ -Salut, - -Quelqu'un avec l'addresse email "{{ g.project.contact_email }}" vous à invité à partager vos dépenses pour "{{ g.project.name }}". - -C'est aussi simple que de dire qui à payé pour quoi, pour qui, et combien celà à coûté, on s'occuppe du reste. - -Vous pouvez vous authentifier avec le lien suivant: {{ url_for(".authenticate", _external=True, token=g.project.generate_token()) }}. -Une fois authentifié, vous pouvez utiliser le lien suivant qui est plus facile à mémoriser: {{ url_for(".list_bills", _external=True) }} -Si votre cookie est supprimé ou si vous vous déconnectez, voous devrez vous réauthentifier en utilisant le premier lien. - -Have fun, diff --git a/ihatemoney/templates/invitation_mail.fr.j2 b/ihatemoney/templates/invitation_mail.fr.j2 new file mode 100644 index 0000000..197edcc --- /dev/null +++ b/ihatemoney/templates/invitation_mail.fr.j2 @@ -0,0 +1,11 @@ +Salut, + +Quelqu'un avec l'adresse "{{ g.project.contact_email }}" vous à invité à partager vos dépenses pour "{{ g.project.name }}". + +C'est aussi simple que de dire qui à payé pour quoi, pour qui, et combien celà à coûté, on s’occupe du reste. + +Vous pouvez vous authentifier avec le lien suivant: {{ url_for(".authenticate", _external=True, token=g.project.generate_token()) }}. +Une fois authentifié, vous pouvez utiliser le lien suivant qui est plus facile à mémoriser: {{ url_for(".list_bills", _external=True) }} +Si votre cookie est supprimé ou si vous vous déconnectez, vous devrez vous authentifier à nouveau en utilisant le premier lien. + +Have fun, diff --git a/ihatemoney/templates/password_reminder.en b/ihatemoney/templates/password_reminder.en deleted file mode 100644 index bc7e609..0000000 --- a/ihatemoney/templates/password_reminder.en +++ /dev/null @@ -1,8 +0,0 @@ -Hi, - -You requested to reset the password of the following project: "{{ project.name }}". -You can reset it here: {{ url_for(".reset_password", _external=True, token=project.generate_token(expiration=3600)) }}. -This link is only valid for 1 hour. - -Hope this helps, -Some weird guys (with beards) diff --git a/ihatemoney/templates/password_reminder.en.j2 b/ihatemoney/templates/password_reminder.en.j2 new file mode 100644 index 0000000..c654354 --- /dev/null +++ b/ihatemoney/templates/password_reminder.en.j2 @@ -0,0 +1,8 @@ +Hi, + +You requested to reset the password of the following project: "{{ project.name }}". +You can reset it here: {{ url_for(".reset_password", _external=True, token=project.generate_token(expiration=3600)) }}. +This link is only valid for one hour. + +Hope this helps, +Some weird guys (with beards) diff --git a/ihatemoney/templates/password_reminder.fr b/ihatemoney/templates/password_reminder.fr deleted file mode 100644 index d4fbc2d..0000000 --- a/ihatemoney/templates/password_reminder.fr +++ /dev/null @@ -1,7 +0,0 @@ -Salut, - -Vous avez demandé à réinitialiser le mot de passe du projet suivant : "{{ project.name }}". -Vous pouvez le réinitialiser ici : {{ url_for(".reset_password", _external=True, token=project.generate_token(expiration=3600)) }}. -Ce lien est seulement valide pendant 1 heure. - -Faites en bon usage ! diff --git a/ihatemoney/templates/password_reminder.fr.j2 b/ihatemoney/templates/password_reminder.fr.j2 new file mode 100644 index 0000000..d4fbc2d --- /dev/null +++ b/ihatemoney/templates/password_reminder.fr.j2 @@ -0,0 +1,7 @@ +Salut, + +Vous avez demandé à réinitialiser le mot de passe du projet suivant : "{{ project.name }}". +Vous pouvez le réinitialiser ici : {{ url_for(".reset_password", _external=True, token=project.generate_token(expiration=3600)) }}. +Ce lien est seulement valide pendant 1 heure. + +Faites en bon usage ! diff --git a/ihatemoney/templates/reminder_mail.en b/ihatemoney/templates/reminder_mail.en deleted file mode 100644 index 8784d2a..0000000 --- a/ihatemoney/templates/reminder_mail.en +++ /dev/null @@ -1,10 +0,0 @@ -Hi, - -You have just (or someone else using your email address) created the project "{{ g.project.name }}" to share your expenses. - -You can access it here: {{ url_for(".list_bills", _external=True) }} (the identifier is {{ g.project.id }}). -If you want to share this project with your friends, you can share the identifier and the shared password with them or send them invitations with the following link: -{{ url_for(".invite", _external=True) }} - -Enjoy, -Some weird guys (with beards) diff --git a/ihatemoney/templates/reminder_mail.en.j2 b/ihatemoney/templates/reminder_mail.en.j2 new file mode 100644 index 0000000..8784d2a --- /dev/null +++ b/ihatemoney/templates/reminder_mail.en.j2 @@ -0,0 +1,10 @@ +Hi, + +You have just (or someone else using your email address) created the project "{{ g.project.name }}" to share your expenses. + +You can access it here: {{ url_for(".list_bills", _external=True) }} (the identifier is {{ g.project.id }}). +If you want to share this project with your friends, you can share the identifier and the shared password with them or send them invitations with the following link: +{{ url_for(".invite", _external=True) }} + +Enjoy, +Some weird guys (with beards) diff --git a/ihatemoney/templates/reminder_mail.fr b/ihatemoney/templates/reminder_mail.fr deleted file mode 100644 index e73938a..0000000 --- a/ihatemoney/templates/reminder_mail.fr +++ /dev/null @@ -1,9 +0,0 @@ -Hey, - -Vous venez de créer le projet "{{ g.project.name }}" pour partager vos dépenses. - -Vous pouvez y accéder ici: {{ url_for(".list_bills", _external=True) }} (l'identifieur est {{ g.project.id }}). -Si vous voulez partager ce projet avec vos amis, vous pouvez partager son identifiant et son code d'accès avec eux ou leur envoyer une invitation avec le lien suivant : -{{ url_for(".invite", _external=True) }} - -Faites en bon usage ! diff --git a/ihatemoney/templates/reminder_mail.fr.j2 b/ihatemoney/templates/reminder_mail.fr.j2 new file mode 100644 index 0000000..e73938a --- /dev/null +++ b/ihatemoney/templates/reminder_mail.fr.j2 @@ -0,0 +1,9 @@ +Hey, + +Vous venez de créer le projet "{{ g.project.name }}" pour partager vos dépenses. + +Vous pouvez y accéder ici: {{ url_for(".list_bills", _external=True) }} (l'identifieur est {{ g.project.id }}). +Si vous voulez partager ce projet avec vos amis, vous pouvez partager son identifiant et son code d'accès avec eux ou leur envoyer une invitation avec le lien suivant : +{{ url_for(".invite", _external=True) }} + +Faites en bon usage ! diff --git a/ihatemoney/web.py b/ihatemoney/web.py index e6df385..6b1b358 100644 --- a/ihatemoney/web.py +++ b/ihatemoney/web.py @@ -242,7 +242,7 @@ def create_project(): message_title = _("You have just created '%(project)s' " "to share your expenses", project=g.project.name) - message_body = render_template("reminder_mail.%s" % + message_body = render_template("reminder_mail.%s.j2" % get_locale().language) msg = Message(message_title, @@ -273,7 +273,7 @@ def remind_password(): project = Project.query.get(form.id.data) # send a link to reset the password - password_reminder = "password_reminder.%s" % get_locale().language + password_reminder = "password_reminder.%s.j2" % get_locale().language current_app.mail.send(Message( "password recovery", body=render_template(password_reminder, project=project), @@ -395,7 +395,7 @@ def invite(): if form.validate(): # send the email - message_body = render_template("invitation_mail.%s" % + message_body = render_template("invitation_mail.%s.j2" % get_locale().language) message_title = _("You have been invited to share your " -- cgit v1.1 From 2019b398f164aa3f7edb8af439c92f1a32d2e920 Mon Sep 17 00:00:00 2001 From: JocelynDelalande Date: Sun, 7 Jan 2018 00:27:42 +0100 Subject: manage commands testing (#313) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rename manage.ConfigTemplate → manage.GenerateConfig To be consistent with the CLI name: `generate-config`. * Add tests for manage.py commands * Run tests from pip-installed package To be able to detect packaging-related issues on test runs. refs #305 --- ihatemoney/manage.py | 8 ++++---- ihatemoney/tests/tests.py | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/manage.py b/ihatemoney/manage.py index 797e6c4..315cfac 100755 --- a/ihatemoney/manage.py +++ b/ihatemoney/manage.py @@ -4,7 +4,7 @@ import os import pkgutil import random import sys -from getpass import getpass +import getpass from flask_script import Manager, Command, Option from flask_migrate import Migrate, MigrateCommand @@ -20,11 +20,11 @@ class GeneratePasswordHash(Command): """Get password from user and hash it without printing it in clear text.""" def run(self): - password = getpass(prompt='Password: ') + password = getpass.getpass(prompt='Password: ') print(generate_password_hash(password)) -class ConfigTemplate(Command): +class GenerateConfig(Command): def get_options(self): return [ Option('config_file', choices=[ @@ -74,7 +74,7 @@ def main(): manager = Manager(app) manager.add_command('db', MigrateCommand) manager.add_command('generate_password_hash', GeneratePasswordHash) - manager.add_command('generate-config', ConfigTemplate) + manager.add_command('generate-config', GenerateConfig) manager.run() diff --git a/ihatemoney/tests/tests.py b/ihatemoney/tests/tests.py index de53c58..d4b6d7a 100644 --- a/ihatemoney/tests/tests.py +++ b/ihatemoney/tests/tests.py @@ -4,6 +4,10 @@ try: import unittest2 as unittest except ImportError: import unittest # NOQA +try: + from unittest.mock import patch +except ImportError: + from mock import patch import os import json @@ -16,6 +20,7 @@ from flask import session from flask_testing import TestCase from ihatemoney.run import create_app, db, load_configuration +from ihatemoney.manage import GenerateConfig, GeneratePasswordHash from ihatemoney import models from ihatemoney import utils @@ -1406,5 +1411,27 @@ class ServerTestCase(IhatemoneyTestCase): self.assertStatus(200, req) +class CommandTestCase(BaseTestCase): + def test_generate_config(self): + """ Simply checks that all config file generation + - raise no exception + - produce something non-empty + """ + cmd = GenerateConfig() + for config_file in cmd.get_options()[0].kwargs['choices']: + with patch('sys.stdout', new=six.StringIO()) as stdout: + cmd.run(config_file) + print(stdout.getvalue()) + self.assertNotEqual(len(stdout.getvalue().strip()), 0) + + def test_generate_password_hash(self): + cmd = GeneratePasswordHash() + with patch('sys.stdout', new=six.StringIO()) as stdout, \ + patch('getpass.getpass', new=lambda prompt: 'secret'): # NOQA + cmd.run() + print(stdout.getvalue()) + self.assertEqual(len(stdout.getvalue().strip()), 187) + + if __name__ == "__main__": unittest.main() -- cgit v1.1 From 0504fd82f52317d902e85a6e448048d5ef1c58d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Fri, 5 Jan 2018 22:36:31 +0100 Subject: Fix the supervisord template. The script was relying on the presence of an environment variable, which is only set when the virtualenv is activated. But a virtualenv does not have to be activated to work (it's possible to call the python command directly). This fixes it by relying on `sys.executable` which should be correct at all times. Fixes #306 --- ihatemoney/conf-templates/supervisord.conf.j2 | 2 +- ihatemoney/manage.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/conf-templates/supervisord.conf.j2 b/ihatemoney/conf-templates/supervisord.conf.j2 index fa16c0c..605f39d 100644 --- a/ihatemoney/conf-templates/supervisord.conf.j2 +++ b/ihatemoney/conf-templates/supervisord.conf.j2 @@ -1,5 +1,5 @@ [program:ihatemoney] -command={{ venv_path }}/bin/gunicorn -c /etc/ihatemoney/gunicorn.conf.py ihatemoney.wsgi:application +command={{ bin_path }}/gunicorn -c /etc/ihatemoney/gunicorn.conf.py ihatemoney.wsgi:application user=ihatemoney autostart=true autorestart=true diff --git a/ihatemoney/manage.py b/ihatemoney/manage.py index 315cfac..73bca57 100755 --- a/ihatemoney/manage.py +++ b/ihatemoney/manage.py @@ -49,9 +49,11 @@ class GenerateConfig(Command): os.path.join('conf-templates/', config_file) + '.j2' ).decode('utf-8') + bin_path = os.path.dirname(sys.executable) + print(Template(template_content).render( pkg_path=os.path.abspath(os.path.dirname(__file__)), - venv_path=os.environ.get('VIRTUAL_ENV'), + bin_path=bin_path, secret_key=self.gen_secret_key(), )) -- cgit v1.1 From 230eafdf58c46b983936cbf4f70b712bbddfd8c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Sun, 14 Jan 2018 16:52:52 +0100 Subject: Use Jinja2 strict rendering. For this I had to create an Jinja2 explicit environment, so I put a function in `ihatemoney.utils.create_jinja2_env(strict_rendering=False)`. When using this environment and if `strict_rendering` is activated, templates using undefined variables will now error out rather than failing silently. --- ihatemoney/conf-templates/apache-vhost.conf.j2 | 3 +-- ihatemoney/manage.py | 14 ++++++-------- ihatemoney/utils.py | 19 +++++++++++++++++-- 3 files changed, 24 insertions(+), 12 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/conf-templates/apache-vhost.conf.j2 b/ihatemoney/conf-templates/apache-vhost.conf.j2 index 3246d27..0527d31 100644 --- a/ihatemoney/conf-templates/apache-vhost.conf.j2 +++ b/ihatemoney/conf-templates/apache-vhost.conf.j2 @@ -1,8 +1,7 @@ ServerAdmin admin@example.com # CUSTOMIZE ServerName ihatemoney.example.com # CUSTOMIZE - - WSGIDaemonProcess ihatemoney user=www-data group=www-data threads=5 python-path={{ pkg_path }} {% if venv_path %}python-home={{ venv_path }}{% endif %} + WSGIDaemonProcess ihatemoney user=www-data group=www-data threads=5 python-path={{ pkg_path }} {% if bin_path %}python-home={{ bin_path }}{% endif %} WSGIScriptAlias / {{ pkg_path }}/wsgi.py WSGIPassAuthorization On diff --git a/ihatemoney/manage.py b/ihatemoney/manage.py index 73bca57..9058b39 100755 --- a/ihatemoney/manage.py +++ b/ihatemoney/manage.py @@ -1,18 +1,17 @@ #!/usr/bin/env python import os -import pkgutil import random import sys import getpass from flask_script import Manager, Command, Option from flask_migrate import Migrate, MigrateCommand -from jinja2 import Template from werkzeug.security import generate_password_hash from ihatemoney.run import create_app from ihatemoney.models import db +from ihatemoney.utils import create_jinja_env class GeneratePasswordHash(Command): @@ -44,15 +43,14 @@ class GenerateConfig(Command): for i in range(50)]) def run(self, config_file): - template_content = pkgutil.get_data( - 'ihatemoney', - os.path.join('conf-templates/', config_file) + '.j2' - ).decode('utf-8') + env = create_jinja_env('conf-templates', strict_rendering=True) + template = env.get_template('%s.j2' % config_file) bin_path = os.path.dirname(sys.executable) + pkg_path = os.path.abspath(os.path.dirname(__file__)) - print(Template(template_content).render( - pkg_path=os.path.abspath(os.path.dirname(__file__)), + print(template.render( + pkg_path=pkg_path, bin_path=bin_path, secret_key=self.gen_secret_key(), )) diff --git a/ihatemoney/utils.py b/ihatemoney/utils.py index 6af0112..a25e3b9 100644 --- a/ihatemoney/utils.py +++ b/ihatemoney/utils.py @@ -2,7 +2,7 @@ import base64 import re from io import BytesIO, StringIO -from jinja2 import filters +import jinja2 from json import dumps from flask import redirect from werkzeug.routing import HTTPException, RoutingException @@ -83,7 +83,7 @@ def minimal_round(*args, **kw): from http://stackoverflow.com/questions/28458524/ """ # Use the original round filter, to deal with the extra arguments - res = filters.do_round(*args, **kw) + res = jinja2.filters.do_round(*args, **kw) # Test if the result is equivalent to an integer and # return depending on it ires = int(res) @@ -170,3 +170,18 @@ class LoginThrottler(): def reset(self, ip): self._attempts.pop(ip, None) + + +def create_jinja_env(folder, strict_rendering=False): + """Creates and return a Jinja2 Environment object, used, to load the + templates. + + :param strict_rendering: + if set to `True`, all templates which use an undefined variable will + throw an exception (default to `False`). + """ + loader = jinja2.PackageLoader('ihatemoney', folder) + kwargs = {'loader': loader} + if strict_rendering: + kwargs['undefined'] = jinja2.StrictUndefined + return jinja2.Environment(**kwargs) -- cgit v1.1 From 830718e1fe5f18959f455a696ebc2172a2d5f253 Mon Sep 17 00:00:00 2001 From: Richard Coates Date: Thu, 25 Jan 2018 17:34:37 +0100 Subject: Make sidebar scrollable (#316) * Make sidebar scrollable Make sidebar scrollable. * Update CHANGELOG.rst Fixes #318 --- ihatemoney/static/css/main.css | 1 + 1 file changed, 1 insertion(+) (limited to 'ihatemoney') diff --git a/ihatemoney/static/css/main.css b/ihatemoney/static/css/main.css index b0120ca..4b35b37 100644 --- a/ihatemoney/static/css/main.css +++ b/ihatemoney/static/css/main.css @@ -74,6 +74,7 @@ body { background-repeat: no-repeat; height: 100%; color: black; + overflow-y: scroll; } @media (min-width: 768px) { -- cgit v1.1 From b93ea4830d5290def99d597f17292a8aa5d4c090 Mon Sep 17 00:00:00 2001 From: 0livd Date: Thu, 25 Jan 2018 17:41:28 +0100 Subject: API: Migrate from flask-rest to flask-restful (#315) The flask-rest custom json encoder is still needed and thus was added to ihatemoney's utils. Closes #298 --- ihatemoney/api.py | 168 +++++++++++++++++++++++----------------------- ihatemoney/run.py | 4 +- ihatemoney/tests/tests.py | 14 ++-- ihatemoney/utils.py | 27 +++++++- 4 files changed, 120 insertions(+), 93 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/api.py b/ihatemoney/api.py index 827202c..31ed06c 100644 --- a/ihatemoney/api.py +++ b/ihatemoney/api.py @@ -1,62 +1,68 @@ # -*- coding: utf-8 -*- from flask import Blueprint, request -from flask_rest import RESTResource, need_auth +from flask_restful import Resource, Api, abort from wtforms.fields.core import BooleanField from ihatemoney.models import db, Project, Person, Bill from ihatemoney.forms import (ProjectForm, EditProjectForm, MemberForm, get_billform_for) from werkzeug.security import check_password_hash +from functools import wraps api = Blueprint("api", __name__, url_prefix="/api") +restful_api = Api(api) -def check_project(*args, **kwargs): +def need_auth(f): """Check the request for basic authentication for a given project. - Return the project if the authorization is good, False otherwise + Return the project if the authorization is good, abort the request with a 401 otherwise """ - auth = request.authorization - - # project_id should be contained in kwargs and equal to the username - if auth and "project_id" in kwargs and \ - auth.username == kwargs["project_id"]: - project = Project.query.get(auth.username) - if project and check_password_hash(project.password, auth.password): - return project - return False - - -class ProjectHandler(object): - - def add(self): + @wraps(f) + def wrapper(*args, **kwargs): + auth = request.authorization + project_id = kwargs.get("project_id") + + if auth and project_id and auth.username == project_id: + project = Project.query.get(auth.username) + if project and check_password_hash(project.password, auth.password): + # The whole project object will be passed instead of project_id + kwargs.pop("project_id") + return f(*args, project=project, **kwargs) + abort(401) + return wrapper + + +class ProjectsHandler(Resource): + def post(self): form = ProjectForm(meta={'csrf': False}) if form.validate(): project = form.save() db.session.add(project) db.session.commit() - return 201, project.id - return 400, form.errors + return project.id, 201 + return form.errors, 400 + + +class ProjectHandler(Resource): + method_decorators = [need_auth] - @need_auth(check_project, "project") def get(self, project): - return 200, project + return project - @need_auth(check_project, "project") def delete(self, project): db.session.delete(project) db.session.commit() - return 200, "DELETED" + return "DELETED" - @need_auth(check_project, "project") - def update(self, project): + def put(self, project): form = EditProjectForm(meta={'csrf': False}) if form.validate(): form.update(project) db.session.commit() - return 200, "UPDATED" - return 400, form.errors + return "UPDATED" + return form.errors, 400 class APIMemberForm(MemberForm): @@ -71,98 +77,92 @@ class APIMemberForm(MemberForm): return super(APIMemberForm, self).save(project, person) -class MemberHandler(object): +class MembersHandler(Resource): + method_decorators = [need_auth] - def get(self, project, member_id): - member = Person.query.get(member_id, project) - if not member or member.project != project: - return 404, "Not Found" - return 200, member - - def list(self, project): - return 200, project.members + def get(self, project): + return project.members - def add(self, project): + def post(self, project): form = MemberForm(project, meta={'csrf': False}) if form.validate(): member = Person() form.save(project, member) db.session.commit() - return 201, member.id - return 400, form.errors + return member.id, 201 + return form.errors, 400 + + +class MemberHandler(Resource): + method_decorators = [need_auth] + + def get(self, project, member_id): + member = Person.query.get(member_id, project) + if not member or member.project != project: + return "Not Found", 404 + return member - def update(self, project, member_id): + def put(self, project, member_id): form = APIMemberForm(project, meta={'csrf': False}, edit=True) if form.validate(): member = Person.query.get(member_id, project) form.save(project, member) db.session.commit() - return 200, member - return 400, form.errors + return member + return form.errors, 400 def delete(self, project, member_id): if project.remove_member(member_id): - return 200, "OK" - return 404, "Not Found" + return "OK" + return "Not Found", 404 -class BillHandler(object): - - def get(self, project, bill_id): - bill = Bill.query.get(project, bill_id) - if not bill: - return 404, "Not Found" - return 200, bill +class BillsHandler(Resource): + method_decorators = [need_auth] - def list(self, project): + def get(self, project): return project.get_bills().all() - def add(self, project): + def post(self, project): form = get_billform_for(project, True, meta={'csrf': False}) if form.validate(): bill = Bill() form.save(bill, project) db.session.add(bill) db.session.commit() - return 201, bill.id - return 400, form.errors + return bill.id, 201 + return form.errors, 400 + - def update(self, project, bill_id): +class BillHandler(Resource): + method_decorators = [need_auth] + + def get(self, project, bill_id): + bill = Bill.query.get(project, bill_id) + if not bill: + return "Not Found", 404 + return bill, 200 + + def put(self, project, bill_id): form = get_billform_for(project, True, meta={'csrf': False}) if form.validate(): bill = Bill.query.get(project, bill_id) form.save(bill, project) db.session.commit() - return 200, bill.id - return 400, form.errors + return bill.id, 200 + return form.errors, 400 def delete(self, project, bill_id): bill = Bill.query.delete(project, bill_id) db.session.commit() if not bill: - return 404, "Not Found" - return 200, "OK" - - -project_resource = RESTResource( - name="project", - route="/projects", - app=api, - actions=["add", "update", "delete", "get"], - handler=ProjectHandler()) - -member_resource = RESTResource( - name="member", - inject_name="project", - route="/projects//members", - app=api, - handler=MemberHandler(), - authentifier=check_project) - -bill_resource = RESTResource( - name="bill", - inject_name="project", - route="/projects//bills", - app=api, - handler=BillHandler(), - authentifier=check_project) + return "Not Found", 404 + return "OK", 200 + + +restful_api.add_resource(ProjectsHandler, '/projects') +restful_api.add_resource(ProjectHandler, '/projects/') +restful_api.add_resource(MembersHandler, "/projects//members") +restful_api.add_resource(MemberHandler, "/projects//members/") +restful_api.add_resource(BillsHandler, "/projects//bills") +restful_api.add_resource(BillHandler, "/projects//bills/") diff --git a/ihatemoney/run.py b/ihatemoney/run.py index e3a7c1e..a8de26f 100644 --- a/ihatemoney/run.py +++ b/ihatemoney/run.py @@ -11,7 +11,7 @@ from werkzeug.contrib.fixers import ProxyFix from ihatemoney.api import api from ihatemoney.models import db -from ihatemoney.utils import PrefixedWSGI, minimal_round +from ihatemoney.utils import PrefixedWSGI, minimal_round, IhmJSONEncoder from ihatemoney.web import main as web_interface from ihatemoney import default_settings @@ -68,6 +68,8 @@ def load_configuration(app, configuration=None): app.config.from_pyfile(env_var_config) else: app.config.from_pyfile('ihatemoney.cfg', silent=True) + # Configure custom JSONEncoder used by the API + app.config['RESTFUL_JSON'] = {'cls': IhmJSONEncoder} def validate_configuration(app): diff --git a/ihatemoney/tests/tests.py b/ihatemoney/tests/tests.py index d4b6d7a..c13131c 100644 --- a/ihatemoney/tests/tests.py +++ b/ihatemoney/tests/tests.py @@ -1053,7 +1053,7 @@ class APITestCase(IhatemoneyTestCase): }) self.assertTrue(400, resp.status_code) - self.assertEqual('{"contact_email": ["Invalid email address."]}', + self.assertEqual('{"contact_email": ["Invalid email address."]}\n', resp.data.decode('utf-8')) # create it @@ -1139,7 +1139,7 @@ class APITestCase(IhatemoneyTestCase): headers=self.get_auth("raclette")) self.assertStatus(200, req) - self.assertEqual('[]', req.data.decode('utf-8')) + self.assertEqual('[]\n', req.data.decode('utf-8')) # add a member req = self.client.post("/api/projects/raclette/members", data={ @@ -1148,7 +1148,7 @@ class APITestCase(IhatemoneyTestCase): # the id of the new member should be returned self.assertStatus(201, req) - self.assertEqual("1", req.data.decode('utf-8')) + self.assertEqual("1\n", req.data.decode('utf-8')) # the list of members should contain one member req = self.client.get("/api/projects/raclette/members", @@ -1223,7 +1223,7 @@ class APITestCase(IhatemoneyTestCase): headers=self.get_auth("raclette")) self.assertStatus(200, req) - self.assertEqual('[]', req.data.decode('utf-8')) + self.assertEqual('[]\n', req.data.decode('utf-8')) def test_bills(self): # create a project @@ -1239,7 +1239,7 @@ class APITestCase(IhatemoneyTestCase): headers=self.get_auth("raclette")) self.assertStatus(200, req) - self.assertEqual("[]", req.data.decode('utf-8')) + self.assertEqual("[]\n", req.data.decode('utf-8')) # add a bill req = self.client.post("/api/projects/raclette/bills", data={ @@ -1252,7 +1252,7 @@ class APITestCase(IhatemoneyTestCase): # should return the id self.assertStatus(201, req) - self.assertEqual(req.data.decode('utf-8'), "1") + self.assertEqual(req.data.decode('utf-8'), "1\n") # get this bill details req = self.client.get("/api/projects/raclette/bills/1", @@ -1288,7 +1288,7 @@ class APITestCase(IhatemoneyTestCase): }, headers=self.get_auth("raclette")) self.assertStatus(400, req) - self.assertEqual('{"date": ["This field is required."]}', req.data.decode('utf-8')) + self.assertEqual('{"date": ["This field is required."]}\n', req.data.decode('utf-8')) # edit a bill req = self.client.put("/api/projects/raclette/bills/1", data={ diff --git a/ihatemoney/utils.py b/ihatemoney/utils.py index 6af0112..aaae2a0 100644 --- a/ihatemoney/utils.py +++ b/ihatemoney/utils.py @@ -3,7 +3,7 @@ import re from io import BytesIO, StringIO from jinja2 import filters -from json import dumps +from json import dumps, JSONEncoder from flask import redirect from werkzeug.routing import HTTPException, RoutingException import six @@ -170,3 +170,28 @@ class LoginThrottler(): def reset(self, ip): self._attempts.pop(ip, None) + + +class IhmJSONEncoder(JSONEncoder): + """Subclass of the default encoder to support custom objects. + Taken from the deprecated flask-rest package.""" + def default(self, o): + if hasattr(o, "_to_serialize"): + # build up the object + data = {} + for attr in o._to_serialize: + data[attr] = getattr(o, attr) + return data + elif hasattr(o, "isoformat"): + return o.isoformat() + else: + try: + from flask_babel import speaklater + if isinstance(o, speaklater.LazyString): + try: + return unicode(o) # For python 2. + except NameError: + return str(o) # For python 3. + except ImportError: + pass + return JSONEncoder.default(self, o) -- cgit v1.1 From 434ee8b85251ee14cb0535cbb92b9b28b84f0b8d Mon Sep 17 00:00:00 2001 From: Jocelyn Delalande Date: Fri, 26 Jan 2018 16:17:43 +0100 Subject: Display sidebar scroll-bar only if required This fix a regression from #316 (scrollbar was displayed all the time). Note that the padding-bottom value is totally empiric, but proved OK on my Fx and Chrome instances + some responsive tests. There might be finer solutions, feel free :-). --- ihatemoney/static/css/main.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ihatemoney') diff --git a/ihatemoney/static/css/main.css b/ihatemoney/static/css/main.css index 4b35b37..94ca4bd 100644 --- a/ihatemoney/static/css/main.css +++ b/ihatemoney/static/css/main.css @@ -74,12 +74,13 @@ body { background-repeat: no-repeat; height: 100%; color: black; - overflow-y: scroll; + overflow-y: auto; } @media (min-width: 768px) { .sidebar { position: fixed; + padding-bottom: 4.5rem; } } -- cgit v1.1 From cf7bd572489aad17bf60026c6618d0ff49f822a9 Mon Sep 17 00:00:00 2001 From: Jocelyn Delalande Date: Sun, 4 Feb 2018 13:10:57 +0100 Subject: Remove unused CSS odd/even classes That was forgotten from fe39258630e55d4a3e1297a01a1c8fd39bad3a4e --- ihatemoney/templates/dashboard.html | 2 +- ihatemoney/templates/settle_bills.html | 2 +- ihatemoney/templates/statistics.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/templates/dashboard.html b/ihatemoney/templates/dashboard.html index b1220bd..807e3e2 100644 --- a/ihatemoney/templates/dashboard.html +++ b/ihatemoney/templates/dashboard.html @@ -4,7 +4,7 @@ {% for project in projects|sort(attribute='name') %} - + {% if project.has_bills() %} diff --git a/ihatemoney/templates/settle_bills.html b/ihatemoney/templates/settle_bills.html index b67a9b8..7ec5e29 100644 --- a/ihatemoney/templates/settle_bills.html +++ b/ihatemoney/templates/settle_bills.html @@ -22,7 +22,7 @@ {% for bill in bills %} - + diff --git a/ihatemoney/templates/statistics.html b/ihatemoney/templates/statistics.html index 061c629..ae1c80e 100644 --- a/ihatemoney/templates/statistics.html +++ b/ihatemoney/templates/statistics.html @@ -22,7 +22,7 @@ {% for member in members %} - + -- cgit v1.1 From 389c7b8bcd2813d8549858265432859259942fd6 Mon Sep 17 00:00:00 2001 From: Jocelyn Delalande Date: Sat, 3 Feb 2018 17:49:12 +0100 Subject: Remove dead code --- ihatemoney/templates/statistics.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ihatemoney') diff --git a/ihatemoney/templates/statistics.html b/ihatemoney/templates/statistics.html index ae1c80e..ee59cb9 100644 --- a/ihatemoney/templates/statistics.html +++ b/ihatemoney/templates/statistics.html @@ -5,7 +5,7 @@
{{ _("Project") }}{{ _("Number of members") }}{{ _("Number of bills") }}{{_("Newest bill")}}{{_("Oldest bill")}}{{_("Actions")}}
{{ project.name }}{{ project.members | count }}{{ project.get_bills().count() }}{{ project.get_bills().all()[0].date }}
{{ _("Who pays?") }}{{ _("To whom?") }}{{ _("How much?") }}
{{ bill.ower }} {{ bill.receiver }} {{ "%0.2f"|format(bill.amount) }}
{{ _("Who?") }}{{ _("Paid") }}{{ _("Spent") }}{{ _("Balance") }}
{{ member.name }} {{ "%0.2f"|format(paid[member.id]) }} {{ "%0.2f"|format(spent[member.id]) }}
{% set balance = g.project.balance %} {% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2) != 0 %} - +
{{ member.name }} {% if balance[member.id]|round(2) > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }} -- cgit v1.1 From b1a4572e8c72e1d7f49b07aaeb5be0f3603bf0a7 Mon Sep 17 00:00:00 2001 From: Jocelyn Delalande Date: Sat, 3 Feb 2018 18:04:06 +0100 Subject: Change statistics data structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clearer data structure, and simpler template This commit has a side effect: sidebar now hides disabled members. IMHO, the disabled members should either be hidden or shown consistently between sidebar and central table. Previous status was: shown in sidebar (if balance ≠ 0) and hidden in central table. --- ihatemoney/templates/statistics.html | 19 +++++++++---------- ihatemoney/tests/tests.py | 24 ++++++++++++------------ ihatemoney/web.py | 27 ++++++++++++++------------- 3 files changed, 35 insertions(+), 35 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/templates/statistics.html b/ihatemoney/templates/statistics.html index ee59cb9..1b07a33 100644 --- a/ihatemoney/templates/statistics.html +++ b/ihatemoney/templates/statistics.html @@ -3,12 +3,11 @@ {% block sidebar %}
- {% set balance = g.project.balance %} - {% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2) != 0 %} + {% for stat in members_stats| sort(attribute='member.name') %} - - + {% endfor %} @@ -21,12 +20,12 @@
{{ member.name }} - {% if balance[member.id]|round(2) > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }} + {{ stat.member.name }} + {% if stat.balance|round(2) > 0 %}+{% endif %}{{ "%.2f" | format(stat.balance) }}
- {% for member in members %} + {% for stat in members_stats %} - - - - + + + + {% endfor %} diff --git a/ihatemoney/tests/tests.py b/ihatemoney/tests/tests.py index c13131c..3582032 100644 --- a/ihatemoney/tests/tests.py +++ b/ihatemoney/tests/tests.py @@ -750,24 +750,24 @@ class BudgetTestCase(IhatemoneyTestCase): }) response = self.client.get("/raclette/statistics") - self.assertIn("\n " - + "\n " - + "\n " + self.assertIn("\n " + + "\n " + + "\n " + "\n", response.data.decode('utf-8')) - self.assertIn("\n " - + "\n " - + "\n " + self.assertIn("\n " + + "\n " + + "\n " + "\n", response.data.decode('utf-8')) - self.assertIn("\n " - + "\n " - + "\n " + self.assertIn("\n " + + "\n " + + "\n " + "\n", response.data.decode('utf-8')) - self.assertIn("\n " - + "\n " - + "\n " + self.assertIn("\n " + + "\n " + + "\n " + "\n", response.data.decode('utf-8')) diff --git a/ihatemoney/web.py b/ihatemoney/web.py index 6b1b358..85b02e5 100644 --- a/ihatemoney/web.py +++ b/ihatemoney/web.py @@ -566,21 +566,22 @@ def settle_bill(): @main.route("//statistics") def statistics(): """Compute what each member has paid and spent and display it""" - members = g.project.active_members - balance = g.project.balance - paid = {} - spent = {} - for member in members: - paid[member.id] = sum([bill.amount - for bill in g.project.get_member_bills(member.id).all()]) - spent[member.id] = sum([bill.pay_each() * member.weight - for bill in g.project.get_bills().all() if member in bill.owers]) + members_stats = [{ + 'member': member, + 'paid': sum([ + bill.amount + for bill in g.project.get_member_bills(member.id).all() + ]), + 'spent': sum([ + bill.pay_each() * member.weight + for bill in g.project.get_bills().all() if member in bill.owers + ]), + 'balance': g.project.balance[member.id] + } for member in g.project.active_members] + return render_template( "statistics.html", - members=members, - balance=balance, - paid=paid, - spent=spent, + members_stats=members_stats, current_view='statistics', ) -- cgit v1.1 From 036cd05e5716a694f575b3c65f6541f04a8b48bf Mon Sep 17 00:00:00 2001 From: Jocelyn Delalande Date: Sat, 3 Feb 2018 18:26:44 +0100 Subject: Move member stats computation to a dedicated method --- ihatemoney/models.py | 20 ++++++++++++++++++++ ihatemoney/web.py | 15 +-------------- 2 files changed, 21 insertions(+), 14 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/models.py b/ihatemoney/models.py index aa3083d..c6ce23f 100644 --- a/ihatemoney/models.py +++ b/ihatemoney/models.py @@ -53,6 +53,26 @@ class Project(db.Model): return balances @property + def members_stats(self): + """Compute what each member has paid + + :return: one stat dict per member + :rtype list: + """ + return [{ + 'member': member, + 'paid': sum([ + bill.amount + for bill in self.get_member_bills(member.id).all() + ]), + 'spent': sum([ + bill.pay_each() * member.weight + for bill in self.get_bills().all() if member in bill.owers + ]), + 'balance': self.balance[member.id] + } for member in self.active_members] + + @property def uses_weights(self): return len([i for i in self.members if i.weight != 1]) > 0 diff --git a/ihatemoney/web.py b/ihatemoney/web.py index 85b02e5..1e16202 100644 --- a/ihatemoney/web.py +++ b/ihatemoney/web.py @@ -566,22 +566,9 @@ def settle_bill(): @main.route("//statistics") def statistics(): """Compute what each member has paid and spent and display it""" - members_stats = [{ - 'member': member, - 'paid': sum([ - bill.amount - for bill in g.project.get_member_bills(member.id).all() - ]), - 'spent': sum([ - bill.pay_each() * member.weight - for bill in g.project.get_bills().all() if member in bill.owers - ]), - 'balance': g.project.balance[member.id] - } for member in g.project.active_members] - return render_template( "statistics.html", - members_stats=members_stats, + members_stats=g.project.members_stats, current_view='statistics', ) -- cgit v1.1 From b95ea7f4e68a0794a44e68621a8210bb4db43e67 Mon Sep 17 00:00:00 2001 From: Jocelyn Delalande Date: Sat, 3 Feb 2018 18:52:04 +0100 Subject: Add statistics support to API --- ihatemoney/api.py | 8 ++++++++ ihatemoney/tests/tests.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'ihatemoney') diff --git a/ihatemoney/api.py b/ihatemoney/api.py index 31ed06c..6068cf7 100644 --- a/ihatemoney/api.py +++ b/ihatemoney/api.py @@ -65,6 +65,13 @@ class ProjectHandler(Resource): return form.errors, 400 +class ProjectStatsHandler(Resource): + method_decorators = [need_auth] + + def get(self, project): + return project.members_stats + + class APIMemberForm(MemberForm): """ Member is not disablable via a Form. @@ -163,6 +170,7 @@ class BillHandler(Resource): restful_api.add_resource(ProjectsHandler, '/projects') restful_api.add_resource(ProjectHandler, '/projects/') restful_api.add_resource(MembersHandler, "/projects//members") +restful_api.add_resource(ProjectStatsHandler, "/projects//statistics") restful_api.add_resource(MemberHandler, "/projects//members/") restful_api.add_resource(BillsHandler, "/projects//bills") restful_api.add_resource(BillHandler, "/projects//bills/") diff --git a/ihatemoney/tests/tests.py b/ihatemoney/tests/tests.py index 3582032..3797f09 100644 --- a/ihatemoney/tests/tests.py +++ b/ihatemoney/tests/tests.py @@ -1325,6 +1325,40 @@ class APITestCase(IhatemoneyTestCase): headers=self.get_auth("raclette")) self.assertStatus(404, req) + def test_statistics(self): + # create a project + self.api_create("raclette") + + # add members + self.api_add_member("raclette", "alexis") + self.api_add_member("raclette", "fred") + + # add a bill + req = self.client.post("/api/projects/raclette/bills", data={ + 'date': '2011-08-10', + 'what': 'fromage', + 'payer': "1", + 'payed_for': ["1", "2"], + 'amount': '25', + }, headers=self.get_auth("raclette")) + + # get the list of bills (should be empty) + req = self.client.get("/api/projects/raclette/statistics", + headers=self.get_auth("raclette")) + self.assertStatus(200, req) + self.assertEqual([ + {'balance': 12.5, + 'member': {'activated': True, 'id': 1, + 'name': 'alexis', 'weight': 1.0}, + 'paid': 25.0, + 'spent': 12.5}, + {'balance': -12.5, + 'member': {'activated': True, 'id': 2, + 'name': 'fred', 'weight': 1.0}, + 'paid': 0, + 'spent': 12.5}], + json.loads(req.data.decode('utf-8'))) + def test_username_xss(self): # create a project # self.api_create("raclette") -- cgit v1.1 From 74f72a46d55fbf1507acbe5ad9ac3df9e92a822e Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Tue, 15 May 2018 21:45:24 +0200 Subject: new extraction with pybabel --- ihatemoney/messages.pot | 374 ++++++++++++++++++++++++++++++------------------ 1 file changed, 238 insertions(+), 136 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/messages.pot b/ihatemoney/messages.pot index 0b1759b..4a15259 100644 --- a/ihatemoney/messages.pot +++ b/ihatemoney/messages.pot @@ -1,111 +1,127 @@ # Translations template for PROJECT. -# Copyright (C) 2013 ORGANIZATION +# Copyright (C) 2018 ORGANIZATION # This file is distributed under the same license as the PROJECT project. -# FIRST AUTHOR , 2013. +# FIRST AUTHOR , 2018. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2013-10-13 21:32+0200\n" +"POT-Creation-Date: 2018-05-15 21:43+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 0.9.6\n" +"Generated-By: Babel 2.5.3\n" -#: forms.py:22 -msgid "Select all" -msgstr "" - -#: forms.py:22 -msgid "Select none" -msgstr "" - -#: forms.py:61 +#: forms.py:46 msgid "Project name" msgstr "" -#: forms.py:62 forms.py:86 forms.py:102 +#: forms.py:47 forms.py:71 forms.py:88 msgid "Private code" msgstr "" -#: forms.py:63 +#: forms.py:48 msgid "Email" msgstr "" -#: forms.py:85 forms.py:101 forms.py:107 +#: forms.py:70 forms.py:87 forms.py:98 msgid "Project identifier" msgstr "" -#: forms.py:87 templates/send_invites.html:5 +#: forms.py:72 msgid "Create the project" msgstr "" -#: forms.py:92 +#: forms.py:77 msgid "" "The project identifier is used to log in and for the URL of the project. " "We tried to generate an identifier for you but a project with this " "identifier already exists. Please create a new identifier that you will " -"be able to remember." +"be able to remember" msgstr "" -#: forms.py:103 +#: forms.py:89 forms.py:94 msgid "Get in" msgstr "" -#: forms.py:108 +#: forms.py:93 +msgid "Admin password" +msgstr "" + +#: forms.py:99 msgid "Send me the code by email" msgstr "" -#: forms.py:112 +#: forms.py:103 msgid "This project does not exists" msgstr "" -#: forms.py:116 +#: forms.py:108 +msgid "Password mismatch" +msgstr "" + +#: forms.py:109 +msgid "Password" +msgstr "" + +#: forms.py:110 +msgid "Password confirmation" +msgstr "" + +#: forms.py:111 +msgid "Reset password" +msgstr "" + +#: forms.py:115 msgid "Date" msgstr "" -#: forms.py:117 +#: forms.py:116 msgid "What?" msgstr "" -#: forms.py:118 +#: forms.py:117 msgid "Payer" msgstr "" -#: forms.py:119 +#: forms.py:118 msgid "Amount paid" msgstr "" -#: forms.py:120 templates/list_bills.html:103 +#: forms.py:119 templates/forms.html:100 templates/list_bills.html:101 msgid "For whom?" msgstr "" -#: forms.py:122 +#: forms.py:121 msgid "Submit" msgstr "" -#: forms.py:123 +#: forms.py:122 msgid "Submit and add a new one" msgstr "" -#: forms.py:149 +#: forms.py:146 msgid "Bills can't be null" msgstr "" -#: forms.py:154 +#: forms.py:151 msgid "Name" msgstr "" -#: forms.py:155 templates/forms.html:95 +#: forms.py:152 +msgid "Weight" +msgstr "" + +#: forms.py:153 templates/forms.html:123 msgid "Add" msgstr "" -#: forms.py:163 +#: forms.py:162 msgid "User name incorrect" msgstr "" @@ -113,105 +129,151 @@ msgstr "" msgid "This project already have this member" msgstr "" -#: forms.py:178 +#: forms.py:183 msgid "People to notify" msgstr "" -#: forms.py:179 +#: forms.py:184 msgid "Send invites" msgstr "" -#: forms.py:185 +#: forms.py:190 #, python-format msgid "The email %(email)s is not valid" msgstr "" -#: forms.py:191 -msgid "Start date" +#: forms.py:196 +msgid "What do you want to download ?" msgstr "" -#: forms.py:192 -msgid "End date" +#: forms.py:199 +msgid "bills" msgstr "" -#: web.py:95 +#: forms.py:199 +msgid "transactions" +msgstr "" + +#: forms.py:201 +msgid "Export file format" +msgstr "" + +#: web.py:129 +msgid "Too many failed login attempts, please retry later." +msgstr "" + +#: web.py:144 +#, python-format +msgid "This admin password is not the right one. Only %(num)d attempts left." +msgstr "" + +#: web.py:167 +msgid "You either provided a bad token or no project identifier." +msgstr "" + +#: web.py:195 msgid "This private code is not the right one" msgstr "" -#: web.py:147 +#: web.py:242 #, python-format msgid "You have just created '%(project)s' to share your expenses" msgstr "" -#: web.py:165 +#: web.py:260 #, python-format msgid "%(msg_compl)sThe project identifier is %(project)s" msgstr "" -#: web.py:185 -msgid "a mail has been sent to you with the password" +#: web.py:281 +msgid "A link to reset your password has been sent to your email." +msgstr "" + +#: web.py:291 +msgid "No token provided" +msgstr "" + +#: web.py:294 +msgid "Invalid token" msgstr "" -#: web.py:211 +#: web.py:297 +msgid "Unknown project" +msgstr "" + +#: web.py:303 +msgid "Password successfully reset." +msgstr "" + +#: web.py:351 msgid "Project successfully deleted" msgstr "" -#: web.py:254 +#: web.py:401 #, python-format msgid "You have been invited to share your expenses for %(project)s" msgstr "" -#: web.py:261 +#: web.py:408 msgid "Your invitations have been sent" msgstr "" -#: web.py:290 +#: web.py:439 #, python-format msgid "%(member)s had been added" msgstr "" -#: web.py:303 +#: web.py:452 #, python-format msgid "%(name)s is part of this project again" msgstr "" -#: web.py:312 +#: web.py:461 #, python-format -msgid "User '%(name)s' has been deactivated" +msgid "" +"User '%(name)s' has been deactivated. It will still appear in the users " +"list until its balance becomes zero." msgstr "" -#: web.py:314 +#: web.py:465 #, python-format msgid "User '%(name)s' has been removed" msgstr "" -#: web.py:331 +#: web.py:480 +#, python-format +msgid "User '%(name)s' has been edited" +msgstr "" + +#: web.py:500 msgid "The bill has been added" msgstr "" -#: web.py:351 +#: web.py:520 msgid "The bill has been deleted" msgstr "" -#: web.py:369 +#: web.py:538 msgid "The bill has been modified" msgstr "" -#: templates/add_bill.html:9 +#: templates/add_bill.html:9 templates/edit_member.html:9 msgid "Back to the list" msgstr "" +#: templates/admin.html:10 +msgid "Administration tasks are currently disabled." +msgstr "" + #: templates/authenticate.html:6 -msgid "" -"The project you are trying to access do not exist, do you want \n" -"to" +msgid "The project you are trying to access do not exist, do you want to" msgstr "" -#: templates/authenticate.html:7 +#: templates/authenticate.html:8 msgid "create it" msgstr "" -#: templates/authenticate.html:7 +#: templates/authenticate.html:8 msgid "?" msgstr "" @@ -239,6 +301,24 @@ msgstr "" msgid "Oldest bill" msgstr "" +#: templates/dashboard.html:5 templates/list_bills.html:101 +msgid "Actions" +msgstr "" + +#: templates/dashboard.html:17 templates/list_bills.html:65 +#: templates/list_bills.html:111 +msgid "edit" +msgstr "" + +#: templates/dashboard.html:18 templates/forms.html:83 +#: templates/list_bills.html:112 +msgid "delete" +msgstr "" + +#: templates/dashboard.html:25 +msgid "The Dashboard is currently deactivated." +msgstr "" + #: templates/edit_project.html:6 templates/list_bills.html:24 msgid "you sure?" msgstr "" @@ -247,44 +327,59 @@ msgstr "" msgid "Edit this project" msgstr "" -#: templates/forms.html:23 +#: templates/edit_project.html:15 +msgid "Download this project's data" +msgstr "" + +#: templates/forms.html:27 msgid "Can't remember the password?" msgstr "" -#: templates/forms.html:26 +#: templates/forms.html:30 msgid "Cancel" msgstr "" -#: templates/forms.html:68 +#: templates/forms.html:82 msgid "Edit the project" msgstr "" -#: templates/forms.html:69 templates/list_bills.html:70 -#: templates/list_bills.html:114 -msgid "delete" -msgstr "" - -#: templates/forms.html:77 +#: templates/forms.html:91 msgid "Edit this bill" msgstr "" -#: templates/forms.html:77 templates/list_bills.html:94 +#: templates/forms.html:91 templates/list_bills.html:89 msgid "Add a bill" msgstr "" -#: templates/forms.html:95 +#: templates/forms.html:103 +msgid "Select all" +msgstr "" + +#: templates/forms.html:103 +msgid "Select none" +msgstr "" + +#: templates/forms.html:122 msgid "Type user name here" msgstr "" -#: templates/forms.html:102 +#: templates/forms.html:129 +msgid "Edit this member" +msgstr "" + +#: templates/forms.html:145 msgid "Send the invitations" msgstr "" -#: templates/forms.html:103 +#: templates/forms.html:146 msgid "No, thanks" msgstr "" -#: templates/home.html:8 +#: templates/forms.html:157 +msgid "Download" +msgstr "" + +#: templates/home.html:7 msgid "Manage your shared
expenses, easily" msgstr "" @@ -292,39 +387,39 @@ msgstr "" msgid "Try out the demo" msgstr "" -#: templates/home.html:12 +#: templates/home.html:13 msgid "You're sharing a house?" msgstr "" -#: templates/home.html:12 +#: templates/home.html:13 msgid "Going on holidays with friends?" msgstr "" -#: templates/home.html:12 +#: templates/home.html:13 msgid "Simply sharing money with others?" msgstr "" -#: templates/home.html:12 +#: templates/home.html:13 msgid "We can help!" msgstr "" -#: templates/home.html:24 +#: templates/home.html:21 msgid "Log to an existing project" msgstr "" -#: templates/home.html:28 +#: templates/home.html:25 msgid "log in" msgstr "" -#: templates/home.html:29 +#: templates/home.html:26 msgid "can't remember your password?" msgstr "" -#: templates/home.html:36 +#: templates/home.html:34 templates/home.html:42 msgid "or create a new one" msgstr "" -#: templates/home.html:40 +#: templates/home.html:38 msgid "let's get started" msgstr "" @@ -338,91 +433,91 @@ msgstr "" msgid "Account manager" msgstr "" -#: templates/layout.html:45 templates/settle_bills.html:4 +#: templates/layout.html:39 msgid "Bills" msgstr "" -#: templates/layout.html:46 templates/settle_bills.html:5 +#: templates/layout.html:40 msgid "Settle" msgstr "" -#: templates/layout.html:53 +#: templates/layout.html:41 +msgid "Statistics" +msgstr "" + +#: templates/layout.html:48 msgid "options" msgstr "" -#: templates/layout.html:55 +#: templates/layout.html:50 msgid "Project settings" msgstr "" -#: templates/layout.html:59 +#: templates/layout.html:54 msgid "switch to" msgstr "" -#: templates/layout.html:62 +#: templates/layout.html:57 msgid "Start a new project" msgstr "" -#: templates/layout.html:64 +#: templates/layout.html:59 msgid "Logout" msgstr "" -#: templates/layout.html:92 +#: templates/layout.html:66 +msgid "Dashboard" +msgstr "" + +#: templates/layout.html:89 msgid "This is a free software" msgstr "" -#: templates/layout.html:92 +#: templates/layout.html:89 msgid "you can contribute and improve it!" msgstr "" -#: templates/list_bills.html:74 -msgid "reactivate" +#: templates/list_bills.html:63 +msgid "deactivate" msgstr "" -#: templates/list_bills.html:88 -msgid "The project identifier is" +#: templates/list_bills.html:70 +msgid "reactivate" msgstr "" -#: templates/list_bills.html:88 -msgid "remember it!" +#: templates/list_bills.html:82 +msgid "Invite people to join this project!" msgstr "" -#: templates/list_bills.html:89 +#: templates/list_bills.html:83 msgid "Add a new bill" msgstr "" -#: templates/list_bills.html:103 +#: templates/list_bills.html:101 msgid "When?" msgstr "" -#: templates/list_bills.html:103 +#: templates/list_bills.html:101 msgid "Who paid?" msgstr "" -#: templates/list_bills.html:103 +#: templates/list_bills.html:101 msgid "For what?" msgstr "" -#: templates/list_bills.html:103 templates/settle_bills.html:31 +#: templates/list_bills.html:101 templates/settle_bills.html:22 msgid "How much?" msgstr "" -#: templates/list_bills.html:103 -msgid "Actions" -msgstr "" - -#: templates/list_bills.html:111 +#: templates/list_bills.html:109 msgid "each" msgstr "" -#: templates/list_bills.html:113 -msgid "edit" -msgstr "" - -#: templates/list_bills.html:122 +#: templates/list_bills.html:120 msgid "Nothing to list yet. You probably want to" msgstr "" -#: templates/list_bills.html:122 +#: templates/list_bills.html:120 msgid "add a bill" msgstr "" @@ -434,43 +529,50 @@ msgstr "" msgid "Your projects" msgstr "" -#: templates/send_invites.html:6 -msgid "Invite people" -msgstr "" - -#: templates/send_invites.html:7 -msgid "Use it!" +#: templates/reset_password.html:7 +msgid "Reset your password" msgstr "" -#: templates/send_invites.html:11 +#: templates/send_invites.html:4 msgid "Invite people to join this project" msgstr "" -#: templates/send_invites.html:12 +#: templates/send_invites.html:5 msgid "" -"Specify a (coma separated) list of email adresses you want to notify " -"about the \n" +"Specify a (comma separated) list of email adresses you want to notify " +"about the\n" "creation of this budget management project and we will send them an email" " for you." msgstr "" -#: templates/send_invites.html:14 -msgid "If you prefer, you can" +#: templates/send_invites.html:7 +msgid "" +"If you prefer, you can share the project identifier and the shared\n" +"password by other communication means. Or even directly share the " +"following link:" +msgstr "" + +#: templates/settle_bills.html:22 +msgid "Who pays?" msgstr "" -#: templates/send_invites.html:14 -msgid "skip this step" +#: templates/settle_bills.html:22 +msgid "To whom?" msgstr "" -#: templates/send_invites.html:14 -msgid "and notify them yourself" +#: templates/statistics.html:21 +msgid "Who?" msgstr "" -#: templates/settle_bills.html:31 -msgid "Who pays?" +#: templates/statistics.html:21 +msgid "Paid" msgstr "" -#: templates/settle_bills.html:31 -msgid "To whom?" +#: templates/statistics.html:21 +msgid "Spent" +msgstr "" + +#: templates/statistics.html:21 +msgid "Balance" msgstr "" -- cgit v1.1 From fb31868278af06322273ad94c6e58eaa32bb5823 Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Tue, 15 May 2018 21:47:01 +0200 Subject: update locales from template with pybabel --- ihatemoney/translations/fr/LC_MESSAGES/messages.po | 435 +++++++++++---------- 1 file changed, 236 insertions(+), 199 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/translations/fr/LC_MESSAGES/messages.po b/ihatemoney/translations/fr/LC_MESSAGES/messages.po index b344098..334fa8e 100644 --- a/ihatemoney/translations/fr/LC_MESSAGES/messages.po +++ b/ihatemoney/translations/fr/LC_MESSAGES/messages.po @@ -7,129 +7,122 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2013-10-13 21:32+0200\n" +"POT-Creation-Date: 2018-05-15 21:43+0200\n" "PO-Revision-Date: 2011-10-14 23:51+0200\n" "Last-Translator: Quentin Roy \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 0.9.6\n" +"Generated-By: Babel 2.5.3\n" -#: forms.py:22 -msgid "Select all" -msgstr "Tout cocher" - -#: forms.py:22 -msgid "Select none" -msgstr "Tout décocher" - -#: forms.py:61 +#: forms.py:46 msgid "Project name" msgstr "Nom de projet" -#: forms.py:62 forms.py:86 forms.py:102 +#: forms.py:47 forms.py:71 forms.py:88 msgid "Private code" msgstr "Code d'accès" -#: forms.py:63 +#: forms.py:48 msgid "Email" msgstr "Email" -#: forms.py:85 forms.py:101 forms.py:107 +#: forms.py:70 forms.py:87 forms.py:98 msgid "Project identifier" msgstr "Identifiant du projet" -#: forms.py:87 -msgid "Admin password" -msgstr "Mot de passe administrateur" - -#: forms.py:87 templates/send_invites.html:5 +#: forms.py:72 msgid "Create the project" msgstr "Créer le projet" -#: forms.py:92 +#: forms.py:77 msgid "" "The project identifier is used to log in and for the URL of the project. " "We tried to generate an identifier for you but a project with this " "identifier already exists. Please create a new identifier that you will " -"be able to remember." +"be able to remember" msgstr "" -"L'identifiant du projet est utilisé pour se connecter." -"Nous avons essayé de générer un identifiant mais " -"celui ci existe déjà. Merci de créer un nouvel identifiant que vous serez" -" capable de retenir" -#: forms.py:103 +#: forms.py:89 forms.py:94 msgid "Get in" msgstr "Entrer" -#: forms.py:107 +#: forms.py:93 +msgid "Admin password" +msgstr "Mot de passe administrateur" + +#: forms.py:99 +msgid "Send me the code by email" +msgstr "Envoyez moi le code par email" + +#: forms.py:103 +msgid "This project does not exists" +msgstr "Ce projet n'existe pas" + +#: forms.py:108 msgid "Password mismatch" msgstr "Les mots de passe fournis ne sont pas les mêmes." #: forms.py:109 -msgid "Password confirmation" -msgstr "Confirmation du mot de passe" - -#: forms.py:107 msgid "Password" msgstr "Mot de passe" -#: forms.py:108 -msgid "Send me the code by email" -msgstr "Envoyez moi le code par email" +#: forms.py:110 +msgid "Password confirmation" +msgstr "Confirmation du mot de passe" -#: forms.py:112 -msgid "This project does not exists" -msgstr "Ce projet n'existe pas" +#: forms.py:111 +msgid "Reset password" +msgstr "" -#: forms.py:116 +#: forms.py:115 msgid "Date" msgstr "Date" -#: forms.py:117 +#: forms.py:116 msgid "What?" msgstr "Quoi ?" -#: forms.py:118 +#: forms.py:117 msgid "Payer" msgstr "Payeur" -#: forms.py:119 +#: forms.py:118 msgid "Amount paid" msgstr "Montant" -#: forms.py:120 templates/list_bills.html:103 +#: forms.py:119 templates/forms.html:100 templates/list_bills.html:101 msgid "For whom?" msgstr "Pour qui ?" -#: forms.py:122 +#: forms.py:121 msgid "Submit" msgstr "Valider" -#: forms.py:123 +#: forms.py:122 msgid "Submit and add a new one" msgstr "Valider et ajouter une autre facture" -#: forms.py:149 +#: forms.py:146 msgid "Bills can't be null" msgstr "Le montant d'une facture ne peut pas être nul." -#: forms.py:154 +#: forms.py:151 msgid "Name" msgstr "Nom" -#: forms.py:155 +#: forms.py:152 msgid "Weight" msgstr "Parts" -#: forms.py:155 templates/forms.html:95 +#: forms.py:153 templates/forms.html:123 msgid "Add" msgstr "Ajouter" -#: forms.py:163 +#: forms.py:162 msgid "User name incorrect" msgstr "Nom d'utilisateur incorrect" @@ -137,159 +130,158 @@ msgstr "Nom d'utilisateur incorrect" msgid "This project already have this member" msgstr "Ce membre existe déjà pour ce projet" -#: forms.py:178 +#: forms.py:183 msgid "People to notify" msgstr "Personnes à prévenir" -#: forms.py:179 +#: forms.py:184 msgid "Send invites" msgstr "Envoyer les invitations" -#: forms.py:185 +#: forms.py:190 #, python-format msgid "The email %(email)s is not valid" msgstr "L'email %(email)s est invalide" -#: forms.py:191 -msgid "Start date" -msgstr "Date de départ" - -#: forms.py:192 -msgid "End date" -msgstr "Date de fin" - -#: forms.py:202 +#: forms.py:196 msgid "What do you want to download ?" msgstr "Que voulez-vous télécharger ?" -#: forms.py:205 +#: forms.py:199 msgid "bills" msgstr "factures" -#: forms.py:205 +#: forms.py:199 msgid "transactions" msgstr "remboursements" -#: forms.py:206 +#: forms.py:201 msgid "Export file format" msgstr "Format du fichier d'export" -#: web.py:95 +#: web.py:129 +msgid "Too many failed login attempts, please retry later." +msgstr "Trop d'échecs d'authentification successifs, veuillez réessayer plus tard." + +#: web.py:144 +#, python-format +msgid "This admin password is not the right one. Only %(num)d attempts left." +msgstr "" +"Le mot de passe administrateur que vous avez entré n'est pas correct. " +"Plus que %(num)d tentatives." + +#: web.py:167 msgid "You either provided a bad token or no project identifier." msgstr "L'identifiant du projet ou le token fourni n'est pas correct." -#: web.py:95 +#: web.py:195 msgid "This private code is not the right one" msgstr "Le code que vous avez entré n'est pas correct" -#: web.py:106 -msgid "This admin password is not the right one. Only %(num)d attempts left." -msgstr "Le mot de passe administrateur que vous avez entré n'est pas correct. Plus que %(num)d tentatives." - -#: web.py:106 -msgid "Too many failed login attempts, please retry later." -msgstr "Trop d'échecs d'authentification successifs, veuillez réessayer plus tard." - -#: web.py:147 +#: web.py:242 #, python-format msgid "You have just created '%(project)s' to share your expenses" msgstr "Vous venez de créer '%(project)s' pour partager vos dépenses" -#: web.py:165 +#: web.py:260 #, python-format msgid "%(msg_compl)sThe project identifier is %(project)s" msgstr "L'identifiant de ce projet est '%(project)s'" -#: web.py:185 +#: web.py:281 msgid "A link to reset your password has been sent to your email." msgstr "Un lien pour changer votre mot de passe vous a été envoyé par mail." -#: web.py:211 -msgid "Project successfully deleted" -msgstr "Projet supprimé" - -#: web.py:254 -#, python-format -msgid "You have been invited to share your expenses for %(project)s" -msgstr "Vous avez été invité à partager vos dépenses pour %(project)s" +#: web.py:291 +msgid "No token provided" +msgstr "" -#: web.py:259 -#, python-format -msgid ""No token provided"" -msgstr "Aucun token n'a été fourni." +#: web.py:294 +msgid "Invalid token" +msgstr "Token invalide" -#: web.py:259 -#, python-format +#: web.py:297 msgid "Unknown project" msgstr "Project inconnu" -#: web.py:261 -#, python-format -msgid "Invalid token" -msgstr "Token invalide" - -#: web.py:267 -#, python-format +#: web.py:303 msgid "Password successfully reset." msgstr "Le mot de passe a été changé avec succès." -#: web.py:261 +#: web.py:351 +msgid "Project successfully deleted" +msgstr "Projet supprimé" + +#: web.py:401 +#, python-format +msgid "You have been invited to share your expenses for %(project)s" +msgstr "Vous avez été invité à partager vos dépenses pour %(project)s" + +#: web.py:408 msgid "Your invitations have been sent" msgstr "Vos invitations ont bien été envoyées" -#: web.py:290 +#: web.py:439 #, python-format msgid "%(member)s had been added" msgstr "%(member)s a bien été ajouté" -#: web.py:303 +#: web.py:452 #, python-format msgid "%(name)s is part of this project again" msgstr "%(name)s a rejoint le projet" -#: web.py:312 +#: web.py:461 #, python-format -msgid "User '%(name)s' has been deactivated" -msgstr "Le membre '%(name)s' a été désactivé" +msgid "" +"User '%(name)s' has been deactivated. It will still appear in the users " +"list until its balance becomes zero." +msgstr "" +"Le membre '%(name)s' a été désactivé. Il continuera d'apparaître jusqu'à " +"ce que sa balance devienne égale à zéro." -#: web.py:314 +#: web.py:465 #, python-format -msgid "User '%(name)s' has been deactivated. It will still appear in the users list until its balance becomes zero." -msgstr "Le membre '%(name)s' a été désactivé. Il continuera d'apparaître jusqu'à ce que sa balance devienne égale à zéro." +msgid "User '%(name)s' has been removed" +msgstr "" -#: web.py:331 +#: web.py:480 +#, python-format +msgid "User '%(name)s' has been edited" +msgstr "" + +#: web.py:500 msgid "The bill has been added" msgstr "La facture a bien été ajoutée" -#: web.py:351 +#: web.py:520 msgid "The bill has been deleted" msgstr "La facture a été supprimée" -#: web.py:369 +#: web.py:538 msgid "The bill has been modified" msgstr "La facture a été modifiée" -#: templates/add_bill.html:9 +#: templates/add_bill.html:9 templates/edit_member.html:9 msgid "Back to the list" msgstr "Retourner à la liste" +#: templates/admin.html:10 +msgid "Administration tasks are currently disabled." +msgstr "Les tâches d'administration sont actuellement désactivées." + #: templates/authenticate.html:6 -msgid "" -"The project you are trying to access do not exist, do you want to" +msgid "The project you are trying to access do not exist, do you want to" msgstr "Le projet auquel vous essayez d'acceder n'existe pas. Souhaitez vous" -#: templates/authenticate.html:7 +#: templates/authenticate.html:8 msgid "create it" msgstr "le créer" -#: templates/authenticate.html:7 +#: templates/authenticate.html:8 msgid "?" msgstr " ?" -#: templates/authenticate.html:7 -msgid "Administration tasks are currently disabled." -msgstr "Les tâches d'administration sont actuellement désactivées." - #: templates/create_project.html:4 msgid "Create a new project" msgstr "Créer un nouveau projet" @@ -314,6 +306,20 @@ msgstr "Facture la plus récente" msgid "Oldest bill" msgstr "Facture la plus ancienne" +#: templates/dashboard.html:5 templates/list_bills.html:101 +msgid "Actions" +msgstr "Actions" + +#: templates/dashboard.html:17 templates/list_bills.html:65 +#: templates/list_bills.html:111 +msgid "edit" +msgstr "éditer" + +#: templates/dashboard.html:18 templates/forms.html:83 +#: templates/list_bills.html:112 +msgid "delete" +msgstr "supprimer" + #: templates/dashboard.html:25 msgid "The Dashboard is currently deactivated." msgstr "La page d'administration est actuellement désactivée." @@ -326,60 +332,59 @@ msgstr "c'est sûr ?" msgid "Edit this project" msgstr "Éditer ce projet" -#: templates/forms.html:23 +#: templates/edit_project.html:15 +msgid "Download this project's data" +msgstr "Télécharger les données de ce projet" + +#: templates/forms.html:27 msgid "Can't remember the password?" msgstr "Vous ne vous souvenez plus du code d'accès ?" -#: templates/forms.html:26 +#: templates/forms.html:30 msgid "Cancel" msgstr "Annuler" -#: templates/forms.html:68 +#: templates/forms.html:82 msgid "Edit the project" msgstr "Éditer le projet" -#: templates/list_bills.html:70 -msgid "deactivate" -msgstr "désactiver" - -#: templates/forms.html:69 templates/list_bills.html:70 -#: templates/list_bills.html:114 -msgid "delete" -msgstr "supprimer" - -#: templates/forms.html:77 +#: templates/forms.html:91 msgid "Edit this bill" msgstr "Éditer cette facture" -#: templates/forms.html:77 templates/list_bills.html:94 +#: templates/forms.html:91 templates/list_bills.html:89 msgid "Add a bill" msgstr "Ajouter une facture" -#: templates/forms.html:95 +#: templates/forms.html:103 +msgid "Select all" +msgstr "Tout cocher" + +#: templates/forms.html:103 +msgid "Select none" +msgstr "Tout décocher" + +#: templates/forms.html:122 msgid "Type user name here" msgstr "Nouveau participant" -#: templates/forms.html:100 +#: templates/forms.html:129 msgid "Edit this member" msgstr "Éditer ce participant" -#: templates/forms.html:102 +#: templates/forms.html:145 msgid "Send the invitations" msgstr "Envoyer les invitations" -#: templates/forms.html:103 +#: templates/forms.html:146 msgid "No, thanks" msgstr "Non merci" -#: templates/forms.html:136 -msgid "Download this project's data" -msgstr "Télécharger les données de ce projet" - -#: templates/forms.html:136 +#: templates/forms.html:157 msgid "Download" msgstr "Télécharger" -#: templates/home.html:8 +#: templates/home.html:7 msgid "Manage your shared
expenses, easily" msgstr "Gérez vos dépenses
partagées, facilement" @@ -387,39 +392,39 @@ msgstr "Gérez vos dépenses
partagées, facilement" msgid "Try out the demo" msgstr "Essayez la démo" -#: templates/home.html:12 +#: templates/home.html:13 msgid "You're sharing a house?" msgstr "Vous êtes en colocation ?" -#: templates/home.html:12 +#: templates/home.html:13 msgid "Going on holidays with friends?" msgstr "Partez en vacances avec des amis ?" -#: templates/home.html:12 +#: templates/home.html:13 msgid "Simply sharing money with others?" msgstr "Ça vous arrive de partager de l'argent avec d'autres ?" -#: templates/home.html:12 +#: templates/home.html:13 msgid "We can help!" msgstr "On peut vous aider !" -#: templates/home.html:24 +#: templates/home.html:21 msgid "Log to an existing project" msgstr "Se connecter à un projet existant" -#: templates/home.html:28 +#: templates/home.html:25 msgid "log in" msgstr "se connecter" -#: templates/home.html:29 +#: templates/home.html:26 msgid "can't remember your password?" msgstr "vous ne vous souvenez plus du code d'accès ?" -#: templates/home.html:36 +#: templates/home.html:34 templates/home.html:42 msgid "or create a new one" msgstr "ou créez en un nouveau" -#: templates/home.html:40 +#: templates/home.html:38 msgid "let's get started" msgstr "c'est parti !" @@ -435,95 +440,91 @@ msgstr "" msgid "Account manager" msgstr "Gestion de comptes" -#: templates/layout.html:45 templates/settle_bills.html:4 +#: templates/layout.html:39 msgid "Bills" msgstr "Factures" -#: templates/layout.html:46 templates/settle_bills.html:5 +#: templates/layout.html:40 msgid "Settle" msgstr "Remboursements" -#: templates/layout.html:50 +#: templates/layout.html:41 msgid "Statistics" msgstr "Statistiques" -#: templates/layout.html:53 +#: templates/layout.html:48 msgid "options" msgstr "options" -#: templates/layout.html:55 +#: templates/layout.html:50 msgid "Project settings" msgstr "Options du projet" -#: templates/layout.html:59 +#: templates/layout.html:54 msgid "switch to" msgstr "aller à" -#: templates/layout.html:62 +#: templates/layout.html:57 msgid "Start a new project" msgstr "Nouveau projet" -#: templates/layout.html:64 +#: templates/layout.html:59 msgid "Logout" msgstr "Se déconnecter" -#: templates/layout.html:92 +#: templates/layout.html:66 +msgid "Dashboard" +msgstr "" + +#: templates/layout.html:89 msgid "This is a free software" msgstr "Ceci est un logiciel libre" -#: templates/layout.html:92 +#: templates/layout.html:89 msgid "you can contribute and improve it!" msgstr "vous pouvez y contribuer et l'améliorer" -#: templates/list_bills.html:74 +#: templates/list_bills.html:63 +msgid "deactivate" +msgstr "désactiver" + +#: templates/list_bills.html:70 msgid "reactivate" msgstr "ré-activer" -#: templates/list_bills.html:88 -msgid "Invite" -msgstr "Invitez" - -#: templates/list_bills.html:88 +#: templates/list_bills.html:82 msgid "Invite people to join this project!" msgstr "Invitez d'autres personnes à rejoindre ce projet !" -#: templates/list_bills.html:89 +#: templates/list_bills.html:83 msgid "Add a new bill" msgstr "Nouvelle facture" -#: templates/list_bills.html:103 +#: templates/list_bills.html:101 msgid "When?" msgstr "Quand ?" -#: templates/list_bills.html:103 +#: templates/list_bills.html:101 msgid "Who paid?" msgstr "Qui a payé ?" -#: templates/list_bills.html:103 +#: templates/list_bills.html:101 msgid "For what?" msgstr "Pour quoi ?" -#: templates/list_bills.html:103 templates/settle_bills.html:31 +#: templates/list_bills.html:101 templates/settle_bills.html:22 msgid "How much?" msgstr "Combien ?" -#: templates/list_bills.html:103 -msgid "Actions" -msgstr "Actions" - -#: templates/list_bills.html:111 +#: templates/list_bills.html:109 msgid "each" msgstr "chacun" -#: templates/list_bills.html:113 -msgid "edit" -msgstr "éditer" - -#: templates/list_bills.html:122 +#: templates/list_bills.html:120 msgid "Nothing to list yet. You probably want to" msgstr "Rien à lister pour l'instant. Vous voulez surement" -#: templates/list_bills.html:122 +#: templates/list_bills.html:120 msgid "add a bill" msgstr "ajouter une facture" @@ -535,15 +536,15 @@ msgstr "Rappel du code d'accès" msgid "Your projects" msgstr "Vos projets" -#: templates/reset_password.html:2 +#: templates/reset_password.html:7 msgid "Reset your password" msgstr "Changez votre mot de passe" -#: templates/send_invites.html:11 +#: templates/send_invites.html:4 msgid "Invite people to join this project" msgstr "Invitez des personnes à rejoindre ce projet" -#: templates/send_invites.html:12 +#: templates/send_invites.html:5 msgid "" "Specify a (comma separated) list of email adresses you want to notify " "about the\n" @@ -553,33 +554,69 @@ msgstr "" "Entrez les addresses des personnes que vous souhaitez inviter, séparées " "par des virgules. On s'occupe de leur envoyer un email." -#: templates/send_invites.html:14 -msgid "If you prefer, you can share the project identifier and the shared\n" -"password by other communication means. Or even directly share the following link:" -msgstr "Si vous préférez vous pouvez partager l'identifiant du projet et son mot " -"de passe par un autre moyen de communication. Ou directement partager le lien " -"suivant :" +#: templates/send_invites.html:7 +msgid "" +"If you prefer, you can share the project identifier and the shared\n" +"password by other communication means. Or even directly share the " +"following link:" +msgstr "" +"Si vous préférez vous pouvez partager l'identifiant du projet et son mot " +"de passe par un autre moyen de communication. Ou directement partager le " +"lien suivant :" -#: templates/settle_bills.html:31 +#: templates/settle_bills.html:22 msgid "Who pays?" msgstr "Qui doit payer ?" -#: templates/settle_bills.html:31 +#: templates/settle_bills.html:22 msgid "To whom?" msgstr "Pour qui ?" -#: templates/statistics.html:22 +#: templates/statistics.html:21 msgid "Who?" msgstr "Qui ?" -#: templates/statistics.html:22 +#: templates/statistics.html:21 msgid "Paid" msgstr "A payé" -#: templates/statistics.html:22 +#: templates/statistics.html:21 msgid "Spent" msgstr "A dépensé" -#: templates/statistics.html:22 +#: templates/statistics.html:21 msgid "Balance" msgstr "Solde" + +#~ msgid "" +#~ "The project identifier is used to " +#~ "log in and for the URL of " +#~ "the project. We tried to generate " +#~ "an identifier for you but a " +#~ "project with this identifier already " +#~ "exists. Please create a new identifier" +#~ " that you will be able to " +#~ "remember." +#~ msgstr "" +#~ "L'identifiant du projet est utilisé pour" +#~ " se connecter.Nous avons essayé de " +#~ "générer un identifiant mais celui ci " +#~ "existe déjà. Merci de créer un " +#~ "nouvel identifiant que vous serez " +#~ "capable de retenir" + +#~ msgid "Start date" +#~ msgstr "Date de départ" + +#~ msgid "End date" +#~ msgstr "Date de fin" + +#~ msgid "\"No token provided\"" +#~ msgstr "Aucun token n'a été fourni." + +#~ msgid "User '%(name)s' has been deactivated" +#~ msgstr "Le membre '%(name)s' a été désactivé" + +#~ msgid "Invite" +#~ msgstr "Invitez" + -- cgit v1.1 From 1947a5ae785ab17d5da09548819f1e4ba6b0d85a Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Tue, 15 May 2018 21:50:31 +0200 Subject: update fr l10n --- ihatemoney/translations/fr/LC_MESSAGES/messages.po | 103 +++++++++++---------- 1 file changed, 53 insertions(+), 50 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/translations/fr/LC_MESSAGES/messages.po b/ihatemoney/translations/fr/LC_MESSAGES/messages.po index 334fa8e..5179f60 100644 --- a/ihatemoney/translations/fr/LC_MESSAGES/messages.po +++ b/ihatemoney/translations/fr/LC_MESSAGES/messages.po @@ -2,20 +2,21 @@ # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # Alexis Métaireau , 2011. -# +# Adrien CLERC, 2018. msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-05-15 21:43+0200\n" -"PO-Revision-Date: 2011-10-14 23:51+0200\n" -"Last-Translator: Quentin Roy \n" -"Language: fr\n" +"PO-Revision-Date: 2018-05-15 22:00+0200\n" +"Last-Translator: Adrien CLERC <>\n" "Language-Team: fr \n" -"Plural-Forms: nplurals=2; plural=(n > 1)\n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Virtaal 0.7.1\n" "Generated-By: Babel 2.5.3\n" #: forms.py:46 @@ -24,7 +25,7 @@ msgstr "Nom de projet" #: forms.py:47 forms.py:71 forms.py:88 msgid "Private code" -msgstr "Code d'accès" +msgstr "Code d’accès" #: forms.py:48 msgid "Email" @@ -45,6 +46,9 @@ msgid "" "identifier already exists. Please create a new identifier that you will " "be able to remember" msgstr "" +"L’identifiant du projet est utilisé pour se connecter et pour l’URL du " +"projet. Nous avons essayé de générer un identifiant mais celui ci existe " +"déjà. Merci de créer un nouvel identifiant que vous serez capable de retenir" #: forms.py:89 forms.py:94 msgid "Get in" @@ -60,11 +64,11 @@ msgstr "Envoyez moi le code par email" #: forms.py:103 msgid "This project does not exists" -msgstr "Ce projet n'existe pas" +msgstr "Ce projet n’existe pas" #: forms.py:108 msgid "Password mismatch" -msgstr "Les mots de passe fournis ne sont pas les mêmes." +msgstr "Les mots de passe sont différents" #: forms.py:109 msgid "Password" @@ -76,7 +80,7 @@ msgstr "Confirmation du mot de passe" #: forms.py:111 msgid "Reset password" -msgstr "" +msgstr "Réinitialiser le mot de passe" #: forms.py:115 msgid "Date" @@ -108,7 +112,7 @@ msgstr "Valider et ajouter une autre facture" #: forms.py:146 msgid "Bills can't be null" -msgstr "Le montant d'une facture ne peut pas être nul." +msgstr "Le montant d’une facture ne peut pas être nul" #: forms.py:151 msgid "Name" @@ -124,7 +128,7 @@ msgstr "Ajouter" #: forms.py:162 msgid "User name incorrect" -msgstr "Nom d'utilisateur incorrect" +msgstr "Nom d’utilisateur incorrect" #: forms.py:167 msgid "This project already have this member" @@ -141,11 +145,11 @@ msgstr "Envoyer les invitations" #: forms.py:190 #, python-format msgid "The email %(email)s is not valid" -msgstr "L'email %(email)s est invalide" +msgstr "L’email %(email)s est invalide" #: forms.py:196 msgid "What do you want to download ?" -msgstr "Que voulez-vous télécharger ?" +msgstr "Que voulez-vous télécharger ?" #: forms.py:199 msgid "bills" @@ -157,36 +161,36 @@ msgstr "remboursements" #: forms.py:201 msgid "Export file format" -msgstr "Format du fichier d'export" +msgstr "Format du fichier d’export" #: web.py:129 msgid "Too many failed login attempts, please retry later." -msgstr "Trop d'échecs d'authentification successifs, veuillez réessayer plus tard." +msgstr "Trop d'échecs d’authentification successifs, veuillez réessayer plus tard." #: web.py:144 #, python-format msgid "This admin password is not the right one. Only %(num)d attempts left." msgstr "" -"Le mot de passe administrateur que vous avez entré n'est pas correct. " +"Le mot de passe administrateur que vous avez entré n’est pas correct. " "Plus que %(num)d tentatives." #: web.py:167 msgid "You either provided a bad token or no project identifier." -msgstr "L'identifiant du projet ou le token fourni n'est pas correct." +msgstr "L’identifiant du projet ou le token fourni n’est pas correct." #: web.py:195 msgid "This private code is not the right one" -msgstr "Le code que vous avez entré n'est pas correct" +msgstr "Le code que vous avez entré n’est pas correct" #: web.py:242 #, python-format msgid "You have just created '%(project)s' to share your expenses" -msgstr "Vous venez de créer '%(project)s' pour partager vos dépenses" +msgstr "Vous venez de créer « %(project)s » pour partager vos dépenses" #: web.py:260 #, python-format msgid "%(msg_compl)sThe project identifier is %(project)s" -msgstr "L'identifiant de ce projet est '%(project)s'" +msgstr "%(msg_compl)sL’identifiant de ce projet est %(project)s" #: web.py:281 msgid "A link to reset your password has been sent to your email." @@ -194,7 +198,7 @@ msgstr "Un lien pour changer votre mot de passe vous a été envoyé par mail." #: web.py:291 msgid "No token provided" -msgstr "" +msgstr "Aucun token n’a été fourni" #: web.py:294 msgid "Invalid token" @@ -237,18 +241,18 @@ msgid "" "User '%(name)s' has been deactivated. It will still appear in the users " "list until its balance becomes zero." msgstr "" -"Le membre '%(name)s' a été désactivé. Il continuera d'apparaître jusqu'à " -"ce que sa balance devienne égale à zéro." +"Le membre « %(name)s » a été désactivé. Il continuera d’apparaître jusqu'à " +"ce que sa balance soit nulle." #: web.py:465 #, python-format msgid "User '%(name)s' has been removed" -msgstr "" +msgstr "Le membre « %(name)s » a été supprimé" #: web.py:480 #, python-format msgid "User '%(name)s' has been edited" -msgstr "" +msgstr "Le membre « %(name)s » a été édité" #: web.py:500 msgid "The bill has been added" @@ -268,11 +272,11 @@ msgstr "Retourner à la liste" #: templates/admin.html:10 msgid "Administration tasks are currently disabled." -msgstr "Les tâches d'administration sont actuellement désactivées." +msgstr "Les tâches d’administration sont actuellement désactivées." #: templates/authenticate.html:6 msgid "The project you are trying to access do not exist, do you want to" -msgstr "Le projet auquel vous essayez d'acceder n'existe pas. Souhaitez vous" +msgstr "Le projet auquel vous essayez d’accéder n’existe pas, souhaitez vous" #: templates/authenticate.html:8 msgid "create it" @@ -280,7 +284,7 @@ msgstr "le créer" #: templates/authenticate.html:8 msgid "?" -msgstr " ?" +msgstr " ?" #: templates/create_project.html:4 msgid "Create a new project" @@ -322,11 +326,11 @@ msgstr "supprimer" #: templates/dashboard.html:25 msgid "The Dashboard is currently deactivated." -msgstr "La page d'administration est actuellement désactivée." +msgstr "Le tableau de bord est actuellement désactivée." #: templates/edit_project.html:6 templates/list_bills.html:24 msgid "you sure?" -msgstr "c'est sûr ?" +msgstr "c’est sûr ?" #: templates/edit_project.html:11 msgid "Edit this project" @@ -338,7 +342,7 @@ msgstr "Télécharger les données de ce projet" #: templates/forms.html:27 msgid "Can't remember the password?" -msgstr "Vous ne vous souvenez plus du code d'accès ?" +msgstr "Vous ne vous souvenez plus du code d’accès ?" #: templates/forms.html:30 msgid "Cancel" @@ -386,7 +390,7 @@ msgstr "Télécharger" #: templates/home.html:7 msgid "Manage your shared
expenses, easily" -msgstr "Gérez vos dépenses
partagées, facilement" +msgstr "Gérez vos dépenses
partagées, facilement" #: templates/home.html:9 msgid "Try out the demo" @@ -402,7 +406,7 @@ msgstr "Partez en vacances avec des amis ?" #: templates/home.html:13 msgid "Simply sharing money with others?" -msgstr "Ça vous arrive de partager de l'argent avec d'autres ?" +msgstr "Ça vous arrive de partager de l’argent avec d’autres ?" #: templates/home.html:13 msgid "We can help!" @@ -418,7 +422,7 @@ msgstr "se connecter" #: templates/home.html:26 msgid "can't remember your password?" -msgstr "vous ne vous souvenez plus du code d'accès ?" +msgstr "vous ne vous souvenez plus du code d’accès ?" #: templates/home.html:34 templates/home.html:42 msgid "or create a new one" @@ -426,15 +430,15 @@ msgstr "ou créez en un nouveau" #: templates/home.html:38 msgid "let's get started" -msgstr "c'est parti !" +msgstr "c’est parti !" #: templates/home.html:51 msgid "" "This access code will be sent to your friends. It is stored as-is by the " "server, so don\\'t reuse a personal password!" msgstr "" -"Ce code d\\'accès va être envoyé à vos amis et stocké en clair sur le " -"serveur.N\\'utilisez pas un mot de passe personnel !" +"Ce code d’accès va être envoyé à vos amis et stocké en clair sur le serveur. " +"N’utilisez pas un mot de passe personnel !" #: templates/layout.html:5 msgid "Account manager" @@ -474,7 +478,7 @@ msgstr "Se déconnecter" #: templates/layout.html:66 msgid "Dashboard" -msgstr "" +msgstr "Tableau de bord" #: templates/layout.html:89 msgid "This is a free software" @@ -482,7 +486,7 @@ msgstr "Ceci est un logiciel libre" #: templates/layout.html:89 msgid "you can contribute and improve it!" -msgstr "vous pouvez y contribuer et l'améliorer" +msgstr "vous pouvez y contribuer et l’améliorer !" #: templates/list_bills.html:63 msgid "deactivate" @@ -494,7 +498,7 @@ msgstr "ré-activer" #: templates/list_bills.html:82 msgid "Invite people to join this project!" -msgstr "Invitez d'autres personnes à rejoindre ce projet !" +msgstr "Invitez d’autres personnes à rejoindre ce projet !" #: templates/list_bills.html:83 msgid "Add a new bill" @@ -522,7 +526,7 @@ msgstr "chacun" #: templates/list_bills.html:120 msgid "Nothing to list yet. You probably want to" -msgstr "Rien à lister pour l'instant. Vous voulez surement" +msgstr "Rien à lister pour l’instant. Vous voulez surement" #: templates/list_bills.html:120 msgid "add a bill" @@ -530,7 +534,7 @@ msgstr "ajouter une facture" #: templates/password_reminder.html:4 msgid "Password reminder" -msgstr "Rappel du code d'accès" +msgstr "Rappel du code d’accès" #: templates/recent_projects.html:2 msgid "Your projects" @@ -551,8 +555,8 @@ msgid "" "creation of this budget management project and we will send them an email" " for you." msgstr "" -"Entrez les addresses des personnes que vous souhaitez inviter, séparées " -"par des virgules. On s'occupe de leur envoyer un email." +"Entrez les adresses des personnes que vous souhaitez inviter,\n" +"séparées par des virgules, on s’occupe de leur envoyer un email." #: templates/send_invites.html:7 msgid "" @@ -560,9 +564,9 @@ msgid "" "password by other communication means. Or even directly share the " "following link:" msgstr "" -"Si vous préférez vous pouvez partager l'identifiant du projet et son mot " -"de passe par un autre moyen de communication. Ou directement partager le " -"lien suivant :" +"Si vous préférez vous pouvez partager l’identifiant du projet\n" +"et son mot de passe par un autre moyen de communication. Ou directement " +"partager le lien suivant :" #: templates/settle_bills.html:22 msgid "Who pays?" @@ -598,7 +602,7 @@ msgstr "Solde" #~ " that you will be able to " #~ "remember." #~ msgstr "" -#~ "L'identifiant du projet est utilisé pour" +#~ "L’identifiant du projet est utilisé pour" #~ " se connecter.Nous avons essayé de " #~ "générer un identifiant mais celui ci " #~ "existe déjà. Merci de créer un " @@ -612,11 +616,10 @@ msgstr "Solde" #~ msgstr "Date de fin" #~ msgid "\"No token provided\"" -#~ msgstr "Aucun token n'a été fourni." +#~ msgstr "Aucun token n’a été fourni." #~ msgid "User '%(name)s' has been deactivated" #~ msgstr "Le membre '%(name)s' a été désactivé" #~ msgid "Invite" #~ msgstr "Invitez" - -- cgit v1.1 From 0a9d16b40a715b96625bd29e9d1c82d77a352dd9 Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Tue, 15 May 2018 22:05:42 +0200 Subject: compile translations to MO --- ihatemoney/translations/fr/LC_MESSAGES/messages.mo | Bin 9762 -> 9912 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/translations/fr/LC_MESSAGES/messages.mo b/ihatemoney/translations/fr/LC_MESSAGES/messages.mo index 47b801d..c48d7cb 100644 Binary files a/ihatemoney/translations/fr/LC_MESSAGES/messages.mo and b/ihatemoney/translations/fr/LC_MESSAGES/messages.mo differ -- cgit v1.1 From 893db0bf2c3c6fe6f81a553d59e930d2d1a49dd2 Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Sun, 17 Jun 2018 09:48:19 +0200 Subject: fix fr l10n --- ihatemoney/translations/fr/LC_MESSAGES/messages.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ihatemoney') diff --git a/ihatemoney/translations/fr/LC_MESSAGES/messages.po b/ihatemoney/translations/fr/LC_MESSAGES/messages.po index 5179f60..a4a3e1b 100644 --- a/ihatemoney/translations/fr/LC_MESSAGES/messages.po +++ b/ihatemoney/translations/fr/LC_MESSAGES/messages.po @@ -242,7 +242,7 @@ msgid "" "list until its balance becomes zero." msgstr "" "Le membre « %(name)s » a été désactivé. Il continuera d’apparaître jusqu'à " -"ce que sa balance soit nulle." +"ce que son solde soit nul." #: web.py:465 #, python-format -- cgit v1.1 From a5240fb8a331f50ffc986c25a4a2ddf17e8fd693 Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Sun, 17 Jun 2018 09:49:10 +0200 Subject: compile l10n --- ihatemoney/translations/fr/LC_MESSAGES/messages.mo | Bin 9912 -> 9909 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'ihatemoney') diff --git a/ihatemoney/translations/fr/LC_MESSAGES/messages.mo b/ihatemoney/translations/fr/LC_MESSAGES/messages.mo index c48d7cb..3fa8d8f 100644 Binary files a/ihatemoney/translations/fr/LC_MESSAGES/messages.mo and b/ihatemoney/translations/fr/LC_MESSAGES/messages.mo differ -- cgit v1.1 From c3f8ddd274a40b164b5fceeab44c1c26cf053b04 Mon Sep 17 00:00:00 2001 From: JocelynDelalande Date: Mon, 16 Jul 2018 22:55:54 +0200 Subject: Fix Apache conf template, without relying on environment var (#359) `python-home` is prefered over `python-path`. It will work with or without a virtualenv. See http://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html --- ihatemoney/conf-templates/apache-vhost.conf.j2 | 2 +- ihatemoney/manage.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'ihatemoney') diff --git a/ihatemoney/conf-templates/apache-vhost.conf.j2 b/ihatemoney/conf-templates/apache-vhost.conf.j2 index 0527d31..e169589 100644 --- a/ihatemoney/conf-templates/apache-vhost.conf.j2 +++ b/ihatemoney/conf-templates/apache-vhost.conf.j2 @@ -1,7 +1,7 @@ ServerAdmin admin@example.com # CUSTOMIZE ServerName ihatemoney.example.com # CUSTOMIZE - WSGIDaemonProcess ihatemoney user=www-data group=www-data threads=5 python-path={{ pkg_path }} {% if bin_path %}python-home={{ bin_path }}{% endif %} + WSGIDaemonProcess ihatemoney user=www-data group=www-data threads=5 python-home={{ sys_prefix }} WSGIScriptAlias / {{ pkg_path }}/wsgi.py WSGIPassAuthorization On diff --git a/ihatemoney/manage.py b/ihatemoney/manage.py index 9058b39..3207b55 100755 --- a/ihatemoney/manage.py +++ b/ihatemoney/manage.py @@ -52,6 +52,7 @@ class GenerateConfig(Command): print(template.render( pkg_path=pkg_path, bin_path=bin_path, + sys_prefix=sys.prefix, secret_key=self.gen_secret_key(), )) -- cgit v1.1
{{ _("Who?") }}{{ _("Paid") }}{{ _("Spent") }}{{ _("Balance") }}
{{ member.name }}{{ "%0.2f"|format(paid[member.id]) }}{{ "%0.2f"|format(spent[member.id]) }}{{ "%0.2f"|format(balance[member.id]) }}{{ stat.member.name }}{{ "%0.2f"|format(stat.paid) }}{{ "%0.2f"|format(stat.spent) }}{{ "%0.2f"|format(stat.balance) }}
alexis20.0031.67alexis20.0031.67-11.67fred20.005.83fred20.005.8314.17tata0.002.50tata0.002.50-2.50toto0.000.00toto0.000.000.00