1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/ihatemoney_ynh.git synced 2024-09-03 19:26:15 +02:00

Translate the application using Flask-babel.

The only translation so far is french, but more can be added. The browser language
is used thanks to the HTTP languages headers.

There are still some problems with the translation of some strings, I don't know
why this is. See #12
This commit is contained in:
Alexis Metaireau 2011-10-15 01:19:19 +02:00
parent 45ccc8b509
commit f61d1432c7
27 changed files with 1037 additions and 108 deletions

3
budget/babel.cfg Normal file
View file

@ -0,0 +1,3 @@
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

View file

@ -1,4 +1,5 @@
from flaskext.wtf import *
from flaskext.babel import gettext as _
from flask import request
from wtforms.widgets import html_params
@ -40,10 +41,10 @@ def get_billform_for(project, set_default=True, **kwargs):
class EditProjectForm(Form):
name = TextField("Project name", validators=[Required()])
password = TextField("Private code", validators=[Required()])
contact_email = TextField("Email", validators=[Required(), Email()])
submit = SubmitField("Edit the project")
name = TextField(_("Project name"), validators=[Required()])
password = TextField(_("Private code"), validators=[Required()])
contact_email = TextField(_("Email"), validators=[Required(), Email()])
submit = SubmitField(_("Edit the project"))
def save(self):
"""Create a new project with the information given by this form.
@ -65,46 +66,39 @@ class EditProjectForm(Form):
class ProjectForm(EditProjectForm):
id = TextField("Project identifier", validators=[Required()])
password = PasswordField("Private code", validators=[Required()])
submit = SubmitField("Create the project")
id = TextField(_("Project identifier"), validators=[Required()])
password = PasswordField(_("Private code"), validators=[Required()])
submit = SubmitField(_("Create the project"))
def validate_id(form, field):
form.id.data = slugify(field.data)
if Project.query.get(form.id.data):
raise ValidationError(Markup("""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 you will be able
to remember.
"""))
raise ValidationError(Markup(_("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 you will be able to remember.")))
class AuthenticationForm(Form):
id = TextField("Project identifier", validators=[Required()])
password = PasswordField("Private code", validators=[Required()])
submit = SubmitField("Get in")
id = TextField(_("Project identifier"), validators=[Required()])
password = PasswordField(_("Private code"), validators=[Required()])
submit = SubmitField(_("Get in"))
class PasswordReminder(Form):
id = TextField("Project identifier", validators=[Required()])
submit = SubmitField("Send me the code by email")
id = TextField(_("Project identifier"), validators=[Required()])
submit = SubmitField(_("Send me the code by email"))
def validate_id(form, field):
if not Project.query.get(field.data):
raise ValidationError("This project does not exists")
raise ValidationError(_("This project does not exists"))
class BillForm(Form):
date = DateField("Date", validators=[Required()], default=datetime.now)
what = TextField("What?", validators=[Required()])
payer = SelectField("Payer", validators=[Required()], coerce=int)
amount = DecimalField("Amount payed", validators=[Required()])
payed_for = SelectMultipleField("Who has to pay for this?",
date = DateField(_("Date"), validators=[Required()], default=datetime.now)
what = TextField(_("What?"), validators=[Required()])
payer = SelectField(_("Payer"), validators=[Required()], coerce=int)
amount = DecimalField(_("Amount payed"), validators=[Required()])
payed_for = SelectMultipleField(_("Who has to pay for this?"),
validators=[Required()], widget=select_multi_checkbox, coerce=int)
submit = SubmitField("Send the bill")
submit = SubmitField(_("Send the bill"))
def save(self, bill, project):
bill.payer_id=self.payer.data
@ -129,8 +123,8 @@ class BillForm(Form):
class MemberForm(Form):
name = TextField("Name", validators=[Required()])
submit = SubmitField("Add a member")
name = TextField(_("Name"), validators=[Required()])
submit = SubmitField(_("Add a member"))
def __init__(self, project, *args, **kwargs):
super(MemberForm, self).__init__(*args, **kwargs)
@ -140,7 +134,7 @@ class MemberForm(Form):
if Person.query.filter(Person.name == field.data)\
.filter(Person.project == form.project)\
.filter(Person.activated == True).all():
raise ValidationError("This project already have this member")
raise ValidationError(_("This project already have this member"))
def save(self, project, person):
# if the user is already bound to the project, just reactivate him
@ -150,17 +144,18 @@ class MemberForm(Form):
return person
class InviteForm(Form):
emails = TextAreaField("People to notify")
submit = SubmitField("Send invites")
emails = TextAreaField(_("People to notify"))
submit = SubmitField(_("Send invites"))
def validate_emails(form, field):
validator = Email()
for email in [email.strip() for email in form.emails.data.split(",")]:
if not validator.regex.match(email):
raise ValidationError("The email %s is not valid" % email)
raise ValidationError(_("The email %(email)s is not valid",
email=email))
class CreateArchiveForm(Form):
start_date = DateField("Start date", validators=[Required(),])
end_date = DateField("End date", validators=[Required(),])
name = TextField("Name for this archive (optional)")
start_date = DateField(_("Start date"), validators=[Required(),])
end_date = DateField(_("End date"), validators=[Required(),])
name = TextField(_("Name for this archive (optional)"))

445
budget/messages.pot Normal file
View file

@ -0,0 +1,445 @@
# Translations template for PROJECT.
# Copyright (C) 2011 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2011-10-15 00:42+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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"
#: forms.py:44
msgid "Project name"
msgstr ""
#: forms.py:45 forms.py:70 forms.py:81
msgid "Private code"
msgstr ""
#: forms.py:46
msgid "Email"
msgstr ""
#: forms.py:47
msgid "Edit the project"
msgstr ""
#: forms.py:69 forms.py:80 forms.py:86
msgid "Project identifier"
msgstr ""
#: forms.py:71 templates/send_invites.html:5
msgid "Create the project"
msgstr ""
#: forms.py:76
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 you will be "
"able to remember."
msgstr ""
#: forms.py:82
msgid "Get in"
msgstr ""
#: forms.py:87
msgid "Send me the code by email"
msgstr ""
#: forms.py:91
msgid "This project does not exists"
msgstr ""
#: forms.py:95
msgid "Date"
msgstr ""
#: forms.py:96
msgid "What?"
msgstr ""
#: forms.py:97
msgid "Payer"
msgstr ""
#: forms.py:98
msgid "Amount payed"
msgstr ""
#: forms.py:99
msgid "Who has to pay for this?"
msgstr ""
#: forms.py:101
msgid "Send the bill"
msgstr ""
#: forms.py:126
msgid "Name"
msgstr ""
#: forms.py:127
msgid "Add a member"
msgstr ""
#: forms.py:137
msgid "This project already have this member"
msgstr ""
#: forms.py:147
msgid "People to notify"
msgstr ""
#: forms.py:148
msgid "Send invites"
msgstr ""
#: forms.py:154
#, python-format
msgid "The email %s is not valid"
msgstr ""
#: forms.py:158
msgid "Start date"
msgstr ""
#: forms.py:159
msgid "End date"
msgstr ""
#: forms.py:160
msgid "Name for this archive (optional)"
msgstr ""
#: web.py:91
msgid "This private code is not the right one"
msgstr ""
#: web.py:139
#, python-format
msgid "You have just created '%(projec)s' to share your expenses"
msgstr ""
#: web.py:150
#, python-format
msgid "The project identifier is %(project)s"
msgstr ""
#: web.py:167
msgid "a mail has been sent to you with the password"
msgstr ""
#: web.py:225
#, python-format
msgid "You have been invited to share your expenses for %(project)s"
msgstr ""
#: web.py:232
msgid "Your invitations have been sent"
msgstr ""
#: web.py:253
#, python-format
msgid "%(member)s had been added"
msgstr ""
#: web.py:265
#, python-format
msgid "%(name)s is part of this project again"
msgstr ""
#: web.py:273
#, python-format
msgid "User '%(name)s' has been deactivated"
msgstr ""
#: web.py:275
#, python-format
msgid "User '%(name)s' has been removed"
msgstr ""
#: web.py:288
msgid "The bill has been added"
msgstr ""
#: web.py:303
msgid "The bill has been deleted"
msgstr ""
#: web.py:321
msgid "The bill has been modified"
msgstr ""
#: web.py:338
msgid "The data from XX to XX has been archived"
msgstr ""
#: templates/add_bill.html:4 templates/edit_bill.html:4
msgid "Back to the list"
msgstr ""
#: templates/authenticate.html:6
msgid ""
"The project you are trying to access do not exist, do you want \n"
"to"
msgstr ""
#: templates/authenticate.html:7
msgid "create it"
msgstr ""
#: templates/authenticate.html:7
msgid "?"
msgstr ""
#: templates/create_project.html:4
msgid "Create a new project"
msgstr ""
#: templates/edit_bill.html:8
msgid "Edit a bill"
msgstr ""
#: templates/edit_project.html:4
msgid "Edit this project"
msgstr ""
#: templates/forms.html:24
msgid "Can't remember the password?"
msgstr ""
#: templates/forms.html:27
msgid "Cancel"
msgstr ""
#: templates/forms.html:75
msgid "Edit this bill"
msgstr ""
#: templates/forms.html:75
msgid "Add a bill"
msgstr ""
#: templates/forms.html:91
msgid "Add a new user"
msgstr ""
#: templates/forms.html:99
msgid "Send the invitations"
msgstr ""
#: templates/forms.html:100
msgid "No, thanks"
msgstr ""
#: templates/forms.html:106
msgid "Create an archive"
msgstr ""
#: templates/forms.html:112
msgid "Create the archive"
msgstr ""
#: templates/home.html:9
msgid "Manage your shared <br>expenses, easily"
msgstr ""
#: templates/home.html:10
msgid "Try out the demo"
msgstr ""
#: templates/home.html:13
msgid "You're sharing a house?"
msgstr ""
#: templates/home.html:13
msgid "Going on holidays with friends?"
msgstr ""
#: templates/home.html:13
msgid "Simply sharing money with others?"
msgstr ""
#: templates/home.html:13
msgid "We can help!"
msgstr ""
#: templates/home.html:26
msgid "Log to an existing project"
msgstr ""
#: templates/home.html:28
msgid "log in"
msgstr ""
#: templates/home.html:29
msgid "can't remember your password?"
msgstr ""
#: templates/home.html:34
msgid "or create a new one"
msgstr ""
#: templates/home.html:36
msgid "let's get started"
msgstr ""
#: templates/layout.html:5
msgid "Account manager"
msgstr ""
#: templates/layout.html:48
msgid "Bills"
msgstr ""
#: templates/layout.html:49
msgid "Archives"
msgstr ""
#: templates/layout.html:53
msgid "options"
msgstr ""
#: templates/layout.html:55
msgid "Project settings"
msgstr ""
#: templates/layout.html:59
msgid "switch to"
msgstr ""
#: templates/layout.html:62
msgid "Start a new project"
msgstr ""
#: templates/layout.html:64
msgid "Logout"
msgstr ""
#: templates/layout.html:85
msgid "This is a free software"
msgstr ""
#: templates/layout.html:85
msgid "you can contribute and improve it!"
msgstr ""
#: templates/list_bills.html:30
msgid "you sure?"
msgstr ""
#: templates/list_bills.html:45
msgid "Balance"
msgstr ""
#: templates/list_bills.html:56 templates/list_bills.html:88
msgid "delete"
msgstr ""
#: templates/list_bills.html:56
msgid "reactivate"
msgstr ""
#: templates/list_bills.html:68
msgid "The project identifier is"
msgstr ""
#: templates/list_bills.html:68
msgid "remember it or add this page to you bookmarks!"
msgstr ""
#: templates/list_bills.html:70
msgid "Add a new bill"
msgstr ""
#: templates/list_bills.html:72
msgid "hide this form"
msgstr ""
#: templates/list_bills.html:78
msgid "When?"
msgstr ""
#: templates/list_bills.html:78
msgid "Who paid?"
msgstr ""
#: templates/list_bills.html:78
msgid "For what?"
msgstr ""
#: templates/list_bills.html:78
msgid "Owers"
msgstr ""
#: templates/list_bills.html:78
msgid "How much?"
msgstr ""
#: templates/list_bills.html:78
msgid "Actions"
msgstr ""
#: templates/list_bills.html:87
msgid "edit"
msgstr ""
#: templates/list_bills.html:95
msgid "Nothing to list yet. You probably want to"
msgstr ""
#: templates/list_bills.html:95
msgid "add a bill"
msgstr ""
#: templates/password_reminder.html:4
msgid "Password reminder"
msgstr ""
#: templates/recent_projects.html:2
msgid "Your projects"
msgstr ""
#: templates/send_invites.html:6
msgid "Invite people"
msgstr ""
#: templates/send_invites.html:7
msgid "Use it!"
msgstr ""
#: templates/send_invites.html:11
msgid "Invite people to join this project"
msgstr ""
#: templates/send_invites.html:12
msgid ""
"Specify a (coma 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"
msgstr ""
#: templates/send_invites.html:14
msgid "skip this step"
msgstr ""
#: templates/send_invites.html:14
msgid "and notify them yourself"
msgstr ""

View file

@ -176,4 +176,3 @@ class Archive(db.Model):
def __repr__(self):
return "<Archive>"

View file

@ -2,3 +2,4 @@ flask
flask-wtf
flask-sqlalchemy
flask-mail
flask-babel

View file

@ -1,4 +1,4 @@
from web import main, db, mail
from web import main, db, mail, babel
from api import api
import os
@ -10,7 +10,6 @@ app.config.from_object("default_settings")
app.register_blueprint(main)
app.register_blueprint(api)
# db
db.init_app(app)
db.app = app
@ -19,6 +18,14 @@ db.create_all()
# mail
mail.init_app(app)
# translations
babel.init_app(app)
@babel.localeselector
def get_locale():
return request.accept_languages.best_match(['fr', 'en'])
def main():
app.run(host="0.0.0.0", debug=True)

View file

@ -1,7 +1,7 @@
{% extends "layout.html" %}
{% block top_menu %}
<a href="{{ url_for(".list_bills") }}">Back to the list</a>
<a href="{{ url_for(".list_bills") }}">{{ _("Back to the list") }}</a>
{% endblock %}
{% block content %}

View file

@ -3,8 +3,8 @@
<h2>Authentication</h2>
{% if create_project %}
<p class="info">The project you are trying to access do not exist, do you want
to <a href="{{ url_for(".create_project", project_id=create_project) }}">create it</a>?
<p class="info">{{ _("The project you are trying to access do not exist, do you want
to") }} <a href="{{ url_for(".create_project", project_id=create_project) }}">{{ _("create it") }}</a>{{ _("?") }}
</p>
{% endif %}
<form action="" method="POST" accept-charset="utf-8">

View file

@ -1,7 +1,7 @@
{% extends "layout.html" %}
{% block content %}
<h2>Create a new project</h2>
<h2>{{ _("Create a new project") }}</h2>
<form method="post">
{{ forms.create_project(form) }}
</form>

View file

@ -1,11 +1,11 @@
{% extends "layout.html" %}
{% block top_menu %}
<a href="{{ url_for(".list_bills") }}">Back to the list</a>
<a href="{{ url_for(".list_bills") }}">{{ _("Back to the list") }}</a>
{% endblock %}
{% block content %}
<h2>Edit a bill</h2>
<h2>{{ _("Edit a bill") }}</h2>
<div class="container span-24 add-bill uniForm" style="width: 400px">
<form action="" method="post" class=uniForm">

View file

@ -1,7 +1,7 @@
{% extends "layout.html" %}
{% block content %}
<h2>Edit this project</h2>
<h2>{{ _("Edit this project") }}</h2>
<form method="post">
{{ forms.edit_project(form) }}
</form>

View file

@ -21,10 +21,10 @@
<div class="actions">
<button type="submit" class="btn primary">{{ field.name }}</button>
{% if home %}
<a href="{{ url_for(".remind_password") }}">Can't remember the password?</a>
<a href="{{ url_for(".remind_password") }}">{{ _("Can't remember the password?") }}</a>
{% endif %}
{% if cancel %}
<button id="cancel-form" type="reset" class="btn">Cancel</button>
<button id="cancel-form" type="reset" class="btn">{{ _("Cancel") }}</button>
{% endif %}
</div>
{% endmacro %}
@ -72,7 +72,7 @@
{% macro add_bill(form, edit=False) %}
<fieldset>
<legend>{% if edit %}Edit this {% else %}Add a {% endif %}bill</legend>
<legend>{% if edit %}{{ _("Edit this bill") }} {% else %}{{ _("Add a bill") }} {% endif %}</legend>
{% include "display_errors.html" %}
{{ form.hidden_tag() }}
{{ input(form.date) }}
@ -88,7 +88,7 @@
{% macro add_member(form) %}
{{ form.hidden_tag() }}
{{ form.name }}
<button class="btn">Add a new user</button>
<button class="btn">{{ _("Add a new user") }}</button>
{% endmacro %}
@ -96,20 +96,20 @@
{{ form.hidden_tag() }}
{{ input(form.emails) }}
<div class="actions">
<button class="btn primary">Send the invitations</button>
<a href="{{ url_for(".list_bills") }}">No, thanks</a>
<button class="btn primary">{{ _("Send the invitations") }}</button>
<a href="{{ url_for(".list_bills") }}">{{ _("No, thanks") }}</a>
</div>
{% endmacro %}
{% macro create_archive(form) %}
<fieldset>
<legend>Create an archive</legend>
<legend>{{ _("Create an archive") }}</legend>
{{ form.hidden_tag() }}
{{ input(form.start_date) }}
{{ input(form.end_date) }}
</fieldset>
<div class="actions">
<button class="btn">Create the archive</button>
<button class="btn">{{ _("Create the archive") }}</button>
</div>
{% endmacro %}

View file

@ -6,11 +6,11 @@
{% block header %}
<div id="header">
<div class="slide">
<h1><span>Manage your shared <br>expenses, easily</span></h1>
<a href="{{ url_for(".demo") }}" class="about_link">Try out the demo</a>
<h1><span>{{ _("Manage your shared <br>expenses, easily") }}</span></h1>
<a href="{{ url_for(".demo") }}" class="about_link">{{ _("Try out the demo") }}</a>
</div>
<div class="additional-content">
<p>You're sharing a house?<br /> Going on holidays with friends?<br /> Simply sharing money with others? <br /><strong>We can help!</strong></p>
<p>{{ _("You're sharing a house?") }}<br /> {{ _("Going on holidays with friends?") }}<br /> {{ _("Simply sharing money with others?") }} <br /><strong>{{ _("We can help!") }}</strong></p>
</div>
</div>
@ -23,17 +23,17 @@
<div class="row">
<div class="span8 columns">
<form action="{{ url_for(".authenticate") }}" method="post">
<h3>Log to an existing project...</h3>
<h3>{{ _("Log to an existing project") }}...</h3>
{{ forms.authenticate(auth_form, home=True) }}
<button class="btn">log in</button>
<a class="password-reminder" href="{{ url_for(".remind_password") }}">can't remember your password?</a>
<button class="btn">{{ _("log in") }}</button>
<a class="password-reminder" href="{{ url_for(".remind_password") }}">{{ _("can't remember your password?") }}</a>
</form>
</div>
<div class="span8 columns">
<form class="create" action="{{ url_for(".create_project") }}" method="post">
<h3>...or create a new one</h3>
<h3>...{{ _("or create a new one") }}</h3>
{{ forms.create_project(project_form, home=True) }}
<button class="btn">let's get started</button>
<button class="btn">{{ _("let's get started") }}</button>
</form>
</div>
</div>

View file

@ -0,0 +1,9 @@
Salut,
Quelqu'un avec l'addresse email "{{ g.project.contact_email }}" vuos à 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 accéder à la page ici: {{ config['SITE_URL'] }}{{ url_for(".list_bills") }}, le code est "{{ g.project.password }}".
Have fun,

View file

@ -2,7 +2,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Account manager</title>
<title>{{ _("Account manager") }}</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel=stylesheet type=text/css href="{{ url_for("static", filename='main.css') }}">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
@ -45,23 +45,23 @@
<h3><a class="logo" href="{% if g.project %}{{ url_for(".list_bills") }}{% endif %}">#! money?</a></h3>
{% if g.project %}
<ul>
<li class="active"><a href="">Bills</a></li>
<li><a href="">Archives</a></li>
<li class="active"><a href="">{{ _("Bills") }}</a></li>
<li><a href="">{{ _("Archives") }}</a></li>
</ul>
<ul class="nav secondary-nav">
<li class="menu">
<a href="#" class="menu"><strong>{{ g.project.name }}</strong> options</a>
<a href="#" class="menu"><strong>{{ g.project.name }}</strong> {{ _("options") }}</a>
<ul class="menu-dropdown" style="display: none; ">
<li><a href="{{ url_for(".edit_project") }}">Project settings</a></li>
<li><a href="{{ url_for(".edit_project") }}">{{ _("Project settings") }}</a></li>
<li class="divider"></li>
{% for id, name in session['projects'] %}
{% if id != g.project.id %}
<li><a href="{{ url_for(".list_bills", project_id=id) }}">switch to {{ name }}</a></li>
<li><a href="{{ url_for(".list_bills", project_id=id) }}">{{ _("switch to") }} {{ name }}</a></li>
{% endif %}
{% endfor %}
<li><a href="{{ url_for(".create_project") }}">Start a new project</a></li>
<li><a href="{{ url_for(".create_project") }}">{{ _("Start a new project") }}</a></li>
<li class="divider"></li>
<li><a href="{{ url_for(".exit") }}">Logout</a></li>
<li><a href="{{ url_for(".exit") }}">{{ _("Logout") }}</a></li>
</ul>
</li>
</ul>
@ -82,7 +82,7 @@
{% endblock %}
{% block footer %}
<div id="footer">
<p><a href="https://github.com/ametaireau/budget-manager">This is a free software</a>, you can contribute and improve it!</p>
<p><a href="https://github.com/ametaireau/budget-manager">{{ _("This is a free software") }}</a>, {{ _("you can contribute and improve it!") }}</p>
</div>
{% endblock %}

View file

@ -27,7 +27,7 @@
if ($(this).hasClass("confirm")){
return true;
}
$(this).html("you sure?");
$(this).html("{{_("you sure?")}}");
$(this).addClass("confirm");
return false;
});
@ -42,7 +42,7 @@
{% endblock %}
{% block sidebar %}
<h2>Balance</h2>
<h2>{{ _("Balance") }}</h2>
<table class="balance">
{% set balance = g.project.get_balance() %}
@ -53,7 +53,7 @@
<td class="{% if balance[member] > 0 %}positive{% elif balance[member] < 0 %}negative{% endif %}">
{% if balance[member] > 0 %}+{% endif %}{{ balance[member] }}
</td>
<td> {% if member.activated %}<a class="remove" href="{{ url_for(".remove_member", member_id=member.id) }}">delete</a>{% else %}<a href="{{ url_for(".reactivate", member_id=member.id) }}">reactivate</a>{% endif %}</td>
<td> {% if member.activated %}<a class="remove" href="{{ url_for(".remove_member", member_id=member.id) }}">{{ _("delete") }}</a>{% else %}<a href="{{ url_for(".reactivate", member_id=member.id) }}">{{ _("reactivate") }}</a>{% endif %}</td>
</tr>
{% endif %}
{% endfor %}
@ -65,17 +65,17 @@
{% endblock %}
{% block content %}
<div class="identifier">The project identifier is <a href="{{ url_for(".list_bills") }}">{{ g.project.id }}</a>, remember it or add this page to you bookmarks!</div>
<div class="identifier">{{ _("The project identifier is") }} <a href="{{ url_for(".list_bills") }}">{{ g.project.id }}</a>, {{ _("remember it or add this page to you bookmarks!") }}</div>
<br /><br />
<a id="new-bill" href="{{ url_for(".add_bill") }}" class="primary">Add a new bill</a>
<a id="new-bill" href="{{ url_for(".add_bill") }}" class="primary">{{ _("Add a new bill") }}</a>
<form id="bill-form" action="{{ url_for(".add_bill") }}" method="post" style="display: none">
<a id="hide-bill-form" href="#">hide this form</a>
<a id="hide-bill-form" href="#">{{ _("hide this form") }}</a>
{{ forms.add_bill(bill_form) }}
</form>
{% if bills.count() > 0 %}
<table class="list_bills common-table zebra-striped">
<thead><tr><th>When?</th><th>Who paid?</th><th>For what?</th><th>Owers</th><th>How much?</th><th>Actions</th></tr></thead>
<thead><tr><th>{{ _("When?") }}</th><th>{{ _("Who paid?") }}</th><th>{{ _("For what?") }}</th><th>{{ _("Owers") }}</th><th>{{ _("How much?") }}</th><th>{{ _("Actions") }}</th></tr></thead>
<tbody>
{% for bill in bills %}
<tr class="{{ loop.cycle("odd", "even") }}">
@ -84,15 +84,15 @@
<td>{{ bill.what }}</td>
<td>{% for ower in bill.owers %}{{ ower.name }} {% endfor %}</td>
<td>{{ bill.amount }} ({{ bill.pay_each() }} each)</td>
<td><a href="{{ url_for(".edit_bill", bill_id=bill.id) }}">edit</a>
<a class="delete" href="{{ url_for(".delete_bill", bill_id=bill.id) }}">delete</a></td>
<td><a href="{{ url_for(".edit_bill", bill_id=bill.id) }}">{{ _("edit") }}</a>
<a class="delete" href="{{ url_for(".delete_bill", bill_id=bill.id) }}">{{ _("delete") }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>Nothing to list yet. You probably want to <a id="empty-new-bill" href="{{ url_for(".add_bill") }}">add a bill</a> ?</p>
<p>{{ _("Nothing to list yet. You probably want to") }} <a id="empty-new-bill" href="{{ url_for(".add_bill") }}">{{ _("add a bill") }}</a> ?</p>
{% endif %}
</div>
{% endblock %}

View file

@ -0,0 +1,7 @@
Salut,
Vous avez demandez des informations sur votre mot de passe pour "{{ project.name }}".
Vous pouvez y accéder ici {{ config['SITE_URL'] }}{{ url_for(".list_bills", project_id=project.id) }}, le code d'accès est "{{ project.password }}".
Faites en bon usage !

View file

@ -1,7 +1,7 @@
{% extends "layout.html" %}
{% block content %}
<h2>Password reminder</h2>
<h2>{{ _("Password reminder") }}</h2>
<form method="post">
{{ forms.remind_password(form) }}
</form>

View file

@ -1,5 +1,5 @@
{% if 'projects' in session %}
<h3>Your projects</h3>
<h3>{{ _("Your projects") }}</h3>
<ul>
{% for id, name in session['projects'] %}
<li><a href="{{ url_for("list_bills", project_id=id) }}">{{ name }}</a></li>

View file

@ -0,0 +1,8 @@
Hey,
Vous venez de créer le projet "{{ g.project.name }}" pour partager vos dépenses.
Vous pouvez y accéder ici: {{ config['SITE_URL'] }}{{ url_for(".list_bills") }} (l'identifieur est {{ g.project.id }}),
et le code d'accès "{{ g.project.password }}".
Faites en bon usage !

View file

@ -2,16 +2,16 @@
{% block sidebar %}
<ol>
<li>Create the project</li>
<li><strong>Invite people</strong></li>
<li><a href="{{ url_for(".list_bills") }}">Use it!</a></li>
<li>{{ _("Create the project") }}</li>
<li><strong>{{ _("Invite people") }}</strong></li>
<li><a href="{{ url_for(".list_bills") }}">{{ _("Use it!") }}</a></li>
</ol>
{% endblock %}
{% block content %}
<h2>Invite people to join this project</h2>
<p>Specify a (coma separated) list of email adresses you want to notify about the
creation of this budget management project and we will send them an email for you.</p>
<p>If you prefer, you can <a href="{{ url_for(".list_bills") }}">skip this step</a> and notify them yourself</p>
<h2>{{ _("Invite people to join this project") }}</h2>
<p>{{ _("Specify a (coma separated) list of email adresses you want to notify about the
creation of this budget management project and we will send them an email for you.") }}</p>
<p>{{ _("If you prefer, you can") }} <a href="{{ url_for(".list_bills") }}">{{ _("skip this step") }}</a> {{ _("and notify them yourself") }}</p>
{% include "display_errors.html" %}
<form class="invites" method="post" accept-charset="utf-8">

Binary file not shown.

View file

@ -0,0 +1,450 @@
# French translations for PROJECT.
# Copyright (C) 2011 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2011-10-15 00:42+0200\n"
"PO-Revision-Date: 2011-10-14 23:51+0200\n"
"Last-Translator: Alexis Métaireau <alexis@notmyidea.org>\n"
"Language-Team: fr <LL@li.org>\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"
#: forms.py:44
msgid "Project name"
msgstr "Nom de projet"
#: forms.py:45 forms.py:70 forms.py:81
msgid "Private code"
msgstr "Code d'accès"
#: forms.py:46
msgid "Email"
msgstr "Email"
#: forms.py:47
msgid "Edit the project"
msgstr "Éditer le projet"
#: forms.py:69 forms.py:80 forms.py:86
msgid "Project identifier"
msgstr "Identifiant de projet"
#: forms.py:71 templates/send_invites.html:5
msgid "Create the project"
msgstr "Créer le projet"
#: forms.py:76
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 you will be "
"able to remember."
msgstr ""
"L'identifiant de projet est utilisé pour se connecter et dans l'URL du "
"projetNous avons essayé de générer une identifiant pour ce projet mais "
"celui ci existedéjà. Merci de créer un nouvel identifiant que vous serez "
"capable de retenir"
#: forms.py:82
msgid "Get in"
msgstr "Entrer"
#: forms.py:87
msgid "Send me the code by email"
msgstr "Envoyez moi le code par email"
#: forms.py:91
msgid "This project does not exists"
msgstr "Ce projet n'existe pas"
#: forms.py:95
msgid "Date"
msgstr "Date"
#: forms.py:96
msgid "What?"
msgstr "Quoi ?"
#: forms.py:97
msgid "Payer"
msgstr "Payeur"
#: forms.py:98
msgid "Amount payed"
msgstr "Montant"
#: forms.py:99
msgid "Who has to pay for this?"
msgstr "Qui doit payer pour ça ?"
#: forms.py:101
msgid "Send the bill"
msgstr "Enregistrer la facture"
#: forms.py:126
msgid "Name"
msgstr "Nom"
#: forms.py:127
msgid "Add a member"
msgstr "Ajouter un membre"
#: forms.py:137
msgid "This project already have this member"
msgstr "Ce membre existe déjà pour ce projet"
#: forms.py:147
msgid "People to notify"
msgstr "Personnes à prévenir"
#: forms.py:148
msgid "Send invites"
msgstr "Envoyer les invitations"
#: forms.py:154
#, python-format
msgid "The email %s is not valid"
msgstr "L'email %s est invalide"
#: forms.py:158
msgid "Start date"
msgstr "Date de départ"
#: forms.py:159
msgid "End date"
msgstr "Date de fin"
#: forms.py:160
msgid "Name for this archive (optional)"
msgstr "Nom pour cette archive"
#: web.py:91
msgid "This private code is not the right one"
msgstr "Le code que vous avez entré n'est pas correct"
#: web.py:139
#, 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:150
#, python-format
msgid "The project identifier is %(project)s"
msgstr "L'identifiant de ce projet est '%(project)s'"
#: web.py:167
msgid "a mail has been sent to you with the password"
msgstr "Un email vous à été envoyé avec le mot de passe"
#: web.py:225
#, 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:232
msgid "Your invitations have been sent"
msgstr "Vos invitations ont bien été envoyées"
#: web.py:253
#, python-format
msgid "%(member)s had been added"
msgstr "%(member)s à bien été ajouté"
#: web.py:265
#, python-format
msgid "%(name)s is part of this project again"
msgstr "%(name)s à rejoint le projet"
#: web.py:273
#, python-format
msgid "User '%(name)s' has been deactivated"
msgstr "Le membre '%(name)s' à été désactivé"
#: web.py:275
#, python-format
msgid "User '%(name)s' has been removed"
msgstr "Le membre '%(name)s' à été supprimé"
#: web.py:288
msgid "The bill has been added"
msgstr "La facture à bien été ajoutée"
#: web.py:303
msgid "The bill has been deleted"
msgstr "La facture à été supprimée"
#: web.py:321
msgid "The bill has been modified"
msgstr "La facture à été modifiée"
#: web.py:338
msgid "The data from XX to XX has been archived"
msgstr "Les données de XX à XX ont été archivées"
#: templates/add_bill.html:4 templates/edit_bill.html:4
msgid "Back to the list"
msgstr "Retourner à la liste"
#: templates/authenticate.html:6
msgid ""
"The project you are trying to access do not exist, do you want \n"
"to"
msgstr "Le projet auquel vous essayez d'acceder n'existe pas. Souhaitez vous"
#: templates/authenticate.html:7
msgid "create it"
msgstr "le créer"
#: templates/authenticate.html:7
msgid "?"
msgstr " ?"
#: templates/create_project.html:4
msgid "Create a new project"
msgstr "Créer un nouveau projet"
#: templates/edit_bill.html:8
msgid "Edit a bill"
msgstr "Éditer une facture"
#: templates/edit_project.html:4
msgid "Edit this project"
msgstr "Éditer ce projet"
#: templates/forms.html:24
msgid "Can't remember the password?"
msgstr "Vous ne vous rappelez plus du code d'accès ?"
#: templates/forms.html:27
msgid "Cancel"
msgstr "Annuler"
#: templates/forms.html:75
msgid "Edit this bill"
msgstr "Éditer cette facture"
#: templates/forms.html:75
msgid "Add a bill"
msgstr "Ajouter une facture"
#: templates/forms.html:91
msgid "Add a new user"
msgstr "Ajouter un membre"
#: templates/forms.html:99
msgid "Send the invitations"
msgstr "Envoyer les invitations"
#: templates/forms.html:100
msgid "No, thanks"
msgstr "Non merci"
#: templates/forms.html:106
msgid "Create an archive"
msgstr "Créer une archive"
#: templates/forms.html:112
msgid "Create the archive"
msgstr "Créer l'archive"
#: templates/home.html:9
msgid "Manage your shared <br>expenses, easily"
msgstr "Gérez vos dépenses<br> partagées, facilement"
#: templates/home.html:10
msgid "Try out the demo"
msgstr "Essayez la démo"
#: templates/home.html:13
msgid "You're sharing a house?"
msgstr "Vous êtes en colocation ?"
#: templates/home.html:13
msgid "Going on holidays with friends?"
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 ?"
#: templates/home.html:13
msgid "We can help!"
msgstr "On peut vous aider !"
#: templates/home.html:26
msgid "Log to an existing project"
msgstr "Se connecter à un projet existant"
#: templates/home.html:28
msgid "log in"
msgstr "se connecter"
#: templates/home.html:29
msgid "can't remember your password?"
msgstr "vous ne vous rappelez plus du code d'accès ?"
#: templates/home.html:34
msgid "or create a new one"
msgstr "ou créez en un nouveau"
#: templates/home.html:36
msgid "let's get started"
msgstr "c'est parti !"
#: templates/layout.html:5
msgid "Account manager"
msgstr "Gestion de comptes"
#: templates/layout.html:48
msgid "Bills"
msgstr "Factures"
#: templates/layout.html:49
msgid "Archives"
msgstr "Archives"
#: templates/layout.html:53
msgid "options"
msgstr "options"
#: templates/layout.html:55
msgid "Project settings"
msgstr "Options du projet"
#: templates/layout.html:59
msgid "switch to"
msgstr "aller à"
#: templates/layout.html:62
msgid "Start a new project"
msgstr "Démarrer un nouveau projet"
#: templates/layout.html:64
msgid "Logout"
msgstr "Se déconnecter"
#: templates/layout.html:85
msgid "This is a free software"
msgstr "Ceci est un logiciel libre"
#: templates/layout.html:85
msgid "you can contribute and improve it!"
msgstr "vous pouvez y contribuer et l'améliorer"
#: templates/list_bills.html:30
msgid "you sure?"
msgstr "c'est sûr ?"
#: templates/list_bills.html:45
msgid "Balance"
msgstr "Balance"
#: templates/list_bills.html:56 templates/list_bills.html:88
msgid "delete"
msgstr "supprimer"
#: templates/list_bills.html:56
msgid "reactivate"
msgstr "ré-activer"
#: templates/list_bills.html:68
msgid "The project identifier is"
msgstr "L'identifiant de ce projet est"
#: templates/list_bills.html:68
msgid "remember it or add this page to you bookmarks!"
msgstr "rapellez vous en !"
#: templates/list_bills.html:70
msgid "Add a new bill"
msgstr "Nouvelle facture"
#: templates/list_bills.html:72
msgid "hide this form"
msgstr "cacher ce formulaire"
#: templates/list_bills.html:78
msgid "When?"
msgstr "Quand ?"
#: templates/list_bills.html:78
msgid "Who paid?"
msgstr "Qui à payé ?"
#: templates/list_bills.html:78
msgid "For what?"
msgstr "Pour quoi ?"
#: templates/list_bills.html:78
msgid "Owers"
msgstr "Pour qui ?"
#: templates/list_bills.html:78
msgid "How much?"
msgstr "Combien ?"
#: templates/list_bills.html:78
msgid "Actions"
msgstr "Actions"
#: templates/list_bills.html:87
msgid "edit"
msgstr "éditer"
#: templates/list_bills.html:95
msgid "Nothing to list yet. You probably want to"
msgstr "Rien à lister pour l'instant. Vous voulez surement"
#: templates/list_bills.html:95
msgid "add a bill"
msgstr "ajouter une facture"
#: templates/password_reminder.html:4
msgid "Password reminder"
msgstr "Rappel du code d'accès"
#: templates/recent_projects.html:2
msgid "Your projects"
msgstr "Vos projets"
#: templates/send_invites.html:6
msgid "Invite people"
msgstr "Invitez des gens"
#: templates/send_invites.html:7
msgid "Use it!"
msgstr "Utilisez le !"
#: templates/send_invites.html:11
msgid "Invite people to join this project"
msgstr "Invitez des personnes à rejoindre ce projet"
#: templates/send_invites.html:12
msgid ""
"Specify a (coma 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 ""
"Entrez l'addresse des personnes que vous souhaitez inviter, séparée par "
"des virgules. On s'occupe de leur envoyer un email."
#: templates/send_invites.html:14
msgid "If you prefer, you can"
msgstr "Si vous préférez vous pouvez"
#: templates/send_invites.html:14
msgid "skip this step"
msgstr "sauter cette étape"
#: templates/send_invites.html:14
msgid "and notify them yourself"
msgstr "et les notifier vous même"

View file

@ -2,6 +2,7 @@ from collections import defaultdict
from flask import *
from flaskext.mail import Mail, Message
from flaskext.babel import Babel, get_locale, gettext as _
import werkzeug
# local modules
@ -22,6 +23,8 @@ and `add_project_id` for a quick overview
main = Blueprint("main", __name__)
mail = Mail()
babel = Babel()
@main.url_defaults
def add_project_id(endpoint, values):
@ -85,7 +88,7 @@ def authenticate(project_id=None):
if request.method == "POST":
if form.validate():
if not form.password.data == project.password:
form.errors['password'] = ["This private code is not the right one"]
form.errors['password'] = [_("This private code is not the right one")]
else:
# maintain a list of visited projects
if "projects" not in session:
@ -133,9 +136,10 @@ def create_project():
# send reminder email
g.project = project
message_title = "You have just created '%s' to share your expenses" % g.project.name
message_title = _("You have just created '%(project)s' to share your expenses",
project=g.project.name)
message_body = render_template("reminder_mail")
message_body = render_template("reminder_mail.%s" % get_locale().language)
msg = Message(message_title,
body=message_body,
@ -143,7 +147,7 @@ def create_project():
mail.send(msg)
# redirect the user to the next step (invite)
flash("The project identifier is %s" % project.id)
flash(_("The project identifier is %(project)s", project=project.id))
return redirect(url_for(".invite", project_id=project.id))
return render_template("create_project.html", form=form)
@ -158,9 +162,10 @@ def remind_password():
# send the password reminder
mail.send(Message("password recovery",
body=render_template("password_reminder", project=project),
body=render_template("password_reminder.%s" % get_locale().language,
project=project),
recipients=[project.contact_email]))
flash("a mail has been sent to you with the password")
flash(_("a mail has been sent to you with the password"))
return render_template("password_reminder.html", form=form)
@ -216,16 +221,16 @@ def invite():
if form.validate():
# send the email
message_body = render_template("invitation_mail")
message_body = render_template("invitation_mail.%s" % get_locale().language)
message_title = "You have been invited to share your"\
+ " expenses for %s" % g.project.name
message_title = _("You have been invited to share your expenses for %(project)s",
project=g.project.name)
msg = Message(message_title,
body=message_body,
recipients=[email.strip()
for email in form.emails.data.split(",")])
mail.send(msg)
flash("You invitations have been sent")
flash(_("Your invitations have been sent"))
return redirect(url_for(".list_bills"))
return render_template("send_invites.html", form=form)
@ -246,7 +251,7 @@ def add_member():
if form.validate():
member = form.save(g.project, Person())
db.session.commit()
flash("%s is had been added" % member.name)
flash(_("%(member)s had been added", member=member.name))
return redirect(url_for(".list_bills"))
return render_template("add_member.html", form=form)
@ -258,7 +263,7 @@ def reactivate(member_id):
if person:
person[0].activated = True
db.session.commit()
flash("%s is part of this project again" % person[0].name)
flash(_("%(name)s is part of this project again", name=person[0].name))
return redirect(url_for(".list_bills"))
@ -266,9 +271,9 @@ def reactivate(member_id):
def remove_member(member_id):
member = g.project.remove_member(member_id)
if member.activated == False:
flash("User '%s' has been desactivated" % member.name)
flash(_("User '%(name)s' has been deactivated", name=member.name))
else:
flash("User '%s' has been removed" % member.name)
flash(_("User '%(name)s' has been removed", name=member.name))
return redirect(url_for(".list_bills"))
@ -281,7 +286,7 @@ def add_bill():
db.session.add(form.save(bill, g.project))
db.session.commit()
flash("The bill has been added")
flash(_("The bill has been added"))
return redirect(url_for('.list_bills'))
return render_template("add_bill.html", form=form)
@ -296,7 +301,7 @@ def delete_bill(bill_id):
db.session.delete(bill)
db.session.commit()
flash("The bill has been deleted")
flash(_("The bill has been deleted"))
return redirect(url_for('.list_bills'))
@ -314,7 +319,7 @@ def edit_bill(bill_id):
form.save(bill, g.project)
db.session.commit()
flash("The bill has been modified")
flash(_("The bill has been modified"))
return redirect(url_for('.list_bills'))
form.fill(bill)
@ -331,6 +336,6 @@ def create_archive():
if request.method == "POST":
if form.validate():
pass
flash("The data from XX to XX has been archived")
flash(_("The data from XX to XX has been archived"))
return render_template("create_archive.html", form=form)