Merge branch 'master' into almet/rename-participants

This commit is contained in:
Alexis Métaireau 2021-11-01 18:21:36 +01:00
commit 8d32f8e388
103 changed files with 523 additions and 452 deletions

View file

@ -3,10 +3,40 @@ Changelog
This document describes changes between each past release.
5.0.2 (unreleased)
5.1.2 (unreleased)
==================
- Nothing changed yet.
Changed
-------
- Minor presentation fixes (901)
5.1.1 (2021-10-26)
==================
- No actual change, fixup release because 5.1.0 did not upload to pypi
5.1.0 (2021-10-26)
==================
Added
-----
- Add the option to display a "legal link" at the bottom of pages (#883)
New settings
------------
- Add `LEGAL_LINK <https://ihatemoney.readthedocs.io/en/latest/configuration.html#legal-link>`_ setting (#883)
Changed
-------
- Improve performance of balance and statistics computation (#890)
- Reduce the resolution of showcase pictures by 50% (#880)
- Improve pagination style in the list of bills (#873)
5.0.1 (2021-10-20)
@ -60,6 +90,13 @@ Added
- Add translations for Greek, Esperanto, Italian, Japanese, Portuguese and Swedish
- Publish an `official docker image <https://hub.docker.com/r/ihatemoney/ihatemoney>`_
New settings
------------
- Add `ENABLE_CAPTCHA <https://ihatemoney.readthedocs.io/en/latest/configuration.html#enable-captcha>`_ setting (#844)
- Use and document `SESSION_COOKIE_SECURE <https://ihatemoney.readthedocs.io/en/latest/configuration.html#session-cookie-secure>`_ setting (#845)
- Use and document `BABEL_DEFAULT_TIMEZONE <https://ihatemoney.readthedocs.io/en/latest/configuration.html#babel-default-timezone>`_ setting (#590)
Changed
-------

View file

@ -17,7 +17,9 @@ ENV DEBUG="False" \
SECRET_KEY="tralala" \
SESSION_COOKIE_SECURE="True" \
SQLALCHEMY_DATABASE_URI="sqlite:////database/ihatemoney.db" \
SQLALCHEMY_TRACK_MODIFICATIONS="False"
SQLALCHEMY_TRACK_MODIFICATIONS="False" \
ENABLE_CAPTCHA="False" \
LEGAL_LINK="False"
RUN mkdir -p /etc/ihatemoney &&\
pip install --no-cache-dir gunicorn pymysql;

View file

@ -1,3 +1,3 @@
include *.rst
recursive-include ihatemoney *.rst *.py *.yaml *.po *.mo *.html *.css *.js *.eot *.svg *.woff *.txt *.png *.ini *.cfg *.j2 *.jpg *.gif *.ico
recursive-include ihatemoney *.rst *.py *.yaml *.po *.mo *.html *.css *.js *.eot *.svg *.woff *.txt *.png *.webp *.ini *.cfg *.j2 *.jpg *.gif *.ico
include LICENSE CONTRIBUTORS CHANGELOG.rst

View file

@ -7,6 +7,7 @@ DOC_STAMP = $(VENV)/.doc_env_installed.stamp
INSTALL_STAMP = $(VENV)/.install.stamp
TEMPDIR := $(shell mktemp -d)
ZOPFLIPNG := zopflipng
MAGICK_MOGRIFY := mogrify
.PHONY: all
all: install ## Alias for install
@ -56,8 +57,13 @@ isort: install-dev ## Run the tests
release: install-dev ## Release a new version (see https://ihatemoney.readthedocs.io/en/latest/contributing.html#how-to-release)
$(VENV)/bin/fullrelease
.PHONY: compress-showcase
compress-showcase:
@which $(MAGICK_MOGRIFY) >/dev/null || (echo "ImageMagick 'mogrify' ($(MAGICK_MOGRIFY)) is missing" && exit 1)
$(MAGICK_MOGRIFY) -format webp -resize '75%>' -quality 50 -define webp:method=6:auto-filter=true -path ihatemoney/static/showcase/ 'assets/showcase/*.jpg'
.PHONY: compress-assets
compress-assets: ## Compress static assets
compress-assets: compress-showcase ## Compress static assets
@which $(ZOPFLIPNG) >/dev/null || (echo "ZopfliPNG ($(ZOPFLIPNG)) is missing" && exit 1)
mkdir $(TEMPDIR)/zopfli
$(eval CPUCOUNT := $(shell python -c "import psutil; print(psutil.cpu_count(logical=False))"))

View file

@ -13,11 +13,16 @@ I hate money
:target: https://liberapay.com/IHateMoney/donate
:alt: Donate
.. image:: https://img.shields.io/badge/-Docker%20image-black?logo=docker
:target: https://hub.docker.com/r/ihatemoney/ihatemoney/general
:alt: Docker image
*I hate money* is a web application made to ease shared budget management.
It keeps track of who bought what, when, and for whom; and helps to settle the
bills.
* `Online documentation <https://ihatemoney.readthedocs.org>`_
* `Online documentation <https://ihatemoney.readthedocs.io>`_
* `Hosted version <https://ihatemoney.org>`_
* `Mailing list <https://mailman.alwaysdata.com/postorius/lists/info.ihatemoney.org/>`_
(to get updates when needed).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 576 KiB

After

Width:  |  Height:  |  Size: 602 KiB

BIN
assets/showcase/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 KiB

After

Width:  |  Height:  |  Size: 448 KiB

BIN
assets/showcase/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 461 KiB

After

Width:  |  Height:  |  Size: 482 KiB

BIN
assets/showcase/6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 KiB

After

Width:  |  Height:  |  Size: 513 KiB

BIN
assets/showcase/8.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 KiB

After

Width:  |  Height:  |  Size: 823 KiB

View file

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View file

@ -22,6 +22,8 @@ SESSION_COOKIE_SECURE = $SESSION_COOKIE_SECURE
SQLACHEMY_DEBUG = DEBUG
SQLALCHEMY_DATABASE_URI = "$SQLALCHEMY_DATABASE_URI"
SQLALCHEMY_TRACK_MODIFICATIONS = $SQLALCHEMY_TRACK_MODIFICATIONS
ENABLE_CAPTCHA = $ENABLE_CAPTCHA
LEGAL_LINK = "$LEGAL_LINK"
EOF
# Start gunicorn without forking

View file

@ -24,5 +24,7 @@ services:
- SESSION_COOKIE_SECURE=True
- SQLALCHEMY_DATABASE_URI=sqlite:////database/ihatemoney.db
- SQLALCHEMY_TRACK_MODIFICATIONS=False
- ENABLE_CAPTCHA=False
- LEGAL_LINK=
ports:
- "8000:8000"

View file

@ -161,6 +161,15 @@ Note: this setting is actually interpreted by Flask-Babel, see the
It is possible to add a simple captcha in order to filter out spammer bots on the form creation.
In order to do so, you just have to set `ENABLE_CAPTCHA = True`.
`LEGAL_LINK`
------------
You may want to point to a special legal page, for instance to give information
about GDPR, or how you handle the data of your users.
If you want to do this, you can use the `LEGAL_LINK` setting. Set it to the URL
you want.
Configuring emails sending
--------------------------
@ -176,4 +185,3 @@ possible to configure it to act differently, thanks to the great
* **MAIL_USERNAME** : default **None**
* **MAIL_PASSWORD** : default **None**
* **DEFAULT_MAIL_SENDER** : default **None**

View file

@ -82,6 +82,13 @@ And then run the application::
cd ihatemoney
python run.py
The docker way
--------------
If you prefer to use docker, then you can build your image with::
docker build -t ihatemoney .
Accessing dev server
--------------------
@ -213,13 +220,52 @@ And to produce a HTML doc in the `docs/_output` folder::
How to release?
===============
In order to prepare a new release, we are following the following steps:
Requirements
------------
To create a new release, make sure you fullfil all requirements:
- Are you a maintainer of the pypi package?
- Are you sure you have no local tags? They will all be published
to the github process as part of the release process
- Make sure you have a ``~/.pypirc`` file with the following content,
replacing ``YOUR_PYPI_USERNAME`` with your real username::
[distutils]
index-servers =
pypi
[pypi]
username:YOUR_PYPI_USERNAME
Choosing a version number
-------------------------
The project follows `semantic versioning <https://semver.org/>`_.
To sum things up:
- **if there is a breaking change since the last release:** increase the major
version number (11.X.Y -> 12.0.0). Example of breaking changes: drop support
for an old version of python, new setting without default value (requires
an admin to configure the new setting), changed URL paths, any other incompatible
change. Make sure to :ref:`document the upgrade process<upgrade>`.
- **if there is a significant new feature or a new setting:** increase the minor
version number (11.4.Y -> 11.5.0). Make sure to :ref:`document any new settings<configuration>`.
- **if it's mostly bugfixes and small changes:** increase the patch version number
(11.4.8 -> 11.4.9)
Making the release
------------------
In order to issue a new release, follow the following steps:
- Merge remaining pull requests;
- Switch to the master branch;
- Update :file:`CHANGELOG.rst` with the last changes;
- Update :file:`CONTRIBUTORS`;
- Update known good versions of dependencies in ``setup.cfg``
- If needed, recompress assets. It requires zopflipng::
- Update :file:`CONTRIBUTORS` (instructions inside the file);
- If needed, recompress assets. It requires zopflipng and ImageMagick `mogrify`::
make compress-assets
@ -228,12 +274,22 @@ In order to prepare a new release, we are following the following steps:
make update-translations
make build-translations
Once this is done, use the "release" instruction::
- If you're not completely sure of yourself at this point, you
can optionally: create a new branch, push it, open a pull request,
check the CI result, and then merge the branch to master.
Once this is done, make sure your local git repository is on the master branch,
and let's release!::
make release
And the new version should be published on PyPI.
This will publish the new version to `the Python Package Index <https://pypi.org>`_ (PyPI)
and publish a tag in the git repository.
.. note:: The above command will prompt for version number, handle
:file:`CHANGELOG.rst` and :file:`setup.cfg` updates, package creation,
pypi upload. It will prompt you before each step to get your consent.
Finally, create a release on Github and copy the relevant changelog extract into it.
Unfortunately, you need to manually convert links to Markdown...
We have a `discussion to automate this step <https://github.com/spiral-project/ihatemoney/issues/894>`_.

View file

@ -3,19 +3,80 @@
Installation
############
We lack some knowledge about packaging to make Ihatemoney installable on mainstream
Linux distributions. If you want to give us a hand on the topic, please
check-out `the issue about debian packaging <https://github.com/spiral-project/ihatemoney/issues/227>`_.
There are multiple ways to install «Ihatemoney» on your system :
If you are using Yunohost (a server operating system aiming to make self-hosting accessible to anyone),
you can use the `Ihatemoney package <https://github.com/YunoHost-Apps/ihatemoney_ynh>`_.
1. :ref:`Via Docker<Docker>`.
2. `Via Yunohost <https://github.com/YunoHost-Apps/ihatemoney_ynh>`_
(a server operating system aiming to make self-hosting accessible to anyone)
3. Do a :ref:`manual installation<manual-installation>`.
Otherwise, follow these instructions to install it manually:
.. note:: We lack some knowledge about packaging to make Ihatemoney installable
on mainstream Linux distributions. If you want to give us a hand on the topic,
please check-out `the issue about debian packaging <https://github.com/spiral-project/ihatemoney/issues/227>`_.
.. _docker:
With Docker
===========
Docker images are published `on the Docker hub <https://hub.docker.com/r/ihatemoney/ihatemoney/>`_.
This is probably the simplest way to get something running. Once you have Docker installed
on your system, just issue ::
docker run -d -p 8000:8000 ihatemoney/ihatemoney
Ihatemoney is now available on http://localhost:8000.
All :ref:`settings<configuration>` can be passed with ``-e`` parameters
e.g. with a secure ``SECRET_KEY``, an external mail server and an
external database::
docker run -d -p 8000:8000 \
-e SECRET_KEY="supersecure" \
-e SQLALCHEMY_DATABASE_URI="mysql+pymysql://user:pass@10.42.58.250/ihm" \
-e MAIL_SERVER=smtp.gmail.com \
-e MAIL_PORT=465 \
-e MAIL_USERNAME=your-email@gmail.com \
-e MAIL_PASSWORD=your-password \
-e MAIL_USE_SSL=True \
ihatemoney/ihatemoney
.. note: Connecting to a postgresql database is not supported for now in the
docker container.
A volume can also be specified to persist the default database file::
docker run -d -p 8000:8000 -v /host/path/to/database:/database ihatemoney/ihatemoney
To enable the Admin dashboard, first generate a hashed password with::
docker run -it --rm --entrypoint ihatemoney ihatemoney/ihatemoney generate_password_hash
At the prompt, enter a password to use for the admin dashboard. The
command will print the hashed password string.
Add these additional environment variables to the docker run invocation::
-e ACTIVATE_ADMIN_DASHBOARD=True \
-e ADMIN_PASSWORD=<hashed_password_string> \
Additional gunicorn parameters can be passed using the docker ``CMD``
parameter.
For example, use the following command to add more gunicorn workers::
docker run -d -p 8000:8000 ihatemoney/ihatemoney -w 3
.. _manual-installation:
Manual Installation
===================
.. _installation-requirements:
Requirements
============
------------
«Ihatemoney» depends on:
@ -23,18 +84,19 @@ Requirements
* **A Backend**: to choose among SQLite, PostgreSQL, MariaDB (>= 10.3.2) or Memory.
* **Virtual environment** (recommended): `python3-venv` package under Debian/Ubuntu.
We recommend to use `virtual environment <https://docs.python.org/3/tutorial/venv.html>`_ but
it will work without if you prefer.
We recommend using `virtual environments <https://docs.python.org/3/tutorial/venv.html>`_
to isolate the installation from other softwares on your machine, but it's not mandatory.
If wondering about the backend, SQLite is the simplest and will work fine for
most small to medium setups.
.. note:: If curious, source config templates can be found in the `project git repository <https://github.com/spiral-project/ihatemoney/tree/master/ihatemoney/conf-templates>`_.
.. note:: If curious, source config templates can be found in the
`project git repository <https://github.com/spiral-project/ihatemoney/tree/master/ihatemoney/conf-templates>`_.
.. _virtualenv-preparation:
Prepare virtual environment (recommended)
=========================================
-----------------------------------------
Choose an installation path, here the current user's home directory (`~`).
@ -51,18 +113,14 @@ Activate the virtual environment::
terminal.
Install
=======
-------
Install the latest release with pip::
pip install ihatemoney
.. warning:: The current release of ihatemoney (4.1.5) does not work with SQLAlchemy 1.4.
The dependency will be fixed in the next version, but in the meantime you
can work around the issue with: ``pip install 'SQLAlchemy>=1.3,<1.4'``.
Test it
=======
-------
Once installed, you can start a test server::
@ -70,8 +128,23 @@ Once installed, you can start a test server::
And point your browser at `http://localhost:5000 <http://localhost:5000>`_.
Generate your configuration
---------------------------
1. Initialize the ihatemoney directories::
mkdir /etc/ihatemoney /var/lib/ihatemoney
2. Generate settings::
ihatemoney generate-config ihatemoney.cfg > /etc/ihatemoney/ihatemoney.cfg
chmod 740 /etc/ihatemoney/ihatemoney.cfg
You probably want to adjust ``/etc/ihatemoney/ihatemoney.cfg`` contents,
you may do it later, see :ref:`configuration`.
Configure database with MariaDB (optional)
================================================
------------------------------------------
.. note:: Only required if you use MariaDB. Make sure to use MariaDB 10.3.2 or newer.
@ -86,9 +159,8 @@ Configure database with MariaDB (optional)
3. Create an empty database and a database user
4. Configure :ref:`SQLALCHEMY_DATABASE_URI <configuration>` accordingly
Configure database with PostgreSQL (optional)
=============================================
---------------------------------------------
.. note:: Only required if you use Postgresql.
@ -105,32 +177,17 @@ Configure database with PostgreSQL (optional)
3. Configure :ref:`SQLALCHEMY_DATABASE_URI <configuration>` accordingly.
Configure a reverse proxy
-------------------------
Deploy it
=========
When deploying this service in production, you want to have a reverse proxy
in front of the python application.
Now, if you want to deploy it on your own server, you have many options.
Three of them are documented at the moment.
*Of course, if you want to contribute another configuration, feel free
to open a pull-request against this repository!*
Whatever your installation option is…
--------------------------------------
1. Initialize the ihatemoney directories::
mkdir /etc/ihatemoney /var/lib/ihatemoney
2. Generate settings::
ihatemoney generate-config ihatemoney.cfg > /etc/ihatemoney/ihatemoney.cfg
chmod 740 /etc/ihatemoney/ihatemoney.cfg
You probably want to adjust ``/etc/ihatemoney/ihatemoney.cfg`` contents,
you may do it later, see :ref:`configuration`.
Here are documented two stacks. You can of course use another one if you want.
Don't hesitate to contribute a small tutorial here if you want.
1. Apache and `mod_wsgi`
2. Nginx, Gunicorn and Supervisord/Systemd
With Apache and mod_wsgi
------------------------
@ -206,52 +263,3 @@ Install Gunicorn::
.. [#systemd-services] ``/etc/systemd/system/ihatemoney.service``
path may change depending on your distribution.
With Docker
-----------
Build the image::
docker build -t ihatemoney .
Start a daemonized Ihatemoney container::
docker run -d -p 8000:8000 ihatemoney
Ihatemoney is now available on http://localhost:8000.
All Ihatemoney settings can be passed with ``-e`` parameters
e.g. with a secure ``SECRET_KEY``, an external mail server and an
external database::
docker run -d -p 8000:8000 \
-e SECRET_KEY="supersecure" \
-e SQLALCHEMY_DATABASE_URI="mysql+pymysql://user:pass@172.17.0.5/ihm" \
-e MAIL_SERVER=smtp.gmail.com \
-e MAIL_PORT=465 \
-e MAIL_USERNAME=your-email@gmail.com \
-e MAIL_PASSWORD=your-password \
-e MAIL_USE_SSL=True \
ihatemoney
A volume can also be specified to persist the default database file::
docker run -d -p 8000:8000 -v /host/path/to/database:/database ihatemoney
To enable the Admin dashboard, first generate a hashed password with::
docker run -it --rm --entrypoint ihatemoney ihatemoney generate_password_hash
At the prompt, enter a password to use for the admin dashboard. The
command will print the hashed password string.
Add these additional environment variables to the docker run invocation::
-e ACTIVATE_ADMIN_DASHBOARD=True \
-e ADMIN_PASSWORD=<hashed_password_string> \
Additional gunicorn parameters can be passed using the docker ``CMD``
parameter.
For example, use the following command to add more gunicorn workers::
docker run -d -p 8000:8000 ihatemoney -w 3

View file

@ -1,3 +1,5 @@
.. _upgrade:
Upgrading
#########

View file

@ -46,3 +46,8 @@ SESSION_COOKIE_SECURE = True
# You can activate an optional CAPTCHA if you want to. It can be helpful
# to filter spammer bots.
# ENABLE_CAPTCHA = True
# You may want to point to a special legal page, for instance to give information
# about GDPR, or how you handle the data of your users.
# Set this variable to the URL you want.
# LEGAL_LINK = ""

View file

@ -33,3 +33,4 @@ SUPPORTED_LANGUAGES = [
"zh_Hans",
]
ENABLE_CAPTCHA = False
LEGAL_LINK = ""

View file

@ -304,10 +304,10 @@ class ResetPasswordForm(FlaskForm):
class BillForm(FlaskForm):
date = DateField(_("Date"), validators=[DataRequired()], default=datetime.now)
date = DateField(_("When?"), validators=[DataRequired()], default=datetime.now)
what = StringField(_("What?"), validators=[DataRequired()])
payer = SelectField(_("Payer"), validators=[DataRequired()], coerce=int)
amount = CalculatorStringField(_("Amount paid"), validators=[DataRequired()])
payer = SelectField(_("Who paid?"), validators=[DataRequired()], coerce=int)
amount = CalculatorStringField(_("How much?"), validators=[DataRequired()])
currency_helper = CurrencyConverter()
original_currency = SelectField(_("Currency"), validators=[DataRequired()])
external_link = URLField(

View file

@ -742,6 +742,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""

View file

@ -99,27 +99,37 @@ class Project(db.Model):
return [m for m in self.members if m.activated]
@property
def balance(self):
def full_balance(self):
"""Returns a triple of dicts:
- dict mapping each member to its balance
- dict mapping each member to how much he/she should pay others
(i.e. how much he/she benefited from bills)
- dict mapping each member to how much he/she should be paid by
others (i.e. how much he/she has paid for bills)
"""
balances, should_pay, should_receive = (defaultdict(int) for time in (1, 2, 3))
# for each person
for person in self.members:
# get the list of bills he has to pay
bills = Bill.query.options(orm.subqueryload(Bill.owers)).filter(
Bill.owers.contains(person)
)
for bill in bills.all():
if person != bill.payer:
share = bill.pay_each() * person.weight
should_pay[person] += share
should_receive[bill.payer] += share
for bill in self.get_bills_unordered().all():
should_receive[bill.payer.id] += bill.converted_amount
total_weight = sum(ower.weight for ower in bill.owers)
for ower in bill.owers:
should_pay[ower.id] += (
ower.weight * bill.converted_amount / total_weight
)
for person in self.members:
balance = should_receive[person] - should_pay[person]
balance = should_receive[person.id] - should_pay[person.id]
balances[person.id] = balance
return balances
return balances, should_pay, should_receive
@property
def balance(self):
return self.full_balance[0]
@property
def members_stats(self):
@ -128,23 +138,13 @@ class Project(db.Model):
:return: one stat dict per participant
:rtype list:
"""
balance, spent, paid = self.full_balance
return [
{
"member": member,
"paid": sum(
[
bill.converted_amount
for bill in self.get_member_bills(member.id).all()
]
),
"spent": sum(
[
bill.pay_each() * member.weight
for bill in self.get_bills_unordered().all()
if member in bill.owers
]
),
"balance": self.balance[member.id],
"paid": paid[member.id],
"spent": spent[member.id],
"balance": balance[member.id],
}
for member in self.active_members
]
@ -232,8 +232,13 @@ class Project(db.Model):
def get_bills_unordered(self):
"""Base query for bill list"""
# The subqueryload option allows to pre-load data from the
# billowers table, which makes access to this data much faster.
# Without this option, any access to bill.owers would trigger a
# new SQL query, ruining overall performance.
return (
Bill.query.join(Person, Project)
Bill.query.options(orm.subqueryload(Bill.owers))
.join(Person, Project)
.filter(Bill.payer_id == Person.id)
.filter(Person.project_id == Project.id)
.filter(Project.id == self.id)
@ -572,7 +577,10 @@ class Bill(db.Model):
}
def pay_each_default(self, amount):
"""Compute what each share has to pay"""
"""Compute what each share has to pay. Warning: this is slow, if you need
to compute this for many bills, do it differently (see
balance_full function)
"""
if self.owers:
weights = (
db.session.query(func.sum(Person.weight))
@ -587,6 +595,9 @@ class Bill(db.Model):
return self.what
def pay_each(self):
"""Warning: this is slow, if you need to compute this for many bills, do
it differently (see balance_full function)
"""
return self.pay_each_default(self.converted_amount)
def __repr__(self):

View file

@ -69,6 +69,11 @@ body {
width: 55px;
}
#header .side-to-side {
/* avoid the man with his hand pointing at nothing */
white-space: nowrap;
}
#header .shareimg {
width: 80px;
margin-left: 5px;

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="34.337px" height="34.337px" viewBox="0 0 34.337 34.337" style="enable-background:new 0 0 34.337 34.337;"
xml:space="preserve">
<g>
<path d="M33.594,16.644l-7.147,7.15c-1.008,1.013-2.668,0.986-3.705-0.05c-0.896-0.896-1.029-2.255-0.4-3.261l-3.149-3.149
l-2.556,2.559c0.096,0.812-0.158,1.656-0.781,2.278L4.729,33.294c-0.541,0.541-1.25,0.812-1.959,0.812s-1.418-0.271-1.959-0.812
c-1.082-1.082-1.082-2.837,0-3.918l11.123-11.123c0.815-0.815,2.016-1.016,3.02-0.602l2.277-2.277l-3.147-3.148
c-1.003,0.633-2.363,0.496-3.261-0.399c-1.037-1.037-1.061-2.695-0.051-3.705l7.148-7.149c1.011-1.01,2.668-0.986,3.706,0.049
c0.896,0.896,1.03,2.26,0.399,3.263l8.258,8.259c1.006-0.63,2.363-0.496,3.261,0.4C34.58,13.978,34.604,15.635,33.594,16.644z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 710 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View file

@ -10,8 +10,11 @@
</a>
{% endif %}
{% if g.lang == 'fr' %}
ou <a class="showcase btn" onclick="javascript:showGallery(); return false;">Voir la BD explicative</a>
<img class="showcaseimg" src="{{ url_for("static", filename='images/indicate.svg') }}" />
ou
<span class="side-to-side">
<a class="showcase btn" onclick="javascript:showGallery(); return false;">Voir la BD explicative</a>
<img class="showcaseimg" src="{{ url_for("static", filename='images/indicate.svg') }}" />
</span>
{% endif %}
</div>
<div class="col-xs-12 col-sm-4">

View file

@ -150,6 +150,11 @@
<i class="icon admin">{{ static_include("images/cog.svg") | safe }}</i>
</a>
{% endif %}
{% if config.LEGAL_LINK %}
<a target="_blank" rel="noopener" data-toggle="tooltip" data-placement="top" title="{{ _('Legal information') }}" href="{{ config.LEGAL_LINK }}">
<i class="icon legal">{{ static_include("images/legal.svg") | safe }}</i>
</a>
{% endif %}
</div>
<div class="footer-left">

View file

@ -82,7 +82,7 @@
</div>
</div>
</div>
<div class="clearfix"></div>
{% if bills.pages > 1 %}
<ul class="pagination" id="pagination-top">
<li class="page-item {% if bills.page == 1 %}disabled{% endif %}"><a class="page-link" href="{{ url_for('main.list_bills', page=bills.prev_num) }}">&laquo; {{ _("Newer bills") }}</a></li>
@ -98,7 +98,7 @@
{% endif %}
{% if bills.total > 0 %}
<div class="clearfix"></div>
<table id="bill_table" class="col table table-striped table-hover table-responsive-sm">
<thead>

View file

@ -33,7 +33,7 @@
</div>
<script type="text/javascript">
var pswpElement = document.getElementById('pswp');
var items = JSON.parse('[{"h": 2450, "src": "/static/showcase/1.jpg", "w": 2450}, {"h": 2509, "src": "/static/showcase/2.jpg", "w": 2221}, {"h": 2536, "src": "/static/showcase/3.jpg", "w": 2101}, {"h": 2722, "src": "/static/showcase/4.jpg", "w": 2348}, {"h": 2745, "src": "/static/showcase/5.jpg", "w": 1804}, {"h": 3307, "src": "/static/showcase/6.jpg", "w": 2897}, {"h": 2321, "src": "/static/showcase/7.jpg", "w": 2239}, {"h": 2470, "src": "/static/showcase/8.jpg", "w": 2419}, {"h": 3307, "src": "/static/showcase/9.jpg", "w": 2602}]');
var items = JSON.parse('[{"h": 2450, "src": "/static/showcase/1.webp", "w": 2450}, {"h": 2509, "src": "/static/showcase/2.webp", "w": 2221}, {"h": 2536, "src": "/static/showcase/3.webp", "w": 2101}, {"h": 2722, "src": "/static/showcase/4.webp", "w": 2348}, {"h": 2745, "src": "/static/showcase/5.webp", "w": 1804}, {"h": 3307, "src": "/static/showcase/6.webp", "w": 2897}, {"h": 2321, "src": "/static/showcase/7.webp", "w": 2239}, {"h": 2470, "src": "/static/showcase/8.webp", "w": 2419}, {"h": 3307, "src": "/static/showcase/9.webp", "w": 2602}]');
var options = {
index: 0,
loop: false,

View file

@ -50,27 +50,33 @@ class BaseTestCase(TestCase):
follow_redirects=True,
)
def post_project(self, name, follow_redirects=True, default_currency="XXX"):
def post_project(
self, id, follow_redirects=True, default_currency="XXX", name=None
):
"""Create a fake project"""
if name is None:
name = id
# create the project
return self.client.post(
"/create",
data={
"name": name,
"id": name,
"password": name,
"contact_email": f"{name}@notmyidea.org",
"id": id,
"password": id,
"contact_email": f"{id}@notmyidea.org",
"default_currency": default_currency,
},
follow_redirects=follow_redirects,
)
def create_project(self, name, default_currency="XXX"):
def create_project(self, id, default_currency="XXX", name=None):
if name is None:
name = str(id)
project = models.Project(
id=name,
name=str(name),
password=generate_password_hash(name),
contact_email=f"{name}@notmyidea.org",
id=id,
name=name,
password=generate_password_hash(id),
contact_email=f"{id}@notmyidea.org",
default_currency=default_currency,
)
models.db.session.add(project)

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -765,6 +765,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""
@ -1009,4 +1012,3 @@ msgstr ""
#~ msgid "Participants to notify"
#~ msgstr ""

View file

@ -3,7 +3,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
<<<<<<< HEAD
"POT-Creation-Date: 2021-11-01 18:01+0100\n"
=======
"POT-Creation-Date: 2021-10-26 23:38+0200\n"
>>>>>>> master
"PO-Revision-Date: 2021-09-05 13:34+0000\n"
"Last-Translator: Clonewayx <fillip1@seznam.cz>\n"
"Language: cs\n"
@ -13,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -773,6 +777,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -815,6 +815,10 @@ msgstr "Dokumentation"
msgid "Administation Dashboard"
msgstr "Dashboard Administration"
#, fuzzy
msgid "Legal information"
msgstr "Bestätigung löschen"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" ist freie Software"
@ -1068,4 +1072,3 @@ msgstr "Zeitraum"
#~ msgid "Participants to notify"
#~ msgstr "Teilnehmer hinzufügen"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -790,6 +790,10 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
#, fuzzy
msgid "Legal information"
msgstr "Επιβεβαίωση Διαγραφής"
msgid "\"I hate money\" is free software"
msgstr ""
@ -1013,28 +1017,3 @@ msgstr "Περίοδος"
#~ msgid "People to notify"
#~ msgstr "Πρόσωπα προς ενημέρωση"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid ""
#~ "User '%(name)s' has been deactivated. It"
#~ " will still appear in the users "
#~ "list until its balance becomes zero."
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Ο χρήστης \"%(name)s\" έχει τροποποιηθεί"
#~ msgid "Number of members"
#~ msgstr "Αριθμός μελών"
#~ msgid "Edit this member"
#~ msgstr "Επεξεργασία αυτού του μέλους"
#~ msgid "Participants to notify"
#~ msgstr ""

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -806,6 +806,10 @@ msgstr "Dokumentaro"
msgid "Administation Dashboard"
msgstr "Administra panelo"
#, fuzzy
msgid "Legal information"
msgstr "Konfirmo de forigo"
msgid "\"I hate money\" is free software"
msgstr "«I hate money» estas libera programo"
@ -1017,22 +1021,3 @@ msgstr "Periodo"
#~ msgid "People to notify"
#~ msgstr "Sciigotaj homoj"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Uzanto «%(name)s» estis redaktita"
#~ msgid "Number of members"
#~ msgstr "Nombro de anoj"
#~ msgid "Edit this member"
#~ msgstr "Redakti ĉi tiun anon"
#~ msgid "Participants to notify"
#~ msgstr "aldoni partoprenantojn"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -775,6 +775,9 @@ msgstr "Documentación"
msgid "Administation Dashboard"
msgstr "Panel de administración"
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""
@ -1019,4 +1022,3 @@ msgstr "Período"
#~ msgid "Participants to notify"
#~ msgstr "añadir participantes"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -817,6 +817,10 @@ msgstr "Documentación"
msgid "Administation Dashboard"
msgstr "Panel de administración"
#, fuzzy
msgid "Legal information"
msgstr "Confirmación de eliminación"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" es un software libre"
@ -1055,22 +1059,3 @@ msgstr "Período"
#~ msgid "People to notify"
#~ msgstr "Personas a notificar"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "El usuario '%(name)s' ha sido editado"
#~ msgid "Number of members"
#~ msgstr "Número de miembros"
#~ msgid "Edit this member"
#~ msgstr "Editar este miembro"
#~ msgid "Participants to notify"
#~ msgstr "agregar participantes"

View file

@ -3,7 +3,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
<<<<<<< HEAD
"POT-Creation-Date: 2021-11-01 18:01+0100\n"
=======
"POT-Creation-Date: 2021-10-26 23:38+0200\n"
>>>>>>> master
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language: fa\n"
@ -12,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -758,6 +762,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""

View file

@ -17,7 +17,9 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.9-dev\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -820,6 +822,9 @@ msgstr "Documentation"
msgid "Administation Dashboard"
msgstr "Panneau d'aministration"
msgid "Legal information"
msgstr "Mentions légales"
msgid "\"I hate money\" is free software"
msgstr "« I hate money » est un logiciel libre"
@ -843,10 +848,10 @@ msgid "Add a new bill"
msgstr "Nouvelle facture"
msgid "Newer bills"
msgstr "Nouvelles factures"
msgstr "Factures récentes"
msgid "Older bills"
msgstr "Ancienne factures"
msgstr "Factures précédentes"
msgid "When?"
msgstr "Quand ?"
@ -1270,4 +1275,3 @@ msgstr "Période"
#~ msgid "Participants to notify"
#~ msgstr "ajouter des participant⋅e⋅s"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -815,6 +815,10 @@ msgstr "प्रलेखन"
msgid "Administation Dashboard"
msgstr "व्यवस्थापन डैशबोर्ड"
#, fuzzy
msgid "Legal information"
msgstr "पुष्टिकरण हटाएं"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" एक मुफ्त सॉफ्टवेयर है"
@ -1031,22 +1035,3 @@ msgstr "अवधि"
#~ msgid "People to notify"
#~ msgstr "सूचित किये जाने वाले लोग"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "उपयोगकर्ता '%(name)s' को संपादित कर दिया गया है"
#~ msgid "Number of members"
#~ msgstr "सदस्यों की संख्या"
#~ msgid "Edit this member"
#~ msgstr "इस सदस्य को संपादित करें"
#~ msgid "Participants to notify"
#~ msgstr "प्रतिभागियों को जोड़ें"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -810,6 +810,10 @@ msgstr "Dokumentasi"
msgid "Administation Dashboard"
msgstr "Dasbor Administrasi"
#, fuzzy
msgid "Legal information"
msgstr "Hapus Konfirmasi"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" adalah perangkat lunak gratis"
@ -1054,22 +1058,3 @@ msgstr "Periode"
#~ msgid "People to notify"
#~ msgstr "Orang yang akan diberi pemberitahuan"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Pengguna %(name)s telah diperbarui"
#~ msgid "Number of members"
#~ msgstr "Jumlah anggota"
#~ msgid "Edit this member"
#~ msgstr "Ubah anggota ini"
#~ msgid "Participants to notify"
#~ msgstr "tambah partisipan"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -821,6 +821,10 @@ msgstr "Documentazione"
msgid "Administation Dashboard"
msgstr "Cruscotto Amministrazione"
#, fuzzy
msgid "Legal information"
msgstr "Cancella Conferma"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" è un software libero"
@ -1059,22 +1063,3 @@ msgstr "Periodo"
#~ msgid "People to notify"
#~ msgstr "Persone da informare"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "L'utente '%(name)s' è stato aggiornato"
#~ msgid "Number of members"
#~ msgstr "Numero di membri"
#~ msgid "Edit this member"
#~ msgstr "Modifica questo membro"
#~ msgid "Participants to notify"
#~ msgstr "aggiunti partecipanti"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -787,6 +787,10 @@ msgstr "書類"
msgid "Administation Dashboard"
msgstr "管理ダッシュボード"
#, fuzzy
msgid "Legal information"
msgstr "確認を削除する"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\"は無料のソフトウェアです"
@ -994,22 +998,3 @@ msgstr "期間"
#~ msgid "People to notify"
#~ msgstr "知らせたい人"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "ユーザー%(name)sが既に編集されました"
#~ msgid "Number of members"
#~ msgstr "メンバー数"
#~ msgid "Edit this member"
#~ msgstr "このメンバーを編集する"
#~ msgid "Participants to notify"
#~ msgstr "参加者を追加する"

View file

@ -3,7 +3,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
<<<<<<< HEAD
"POT-Creation-Date: 2021-11-01 18:01+0100\n"
=======
"POT-Creation-Date: 2021-10-26 23:38+0200\n"
>>>>>>> master
"PO-Revision-Date: 2021-10-17 04:56+0000\n"
"Last-Translator: a-g-rao <athrigrao@gmail.com>\n"
"Language: kn\n"
@ -13,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -768,6 +772,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""

View file

@ -3,7 +3,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
<<<<<<< HEAD
"POT-Creation-Date: 2021-11-01 18:01+0100\n"
=======
"POT-Creation-Date: 2021-10-26 23:38+0200\n"
>>>>>>> master
"PO-Revision-Date: 2021-07-18 12:32+0000\n"
"Last-Translator: Kemystra <izzmin97@gmail.com>\n"
"Language: ms\n"
@ -13,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -775,6 +779,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""

View file

@ -3,7 +3,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
<<<<<<< HEAD
"POT-Creation-Date: 2021-11-01 18:01+0100\n"
=======
"POT-Creation-Date: 2021-10-26 23:38+0200\n"
>>>>>>> master
"PO-Revision-Date: 2021-07-18 20:48+0000\n"
"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
"Language: nb_NO\n"
@ -13,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -842,6 +846,10 @@ msgstr "Dokumentasjon"
msgid "Administation Dashboard"
msgstr "Administrasjonsoversiktspanel"
#, fuzzy
msgid "Legal information"
msgstr "Slettingsbekreftelse"
#, fuzzy
msgid "\"I hate money\" is free software"
msgstr "\"Jeg hater penger\" er fri programvare"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -806,6 +806,10 @@ msgstr "Documentatie"
msgid "Administation Dashboard"
msgstr "Administratie-overzicht"
#, fuzzy
msgid "Legal information"
msgstr "Bevestiging Verwijdering"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" is vrije software"
@ -1045,22 +1049,3 @@ msgstr "Periode"
#~ msgid "People to notify"
#~ msgstr "Te melden personen"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "De gebruiker '%(name)s' is aangepast"
#~ msgid "Number of members"
#~ msgstr "Aantal deelnemers"
#~ msgid "Edit this member"
#~ msgstr "Deze deelnemer bewerken"
#~ msgid "Participants to notify"
#~ msgstr "deelnemers toevoegen"

View file

@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -812,6 +812,10 @@ msgstr "Dokumentacja"
msgid "Administation Dashboard"
msgstr "Kokpit administracyjny"
#, fuzzy
msgid "Legal information"
msgstr "Usuń potwierdzenie"
msgid "\"I hate money\" is free software"
msgstr "„I Hate Money” to darmowe oprogramowanie"
@ -1047,22 +1051,3 @@ msgstr "Okres"
#~ msgid "People to notify"
#~ msgstr "Osoby do powiadomienia"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Użytkownik „%(name)s” został edytowany"
#~ msgid "Number of members"
#~ msgstr "Liczba użytkowników"
#~ msgid "Edit this member"
#~ msgstr "Edytuj tego członka"
#~ msgid "Participants to notify"
#~ msgstr "dodać członków"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -816,6 +816,10 @@ msgstr "Documentação"
msgid "Administation Dashboard"
msgstr "Painel de Administração"
#, fuzzy
msgid "Legal information"
msgstr "Deletar Confirmação"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" é um software livre"
@ -1031,22 +1035,3 @@ msgstr "Período"
#~ msgid "People to notify"
#~ msgstr "Pessoas para notificar"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Utilizador '%(name)s' foi editado"
#~ msgid "Number of members"
#~ msgstr "Quantidade de membros"
#~ msgid "Edit this member"
#~ msgstr "Editar este membro"
#~ msgid "Participants to notify"
#~ msgstr "adicionar participantes"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -814,6 +814,10 @@ msgstr "Documentação"
msgid "Administation Dashboard"
msgstr "Painel de Administração"
#, fuzzy
msgid "Legal information"
msgstr "Deletar Confirmação"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" é um software livre"
@ -1029,22 +1033,3 @@ msgstr "Período"
#~ msgid "People to notify"
#~ msgstr "Pessoas para notificar"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Usuário '%(name)s' foi editado"
#~ msgid "Number of members"
#~ msgstr "Número de membros"
#~ msgid "Edit this member"
#~ msgstr "Editar este membro"
#~ msgid "Participants to notify"
#~ msgstr "adicionar participantes"

View file

@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -813,6 +813,10 @@ msgstr "Документация"
msgid "Administation Dashboard"
msgstr "Панель инструментов администратора"
#, fuzzy
msgid "Legal information"
msgstr "Подтверждение удаления"
msgid "\"I hate money\" is free software"
msgstr "\" I hate money \" - бесплатная программа"
@ -1046,22 +1050,3 @@ msgstr "Период"
#~ msgid "People to notify"
#~ msgstr "Люди для уведомления"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Пользователь '%(name)s' был изменён"
#~ msgid "Number of members"
#~ msgstr "Число участников"
#~ msgid "Edit this member"
#~ msgstr "Изменить этого участника"
#~ msgid "Participants to notify"
#~ msgstr "добавить пользователя"

View file

@ -3,7 +3,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
<<<<<<< HEAD
"POT-Creation-Date: 2021-11-01 18:01+0100\n"
=======
"POT-Creation-Date: 2021-10-26 23:38+0200\n"
>>>>>>> master
"PO-Revision-Date: 2021-04-09 13:26+0000\n"
"Last-Translator: Rastko Sarcevic <ralesarcevic@gmail.com>\n"
"Language: sr\n"
@ -14,7 +18,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -765,6 +769,9 @@ msgstr "Dokumentacija"
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""

View file

@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -783,6 +783,10 @@ msgstr "Dokumentation"
msgid "Administation Dashboard"
msgstr ""
#, fuzzy
msgid "Legal information"
msgstr "Ta bort bekräftelse"
msgid "\"I hate money\" is free software"
msgstr "\"Jag hatar pengar\" är en fri mjukvara"
@ -988,28 +992,3 @@ msgstr "Period"
#~ msgid "People to notify"
#~ msgstr "Personer att meddela"
#~ msgid "Error activating member"
#~ msgstr ""
#~ msgid "Error removing member"
#~ msgstr ""
#~ msgid ""
#~ "User '%(name)s' has been deactivated. It"
#~ " will still appear in the users "
#~ "list until its balance becomes zero."
#~ msgstr ""
#~ msgid "User '%(name)s' has been edited"
#~ msgstr "Användaren '%(name)s' har blivit redigerad"
#~ msgid "Number of members"
#~ msgstr "Antalet medlemmar"
#~ msgid "Edit this member"
#~ msgstr "Redigera det här numret"
#~ msgid "Participants to notify"
#~ msgstr "lägg till deltagare"

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -783,6 +783,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""
@ -1026,4 +1029,3 @@ msgstr ""
#~ msgid "Participants to notify"
#~ msgstr ""

View file

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -759,6 +759,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""
@ -937,4 +940,3 @@ msgstr ""
#~ msgid "Participants to notify"
#~ msgstr ""

View file

@ -13,7 +13,9 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.9-dev\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -815,6 +817,9 @@ msgstr "Belgelendirme"
msgid "Administation Dashboard"
msgstr "Yönetici Gösterge Paneli"
msgid "Legal information"
msgstr "Yasal bilgiler"
msgid "\"I hate money\" is free software"
msgstr "\"I hate money\" özgür bir yazılımdır"
@ -1062,4 +1067,3 @@ msgstr "Dönem"
#~ msgid "Participants to notify"
#~ msgstr "katılımcılar ekle"

View file

@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
"Generated-By: Babel 2.9.0\n"
msgid ""
"Not a valid amount or expression. Only numbers and + - * / operators are "
@ -771,6 +771,9 @@ msgstr ""
msgid "Administation Dashboard"
msgstr ""
msgid "Legal information"
msgstr ""
msgid "\"I hate money\" is free software"
msgstr ""
@ -1025,4 +1028,3 @@ msgstr ""
#~ msgid "Participants to notify"
#~ msgstr ""

Some files were not shown because too many files have changed in this diff Show more