mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-06 21:11:49 +02:00
Merge branch 'master' into almet/feat/showcase
This commit is contained in:
commit
af1562ce24
72 changed files with 7043 additions and 1059 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -1,4 +1,3 @@
|
|||
ihatemoney.cfg
|
||||
*.pyc
|
||||
*.egg-info
|
||||
dist
|
||||
|
@ -10,5 +9,11 @@ dist
|
|||
build
|
||||
.vscode
|
||||
.env
|
||||
.pytest_cache
|
||||
|
||||
.pytest_cache
|
||||
ihatemoney/budget.db
|
||||
.idea/
|
||||
.envrc
|
||||
.DS_Store
|
||||
.idea
|
||||
.python-version
|
||||
|
||||
|
|
13
.isort.cfg
Normal file
13
.isort.cfg
Normal file
|
@ -0,0 +1,13 @@
|
|||
[settings]
|
||||
# Needed for black compatibility
|
||||
multi_line_output=3
|
||||
include_trailing_comma=True
|
||||
force_grid_wrap=0
|
||||
line_length=88
|
||||
combine_as_imports=True
|
||||
|
||||
# If set, imports will be sorted within their section independent to the import_type.
|
||||
force_sort_within_sections=True
|
||||
|
||||
# skip
|
||||
skip_glob=.local,**/migrations/**,**/node_modules/**,**/node-forge/**
|
|
@ -1,9 +1,9 @@
|
|||
sudo: false
|
||||
language: python
|
||||
python:
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "3.7"
|
||||
- "3.8"
|
||||
script: tox
|
||||
install:
|
||||
- pip install tox-travis
|
||||
|
|
|
@ -9,7 +9,7 @@ This document describes changes between each past release.
|
|||
- Add support for espanol latino america (es_419)
|
||||
- Use the external debts lib to solve settlements (#476)
|
||||
- Remove balance column in statistics view (#323)
|
||||
|
||||
- Remove requirements files in favor of setup.cfg pinning (#558)
|
||||
|
||||
4.1.3 (2019-09-18)
|
||||
==================
|
||||
|
|
|
@ -7,20 +7,27 @@ Adrien CLERC
|
|||
Alexandre Avenel
|
||||
Alexis Métaireau
|
||||
Allan Nordhøy
|
||||
am97
|
||||
Andrew Dickinson
|
||||
Arnaud Bos
|
||||
Baptiste Jonglez
|
||||
Benjamin Bouvier
|
||||
Berteh
|
||||
bmatticus
|
||||
Brice Maron
|
||||
Byron Ullauri
|
||||
Carey Metcalfe
|
||||
Daniel Schreiber
|
||||
DavidRThrashJr
|
||||
donkers
|
||||
Edwin Smulders
|
||||
Elizabeth Sherrock
|
||||
eMerzh
|
||||
Feth AREZKI
|
||||
Frédéric Sureau
|
||||
Glandos
|
||||
Heimen Stoffels
|
||||
James Leong
|
||||
Jocelyn Delalande
|
||||
Lucas Verney
|
||||
Luc Didry
|
||||
|
@ -37,5 +44,6 @@ Richard Coates
|
|||
THANOS SIOURDAKIS
|
||||
Toover
|
||||
Xavier Mehrenberger
|
||||
zorun
|
||||
|
||||
The manual drawings are from Coline Billon, they are under CC BY 4.0.
|
||||
|
|
|
@ -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
|
||||
include LICENSE CONTRIBUTORS CHANGELOG.rst requirements.txt
|
||||
include LICENSE CONTRIBUTORS CHANGELOG.rst
|
||||
|
|
29
Makefile
29
Makefile
|
@ -11,10 +11,10 @@ ZOPFLIPNG := zopflipng
|
|||
.PHONY: all
|
||||
all: install ## Alias for install
|
||||
.PHONY: install
|
||||
install: virtualenv $(INSTALL_STAMP) ## Install dependencies
|
||||
install: virtualenv setup.cfg $(INSTALL_STAMP) ## Install dependencies
|
||||
$(INSTALL_STAMP):
|
||||
$(VENV)/bin/pip install -U pip
|
||||
$(VENV)/bin/pip install -r requirements.txt
|
||||
$(VENV)/bin/pip install -e .
|
||||
touch $(INSTALL_STAMP)
|
||||
|
||||
.PHONY: virtualenv
|
||||
|
@ -23,9 +23,9 @@ $(PYTHON):
|
|||
$(VIRTUALENV) $(VENV)
|
||||
|
||||
.PHONY: install-dev
|
||||
install-dev: $(INSTALL_STAMP) $(DEV_STAMP) ## Install development dependencies
|
||||
$(DEV_STAMP): $(PYTHON) dev-requirements.txt
|
||||
$(VENV)/bin/pip install -Ur dev-requirements.txt
|
||||
install-dev: virtualenv setup.cfg $(INSTALL_STAMP) $(DEV_STAMP) ## Install development dependencies
|
||||
$(DEV_STAMP): $(PYTHON)
|
||||
$(VENV)/bin/pip install -Ue .[dev]
|
||||
touch $(DEV_STAMP)
|
||||
|
||||
.PHONY: remove-install-stamp
|
||||
|
@ -41,11 +41,19 @@ serve: install ## Run the ihatemoney server
|
|||
$(PYTHON) -m ihatemoney.manage runserver
|
||||
|
||||
.PHONY: test
|
||||
test: $(DEV_STAMP) ## Run the tests
|
||||
test: install-dev ## Run the tests
|
||||
$(VENV)/bin/tox
|
||||
|
||||
.PHONY: black
|
||||
black: install-dev ## Run the tests
|
||||
$(VENV)/bin/black --target-version=py34 .
|
||||
|
||||
.PHONY: isort
|
||||
isort: install-dev ## Run the tests
|
||||
$(VENV)/bin/isort -rc .
|
||||
|
||||
.PHONY: release
|
||||
release: $(DEV_STAMP) ## Release a new version (see https://ihatemoney.readthedocs.io/en/latest/contributing.html#how-to-release)
|
||||
release: install-dev ## Release a new version (see https://ihatemoney.readthedocs.io/en/latest/contributing.html#how-to-release)
|
||||
$(VENV)/bin/fullrelease
|
||||
|
||||
.PHONY: compress-assets
|
||||
|
@ -76,13 +84,6 @@ create-empty-database-revision: ## Create an empty database revision
|
|||
@read -p "Please enter a message describing this revision: " rev_message; \
|
||||
$(PYTHON) -m ihatemoney.manage db revision -d ihatemoney/migrations -m "$${rev_message}"
|
||||
|
||||
.PHONY: build-requirements
|
||||
build-requirements: ## Save currently installed packages to requirements.txt
|
||||
$(VIRTUALENV) $(TEMPDIR)
|
||||
$(TEMPDIR)/bin/pip install -U pip
|
||||
$(TEMPDIR)/bin/pip install -Ue "."
|
||||
$(TEMPDIR)/bin/pip freeze | grep -v -- '-e' > requirements.txt
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## Destroy the virtual environment
|
||||
rm -rf .venv
|
||||
|
|
12
README.rst
12
README.rst
|
@ -5,6 +5,10 @@ I hate money
|
|||
:target: https://travis-ci.org/spiral-project/ihatemoney
|
||||
:alt: Travis CI Build Status
|
||||
|
||||
.. image:: https://hosted.weblate.org/widgets/i-hate-money/-/i-hate-money/svg-badge.svg
|
||||
:target: https://hosted.weblate.org/engage/i-hate-money/?utm_source=widget
|
||||
:alt: Translation status from Weblate
|
||||
|
||||
*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.
|
||||
|
@ -21,7 +25,7 @@ encouraged to do so.
|
|||
Requirements
|
||||
============
|
||||
|
||||
* **Python**: 3.5, 3.6, 3.7.
|
||||
* **Python**: 3.6, 3.7, 3.8.
|
||||
* **Backends**: MySQL, PostgreSQL, SQLite, Memory.
|
||||
|
||||
Contributing
|
||||
|
@ -31,3 +35,9 @@ Do you wish to contribute to IHateMoney? Fantastic! There's a lot of very
|
|||
useful help on the official `contributing
|
||||
<https://ihatemoney.readthedocs.io/en/latest/contributing.html>`_ page.
|
||||
|
||||
Translation status
|
||||
==================
|
||||
|
||||
.. image:: https://hosted.weblate.org/widgets/i-hate-money/-/i-hate-money/multi-blue.svg
|
||||
:target: https://hosted.weblate.org/engage/i-hate-money/?utm_source=widget
|
||||
:alt: Translation status for each language
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
zest.releaser
|
||||
tox
|
||||
pytest
|
||||
flake8
|
||||
Flask-Testing
|
||||
black ; python_version >= '3.6'
|
|
@ -1,6 +1,3 @@
|
|||
# coding: utf8
|
||||
import sys, os
|
||||
|
||||
templates_path = ["_templates"]
|
||||
source_suffix = ".rst"
|
||||
master_doc = "index"
|
||||
|
|
|
@ -1,14 +1,64 @@
|
|||
Contributing
|
||||
############
|
||||
|
||||
Setup a dev environment
|
||||
=======================
|
||||
.. _how-to-contribute:
|
||||
|
||||
You must develop on top of the git master branch::
|
||||
How to contribute
|
||||
=================
|
||||
|
||||
You would like to contribute? First, thanks a bunch! This project is a small
|
||||
project with just a few people behind it, so any help is appreciated!
|
||||
|
||||
There are different ways to help us, regarding if you are a designer,
|
||||
a developer or an user.
|
||||
|
||||
As a developer
|
||||
--------------
|
||||
|
||||
If you want to contribute code, you can write it and then issue a pull request
|
||||
on github. To get started, please read :ref:`setup-dev-environment` and
|
||||
:ref:`contributing-developer`.
|
||||
|
||||
As a designer / Front-end developer
|
||||
-----------------------------------
|
||||
|
||||
Feel free to provide mockups, or to involve yourself in the discussions
|
||||
happening on the GitHub issue tracker. All ideas are welcome. Of course, if you
|
||||
know how to implement them, feel free to fork and make a pull request.
|
||||
|
||||
As a translator
|
||||
---------------
|
||||
|
||||
If you're able to translate Ihatemoney in your own language,
|
||||
head over to `the website we use for translations <https://hosted.weblate.org/projects/i-hate-money/i-hate-money/>`_
|
||||
and start translating.
|
||||
|
||||
All the heavy lifting will be done automatically, and your strings will
|
||||
eventually be integrated.
|
||||
|
||||
Once a language is ready to be integrated, add it to the
|
||||
``SUPPORTED_LANGUAGES`` list, in ``ihatemoney/default_settings.py``.
|
||||
|
||||
End-user
|
||||
--------
|
||||
|
||||
You are using the application and found a bug? You have some ideas about how to
|
||||
improve the project? Please tell us `by filling a new issue <https://github.com/spiral-project/ihatemoney/issues>`_.
|
||||
Or, if you prefer, you can send me an e-mail to `alexis@notmyidea.org` and I
|
||||
will update the issue tracker with your feedback.
|
||||
|
||||
Thanks again!
|
||||
|
||||
.. _setup-dev-environment:
|
||||
|
||||
Set up a dev environment
|
||||
========================
|
||||
|
||||
You must develop on top of the Git master branch::
|
||||
|
||||
git clone https://github.com/spiral-project/ihatemoney.git
|
||||
|
||||
Then you need to build your dev environments. Choose your way…
|
||||
Then you need to build your dev environment. Choose your way…
|
||||
|
||||
The quick way
|
||||
-------------
|
||||
|
@ -23,10 +73,8 @@ install dependencies, and run the test server.
|
|||
The hard way
|
||||
------------
|
||||
|
||||
Alternatively, you can also use the `requirements.txt` file to install the
|
||||
dependencies yourself. That would be::
|
||||
Alternatively, you can use pip to install dependencies yourself. That would be::
|
||||
|
||||
pip install -r requirements.txt
|
||||
pip install -e .
|
||||
|
||||
And then run the application::
|
||||
|
@ -43,28 +91,10 @@ It's as simple as that!
|
|||
Updating
|
||||
--------
|
||||
|
||||
In case you want to update to newer versions (from git), you can just run the "update" command::
|
||||
In case you want to update to newer versions (from Git), you can just run the "update" command::
|
||||
|
||||
make update
|
||||
|
||||
Create database migrations
|
||||
--------------------------
|
||||
|
||||
In case you need to modify the database schema, first update the models in
|
||||
``ihatemoney/models.py``. Then run the following command to create a new
|
||||
database revision file::
|
||||
|
||||
make create-database-revision
|
||||
|
||||
If your changes are simple enough, the generated script will be populated with
|
||||
the necessary migrations steps. You can edit the generated script. eg: to add
|
||||
data migrations.
|
||||
|
||||
For complex migrations, it is recommended to start from an empty revision file
|
||||
which can be created with the following command::
|
||||
|
||||
make create-empty-database-revision
|
||||
|
||||
Useful settings
|
||||
----------------
|
||||
|
||||
|
@ -80,64 +110,81 @@ Then before running the application, declare its path with ::
|
|||
|
||||
export IHATEMONEY_SETTINGS_FILE_PATH="$(pwd)/settings.cfg"
|
||||
|
||||
How to contribute
|
||||
=================
|
||||
.. _contributing-developer:
|
||||
|
||||
You would like to contribute? First, thanks a bunch! This project is a small
|
||||
project with just a few people behind it, so any help is appreciated!
|
||||
Contributing as a developer
|
||||
===========================
|
||||
|
||||
There are different ways to help us, regarding if you are a designer,
|
||||
a developer or an user.
|
||||
All code contributions should be submitted as Pull Requests on the
|
||||
`github project <https://github.com/spiral-project/ihatemoney>`_.
|
||||
|
||||
As a developer
|
||||
--------------
|
||||
Below are some points that you should check to help you prepare your Pull Request.
|
||||
|
||||
If you want to contribute code, you can write it and then issue a pull request
|
||||
on github. Please, think about updating and running the tests before asking for
|
||||
a pull request as it will help us to maintain the code clean and running.
|
||||
Running tests
|
||||
-------------
|
||||
|
||||
To do so::
|
||||
Please, think about updating and running the tests before asking for a pull request
|
||||
as it will help us to maintain the code clean and running.
|
||||
|
||||
To run the tests::
|
||||
|
||||
make test
|
||||
|
||||
We are using the `black <https://black.readthedocs.io/en/stable/>`_ formatter
|
||||
for all the python files in this project. Be sure to run it locally on your
|
||||
files. To do so, just run::
|
||||
Tests can be edited in ``ihatemoney/tests/tests.py``. If some test cases fail because
|
||||
of your changes, first check whether your code correctly handle these cases.
|
||||
If you are confident that your code is correct and that the test cases simply need
|
||||
to be updated to match your changes, update the test cases and send them as part of
|
||||
your pull request.
|
||||
|
||||
black ihatemoney
|
||||
If you are introducing a new feature, you need to either add tests to existing classes,
|
||||
or add a new class (if your new feature is significantly different from existing code).
|
||||
|
||||
You can also integrate it with your dev environment (as a *format-on-save*
|
||||
hook, for instance).
|
||||
|
||||
As a designer / Front-end developer
|
||||
-----------------------------------
|
||||
|
||||
Feel free to provide us mockups or to involve yourself into the discussions
|
||||
hapenning on the github issue tracker. All ideas are welcome. Of course, if you
|
||||
know how to implement them, feel free to fork and make a pull request.
|
||||
|
||||
As a translator
|
||||
Formatting code
|
||||
---------------
|
||||
|
||||
If you're able to translate Ihatemoney in your own language,
|
||||
head over to `the website we use for translations <https://hosted.weblate.org/settings/i-hate-money/i-hate-money/>`_
|
||||
and start translating!
|
||||
We are using `black <https://black.readthedocs.io/en/stable/>`_ and
|
||||
`isort <https://timothycrosley.github.io/isort/>`_ formatters for all the Python
|
||||
files in this project. Be sure to run it locally on your files.
|
||||
To do so, just run::
|
||||
|
||||
All the heavy lifting will be done automatically, and your strings will
|
||||
eventually be integrated.
|
||||
make black isort
|
||||
|
||||
Once a language is ready to be integrated, add it to the
|
||||
``SUPPORTED_LANGUAGES`` list, in ``ihatemoney/default_settings.py``.
|
||||
You can also integrate them with your dev environment (as a *format-on-save*
|
||||
hook, for instance).
|
||||
|
||||
End-user
|
||||
--------
|
||||
Creating database migrations
|
||||
----------------------------
|
||||
|
||||
You are using the application and found a bug? You have some ideas about how to
|
||||
improve the project? Please tell us `by filling a new issue <https://github.com/spiral-project/ihatemoney/issues>`_.
|
||||
Or, if you prefer, you can send me an email to `alexis@notmyidea.org` and I
|
||||
will update the issue tracker with your feedback.
|
||||
In case you need to modify the database schema, first make sure that you have
|
||||
an up-to-date database by running the dev server at least once (the quick way
|
||||
or the hard way, see above). The dev server applies all existing migrations
|
||||
when starting up.
|
||||
|
||||
You can now update the models in ``ihatemoney/models.py``. Then run the following
|
||||
command to create a new database revision file::
|
||||
|
||||
make create-database-revision
|
||||
|
||||
If your changes are simple enough, the generated script will be populated with
|
||||
the necessary migrations steps. You can view and edit the generated script, which
|
||||
is useful to review that the expected model changes have been properly detected.
|
||||
Usually the auto-detection works well in most cases, but you can of course edit the
|
||||
script to fix small issues. You could also edit the script to add data migrations.
|
||||
|
||||
When you are done with your changes, don't forget to add the migration script to
|
||||
your final git commit!
|
||||
|
||||
If the migration script looks completely wrong, remove the script and start again
|
||||
with an empty database. The simplest way is to remove or rename the dev database
|
||||
located at ``/tmp/ihatemoney.db``, and run the dev server at least once.
|
||||
|
||||
For complex migrations, it is recommended to start from an empty revision file
|
||||
which can be created with the following command::
|
||||
|
||||
make create-empty-database-revision
|
||||
|
||||
You then need to write the migration steps yourself.
|
||||
|
||||
Thanks again!
|
||||
|
||||
How to build the documentation ?
|
||||
================================
|
||||
|
@ -150,7 +197,7 @@ Install doc dependencies (within the virtualenv, if any)::
|
|||
|
||||
pip install -r docs/requirements.txt
|
||||
|
||||
And to produce html doc in `docs/_output` folder::
|
||||
And to produce a HTML doc in the `docs/_output` folder::
|
||||
|
||||
cd docs/
|
||||
make html
|
||||
|
@ -173,7 +220,7 @@ In order to prepare a new release, we are following the following steps:
|
|||
make compress-assets
|
||||
|
||||
- Build the translations::
|
||||
|
||||
|
||||
make update-translations
|
||||
make build-translations
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ Requirements
|
|||
|
||||
«Ihatemoney» depends on:
|
||||
|
||||
* **Python**: either 3.5, 3.6 or 3.7 will work.
|
||||
* **Python**: either 3.6, 3.7 or 3.8 will work.
|
||||
* **A Backend**: to choose among MySQL, PostgreSQL, SQLite or Memory.
|
||||
* **Virtualenv** (recommended): `virtualenv` package under Debian/Ubuntu.
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Sphinx==1.5.5
|
||||
docutils==0.13.1
|
||||
Sphinx==3.0.3
|
||||
docutils==0.16
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# coding: utf8
|
||||
from flask import request, current_app
|
||||
from functools import wraps
|
||||
|
||||
from flask import current_app, request
|
||||
from flask_restful import Resource, abort
|
||||
from werkzeug.security import check_password_hash
|
||||
from wtforms.fields.core import BooleanField
|
||||
|
||||
from ihatemoney.models import db, Project, Person, Bill
|
||||
from ihatemoney.forms import ProjectForm, EditProjectForm, MemberForm, get_billform_for
|
||||
from werkzeug.security import check_password_hash
|
||||
from functools import wraps
|
||||
from ihatemoney.forms import EditProjectForm, MemberForm, ProjectForm, get_billform_for
|
||||
from ihatemoney.models import Bill, Person, Project, db
|
||||
|
||||
|
||||
def need_auth(f):
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
# coding: utf8
|
||||
from flask import Blueprint
|
||||
from flask_restful import Api
|
||||
from flask_cors import CORS
|
||||
from flask_restful import Api
|
||||
|
||||
from ihatemoney.api.common import (
|
||||
ProjectsHandler,
|
||||
ProjectHandler,
|
||||
TokenHandler,
|
||||
MemberHandler,
|
||||
ProjectStatsHandler,
|
||||
MembersHandler,
|
||||
BillHandler,
|
||||
BillsHandler,
|
||||
MemberHandler,
|
||||
MembersHandler,
|
||||
ProjectHandler,
|
||||
ProjectsHandler,
|
||||
ProjectStatsHandler,
|
||||
TokenHandler,
|
||||
)
|
||||
|
||||
api = Blueprint("api", __name__, url_prefix="/api")
|
||||
|
|
46
ihatemoney/currency_convertor.py
Normal file
46
ihatemoney/currency_convertor.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
from cachetools import TTLCache, cached
|
||||
import requests
|
||||
|
||||
|
||||
class Singleton(type):
|
||||
_instances = {}
|
||||
|
||||
def __call__(cls, *args, **kwargs):
|
||||
if cls not in cls._instances:
|
||||
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||
return cls._instances[cls]
|
||||
|
||||
|
||||
class CurrencyConverter(object, metaclass=Singleton):
|
||||
# Get exchange rates
|
||||
default = "No Currency"
|
||||
api_url = "https://api.exchangeratesapi.io/latest?base=USD"
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@cached(cache=TTLCache(maxsize=1, ttl=86400))
|
||||
def get_rates(self):
|
||||
rates = requests.get(self.api_url).json()["rates"]
|
||||
rates[self.default] = 1.0
|
||||
return rates
|
||||
|
||||
def get_currencies(self):
|
||||
rates = [rate for rate in self.get_rates()]
|
||||
rates.sort(key=lambda rate: "" if rate == self.default else rate)
|
||||
return rates
|
||||
|
||||
def exchange_currency(self, amount, source_currency, dest_currency):
|
||||
if (
|
||||
source_currency == dest_currency
|
||||
or source_currency == self.default
|
||||
or dest_currency == self.default
|
||||
):
|
||||
return amount
|
||||
|
||||
rates = self.get_rates()
|
||||
source_rate = rates[source_currency]
|
||||
dest_rate = rates[dest_currency]
|
||||
new_amount = (float(amount) / source_rate) * dest_rate
|
||||
# round to two digits because we are dealing with money
|
||||
return round(new_amount, 2)
|
|
@ -8,4 +8,4 @@ ACTIVATE_DEMO_PROJECT = True
|
|||
ADMIN_PASSWORD = ""
|
||||
ALLOW_PUBLIC_PROJECT_CREATION = True
|
||||
ACTIVATE_ADMIN_DASHBOARD = False
|
||||
SUPPORTED_LANGUAGES = ["en", "fr", "de", "nl", "es_419"]
|
||||
SUPPORTED_LANGUAGES = ["en", "fr", "de", "nl", "es_419", "nb_NO", "id"]
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
import copy
|
||||
from datetime import datetime
|
||||
from re import match
|
||||
|
||||
import email_validator
|
||||
from flask import request
|
||||
from flask_babel import lazy_gettext as _
|
||||
from flask_wtf.file import FileAllowed, FileField, FileRequired
|
||||
from flask_wtf.form import FlaskForm
|
||||
from wtforms.fields.core import SelectField, SelectMultipleField
|
||||
from jinja2 import Markup
|
||||
from werkzeug.security import check_password_hash, generate_password_hash
|
||||
from wtforms.fields.core import Label, SelectField, SelectMultipleField
|
||||
from wtforms.fields.html5 import DateField, DecimalField, URLField
|
||||
from wtforms.fields.simple import PasswordField, SubmitField, StringField
|
||||
from wtforms.fields.simple import BooleanField, PasswordField, StringField, SubmitField
|
||||
from wtforms.validators import (
|
||||
Email,
|
||||
DataRequired,
|
||||
ValidationError,
|
||||
Email,
|
||||
EqualTo,
|
||||
NumberRange,
|
||||
Optional,
|
||||
ValidationError,
|
||||
)
|
||||
from flask_wtf.file import FileField, FileAllowed, FileRequired
|
||||
|
||||
from flask_babel import lazy_gettext as _
|
||||
from flask import request
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
from datetime import datetime
|
||||
from re import match
|
||||
from jinja2 import Markup
|
||||
|
||||
import email_validator
|
||||
|
||||
from ihatemoney.models import Project, Person
|
||||
from ihatemoney.utils import slugify, eval_arithmetic_expression
|
||||
from ihatemoney.currency_convertor import CurrencyConverter
|
||||
from ihatemoney.models import LoggingMode, Person, Project
|
||||
from ihatemoney.utils import eval_arithmetic_expression, slugify
|
||||
|
||||
|
||||
def strip_filter(string):
|
||||
|
@ -33,6 +33,18 @@ def strip_filter(string):
|
|||
return string
|
||||
|
||||
|
||||
def get_editprojectform_for(project, **kwargs):
|
||||
"""Return an instance of EditProjectForm configured for a particular project.
|
||||
"""
|
||||
form = EditProjectForm(**kwargs)
|
||||
choices = copy.copy(form.default_currency.choices)
|
||||
choices.sort(
|
||||
key=lambda rates: "" if rates[0] == project.default_currency else rates[0]
|
||||
)
|
||||
form.default_currency.choices = choices
|
||||
return form
|
||||
|
||||
|
||||
def get_billform_for(project, set_default=True, **kwargs):
|
||||
"""Return an instance of BillForm configured for a particular project.
|
||||
|
||||
|
@ -41,6 +53,23 @@ def get_billform_for(project, set_default=True, **kwargs):
|
|||
|
||||
"""
|
||||
form = BillForm(**kwargs)
|
||||
if form.original_currency.data == "None":
|
||||
form.original_currency.data = project.default_currency
|
||||
|
||||
if form.original_currency.data != CurrencyConverter.default:
|
||||
choices = copy.copy(form.original_currency.choices)
|
||||
choices.remove((CurrencyConverter.default, CurrencyConverter.default))
|
||||
choices.sort(
|
||||
key=lambda rates: "" if rates[0] == project.default_currency else rates[0]
|
||||
)
|
||||
form.original_currency.choices = choices
|
||||
else:
|
||||
form.original_currency.render_kw = {"default": True}
|
||||
form.original_currency.data = CurrencyConverter.default
|
||||
|
||||
form.original_currency.label = Label(
|
||||
"original_currency", "Currency (Default: %s)" % (project.default_currency)
|
||||
)
|
||||
active_members = [(m.id, m.name) for m in project.active_members]
|
||||
|
||||
form.payed_for.choices = form.payer.choices = active_members
|
||||
|
@ -89,6 +118,28 @@ class EditProjectForm(FlaskForm):
|
|||
name = StringField(_("Project name"), validators=[DataRequired()])
|
||||
password = StringField(_("Private code"), validators=[DataRequired()])
|
||||
contact_email = StringField(_("Email"), validators=[DataRequired(), Email()])
|
||||
project_history = BooleanField(_("Enable project history"))
|
||||
ip_recording = BooleanField(_("Use IP tracking for project history"))
|
||||
currency_helper = CurrencyConverter()
|
||||
default_currency = SelectField(
|
||||
_("Default Currency"),
|
||||
choices=[
|
||||
(currency_name, currency_name)
|
||||
for currency_name in currency_helper.get_currencies()
|
||||
],
|
||||
validators=[DataRequired()],
|
||||
)
|
||||
|
||||
@property
|
||||
def logging_preference(self):
|
||||
"""Get the LoggingMode object corresponding to current form data."""
|
||||
if not self.project_history.data:
|
||||
return LoggingMode.DISABLED
|
||||
else:
|
||||
if self.ip_recording.data:
|
||||
return LoggingMode.RECORD_IP
|
||||
else:
|
||||
return LoggingMode.ENABLED
|
||||
|
||||
def save(self):
|
||||
"""Create a new project with the information given by this form.
|
||||
|
@ -100,22 +151,33 @@ class EditProjectForm(FlaskForm):
|
|||
id=self.id.data,
|
||||
password=generate_password_hash(self.password.data),
|
||||
contact_email=self.contact_email.data,
|
||||
logging_preference=self.logging_preference,
|
||||
default_currency=self.default_currency.data,
|
||||
)
|
||||
return project
|
||||
|
||||
def update(self, project):
|
||||
"""Update the project with the information from the form"""
|
||||
project.name = self.name.data
|
||||
project.password = generate_password_hash(self.password.data)
|
||||
|
||||
# Only update password if changed to prevent spurious log entries
|
||||
if not check_password_hash(project.password, self.password.data):
|
||||
project.password = generate_password_hash(self.password.data)
|
||||
|
||||
project.contact_email = self.contact_email.data
|
||||
project.logging_preference = self.logging_preference
|
||||
project.default_currency = self.default_currency.data
|
||||
|
||||
return project
|
||||
|
||||
|
||||
class UploadForm(FlaskForm):
|
||||
file = FileField(
|
||||
"JSON", validators=[FileRequired(), FileAllowed(["json", "JSON"], "JSON only!")]
|
||||
"JSON",
|
||||
validators=[FileRequired(), FileAllowed(["json", "JSON"], "JSON only!")],
|
||||
description=_("Import previously exported JSON file"),
|
||||
)
|
||||
submit = SubmitField(_("Import"))
|
||||
|
||||
|
||||
class ProjectForm(EditProjectForm):
|
||||
|
@ -123,6 +185,14 @@ class ProjectForm(EditProjectForm):
|
|||
password = PasswordField(_("Private code"), validators=[DataRequired()])
|
||||
submit = SubmitField(_("Create the project"))
|
||||
|
||||
def save(self):
|
||||
# WTForms Boolean Fields don't insert the default value when the
|
||||
# request doesn't include any value the way that other fields do,
|
||||
# so we'll manually do it here
|
||||
self.project_history.data = LoggingMode.default() != LoggingMode.DISABLED
|
||||
self.ip_recording.data = LoggingMode.default() == LoggingMode.RECORD_IP
|
||||
return super().save()
|
||||
|
||||
def validate_id(form, field):
|
||||
form.id.data = slugify(field.data)
|
||||
if (form.id.data == "dashboard") or Project.query.get(form.id.data):
|
||||
|
@ -171,6 +241,15 @@ class BillForm(FlaskForm):
|
|||
what = StringField(_("What?"), validators=[DataRequired()])
|
||||
payer = SelectField(_("Payer"), validators=[DataRequired()], coerce=int)
|
||||
amount = CalculatorStringField(_("Amount paid"), validators=[DataRequired()])
|
||||
currency_helper = CurrencyConverter()
|
||||
original_currency = SelectField(
|
||||
_("Currency"),
|
||||
choices=[
|
||||
(currency_name, currency_name)
|
||||
for currency_name in currency_helper.get_currencies()
|
||||
],
|
||||
validators=[DataRequired()],
|
||||
)
|
||||
external_link = URLField(
|
||||
_("External link"),
|
||||
validators=[Optional()],
|
||||
|
@ -189,6 +268,10 @@ class BillForm(FlaskForm):
|
|||
bill.external_link = self.external_link.data
|
||||
bill.date = self.date.data
|
||||
bill.owers = [Person.query.get(ower, project) for ower in self.payed_for.data]
|
||||
bill.original_currency = self.original_currency.data
|
||||
bill.converted_amount = self.currency_helper.exchange_currency(
|
||||
bill.amount, bill.original_currency, project.default_currency
|
||||
)
|
||||
return bill
|
||||
|
||||
def fake_form(self, bill, project):
|
||||
|
@ -198,6 +281,10 @@ class BillForm(FlaskForm):
|
|||
bill.external_link = ""
|
||||
bill.date = self.date
|
||||
bill.owers = [Person.query.get(ower, project) for ower in self.payed_for]
|
||||
bill.original_currency = CurrencyConverter.default
|
||||
bill.converted_amount = self.currency_helper.exchange_currency(
|
||||
bill.amount, bill.original_currency, project.default_currency
|
||||
)
|
||||
|
||||
return bill
|
||||
|
||||
|
@ -206,6 +293,7 @@ class BillForm(FlaskForm):
|
|||
self.amount.data = bill.amount
|
||||
self.what.data = bill.what
|
||||
self.external_link.data = bill.external_link
|
||||
self.original_currency.data = bill.original_currency
|
||||
self.date.data = bill.date
|
||||
self.payed_for.data = [int(ower.id) for ower in bill.owers]
|
||||
|
||||
|
|
139
ihatemoney/history.py
Normal file
139
ihatemoney/history.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
from flask_babel import gettext as _
|
||||
from sqlalchemy_continuum import Operation, parent_class
|
||||
|
||||
from ihatemoney.models import BillVersion, Person, PersonVersion, ProjectVersion
|
||||
|
||||
|
||||
def get_history_queries(project):
|
||||
"""Generate queries for each type of version object for a given project."""
|
||||
person_changes = PersonVersion.query.filter_by(project_id=project.id)
|
||||
|
||||
project_changes = ProjectVersion.query.filter_by(id=project.id)
|
||||
|
||||
bill_changes = (
|
||||
BillVersion.query.with_entities(BillVersion.id.label("bill_version_id"))
|
||||
.join(Person, BillVersion.payer_id == Person.id)
|
||||
.filter(Person.project_id == project.id)
|
||||
)
|
||||
sub_query = bill_changes.subquery()
|
||||
bill_changes = BillVersion.query.filter(BillVersion.id.in_(sub_query))
|
||||
|
||||
return person_changes, project_changes, bill_changes
|
||||
|
||||
|
||||
def history_sort_key(history_item_dict):
|
||||
"""
|
||||
Return the key necessary to sort history entries. First order sort is time
|
||||
of modification, but for simultaneous modifications we make the re-name
|
||||
modification occur last so that the simultaneous entries make sense using
|
||||
the old name.
|
||||
"""
|
||||
second_order = 0
|
||||
if "prop_changed" in history_item_dict:
|
||||
changed_property = history_item_dict["prop_changed"]
|
||||
if changed_property == "name" or changed_property == "what":
|
||||
second_order = 1
|
||||
|
||||
return history_item_dict["time"], second_order
|
||||
|
||||
|
||||
def describe_version(version_obj):
|
||||
"""Use the base model str() function to describe a version object"""
|
||||
return parent_class(type(version_obj)).__str__(version_obj)
|
||||
|
||||
|
||||
def describe_owers_change(version, human_readable_names):
|
||||
"""Compute the set difference to get added/removed owers lists."""
|
||||
before_owers = {version.id: version for version in version.previous.owers}
|
||||
after_owers = {version.id: version for version in version.owers}
|
||||
|
||||
added_ids = set(after_owers).difference(set(before_owers))
|
||||
removed_ids = set(before_owers).difference(set(after_owers))
|
||||
|
||||
if not human_readable_names:
|
||||
return added_ids, removed_ids
|
||||
|
||||
added = [describe_version(after_owers[ower_id]) for ower_id in added_ids]
|
||||
removed = [describe_version(before_owers[ower_id]) for ower_id in removed_ids]
|
||||
|
||||
return added, removed
|
||||
|
||||
|
||||
def get_history(project, human_readable_names=True):
|
||||
"""
|
||||
Fetch history for all models associated with a given project.
|
||||
:param human_readable_names Whether to replace id numbers with readable names
|
||||
:return A sorted list of dicts with history information
|
||||
"""
|
||||
person_query, project_query, bill_query = get_history_queries(project)
|
||||
history = []
|
||||
for version_list in [person_query.all(), project_query.all(), bill_query.all()]:
|
||||
for version in version_list:
|
||||
object_type = {
|
||||
"Person": _("Participant"),
|
||||
"Bill": _("Bill"),
|
||||
"Project": _("Project"),
|
||||
}[parent_class(type(version)).__name__]
|
||||
|
||||
# Use the old name if applicable
|
||||
if version.previous:
|
||||
object_str = describe_version(version.previous)
|
||||
else:
|
||||
object_str = describe_version(version)
|
||||
|
||||
common_properties = {
|
||||
"time": version.transaction.issued_at.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"operation_type": version.operation_type,
|
||||
"object_type": object_type,
|
||||
"object_desc": object_str,
|
||||
"ip": version.transaction.remote_addr,
|
||||
}
|
||||
|
||||
if version.operation_type == Operation.UPDATE:
|
||||
# Only iterate the changeset if the previous version
|
||||
# Was logged
|
||||
if version.previous:
|
||||
changeset = version.changeset
|
||||
if isinstance(version, BillVersion):
|
||||
if version.owers != version.previous.owers:
|
||||
added, removed = describe_owers_change(
|
||||
version, human_readable_names
|
||||
)
|
||||
|
||||
if added:
|
||||
changeset["owers_added"] = (None, added)
|
||||
if removed:
|
||||
changeset["owers_removed"] = (None, removed)
|
||||
|
||||
# Remove converted_amount if amount changed in the same way.
|
||||
if (
|
||||
"amount" in changeset
|
||||
and "converted_amount" in changeset
|
||||
and changeset["amount"] == changeset["converted_amount"]
|
||||
):
|
||||
del changeset["converted_amount"]
|
||||
|
||||
for (prop, (val_before, val_after),) in changeset.items():
|
||||
if human_readable_names:
|
||||
if prop == "payer_id":
|
||||
prop = "payer"
|
||||
if val_after is not None:
|
||||
val_after = describe_version(version.payer)
|
||||
if version.previous and val_before is not None:
|
||||
val_before = describe_version(
|
||||
version.previous.payer
|
||||
)
|
||||
else:
|
||||
val_after = None
|
||||
|
||||
next_event = common_properties.copy()
|
||||
next_event["prop_changed"] = prop
|
||||
next_event["val_before"] = val_before
|
||||
next_event["val_after"] = val_after
|
||||
history.append(next_event)
|
||||
else:
|
||||
history.append(common_properties)
|
||||
else:
|
||||
history.append(common_properties)
|
||||
|
||||
return sorted(history, key=history_sort_key, reverse=True)
|
|
@ -1,16 +1,16 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import getpass
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import getpass
|
||||
|
||||
from flask_script import Manager, Command, Option
|
||||
from flask_migrate import Migrate, MigrateCommand
|
||||
from flask_script import Command, Manager, Option
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
from ihatemoney.models import Project, db
|
||||
from ihatemoney.run import create_app
|
||||
from ihatemoney.models import db, Project
|
||||
from ihatemoney.utils import create_jinja_env
|
||||
|
||||
|
||||
|
@ -51,7 +51,7 @@ class GenerateConfig(Command):
|
|||
|
||||
def run(self, config_file):
|
||||
env = create_jinja_env("conf-templates", strict_rendering=True)
|
||||
template = env.get_template("%s.j2" % config_file)
|
||||
template = env.get_template(f"{config_file}.j2")
|
||||
|
||||
bin_path = os.path.dirname(sys.executable)
|
||||
pkg_path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
|
|
@ -12,6 +12,18 @@ msgstr ""
|
|||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr ""
|
||||
|
||||
|
@ -106,6 +118,15 @@ msgstr ""
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
|
||||
|
@ -139,6 +160,12 @@ msgstr ""
|
|||
msgid "Password successfully reset."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -150,7 +177,7 @@ msgid "Your invitations have been sent"
|
|||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
|
@ -204,9 +231,6 @@ msgstr ""
|
|||
msgid "Create a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr ""
|
||||
|
||||
|
@ -228,6 +252,9 @@ msgstr ""
|
|||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr ""
|
||||
|
||||
|
@ -237,6 +264,12 @@ msgstr ""
|
|||
msgid "Edit project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -258,6 +291,9 @@ msgstr ""
|
|||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr ""
|
||||
|
||||
|
@ -288,6 +324,177 @@ msgstr ""
|
|||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr ""
|
||||
|
||||
|
@ -335,6 +542,9 @@ msgstr ""
|
|||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -392,6 +602,12 @@ msgstr ""
|
|||
msgid "Add a new bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -418,9 +634,6 @@ msgstr ""
|
|||
msgid "each"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "No bills"
|
||||
msgstr ""
|
||||
|
||||
|
@ -489,15 +702,15 @@ msgstr ""
|
|||
msgid "To whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Spent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ def run_migrations_offline():
|
|||
|
||||
"""
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(url=url)
|
||||
context.configure(url=url, include_object=include_object)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
@ -75,6 +75,7 @@ def run_migrations_online():
|
|||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
include_object=include_object,
|
||||
process_revision_directives=process_revision_directives,
|
||||
**current_app.extensions["migrate"].configure_args
|
||||
)
|
||||
|
@ -86,6 +87,12 @@ def run_migrations_online():
|
|||
connection.close()
|
||||
|
||||
|
||||
def include_object(object, name, type_, reflected, compare_to):
|
||||
if name == "sqlite_sequence":
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
|
|
232
ihatemoney/migrations/versions/2dcb0c0048dc_autologger.py
Normal file
232
ihatemoney/migrations/versions/2dcb0c0048dc_autologger.py
Normal file
|
@ -0,0 +1,232 @@
|
|||
"""autologger
|
||||
|
||||
Revision ID: 2dcb0c0048dc
|
||||
Revises: 6c6fb2b7f229
|
||||
Create Date: 2020-04-10 18:12:41.285590
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "2dcb0c0048dc"
|
||||
down_revision = "6c6fb2b7f229"
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table(
|
||||
"bill_version",
|
||||
sa.Column("id", sa.Integer(), autoincrement=False, nullable=False),
|
||||
sa.Column("payer_id", sa.Integer(), autoincrement=False, nullable=True),
|
||||
sa.Column("amount", sa.Float(), autoincrement=False, nullable=True),
|
||||
sa.Column("date", sa.Date(), autoincrement=False, nullable=True),
|
||||
sa.Column("creation_date", sa.Date(), autoincrement=False, nullable=True),
|
||||
sa.Column("what", sa.UnicodeText(), autoincrement=False, nullable=True),
|
||||
sa.Column(
|
||||
"external_link", sa.UnicodeText(), autoincrement=False, nullable=True
|
||||
),
|
||||
sa.Column("archive", sa.Integer(), autoincrement=False, nullable=True),
|
||||
sa.Column(
|
||||
"transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
|
||||
),
|
||||
sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("operation_type", sa.SmallInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id", "transaction_id"),
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_bill_version_end_transaction_id"),
|
||||
"bill_version",
|
||||
["end_transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_bill_version_operation_type"),
|
||||
"bill_version",
|
||||
["operation_type"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_bill_version_transaction_id"),
|
||||
"bill_version",
|
||||
["transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_table(
|
||||
"billowers_version",
|
||||
sa.Column("bill_id", sa.Integer(), autoincrement=False, nullable=False),
|
||||
sa.Column("person_id", sa.Integer(), autoincrement=False, nullable=False),
|
||||
sa.Column(
|
||||
"transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
|
||||
),
|
||||
sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("operation_type", sa.SmallInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("bill_id", "person_id", "transaction_id"),
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_billowers_version_end_transaction_id"),
|
||||
"billowers_version",
|
||||
["end_transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_billowers_version_operation_type"),
|
||||
"billowers_version",
|
||||
["operation_type"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_billowers_version_transaction_id"),
|
||||
"billowers_version",
|
||||
["transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_table(
|
||||
"person_version",
|
||||
sa.Column("id", sa.Integer(), autoincrement=False, nullable=False),
|
||||
sa.Column(
|
||||
"project_id", sa.String(length=64), autoincrement=False, nullable=True
|
||||
),
|
||||
sa.Column("name", sa.UnicodeText(), autoincrement=False, nullable=True),
|
||||
sa.Column("weight", sa.Float(), autoincrement=False, nullable=True),
|
||||
sa.Column("activated", sa.Boolean(), autoincrement=False, nullable=True),
|
||||
sa.Column(
|
||||
"transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
|
||||
),
|
||||
sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("operation_type", sa.SmallInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id", "transaction_id"),
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_person_version_end_transaction_id"),
|
||||
"person_version",
|
||||
["end_transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_person_version_operation_type"),
|
||||
"person_version",
|
||||
["operation_type"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_person_version_transaction_id"),
|
||||
"person_version",
|
||||
["transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_table(
|
||||
"project_version",
|
||||
sa.Column("id", sa.String(length=64), autoincrement=False, nullable=False),
|
||||
sa.Column("name", sa.UnicodeText(), autoincrement=False, nullable=True),
|
||||
sa.Column(
|
||||
"password", sa.String(length=128), autoincrement=False, nullable=True
|
||||
),
|
||||
sa.Column(
|
||||
"contact_email", sa.String(length=128), autoincrement=False, nullable=True
|
||||
),
|
||||
sa.Column(
|
||||
"logging_preference",
|
||||
sa.Enum("DISABLED", "ENABLED", "RECORD_IP", name="loggingmode"),
|
||||
server_default="ENABLED",
|
||||
autoincrement=False,
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column(
|
||||
"transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
|
||||
),
|
||||
sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("operation_type", sa.SmallInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id", "transaction_id"),
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_project_version_end_transaction_id"),
|
||||
"project_version",
|
||||
["end_transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_project_version_operation_type"),
|
||||
"project_version",
|
||||
["operation_type"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_project_version_transaction_id"),
|
||||
"project_version",
|
||||
["transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_table(
|
||||
"transaction",
|
||||
sa.Column("issued_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("remote_addr", sa.String(length=50), nullable=True),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
bind = op.get_bind()
|
||||
if bind.engine.name == "sqlite":
|
||||
with op.batch_alter_table("project", recreate="always") as batch_op:
|
||||
batch_op.add_column(
|
||||
sa.Column(
|
||||
"logging_preference",
|
||||
sa.Enum("DISABLED", "ENABLED", "RECORD_IP", name="loggingmode"),
|
||||
server_default="ENABLED",
|
||||
nullable=False,
|
||||
),
|
||||
)
|
||||
else:
|
||||
op.add_column(
|
||||
"project",
|
||||
sa.Column(
|
||||
"logging_preference",
|
||||
sa.Enum("DISABLED", "ENABLED", "RECORD_IP", name="loggingmode"),
|
||||
server_default="ENABLED",
|
||||
nullable=False,
|
||||
),
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
|
||||
bind = op.get_bind()
|
||||
if bind.engine.name == "sqlite":
|
||||
with op.batch_alter_table("project", recreate="always") as batch_op:
|
||||
batch_op.drop_column("logging_preference")
|
||||
else:
|
||||
op.drop_column("project", "logging_preference")
|
||||
op.drop_table("transaction")
|
||||
op.drop_index(
|
||||
op.f("ix_project_version_transaction_id"), table_name="project_version"
|
||||
)
|
||||
op.drop_index(
|
||||
op.f("ix_project_version_operation_type"), table_name="project_version"
|
||||
)
|
||||
op.drop_index(
|
||||
op.f("ix_project_version_end_transaction_id"), table_name="project_version"
|
||||
)
|
||||
op.drop_table("project_version")
|
||||
op.drop_index(op.f("ix_person_version_transaction_id"), table_name="person_version")
|
||||
op.drop_index(op.f("ix_person_version_operation_type"), table_name="person_version")
|
||||
op.drop_index(
|
||||
op.f("ix_person_version_end_transaction_id"), table_name="person_version"
|
||||
)
|
||||
op.drop_table("person_version")
|
||||
op.drop_index(
|
||||
op.f("ix_billowers_version_transaction_id"), table_name="billowers_version"
|
||||
)
|
||||
op.drop_index(
|
||||
op.f("ix_billowers_version_operation_type"), table_name="billowers_version"
|
||||
)
|
||||
op.drop_index(
|
||||
op.f("ix_billowers_version_end_transaction_id"), table_name="billowers_version"
|
||||
)
|
||||
op.drop_table("billowers_version")
|
||||
op.drop_index(op.f("ix_bill_version_transaction_id"), table_name="bill_version")
|
||||
op.drop_index(op.f("ix_bill_version_operation_type"), table_name="bill_version")
|
||||
op.drop_index(op.f("ix_bill_version_end_transaction_id"), table_name="bill_version")
|
||||
op.drop_table("bill_version")
|
||||
# ### end Alembic commands ###
|
|
@ -0,0 +1,73 @@
|
|||
"""Add currencies
|
||||
|
||||
Revision ID: 927ed575acbd
|
||||
Revises: cb038f79982e
|
||||
Create Date: 2020-04-25 14:49:41.136602
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "927ed575acbd"
|
||||
down_revision = "cb038f79982e"
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from ihatemoney.currency_convertor import CurrencyConverter
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column("bill", sa.Column("converted_amount", sa.Float(), nullable=True))
|
||||
op.add_column(
|
||||
"bill",
|
||||
sa.Column(
|
||||
"original_currency",
|
||||
sa.String(length=3),
|
||||
server_default=CurrencyConverter.default,
|
||||
nullable=True,
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"bill_version",
|
||||
sa.Column("converted_amount", sa.Float(), autoincrement=False, nullable=True),
|
||||
)
|
||||
op.add_column(
|
||||
"bill_version",
|
||||
sa.Column(
|
||||
"original_currency", sa.String(length=3), autoincrement=False, nullable=True
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"project",
|
||||
sa.Column(
|
||||
"default_currency",
|
||||
sa.String(length=3),
|
||||
server_default=CurrencyConverter.default,
|
||||
nullable=True,
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"project_version",
|
||||
sa.Column(
|
||||
"default_currency", sa.String(length=3), autoincrement=False, nullable=True
|
||||
),
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
op.execute(
|
||||
"""
|
||||
UPDATE bill
|
||||
SET converted_amount = amount
|
||||
WHERE converted_amount IS NULL
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column("project_version", "default_currency")
|
||||
op.drop_column("project", "default_currency")
|
||||
op.drop_column("bill_version", "original_currency")
|
||||
op.drop_column("bill_version", "converted_amount")
|
||||
op.drop_column("bill", "original_currency")
|
||||
op.drop_column("bill", "converted_amount")
|
||||
# ### end Alembic commands ###
|
|
@ -0,0 +1,60 @@
|
|||
"""sqlite_autoincrement
|
||||
|
||||
Revision ID: cb038f79982e
|
||||
Revises: 2dcb0c0048dc
|
||||
Create Date: 2020-04-13 17:40:02.426957
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "cb038f79982e"
|
||||
down_revision = "2dcb0c0048dc"
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
bind = op.get_bind()
|
||||
if bind.engine.name == "sqlite":
|
||||
alter_table_batches = [
|
||||
op.batch_alter_table(
|
||||
"person", recreate="always", table_kwargs={"sqlite_autoincrement": True}
|
||||
),
|
||||
op.batch_alter_table(
|
||||
"bill", recreate="always", table_kwargs={"sqlite_autoincrement": True}
|
||||
),
|
||||
op.batch_alter_table(
|
||||
"billowers",
|
||||
recreate="always",
|
||||
table_kwargs={"sqlite_autoincrement": True},
|
||||
),
|
||||
]
|
||||
|
||||
for batch_op in alter_table_batches:
|
||||
with batch_op:
|
||||
pass
|
||||
|
||||
|
||||
def downgrade():
|
||||
bind = op.get_bind()
|
||||
if bind.engine.name == "sqlite":
|
||||
alter_table_batches = [
|
||||
op.batch_alter_table(
|
||||
"person",
|
||||
recreate="always",
|
||||
table_kwargs={"sqlite_autoincrement": False},
|
||||
),
|
||||
op.batch_alter_table(
|
||||
"bill", recreate="always", table_kwargs={"sqlite_autoincrement": False}
|
||||
),
|
||||
op.batch_alter_table(
|
||||
"billowers",
|
||||
recreate="always",
|
||||
table_kwargs={"sqlite_autoincrement": False},
|
||||
),
|
||||
]
|
||||
|
||||
for batch_op in alter_table_batches:
|
||||
with batch_op:
|
||||
pass
|
|
@ -1,17 +1,49 @@
|
|||
from collections import defaultdict
|
||||
|
||||
from datetime import datetime
|
||||
from flask_sqlalchemy import SQLAlchemy, BaseQuery
|
||||
from flask import g, current_app
|
||||
|
||||
from debts import settle
|
||||
from sqlalchemy import orm
|
||||
from sqlalchemy.sql import func
|
||||
from flask import current_app, g
|
||||
from flask_sqlalchemy import BaseQuery, SQLAlchemy
|
||||
from itsdangerous import (
|
||||
TimedJSONWebSignatureSerializer,
|
||||
URLSafeSerializer,
|
||||
BadSignature,
|
||||
SignatureExpired,
|
||||
TimedJSONWebSignatureSerializer,
|
||||
URLSafeSerializer,
|
||||
)
|
||||
import sqlalchemy
|
||||
from sqlalchemy import orm
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy_continuum import make_versioned, version_class
|
||||
from sqlalchemy_continuum.plugins import FlaskPlugin
|
||||
|
||||
from ihatemoney.patch_sqlalchemy_continuum import PatchedBuilder
|
||||
from ihatemoney.versioning import (
|
||||
ConditionalVersioningManager,
|
||||
LoggingMode,
|
||||
get_ip_if_allowed,
|
||||
version_privacy_predicate,
|
||||
)
|
||||
|
||||
make_versioned(
|
||||
user_cls=None,
|
||||
manager=ConditionalVersioningManager(
|
||||
# Conditionally Disable the versioning based on each
|
||||
# project's privacy preferences
|
||||
tracking_predicate=version_privacy_predicate,
|
||||
# Patch in a fix to a SQLAchemy-Continuum Bug.
|
||||
# See patch_sqlalchemy_continuum.py
|
||||
builder=PatchedBuilder(),
|
||||
),
|
||||
plugins=[
|
||||
FlaskPlugin(
|
||||
# Redirect to our own function, which respects user preferences
|
||||
# on IP address collection
|
||||
remote_addr_factory=get_ip_if_allowed,
|
||||
# Suppress the plugin's attempt to grab a user id,
|
||||
# which imports the flask_login module (causing an error)
|
||||
current_user_id_factory=lambda: None,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
db = SQLAlchemy()
|
||||
|
@ -22,14 +54,24 @@ class Project(db.Model):
|
|||
def get_by_name(self, name):
|
||||
return Project.query.filter(Project.name == name).one()
|
||||
|
||||
# Direct SQLAlchemy-Continuum to track changes to this model
|
||||
__versioned__ = {}
|
||||
|
||||
id = db.Column(db.String(64), primary_key=True)
|
||||
|
||||
name = db.Column(db.UnicodeText)
|
||||
password = db.Column(db.String(128))
|
||||
contact_email = db.Column(db.String(128))
|
||||
logging_preference = db.Column(
|
||||
db.Enum(LoggingMode),
|
||||
default=LoggingMode.default(),
|
||||
nullable=False,
|
||||
server_default=LoggingMode.default().name,
|
||||
)
|
||||
members = db.relationship("Person", backref="project")
|
||||
|
||||
query_class = ProjectQuery
|
||||
default_currency = db.Column(db.String(3))
|
||||
|
||||
@property
|
||||
def _to_serialize(self):
|
||||
|
@ -37,7 +79,9 @@ class Project(db.Model):
|
|||
"id": self.id,
|
||||
"name": self.name,
|
||||
"contact_email": self.contact_email,
|
||||
"logging_preference": self.logging_preference.value,
|
||||
"members": [],
|
||||
"default_currency": self.default_currency,
|
||||
}
|
||||
|
||||
balance = self.balance
|
||||
|
@ -86,7 +130,10 @@ class Project(db.Model):
|
|||
{
|
||||
"member": member,
|
||||
"paid": sum(
|
||||
[bill.amount for bill in self.get_member_bills(member.id).all()]
|
||||
[
|
||||
bill.converted_amount
|
||||
for bill in self.get_member_bills(member.id).all()
|
||||
]
|
||||
),
|
||||
"spent": sum(
|
||||
[
|
||||
|
@ -109,7 +156,7 @@ class Project(db.Model):
|
|||
"""
|
||||
monthly = defaultdict(lambda: defaultdict(float))
|
||||
for bill in self.get_bills().all():
|
||||
monthly[bill.date.year][bill.date.month] += bill.amount
|
||||
monthly[bill.date.year][bill.date.month] += bill.converted_amount
|
||||
return monthly
|
||||
|
||||
@property
|
||||
|
@ -277,8 +324,11 @@ class Project(db.Model):
|
|||
return None
|
||||
return data["project_id"]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return "<Project %s>" % self.name
|
||||
return f"<Project {self.name}>"
|
||||
|
||||
|
||||
class Person(db.Model):
|
||||
|
@ -301,6 +351,11 @@ class Person(db.Model):
|
|||
|
||||
query_class = PersonQuery
|
||||
|
||||
# Direct SQLAlchemy-Continuum to track changes to this model
|
||||
__versioned__ = {}
|
||||
|
||||
__table_args__ = {"sqlite_autoincrement": True}
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
project_id = db.Column(db.String(64), db.ForeignKey("project.id"))
|
||||
bills = db.relationship("Bill", backref="payer")
|
||||
|
@ -331,14 +386,15 @@ class Person(db.Model):
|
|||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return "<Person %s for project %s>" % (self.name, self.project.name)
|
||||
return f"<Person {self.name} for project {self.project.name}>"
|
||||
|
||||
|
||||
# We need to manually define a join table for m2m relations
|
||||
billowers = db.Table(
|
||||
"billowers",
|
||||
db.Column("bill_id", db.Integer, db.ForeignKey("bill.id")),
|
||||
db.Column("person_id", db.Integer, db.ForeignKey("person.id")),
|
||||
db.Column("bill_id", db.Integer, db.ForeignKey("bill.id"), primary_key=True),
|
||||
db.Column("person_id", db.Integer, db.ForeignKey("person.id"), primary_key=True),
|
||||
sqlite_autoincrement=True,
|
||||
)
|
||||
|
||||
|
||||
|
@ -365,6 +421,11 @@ class Bill(db.Model):
|
|||
|
||||
query_class = BillQuery
|
||||
|
||||
# Direct SQLAlchemy-Continuum to track changes to this model
|
||||
__versioned__ = {}
|
||||
|
||||
__table_args__ = {"sqlite_autoincrement": True}
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
payer_id = db.Column(db.Integer, db.ForeignKey("person.id"))
|
||||
|
@ -376,6 +437,9 @@ class Bill(db.Model):
|
|||
what = db.Column(db.UnicodeText)
|
||||
external_link = db.Column(db.UnicodeText)
|
||||
|
||||
original_currency = db.Column(db.String(3))
|
||||
converted_amount = db.Column(db.Float)
|
||||
|
||||
archive = db.Column(db.Integer, db.ForeignKey("archive.id"))
|
||||
|
||||
@property
|
||||
|
@ -389,9 +453,11 @@ class Bill(db.Model):
|
|||
"creation_date": self.creation_date,
|
||||
"what": self.what,
|
||||
"external_link": self.external_link,
|
||||
"original_currency": self.original_currency,
|
||||
"converted_amount": self.converted_amount,
|
||||
}
|
||||
|
||||
def pay_each(self):
|
||||
def pay_each_default(self, amount):
|
||||
"""Compute what each share has to pay"""
|
||||
if self.owers:
|
||||
weights = (
|
||||
|
@ -399,15 +465,20 @@ class Bill(db.Model):
|
|||
.join(billowers, Bill)
|
||||
.filter(Bill.id == self.id)
|
||||
).scalar()
|
||||
return self.amount / weights
|
||||
return amount / weights
|
||||
else:
|
||||
return 0
|
||||
|
||||
def __str__(self):
|
||||
return self.what
|
||||
|
||||
def pay_each(self):
|
||||
return self.pay_each_default(self.converted_amount)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Bill of %s from %s for %s>" % (
|
||||
self.amount,
|
||||
self.payer,
|
||||
", ".join([o.name for o in self.owers]),
|
||||
return (
|
||||
f"<Bill of {self.amount} from {self.payer} for "
|
||||
f"{', '.join([o.name for o in self.owers])}>"
|
||||
)
|
||||
|
||||
|
||||
|
@ -426,3 +497,10 @@ class Archive(db.Model):
|
|||
|
||||
def __repr__(self):
|
||||
return "<Archive>"
|
||||
|
||||
|
||||
sqlalchemy.orm.configure_mappers()
|
||||
|
||||
PersonVersion = version_class(Person)
|
||||
ProjectVersion = version_class(Project)
|
||||
BillVersion = version_class(Bill)
|
||||
|
|
138
ihatemoney/patch_sqlalchemy_continuum.py
Normal file
138
ihatemoney/patch_sqlalchemy_continuum.py
Normal file
|
@ -0,0 +1,138 @@
|
|||
"""
|
||||
A temporary work-around to patch SQLAlchemy-continuum per:
|
||||
https://github.com/kvesteri/sqlalchemy-continuum/pull/242
|
||||
|
||||
Source code reproduced under their license:
|
||||
|
||||
Copyright (c) 2012, Konsta Vesterinen
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy_continuum import Operation
|
||||
from sqlalchemy_continuum.builder import Builder
|
||||
from sqlalchemy_continuum.expression_reflector import VersionExpressionReflector
|
||||
from sqlalchemy_continuum.relationship_builder import RelationshipBuilder
|
||||
from sqlalchemy_continuum.utils import adapt_columns, option
|
||||
|
||||
|
||||
class PatchedRelationShipBuilder(RelationshipBuilder):
|
||||
def association_subquery(self, obj):
|
||||
"""
|
||||
Returns an EXISTS clause that checks if an association exists for given
|
||||
SQLAlchemy declarative object. This query is used by
|
||||
many_to_many_criteria method.
|
||||
|
||||
Example query:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM article_tag_version
|
||||
WHERE article_id = 3
|
||||
AND tag_id = tags_version.id
|
||||
AND operation_type != 2
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM article_tag_version as article_tag_version2
|
||||
WHERE article_tag_version2.tag_id = article_tag_version.tag_id
|
||||
AND article_tag_version2.tx_id <=5
|
||||
AND article_tag_version2.article_id = 3
|
||||
GROUP BY article_tag_version2.tag_id
|
||||
HAVING
|
||||
MAX(article_tag_version2.tx_id) =
|
||||
article_tag_version.tx_id
|
||||
)
|
||||
)
|
||||
|
||||
:param obj: SQLAlchemy declarative object
|
||||
"""
|
||||
|
||||
tx_column = option(obj, "transaction_column_name")
|
||||
join_column = self.property.primaryjoin.right.name
|
||||
object_join_column = self.property.primaryjoin.left.name
|
||||
reflector = VersionExpressionReflector(obj, self.property)
|
||||
|
||||
association_table_alias = self.association_version_table.alias()
|
||||
association_cols = [
|
||||
association_table_alias.c[association_col.name]
|
||||
for _, association_col in self.remote_to_association_column_pairs
|
||||
]
|
||||
|
||||
association_exists = sa.exists(
|
||||
sa.select([1])
|
||||
.where(
|
||||
sa.and_(
|
||||
association_table_alias.c[tx_column] <= getattr(obj, tx_column),
|
||||
association_table_alias.c[join_column]
|
||||
== getattr(obj, object_join_column),
|
||||
*[
|
||||
association_col
|
||||
== self.association_version_table.c[association_col.name]
|
||||
for association_col in association_cols
|
||||
]
|
||||
)
|
||||
)
|
||||
.group_by(*association_cols)
|
||||
.having(
|
||||
sa.func.max(association_table_alias.c[tx_column])
|
||||
== self.association_version_table.c[tx_column]
|
||||
)
|
||||
.correlate(self.association_version_table)
|
||||
)
|
||||
return sa.exists(
|
||||
sa.select([1])
|
||||
.where(
|
||||
sa.and_(
|
||||
reflector(self.property.primaryjoin),
|
||||
association_exists,
|
||||
self.association_version_table.c.operation_type != Operation.DELETE,
|
||||
adapt_columns(self.property.secondaryjoin),
|
||||
)
|
||||
)
|
||||
.correlate(self.local_cls, self.remote_cls)
|
||||
)
|
||||
|
||||
|
||||
class PatchedBuilder(Builder):
|
||||
def build_relationships(self, version_classes):
|
||||
"""
|
||||
Builds relationships for all version classes.
|
||||
|
||||
:param version_classes: list of generated version classes
|
||||
"""
|
||||
for cls in version_classes:
|
||||
if not self.manager.option(cls, "versioning"):
|
||||
continue
|
||||
|
||||
for prop in sa.inspect(cls).iterate_properties:
|
||||
if prop.key == "versions":
|
||||
continue
|
||||
builder = PatchedRelationShipBuilder(self.manager, cls, prop)
|
||||
builder()
|
|
@ -2,13 +2,15 @@ import os
|
|||
import os.path
|
||||
import warnings
|
||||
|
||||
from flask import Flask, g, request, session, render_template
|
||||
from flask import Flask, g, render_template, request, session
|
||||
from flask_babel import Babel
|
||||
from flask_mail import Mail
|
||||
from flask_migrate import Migrate, upgrade, stamp
|
||||
from flask_migrate import Migrate, stamp, upgrade
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
|
||||
from ihatemoney import default_settings
|
||||
from ihatemoney.api.v1 import api as apiv1
|
||||
from ihatemoney.currency_convertor import CurrencyConverter
|
||||
from ihatemoney.models import db
|
||||
from ihatemoney.utils import (
|
||||
IhmJSONEncoder,
|
||||
|
@ -19,8 +21,6 @@ from ihatemoney.utils import (
|
|||
)
|
||||
from ihatemoney.web import main as web_interface
|
||||
|
||||
from ihatemoney import default_settings
|
||||
|
||||
|
||||
def setup_database(app):
|
||||
"""Prepare the database. Create tables, run migrations etc."""
|
||||
|
@ -138,6 +138,9 @@ def create_app(
|
|||
# Configure the a, root="main"pplication
|
||||
setup_database(app)
|
||||
|
||||
# Setup Currency Cache
|
||||
CurrencyConverter()
|
||||
|
||||
mail = Mail()
|
||||
mail.init_app(app)
|
||||
app.mail = mail
|
||||
|
|
|
@ -162,6 +162,11 @@ body {
|
|||
margin-bottom: 20px;
|
||||
margin-left: 25px;
|
||||
}
|
||||
@media (max-width: 400px) {
|
||||
.home .card {
|
||||
min-width: unset;
|
||||
}
|
||||
}
|
||||
/* Other */
|
||||
|
||||
#bills {
|
||||
|
@ -192,7 +197,7 @@ footer {
|
|||
padding: 45px 50px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@media (min-width: 1024px) {
|
||||
footer {
|
||||
padding-left: calc(25% + 50px);
|
||||
}
|
||||
|
@ -332,13 +337,16 @@ footer .footer-left {
|
|||
background: url("../images/see.png") no-repeat right;
|
||||
}
|
||||
|
||||
#bill_table, #monthly_stats {
|
||||
#bill_table,
|
||||
#monthly_stats,
|
||||
#history_table {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.split_bills, #table_overflow.statistics {
|
||||
.split_bills,
|
||||
#table_overflow.statistics {
|
||||
/* The table is shifted to left, so add the spacer width on the right to match */
|
||||
width: calc(100% + 15px);
|
||||
}
|
||||
|
@ -368,6 +376,36 @@ footer .footer-left {
|
|||
background: url("../images/see.png") no-repeat right;
|
||||
}
|
||||
|
||||
.history_icon > .delete,
|
||||
.history_icon > .add,
|
||||
.history_icon > .edit {
|
||||
font-size: 0px;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 2px;
|
||||
margin-right: 10px;
|
||||
margin-top: 3px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.history_icon > .delete {
|
||||
background: url("../images/delete.png") no-repeat right;
|
||||
}
|
||||
|
||||
.history_icon > .edit {
|
||||
background: url("../images/edit.png") no-repeat right;
|
||||
}
|
||||
|
||||
.history_icon > .add {
|
||||
background: url("../images/add.png") no-repeat right;
|
||||
}
|
||||
|
||||
.history_text {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
|
||||
.balance .balance-value {
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -529,6 +567,13 @@ footer .icon svg {
|
|||
fill: white;
|
||||
}
|
||||
|
||||
.icon.icon-red {
|
||||
fill: #dc3545;
|
||||
}
|
||||
.btn:hover .icon.icon-red {
|
||||
fill: white !important;
|
||||
}
|
||||
|
||||
/* align the first column */
|
||||
#monthly_stats tr *:first-child {
|
||||
text-align: right;
|
||||
|
@ -538,3 +583,17 @@ footer .icon svg {
|
|||
.hiddenpswp {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#history_warnings {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
/* edit settings */
|
||||
|
||||
.edit-project form {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.edit-project .custom-file {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
|
BIN
ihatemoney/static/images/add.png
Normal file
BIN
ihatemoney/static/images/add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 B |
8
ihatemoney/static/images/x.svg
Normal file
8
ihatemoney/static/images/x.svg
Normal file
|
@ -0,0 +1,8 @@
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 807 807"><g
|
||||
transform="translate(-20,-20)"
|
||||
id="g8"><polygon
|
||||
id="polygon6"
|
||||
points="173,20 423,269 673,20 827,173 577,423 827,673 673,827 423,577 173,827 20,673 269,423 20,173 "
|
||||
class="fil0" /></g></svg>
|
After Width: | Height: | Size: 291 B |
|
@ -5,3 +5,7 @@ function selectCheckboxes(value){
|
|||
els[i].checked = value;
|
||||
}
|
||||
}
|
||||
|
||||
function localizeTime(utcTimestamp) {
|
||||
return new Date(utcTimestamp).toLocaleString()
|
||||
}
|
||||
|
|
|
@ -10,4 +10,5 @@
|
|||
<div class="col-xs-12 col-sm-5 col-md-4 offset-md-2">
|
||||
<a href='{{ url_for("main.home") }}'>{{ _("The best thing to do is probably to get back to the main page.")}}</a>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,18 +5,43 @@
|
|||
{
|
||||
$(this).html("<a style='color:red; ' href='{{ url_for('.delete_project') }}' >{{_("you sure?")}}</a>");
|
||||
});
|
||||
|
||||
$('.custom-file-input').on('change', function(event) {
|
||||
var filename = [].slice.call(this.files).map(function (file) { return file.name}).join(',')
|
||||
var $labelElement = $(this).parents('.custom-file').find('.custom-file-label')
|
||||
$labelElement.text(filename)
|
||||
})
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>{{ _("Edit project") }}</h2>
|
||||
<p>
|
||||
<form class="form-horizontal" method="post">
|
||||
{{ forms.edit_project(edit_form) }}
|
||||
</form>
|
||||
</p>
|
||||
<div class="container edit-project">
|
||||
|
||||
<h2>{{ _("Download project's data") }}</h2>
|
||||
<p>
|
||||
<h2>{{ _("Edit project") }}</h2>
|
||||
<form class="form-horizontal" method="post">
|
||||
{{ forms.edit_project(edit_form) }}
|
||||
</form>
|
||||
|
||||
|
||||
<h2>{{ _("Import JSON") }}</h2>
|
||||
<form class="form-horizontal" method="post" enctype="multipart/form-data">
|
||||
{{ import_form.hidden_tag() }}
|
||||
|
||||
<div class="custom-file">
|
||||
<div class="form-group">
|
||||
{{ import_form.file(class="custom-file-input") }}
|
||||
<small class="form-text text-muted">
|
||||
{{ import_form.file.description }}
|
||||
</small>
|
||||
</div>
|
||||
<label class="custom-file-label" for="customFile">{{ _('Choose file') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
{{ import_form.submit(class="btn btn-primary") }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h2>{{ _("Download project's data") }}</h2>
|
||||
<div class="list-group download-project">
|
||||
<div class="list-group-item list-group-item-action">
|
||||
<h5 class="d-flex w-100 justify-content-between">
|
||||
|
@ -51,5 +76,5 @@
|
|||
<p class="mb-1 text-muted">{{ _('Download the list of transactions needed to settle the current bills.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -20,6 +20,16 @@
|
|||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro checkbox(field) %}
|
||||
<div class="controls{% if inline %} col-9{% endif %}">
|
||||
{{ field(id=field.name) }}
|
||||
<label for="{{ field.name }}">{{ field.label() }}</label>
|
||||
{% if field.description %}
|
||||
<small id="{{field.name}}_description"" class="form-text text-muted">{{ field.description }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro submit(field, cancel=False, home=False) -%}
|
||||
<div class="actions">
|
||||
<button type="submit" class="btn btn-primary">{{ field.name }}</button>
|
||||
|
@ -65,6 +75,7 @@
|
|||
{{ input(form.name) }}
|
||||
{{ input(form.password) }}
|
||||
{{ input(form.contact_email) }}
|
||||
{{ input(form.default_currency) }}
|
||||
{% if not home %}
|
||||
{{ submit(form.submit, home=True) }}
|
||||
{% endif %}
|
||||
|
@ -78,6 +89,15 @@
|
|||
{{ input(form.name) }}
|
||||
{{ input(form.password) }}
|
||||
{{ input(form.contact_email) }}
|
||||
<div class="form-group">
|
||||
<label for="privacy_checkboxes">{{ _("Privacy Settings") }}</label>
|
||||
<div id="privacy_checkboxes" class="card card-body bg-light">
|
||||
{{ checkbox(form.project_history) }}
|
||||
{{ checkbox(form.ip_recording) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ input(form.default_currency) }}
|
||||
<div class="actions">
|
||||
<button class="btn btn-primary">{{ _("Edit the project") }}</button>
|
||||
<a id="delete-project" style="color:red; margin-left:10px; cursor:pointer; ">{{ _("delete") }}</a>
|
||||
|
@ -104,6 +124,9 @@
|
|||
{{ input(form.what, inline=True) }}
|
||||
{{ input(form.payer, inline=True, class="form-control custom-select") }}
|
||||
{{ input(form.amount, inline=True) }}
|
||||
{% if not form.original_currency.render_kw %}
|
||||
{{ input(form.original_currency, inline=True) }}
|
||||
{% endif %}
|
||||
{{ input(form.external_link, inline=True) }}
|
||||
|
||||
<div class="form-group row">
|
||||
|
|
261
ihatemoney/templates/history.html
Normal file
261
ihatemoney/templates/history.html
Normal file
|
@ -0,0 +1,261 @@
|
|||
{% extends "sidebar_table_layout.html" %}
|
||||
|
||||
{% macro change_to_logging_preference(event) %}
|
||||
{% if event.val_after == LoggingMode.DISABLED %}
|
||||
{% if event.val_before == LoggingMode.ENABLED %}
|
||||
{{ _("Disabled Project History") }}
|
||||
{% else %}
|
||||
{{ _("Disabled Project History & IP Address Recording") }}
|
||||
{% endif %}
|
||||
{% elif event.val_after == LoggingMode.ENABLED %}
|
||||
{% if event.val_before == LoggingMode.DISABLED %}
|
||||
{{ _("Enabled Project History") }}
|
||||
{% elif event.val_before == LoggingMode.RECORD_IP %}
|
||||
{{ _("Disabled IP Address Recording") }}
|
||||
{% else %}
|
||||
{{ _("Enabled Project History") }}
|
||||
{% endif %}
|
||||
{% elif event.val_after == LoggingMode.RECORD_IP %}
|
||||
{% if event.val_before == LoggingMode.DISABLED %}
|
||||
{{ _("Enabled Project History & IP Address Recording") }}
|
||||
{% elif event.val_before == LoggingMode.ENABLED %}
|
||||
{{ _("Enabled IP Address Recording") }}
|
||||
{% else %}
|
||||
{{ _("Enabled Project History & IP Address Recording") }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{# Should be unreachable #}
|
||||
{{ _("History Settings Changed") }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro describe_object(event) %}{{ event.object_type }} <em class="font-italic">{{ event.object_desc }}</em>{% endmacro %}
|
||||
|
||||
{% macro simple_property_change(event, localized_property_name, from=True) %}
|
||||
{{ describe_object(event) }}:
|
||||
{{ localized_property_name }} {{ _("changed") }}
|
||||
{% if from %}{{ _("from") }} <em class="font-italic">{{ event.val_before }}</em>{% endif %}
|
||||
{{ _("to") }} <em class="font-italic">{{ event.val_after }}</em>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro clear_history_modals() %}
|
||||
<!-- Modal -->
|
||||
<div id="confirm-ip-delete" class="modal fade show" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ _('Confirm Remove IP Adresses') }}</h3>
|
||||
<a href="#" class="close" data-dismiss="modal">×</a>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ _("Are you sure you want to delete all recorded IP addresses from this project?
|
||||
The rest of the project history will be unaffected. This action cannot be undone.") }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ _("Close") }}</button>
|
||||
<form action="{{ url_for(".strip_ip_addresses") }}" method="post">
|
||||
<input type="submit" class="btn btn-danger" value="{{ _("Confirm Delete") }}" name="{{ _("Confirm Delete") }}"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div id="confirm-erase" class="modal fade show" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ _('Delete Confirmation') }}</h3>
|
||||
<a href="#" class="close" data-dismiss="modal">×</a>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ _("Are you sure you want to erase all history for this project? This action cannot be undone.") }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ _("Close") }}</button>
|
||||
<form action="{{ url_for(".erase_history") }}" method="post">
|
||||
<input type="submit" class="btn btn-danger" value="{{ _("Confirm Delete") }}" name="{{ _("Confirm Delete") }}"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro owers_changed(event, add) %}
|
||||
{{ describe_object(event) }}: {% if add %}{{ _("Added") }}{% else %}{{ _("Removed") }}{% endif %}
|
||||
{% if event.val_after|length > 1 %}
|
||||
{% for name in event.val_after %}
|
||||
<em class="font-italic">{{ name }}</em>{% if event.val_after|length > 2 and loop.index != event.val_after|length %},{% endif %}
|
||||
{% if loop.index == event.val_after|length - 1 %} {{ _("and") }} {% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<em class="font-italic">{{ event.val_after[0] }}</em>
|
||||
{% endif %}
|
||||
{% if add %}{{ _("to") }}{% else %}{{ _("from") }}{% endif %}
|
||||
{{ _("owers list") }}
|
||||
{% endmacro %}
|
||||
|
||||
{% block sidebar %}
|
||||
<div id="table_overflow">
|
||||
<table class="balance table">
|
||||
<thead>
|
||||
<tr class="d-none d-md-table-row">
|
||||
<th>{{ _("Who?") }}</th>
|
||||
<th class="balance-value">{{ _("Balance") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% set balance = g.project.balance %}
|
||||
{% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2) != 0 %}
|
||||
<tr id="bal-member-{{ member.id }}" action={% if member.activated %}delete{% else %}reactivate{% endif %}>
|
||||
<td class="balance-name">{{ member.name }}</td>
|
||||
<td class="balance-value {% if balance[member.id]|round(2) > 0 %}positive{% elif balance[member.id]|round(2) < 0 %}negative{% endif %}">
|
||||
{% if balance[member.id]|round(2) > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
{% block content %}
|
||||
{% if current_log_pref == LoggingMode.DISABLED or (current_log_pref != LoggingMode.RECORD_IP and any_ip_addresses) %}
|
||||
<div id="history_warnings" class="card card-body bg-light">
|
||||
{% if current_log_pref == LoggingMode.DISABLED %}
|
||||
<p>{% set url = url_for(".edit_project") %}
|
||||
{% trans %}
|
||||
<i>This project has history disabled. New actions won't appear below. You can enable history on the</i>
|
||||
<a href="{{ url }}">settings page</a>
|
||||
{% endtrans %}
|
||||
</p>
|
||||
{% if history %}
|
||||
<p>
|
||||
{% trans %}
|
||||
<i>The table below reflects actions recorded prior to disabling project history. You can
|
||||
<a href="#" data-toggle="modal" data-keyboard="false" data-target="#confirm-erase">clear project history</a> to remove them.</i></p>
|
||||
{% endtrans %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if current_log_pref != LoggingMode.RECORD_IP and any_ip_addresses %}
|
||||
<p>
|
||||
<i>{{ _("Some entries below contain IP addresses, even though this project has IP recording disabled. ") }}
|
||||
<a href="#" data-toggle="modal" data-keyboard="false" data-target="#confirm-ip-delete">{{ _("Delete stored IP addresses") }}</a></i>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ clear_history_modals() }}
|
||||
<span class="float-right mt-3" {% if not history %} data-toggle="tooltip" title="{{_('No history to erase')}}" {% endif %}>
|
||||
<a href="#" class="btn btn-outline-danger float-right {% if not history %} disabled {% endif %}" data-toggle="modal" data-keyboard="false" data-target="#confirm-erase">
|
||||
<i class="icon icon-red plus">{{ static_include("images/x.svg") | safe }}</i>
|
||||
{{ _("Clear Project History") }}
|
||||
</a>
|
||||
</span>
|
||||
<span class="float-right mt-3" {% if not any_ip_addresses %}data-placement="top" data-toggle="tooltip" title="{{_('No IP Addresses to erase')}}" {% endif %}>
|
||||
<a href="#" class="btn btn-outline-danger float-right mr-2 {% if not any_ip_addresses %} disabled {% endif %}" data-toggle="modal" data-keyboard="false" data-target="#confirm-ip-delete">
|
||||
<i class="icon icon-red plus">{{ static_include("images/x.svg") | safe }}</i>
|
||||
{{ _("Delete Stored IP Addresses") }}
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
{% if history %}
|
||||
<table id="history_table" class="split_bills table table-striped">
|
||||
<thead><tr>
|
||||
<th style="width: 15%">{{ _("Time") }}</th>
|
||||
<th style="width: 65%">{{ _("Event") }}</th>
|
||||
<th style="width: 20%">
|
||||
<span data-toggle="tooltip" title="{% if current_log_pref != LoggingMode.RECORD_IP %}
|
||||
{{_('IP address recording can be enabled on the settings page') }}
|
||||
{% else %}
|
||||
{{_('IP address recording can be disabled on the settings page') }}
|
||||
{% endif %}">
|
||||
{{ _("From IP") }}</span></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{% for event in history %}
|
||||
<tr>
|
||||
<td><script>document.write(localizeTime("{{ event.time }}"));</script></td>
|
||||
<td >
|
||||
<div class="history_icon">
|
||||
<i {% if event.operation_type == OperationType.INSERT %}
|
||||
class="add"
|
||||
{% elif event.operation_type == OperationType.UPDATE %}
|
||||
class="edit"
|
||||
{% elif event.operation_type == OperationType.DELETE %}
|
||||
class="delete"
|
||||
{% endif %}
|
||||
></i>
|
||||
</div>
|
||||
<div class="history_text">
|
||||
{% if event.operation_type == OperationType.INSERT %}
|
||||
{{ event.object_type }} <em class="font-italic">{{ event.object_desc }}</em> {{ _("added") }}
|
||||
{% elif event.operation_type == OperationType.UPDATE %}
|
||||
{% if event.object_type == _("Project") %}
|
||||
{% if event.prop_changed == "password" %}
|
||||
{{ _("Project private code changed") }}
|
||||
{% elif event.prop_changed == "logging_preference" %}
|
||||
{{ change_to_logging_preference(event) }}
|
||||
{% elif event.prop_changed == "name" %}
|
||||
{{ _("Project renamed to") }} <em class="font-italic">{{ event.val_after }}</em>
|
||||
{% elif event.prop_changed == "contact_email" %}
|
||||
{{ _("Project contact email changed to") }} <em class="font-italic">{{ event.val_after }}</em>
|
||||
{% else %}
|
||||
{{ _("Project settings modified") }}
|
||||
{% endif %}
|
||||
{% elif event.prop_changed == "activated" %}
|
||||
{{ event.object_type }} <em class="font-italic">{{ event.object_desc }}</em>
|
||||
{% if event.val_after == False %}{{ _("deactivated") }}{% else %}{{ _("reactivated") }}{% endif %}
|
||||
{% elif event.prop_changed == "name" or event.prop_changed == "what" %}
|
||||
{{ describe_object(event) }} {{ _("renamed to") }} <em class="font-italic">{{ event.val_after }}</em>
|
||||
{% elif event.prop_changed == "weight" %}
|
||||
{{ simple_property_change(event, _("Weight")) }}
|
||||
{% elif event.prop_changed == "external_link" %}
|
||||
{{ describe_object(event) }}: {{ _("External link changed to") }}
|
||||
<a href="{{ event.val_after }}" class="font-italic">{{ event.val_after }}</a>
|
||||
{% elif event.prop_changed == "owers_added" %}
|
||||
{{ owers_changed(event, True)}}
|
||||
{% elif event.prop_changed == "owers_removed" %}
|
||||
{{ owers_changed(event, False)}}
|
||||
{% elif event.prop_changed == "payer" %}
|
||||
{{ simple_property_change(event, _("Payer"))}}
|
||||
{% elif event.prop_changed == "amount" %}
|
||||
{{ simple_property_change(event, _("Amount")) }}
|
||||
{% elif event.prop_changed == "date" %}
|
||||
{{ simple_property_change(event, _("Date")) }}
|
||||
{% elif event.prop_changed == "original_currency" %}
|
||||
{{ simple_property_change(event, _("Currency")) }}
|
||||
{% elif event.prop_changed == "converted_amount" %}
|
||||
{{ simple_property_change(event, _("Amount in %(currency)s", currency=g.project.default_currency)) }}
|
||||
{% else %}
|
||||
{{ describe_object(event) }} {{ _("modified") }}
|
||||
{% endif %}
|
||||
{% elif event.operation_type == OperationType.DELETE %}
|
||||
{{ event.object_type }} <em class="font-italic">{{ event.object_desc }}</em> {{ _("removed") }}
|
||||
{% else %}
|
||||
{# Should be unreachable #}
|
||||
{{ describe_object(event) }} {{ _("changed in a unknown way") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
<td>{% if event.ip %}{{ event.ip }}{% else %} -- {% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="py-3 d-flex justify-content-center empty-bill">
|
||||
<div class="card d-inline-flex p-2">
|
||||
<div class="card-body text-center text-muted">
|
||||
<i class="icon icon-white hand-holding-heart">{{ static_include("images/hand-holding-heart.svg") | safe }}</i>
|
||||
<h3>{{ _('Nothing to list')}}</h3>
|
||||
<p>
|
||||
{{ _("Someone probably cleared the project history.") }}
|
||||
</p>
|
||||
</div>
|
||||
</div></div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -47,8 +47,8 @@
|
|||
<li class="nav-item{% if current_view == 'list_bills' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.list_bills") }}">{{ _("Bills") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'settle_bill' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.settle_bill") }}">{{ _("Settle") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'statistics' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.statistics") }}">{{ _("Statistics") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'history' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.history") }}">{{ _("History") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'edit_project' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.edit_project") }}">{{ _("Settings") }}</a></li>
|
||||
<li class="nav-item{% if current_view == 'upload_json' %} active{% endif %}"><a class="nav-link" href="{{ url_for("main.upload_json") }}">{{ _("Import") }}</a></li>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
@ -127,9 +127,13 @@
|
|||
</div>
|
||||
|
||||
<div class="messages">
|
||||
{% for message in get_flashed_messages() %}
|
||||
<div class="flash alert alert-success">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% for category, message in get_flashed_messages(with_categories=true) %}
|
||||
{% if category == "message" %}{# Default category for flash(msg) #}
|
||||
<div class="flash alert alert-success">{{ message }}</div>
|
||||
{% else %}
|
||||
<div class="flash alert alert-{{ category }}">{{ message }}</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% block footer %}
|
||||
|
|
|
@ -117,7 +117,19 @@
|
|||
<div class="clearfix"></div>
|
||||
|
||||
<table id="bill_table" class="col table table-striped table-hover table-responsive-sm">
|
||||
<thead><tr><th>{{ _("When?") }}</th><th>{{ _("Who paid?") }}</<th><th>{{ _("For what?") }}</th><th>{{ _("For whom?") }}</th><th>{{ _("How much?") }}</th><th>{{ _("Actions") }}</th></tr></thead>
|
||||
<thead>
|
||||
<tr><th>{{ _("When?") }}
|
||||
</th><th>{{ _("Who paid?") }}
|
||||
</th><th>{{ _("For what?") }}
|
||||
</th><th>{{ _("For whom?") }}
|
||||
</th><th>{{ _("How much?") }}
|
||||
{% if g.project.default_currency != "No Currency" %}
|
||||
</th><th>{{ _("Amount in %(currency)s", currency=g.project.default_currency) }}
|
||||
{%- else -%}
|
||||
</th><th>{{ _("Amount") }}
|
||||
{% endif %}
|
||||
</th><th>{{ _("Actions") }}</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for bill in bills.items %}
|
||||
<tr owers="{{bill.owers|join(',','id')}}" payer="{{bill.payer.id}}">
|
||||
|
@ -136,7 +148,14 @@
|
|||
{%- else -%}
|
||||
{{ bill.owers|join(', ', 'name') }}
|
||||
{%- endif %}</td>
|
||||
<td>{{ "%0.2f"|format(bill.amount) }} ({{ "%0.2f"|format(bill.pay_each()) }} {{ _("each") }})</td>
|
||||
<td>
|
||||
{% if bill.original_currency != "No Currency" %}
|
||||
{{ "%0.2f"|format(bill.amount) }} {{bill.original_currency}} ({{ "%0.2f"|format(bill.pay_each_default(bill.amount)) }} {{bill.original_currency}} {{ _(" each") }})
|
||||
{%- else -%}
|
||||
{{ "%0.2f"|format(bill.amount) }} ({{ "%0.2f"|format(bill.pay_each_default(bill.amount)) }} {{ _(" each") }})
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ "%0.2f"|format(bill.converted_amount) }}</td>
|
||||
<td class="bill-actions">
|
||||
<a class="edit" href="{{ url_for(".edit_bill", bill_id=bill.id) }}" title="{{ _("edit") }}">{{ _('edit') }}</a>
|
||||
<a class="delete" href="{{ url_for(".delete_bill", bill_id=bill.id) }}" title="{{ _("delete") }}">{{ _('delete') }}</a>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<th class="balance-value">{{ _("Balance") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for stat in members_stats| sort(attribute='member.name') %}
|
||||
{% for stat in members_stats|sort(attribute='member.name') %}
|
||||
<tr>
|
||||
<td class="balance-name">{{ stat.member.name }}</td>
|
||||
<td class="balance-value {% if stat.balance|round(2) > 0 %}positive{% elif stat.balance|round(2) < 0 %}negative{% endif %}">
|
||||
|
@ -27,7 +27,7 @@
|
|||
<table id="bill_table" class="split_bills table table-striped ml-md-n3">
|
||||
<thead><tr><th class="d-md-none">{{ _("Who?") }}</th><th>{{ _("Paid") }}</th><th>{{ _("Spent") }}</th></tr></thead>
|
||||
<tbody>
|
||||
{% for stat in members_stats %}
|
||||
{% for stat in members_stats|sort(attribute='member.name') %}
|
||||
<tr>
|
||||
<td class="d-md-none">{{ stat.member.name }}</td>
|
||||
<td>{{ "%0.2f"|format(stat.paid) }}</td>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>{{ _("Import JSON") }}</h2>
|
||||
<p>
|
||||
<form class="form-horizontal" method="post" enctype="multipart/form-data">
|
||||
{{ forms.upload_json(form) }}
|
||||
</form>
|
||||
</p>
|
||||
{% endblock %}
|
File diff suppressed because it is too large
Load diff
BIN
ihatemoney/translations/cs/LC_MESSAGES/messages.mo
Normal file
BIN
ihatemoney/translations/cs/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
|
@ -1,16 +1,18 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-10-24 18:27+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: cs\n"
|
||||
"Language-Team: none\n"
|
||||
"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Translate Toolkit 2.4.0\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -26,6 +28,18 @@ msgstr ""
|
|||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr ""
|
||||
|
||||
|
@ -120,6 +134,15 @@ msgstr ""
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
|
||||
|
@ -153,6 +176,12 @@ msgstr ""
|
|||
msgid "Password successfully reset."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -164,7 +193,7 @@ msgid "Your invitations have been sent"
|
|||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
|
@ -218,9 +247,6 @@ msgstr ""
|
|||
msgid "Create a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr ""
|
||||
|
||||
|
@ -242,6 +268,9 @@ msgstr ""
|
|||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr ""
|
||||
|
||||
|
@ -251,6 +280,12 @@ msgstr ""
|
|||
msgid "Edit project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -272,6 +307,9 @@ msgstr ""
|
|||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr ""
|
||||
|
||||
|
@ -302,6 +340,177 @@ msgstr ""
|
|||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr ""
|
||||
|
||||
|
@ -349,6 +558,9 @@ msgstr ""
|
|||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -406,6 +618,12 @@ msgstr ""
|
|||
msgid "Add a new bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -432,9 +650,6 @@ msgstr ""
|
|||
msgid "each"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "No bills"
|
||||
msgstr ""
|
||||
|
||||
|
@ -503,14 +718,14 @@ msgstr ""
|
|||
msgid "To whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Spent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
|
Binary file not shown.
|
@ -1,25 +1,26 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-10-12 09:58+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2020-02-12 10:50+0000\n"
|
||||
"Last-Translator: flolilo <flolilo@mailbox.org>\n"
|
||||
"Language-Team: German <https://hosted.weblate.org/projects/i-hate-money/"
|
||||
"i-hate-money/de/>\n"
|
||||
"Language: de\n"
|
||||
"Language-Team: German <https://hosted.weblate.org/projects/i-hate-money/i"
|
||||
"-hate-money/de/>\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 3.11-dev\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
"accepted."
|
||||
msgstr ""
|
||||
"Kein gültiger Betrag oder Ausdruck. Es werden nur Zahlen und die Operatoren +"
|
||||
" - * / akzeptiert."
|
||||
"Kein gültiger Betrag oder Ausdruck. Es werden nur Zahlen und die "
|
||||
"Operatoren + - * / akzeptiert."
|
||||
|
||||
msgid "Project name"
|
||||
msgstr "Projektname"
|
||||
|
@ -30,6 +31,18 @@ msgstr "Privater Code"
|
|||
msgid "Email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Projektkennung"
|
||||
|
||||
|
@ -41,8 +54,8 @@ msgid ""
|
|||
"A project with this identifier (\"%(project)s\") already exists. Please "
|
||||
"choose a new identifier"
|
||||
msgstr ""
|
||||
"Ein Projekt mit der Kennung (\"%(project)s\") existiert bereits. Bitte wähle "
|
||||
"eine andere Kennung"
|
||||
"Ein Projekt mit der Kennung (\"%(project)s\") existiert bereits. Bitte "
|
||||
"wähle eine andere Kennung"
|
||||
|
||||
msgid "Get in"
|
||||
msgstr "Eintreten"
|
||||
|
@ -80,6 +93,12 @@ msgstr "Von"
|
|||
msgid "Amount paid"
|
||||
msgstr "Betrag"
|
||||
|
||||
msgid "External link"
|
||||
msgstr ""
|
||||
|
||||
msgid "A link to an external document, related to this bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "For whom?"
|
||||
msgstr "Für wen?"
|
||||
|
||||
|
@ -120,6 +139,15 @@ msgstr "Einladung senden"
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr "Die E-Mail-Adresse(n) %(email)s ist/sind nicht gültig"
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Projekt"
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr "Zu viele fehlgeschlagene Anmeldeversuche, bitte versuche es später."
|
||||
|
||||
|
@ -130,8 +158,7 @@ msgstr ""
|
|||
"verbleibend."
|
||||
|
||||
msgid "You either provided a bad token or no project identifier."
|
||||
msgstr ""
|
||||
"Du hast entweder einen ungültigen Token oder keine Projekt-ID angegeben."
|
||||
msgstr "Du hast entweder einen ungültigen Token oder keine Projekt-ID angegeben."
|
||||
|
||||
msgid "This private code is not the right one"
|
||||
msgstr "Der private Code ist nicht korrekt"
|
||||
|
@ -158,6 +185,12 @@ msgstr "Unbekanntes Projekt"
|
|||
msgid "Password successfully reset."
|
||||
msgstr "Passwort erfolgreich zurückgesetzt."
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr "Projekt erfolgreich gelöscht"
|
||||
|
||||
|
@ -169,8 +202,8 @@ msgid "Your invitations have been sent"
|
|||
msgstr "Deine Einladungen wurden versendet"
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgstr "%(member)s wurde(n) hinzugefügt"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
|
@ -225,9 +258,6 @@ msgstr "?"
|
|||
msgid "Create a new project"
|
||||
msgstr "Neues Projekt erstellen"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Projekt"
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr "Anzahl der Teilnehmer"
|
||||
|
||||
|
@ -249,6 +279,9 @@ msgstr "Bearbeiten"
|
|||
msgid "delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr "Das Dashboard ist aktuell deaktiviert."
|
||||
|
||||
|
@ -258,6 +291,12 @@ msgstr "Bist du sicher?"
|
|||
msgid "Edit project"
|
||||
msgstr "Projekt bearbeiten"
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr "Projektdaten herunterladen"
|
||||
|
||||
|
@ -279,6 +318,9 @@ msgstr "Passwort vergessen?"
|
|||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr "Projekt bearbeiten"
|
||||
|
||||
|
@ -309,6 +351,177 @@ msgstr "Einladung versenden"
|
|||
msgid "Download"
|
||||
msgstr "Herunterladen"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Wer?"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Bilanz"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr "Verwalten deine geteilten <br />Ausgaben ganz einfach"
|
||||
|
||||
|
@ -343,8 +556,9 @@ msgid ""
|
|||
"This access code will be sent to your friends. It is stored as-is by the "
|
||||
"server, so don\\'t reuse a personal password!"
|
||||
msgstr ""
|
||||
"Dieser Zugangscode wird an deine Freunde gesendet. Es wird als Klartext auf "
|
||||
"dem Server gespeichert. Bitte verwenden daher kein persönliches Passwort!"
|
||||
"Dieser Zugangscode wird an deine Freunde gesendet. Es wird als Klartext "
|
||||
"auf dem Server gespeichert. Bitte verwenden daher kein persönliches "
|
||||
"Passwort!"
|
||||
|
||||
msgid "Account manager"
|
||||
msgstr "Konten"
|
||||
|
@ -358,6 +572,9 @@ msgstr "Bilanz"
|
|||
msgid "Statistics"
|
||||
msgstr "Statistik"
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
|
@ -415,6 +632,12 @@ msgstr "Du kannst anfangen, Teilnehmer hinzuzufügen"
|
|||
msgid "Add a new bill"
|
||||
msgstr "Neue Ausgabe"
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr "Wann?"
|
||||
|
||||
|
@ -485,8 +708,8 @@ msgid ""
|
|||
"You can share the project identifier and the private code by any "
|
||||
"communication means."
|
||||
msgstr ""
|
||||
"Du kannst die Projekt-ID und den privaten Code auf jedem Kommunikationsweg "
|
||||
"weitergeben."
|
||||
"Du kannst die Projekt-ID und den privaten Code auf jedem "
|
||||
"Kommunikationsweg weitergeben."
|
||||
|
||||
msgid "Identifier:"
|
||||
msgstr "ID:"
|
||||
|
@ -495,8 +718,7 @@ msgid "Share the Link"
|
|||
msgstr "Link teilen"
|
||||
|
||||
msgid "You can directly share the following link via your prefered medium"
|
||||
msgstr ""
|
||||
"Du kannst den folgenden Link direkt über dein bevorzugtes Medium teilen"
|
||||
msgstr "Du kannst den folgenden Link direkt über dein bevorzugtes Medium teilen"
|
||||
|
||||
msgid "Send via Emails"
|
||||
msgstr "Per E-Mail versenden"
|
||||
|
@ -507,10 +729,10 @@ msgid ""
|
|||
" creation of this budget management project and we will "
|
||||
"send them an email for you."
|
||||
msgstr ""
|
||||
"Gib eine (durch Kommas getrennte) Liste von E-Mail-Adressen an, die du über "
|
||||
"die\n"
|
||||
"\t\t\tErstellung dieses Projekts informieren möchtest, und wir senden ihnen "
|
||||
"eine E-Mail."
|
||||
"Gib eine (durch Kommas getrennte) Liste von E-Mail-Adressen an, die du "
|
||||
"über die\n"
|
||||
"\t\t\tErstellung dieses Projekts informieren möchtest, und wir senden "
|
||||
"ihnen eine E-Mail."
|
||||
|
||||
msgid "Who pays?"
|
||||
msgstr "Wer zahlt?"
|
||||
|
@ -518,14 +740,21 @@ msgstr "Wer zahlt?"
|
|||
msgid "To whom?"
|
||||
msgstr "An wen?"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Wer?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr "Bezahlt"
|
||||
|
||||
msgid "Spent"
|
||||
msgstr "Ausgegeben"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Bilanz"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Someone probably"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "cleared the project history."
|
||||
#~ msgstr ""
|
||||
|
||||
|
|
Binary file not shown.
|
@ -3,7 +3,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-10-01 21:48+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language: el\n"
|
||||
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.7.0\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -28,6 +28,18 @@ msgstr ""
|
|||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr ""
|
||||
|
||||
|
@ -122,6 +134,15 @@ msgstr ""
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
|
||||
|
@ -155,6 +176,12 @@ msgstr ""
|
|||
msgid "Password successfully reset."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -166,7 +193,7 @@ msgid "Your invitations have been sent"
|
|||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
|
@ -220,9 +247,6 @@ msgstr ""
|
|||
msgid "Create a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr ""
|
||||
|
||||
|
@ -244,6 +268,9 @@ msgstr ""
|
|||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr ""
|
||||
|
||||
|
@ -253,6 +280,12 @@ msgstr ""
|
|||
msgid "Edit project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -274,6 +307,9 @@ msgstr ""
|
|||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr ""
|
||||
|
||||
|
@ -304,6 +340,177 @@ msgstr ""
|
|||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr ""
|
||||
|
||||
|
@ -351,6 +558,9 @@ msgstr ""
|
|||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -408,6 +618,12 @@ msgstr ""
|
|||
msgid "Add a new bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -434,9 +650,6 @@ msgstr ""
|
|||
msgid "each"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "No bills"
|
||||
msgstr ""
|
||||
|
||||
|
@ -505,97 +718,14 @@ msgstr ""
|
|||
msgid "To whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Spent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Not a valid amount or expression.Only"
|
||||
#~ " numbers and + - * / "
|
||||
#~ "operatorsare accepted."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "What do you want to download ?"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "bills"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "transactions"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Export file format"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Edit this project"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Download this project's data"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Type user name here"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "No, thanks"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Manage your shared <br>expenses, easily"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Log to an existing project"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "log in"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "or create a new one"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "let's get started"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "options"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Project settings"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "This is a free software"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Invite people to join this project!"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Added on"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Nothing to list yet. You probably want to"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Specify a (comma separated) list of "
|
||||
#~ "email adresses you want to notify "
|
||||
#~ "about the\n"
|
||||
#~ "creation of this budget management "
|
||||
#~ "project and we will send them an"
|
||||
#~ " email for you."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If you prefer, you can share the project identifier and the shared\n"
|
||||
#~ "password by other communication means. "
|
||||
#~ "Or even directly share the following "
|
||||
#~ "link:"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "A link to reset your password has been sent to your email."
|
||||
#~ msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
|
Binary file not shown.
|
@ -1,19 +1,19 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-10-20 11:52+0200\n"
|
||||
"PO-Revision-Date: 2019-09-25 22:28+0000\n"
|
||||
"Last-Translator: Diego Caraballo <diegocaraballo84@gmail.com>\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2020-05-03 15:20+0000\n"
|
||||
"Last-Translator: Fabian Rodriguez <fabian@fabianrodriguez.com>\n"
|
||||
"Language-Team: Spanish (Latin America) <https://hosted.weblate.org/projects/"
|
||||
"i-hate-money/i-hate-money/es_419/>\n"
|
||||
"Language: es_419\n"
|
||||
"Language-Team: Spanish (Latin America) "
|
||||
"<https://hosted.weblate.org/projects/i-hate-money/i-hate-money/es_419/>\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.7.0\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.1-dev\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -31,6 +31,18 @@ msgstr "Código privado"
|
|||
msgid "Email"
|
||||
msgstr "Correo Electrónico"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr "Habilitar historial del proyecto"
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr "Registrar la IPs para el historial del proyecto"
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr "Importar archivo JSON previamente exportado"
|
||||
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Identificador de proyecto"
|
||||
|
||||
|
@ -127,6 +139,15 @@ msgstr "Enviar invitaciones"
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr "El correo electrónico %(email)s no es válido"
|
||||
|
||||
msgid "Participant"
|
||||
msgstr "Participante"
|
||||
|
||||
msgid "Bill"
|
||||
msgstr "Factura"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Proyecto"
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
"Demasiados intentos fallidos de inicio de sesión, vuelva a intentarlo más"
|
||||
|
@ -164,6 +185,12 @@ msgstr "Proyecto desconocido"
|
|||
msgid "Password successfully reset."
|
||||
msgstr "Contraseña restablecida con éxito."
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr "El proyecto se subió exitosamente"
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr "JSON inválido"
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr "Proyecto eliminado correctamente"
|
||||
|
||||
|
@ -175,8 +202,8 @@ msgid "Your invitations have been sent"
|
|||
msgstr "Sus invitaciones han sido enviadas"
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgstr "se han añadido %(member)s"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr "Se añadieron %(member)s"
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
|
@ -231,9 +258,6 @@ msgstr "?"
|
|||
msgid "Create a new project"
|
||||
msgstr "Crear un nuevo proyecto"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Proyecto"
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr "Número de miembros"
|
||||
|
||||
|
@ -255,6 +279,9 @@ msgstr "Editar"
|
|||
msgid "delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
msgid "see"
|
||||
msgstr "ver"
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr "El panel está desactivado actualmente."
|
||||
|
||||
|
@ -264,6 +291,12 @@ msgstr "¿Estás seguro?"
|
|||
msgid "Edit project"
|
||||
msgstr "Editar proyecto"
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr "Importar JSON"
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr "Escoger un archivo"
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr "Descargar datos del proyecto"
|
||||
|
||||
|
@ -287,6 +320,9 @@ msgstr "¿No recuerdas la contraseña?"
|
|||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr "Ajustes de privacidad"
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr "Editar el proyecto"
|
||||
|
||||
|
@ -309,7 +345,7 @@ msgid "Edit this member"
|
|||
msgstr "Editar este miembro"
|
||||
|
||||
msgid "john.doe@example.com, mary.moe@site.com"
|
||||
msgstr "john.doe@example.com, mary.moe@site.com"
|
||||
msgstr "juan.perez@example.com, ana.rodriguez@site.com"
|
||||
|
||||
msgid "Send the invitations"
|
||||
msgstr "Enviar las invitaciones"
|
||||
|
@ -317,6 +353,199 @@ msgstr "Enviar las invitaciones"
|
|||
msgid "Download"
|
||||
msgstr "Descargar"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr "Historial de proyecto activo"
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr "Historial de proyecto y registros de dirección IP inactivos"
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr "Historial de proyecto activo"
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr "Registro de direcciones IP activo"
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr "Historial de proyecto y registros de dirección IP activos"
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr "Se activó el registros de dirección IP"
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr "Se cambiaron los ajustes del historial"
|
||||
|
||||
msgid "changed"
|
||||
msgstr "cambió"
|
||||
|
||||
msgid "from"
|
||||
msgstr "de"
|
||||
|
||||
msgid "to"
|
||||
msgstr "a"
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr "Confirmar eliminación de direcciones IP"
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
"Por favor confirme la eliminación completa del registro de direcciones IP "
|
||||
"del proyecto.\n"
|
||||
" El resto de historial del proyecto no será afectado. Este "
|
||||
"cambio es irreversible."
|
||||
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr "Confirmar eliminación"
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr "Confirmación de eliminación"
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
"Por favor confirme la eliminación completa del historial del proyecto. Esta "
|
||||
"acción es irreversible."
|
||||
|
||||
msgid "Added"
|
||||
msgstr "Agregado"
|
||||
|
||||
msgid "Removed"
|
||||
msgstr "Eliminado"
|
||||
|
||||
msgid "and"
|
||||
msgstr "y"
|
||||
|
||||
msgid "owers list"
|
||||
msgstr "lista de deudores"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "¿Quién?"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Balance"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <i>El historial de este proyecto ha sido desactivado. Nuevas "
|
||||
"operaciones no apareceran a continuacion. El historial se puede agregar</i> "
|
||||
"\n"
|
||||
" <a href=\"%(url)s\">en la página de ajustes</a>\n"
|
||||
" "
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <i>Este registro muestra la actividad previa a la desactivación "
|
||||
"del historial del proyecto. Use la opción \n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" data-"
|
||||
"target=\"#confirm-erase\">Eliminar historial del proyecto</a> para "
|
||||
"borrarlo.</i></p>\n"
|
||||
" "
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
"Algunos registros contienen direcciones IP, a pesar de que el registro de "
|
||||
"direcciones IP del proyecto no está activo. "
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr "Borrar las direcciones IP registradas"
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr "No hay historial para borrar"
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr "Borrar el historial del proyecto"
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr "No hay direcciones IP para borrar"
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr "Borrar direcciones IP registradas"
|
||||
|
||||
msgid "Time"
|
||||
msgstr "Hora"
|
||||
|
||||
msgid "Event"
|
||||
msgstr "Evento"
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr "El registro de direcciones IP se puede activar en la página de ajustes"
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
"El registro de direcciones IP se puede desactivar en la página de ajustes"
|
||||
|
||||
msgid "From IP"
|
||||
msgstr "IP de origen"
|
||||
|
||||
msgid "added"
|
||||
msgstr "agregado"
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr "Se cambió el código privado del proyecto"
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr "Se cambió el nombre del proyecto a"
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr "Se cambió el correo electrónico de contacto a"
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr "Ajustes del proyecto modificados"
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr "desactivado"
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr "reactivado"
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr "se cambió de nombre a"
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr "Se cambió el enlace externo por"
|
||||
|
||||
msgid "Amount"
|
||||
msgstr "Monto"
|
||||
|
||||
msgid "modified"
|
||||
msgstr "modificado"
|
||||
|
||||
msgid "removed"
|
||||
msgstr "removido"
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr "se cambió de manera desconocida"
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr "Nada por listar"
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr "Es probable que alguien borrara el historial del proyecto."
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr "Gestione sus gastos compartidos <br />fácilmente"
|
||||
|
||||
|
@ -366,6 +595,9 @@ msgstr "Resolver"
|
|||
msgid "Statistics"
|
||||
msgstr "Estadísticas"
|
||||
|
||||
msgid "History"
|
||||
msgstr "Historial"
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Configuración"
|
||||
|
||||
|
@ -423,6 +655,12 @@ msgstr "Deberías comenzar agregando participantes"
|
|||
msgid "Add a new bill"
|
||||
msgstr "Añadir una nueva factura"
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr "Nuevas facturas"
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr "Facturas anteriores"
|
||||
|
||||
msgid "When?"
|
||||
msgstr "¿Cuando?"
|
||||
|
||||
|
@ -449,9 +687,6 @@ msgstr "Todo el mundo menos %(excluded)s"
|
|||
msgid "each"
|
||||
msgstr "Cada"
|
||||
|
||||
msgid "see"
|
||||
msgstr "ver"
|
||||
|
||||
msgid "No bills"
|
||||
msgstr "Sin facturas"
|
||||
|
||||
|
@ -478,7 +713,7 @@ msgstr ""
|
|||
"correos electrónicos."
|
||||
|
||||
msgid "Return to home page"
|
||||
msgstr "Regresar a la página principal"
|
||||
msgstr "Regresar al inicio"
|
||||
|
||||
msgid "Your projects"
|
||||
msgstr "Sus proyectos"
|
||||
|
@ -530,15 +765,17 @@ msgstr "¿Quién paga?"
|
|||
msgid "To whom?"
|
||||
msgstr "¿A quién?"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "¿Quién?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr "Pagado"
|
||||
|
||||
msgid "Spent"
|
||||
msgstr "Gastado"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Balance"
|
||||
msgid "Expenses by Month"
|
||||
msgstr "Gastos por mes"
|
||||
|
||||
msgid "Period"
|
||||
msgstr "Período"
|
||||
|
||||
#~ msgid "%(member)s had been added"
|
||||
#~ msgstr "se han añadido %(member)s"
|
||||
|
|
Binary file not shown.
|
@ -7,9 +7,9 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2019-10-01 21:48+0200\n"
|
||||
"PO-Revision-Date: 2019-10-07 22:56+0000\n"
|
||||
"Last-Translator: Alexis Metaireau <alexis@notmyidea.org>\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2020-04-25 11:14+0000\n"
|
||||
"Last-Translator: Rémy Hubscher <hubscher.remy@gmail.com>\n"
|
||||
"Language-Team: French <https://hosted.weblate.org/projects/i-hate-money/"
|
||||
"i-hate-money/fr/>\n"
|
||||
"Language: fr\n"
|
||||
|
@ -17,15 +17,15 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 3.9-dev\n"
|
||||
"Generated-By: Babel 2.7.0\n"
|
||||
"X-Generator: Weblate 4.0.2-dev\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
"accepted."
|
||||
msgstr ""
|
||||
"Ceci n'est pas pas un montant ou une expression valide. Seuls les nombres"
|
||||
" et les opérateurs + - * / sont acceptés."
|
||||
"Ceci n'est pas un montant ou une expression valide. Seuls les nombres et "
|
||||
"les opérateurs + - * / sont acceptés."
|
||||
|
||||
msgid "Project name"
|
||||
msgstr "Nom de projet"
|
||||
|
@ -36,6 +36,18 @@ msgstr "Code d’accès"
|
|||
msgid "Email"
|
||||
msgstr "Email"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr "Activer l'historique de projet"
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr "Collecter les adresses IP dans l'historique de projet"
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr "Importer un fichier JSON précédemment exporté"
|
||||
|
||||
msgid "Import"
|
||||
msgstr "Importer"
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Identifiant du projet"
|
||||
|
||||
|
@ -132,6 +144,15 @@ msgstr "Envoyer les invitations"
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr "L’email %(email)s est invalide"
|
||||
|
||||
msgid "Participant"
|
||||
msgstr "Participant"
|
||||
|
||||
msgid "Bill"
|
||||
msgstr "Facture"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Projet"
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr "Trop d'échecs d’authentification successifs, veuillez réessayer plus tard."
|
||||
|
||||
|
@ -167,6 +188,12 @@ msgstr "Project inconnu"
|
|||
msgid "Password successfully reset."
|
||||
msgstr "Le mot de passe a été changé avec succès."
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr "Le projet a été correctement importé"
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr "Le fichier JSON est invalide"
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr "Projet supprimé"
|
||||
|
||||
|
@ -178,8 +205,8 @@ msgid "Your invitations have been sent"
|
|||
msgstr "Vos invitations ont bien été envoyées"
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgstr "%(member)s a bien été ajouté"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr "%(member)s a été ajouté"
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
|
@ -234,9 +261,6 @@ msgstr " ?"
|
|||
msgid "Create a new project"
|
||||
msgstr "Créer un nouveau projet"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Projets"
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr "Nombre de membres"
|
||||
|
||||
|
@ -258,6 +282,9 @@ msgstr "éditer"
|
|||
msgid "delete"
|
||||
msgstr "supprimer"
|
||||
|
||||
msgid "see"
|
||||
msgstr "voir"
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr "Le tableau de bord est actuellement désactivée."
|
||||
|
||||
|
@ -267,6 +294,12 @@ msgstr "c’est sûr ?"
|
|||
msgid "Edit project"
|
||||
msgstr "Éditer le projet"
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr "Import JSON"
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr "Choisir un fichier"
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr "Télécharger les données du projet"
|
||||
|
||||
|
@ -288,6 +321,9 @@ msgstr "Vous ne vous souvenez plus du code d’accès ?"
|
|||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr "Vie privée"
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr "Éditer le projet"
|
||||
|
||||
|
@ -318,6 +354,202 @@ msgstr "Envoyer les invitations"
|
|||
msgid "Download"
|
||||
msgstr "Télécharger"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr "Désactiver l'historique du projet"
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr "Désactiver l'historique du projet et l'enregistrement des adresses IP"
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr "Activer l'historique du projet"
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr "Désactiver l'enregistrement des adresses IP"
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr "Activer l'historique du projet et l’enregistrement des adresses IP"
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr "Activer l'enregistrement des adresses IP"
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr "Paramètres d'historique modifiés"
|
||||
|
||||
msgid "changed"
|
||||
msgstr "modifié"
|
||||
|
||||
msgid "from"
|
||||
msgstr "du"
|
||||
|
||||
msgid "to"
|
||||
msgstr "au"
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr "Confirmer la suppression des adresses IP"
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
"Êtes-vous sur de vouloir supprimer toutes les adresses IP enregistrées pour "
|
||||
"ce projet ?\n"
|
||||
"Le reste de l'historique ne sera pas affecté. Cette action n'est pas "
|
||||
"réversible."
|
||||
|
||||
msgid "Close"
|
||||
msgstr "Fermer"
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr "Confirmer la suppression"
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr "Confirmation de suppression"
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
"Êtes-vous sur de vouloir supprimer tout l'historique du projet ? Cette "
|
||||
"action n'est pas réversible."
|
||||
|
||||
msgid "Added"
|
||||
msgstr "Ajouté"
|
||||
|
||||
msgid "Removed"
|
||||
msgstr "Supprimé"
|
||||
|
||||
msgid "and"
|
||||
msgstr "et"
|
||||
|
||||
msgid "owers list"
|
||||
msgstr "Liste des débiteurs"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Qui ?"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Solde"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <i>L'historique de ce projet a été désactivé. Les nouvelles "
|
||||
"actions n'apparaîtront pas ci-dessous. Vous pouvez réactiver l'historique"
|
||||
" du projet dans les </i>\n"
|
||||
" <a href=\"%(url)s\">paramètres du projet</a>\n"
|
||||
" "
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <i>Le tableau ci-dessous liste les actions enregistrées avant"
|
||||
" la désactivation de l'historique du projet. Vous pouvez\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> cliquer ici pour"
|
||||
" les supprimer.</i></p>\n"
|
||||
" "
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
"Certaines entrées de l'historique contiennent une adresse IP, bien que ce"
|
||||
" projet ait désactivé l'enregistrement des adresses IP. "
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr "Supprimer toutes les adresses IP enregistrées"
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr "Aucun historique à supprimer"
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr "Supprimer les entrées de l'historique du projet"
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr "Aucune adresse IP à supprimer"
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr "Supprimer les adresses IP enregistrées"
|
||||
|
||||
msgid "Time"
|
||||
msgstr "Heure"
|
||||
|
||||
msgid "Event"
|
||||
msgstr "Évènement"
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
"L'enregistrement des adresses IP peut-être activé dans les paramètres de "
|
||||
"la page"
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
"L'enregistrement des adresses IP peut-être désactivé dans les paramètres "
|
||||
"de la page"
|
||||
|
||||
msgid "From IP"
|
||||
msgstr "Depuis l'IP"
|
||||
|
||||
msgid "added"
|
||||
msgstr "ajouté"
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr "Le mot de passe du projet a été modifié"
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr "Le projet a été renommé"
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr "L'adresse email de contact du projet a été modifié en"
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr "Les paramètres du projet ont été modifiés"
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr "désactivé"
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr "réactivé"
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr "renommé en"
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr "Le lien d'accès a été modifié en"
|
||||
|
||||
msgid "Amount"
|
||||
msgstr "Montant"
|
||||
|
||||
msgid "modified"
|
||||
msgstr "modifié"
|
||||
|
||||
msgid "removed"
|
||||
msgstr "supprimé"
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr "modifié d'une manière inconnue"
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr "Rien à afficher"
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr "Quelqu'un a probablement vidé l'historique du projet."
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr "Gérez vos dépenses <br />partagées, facilement"
|
||||
|
||||
|
@ -367,6 +599,9 @@ msgstr "Remboursements"
|
|||
msgid "Statistics"
|
||||
msgstr "Statistiques"
|
||||
|
||||
msgid "History"
|
||||
msgstr "Historique"
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Options"
|
||||
|
||||
|
@ -424,6 +659,12 @@ msgstr "Vous devriez commencer par ajouter des participants"
|
|||
msgid "Add a new bill"
|
||||
msgstr "Nouvelle facture"
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr "Nouvelles factures"
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr "Ancienne factures"
|
||||
|
||||
msgid "When?"
|
||||
msgstr "Quand ?"
|
||||
|
||||
|
@ -450,9 +691,6 @@ msgstr "Tout le monde sauf %(excluded)s"
|
|||
msgid "each"
|
||||
msgstr "chacun"
|
||||
|
||||
msgid "see"
|
||||
msgstr "voir"
|
||||
|
||||
msgid "No bills"
|
||||
msgstr "Pas encore de factures"
|
||||
|
||||
|
@ -527,27 +765,17 @@ msgstr "Qui doit payer ?"
|
|||
msgid "To whom?"
|
||||
msgstr "Pour qui ?"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Qui ?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr "A payé"
|
||||
|
||||
msgid "Spent"
|
||||
msgstr "A dépensé"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Solde"
|
||||
|
||||
msgid "Import"
|
||||
msgstr "Importer"
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr "Le projet a été correctement importé"
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr "Le fichier JSON est invalide"
|
||||
msgid "Expenses by Month"
|
||||
msgstr "Dépenses par mois"
|
||||
|
||||
msgid "Period"
|
||||
msgstr "Période"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The project identifier is used to "
|
||||
|
@ -695,3 +923,72 @@ msgstr "Le fichier JSON est invalide"
|
|||
|
||||
#~ msgid "A link to reset your password has been sent to your email."
|
||||
#~ msgstr "Un lien pour changer votre mot de passe vous a été envoyé par mail."
|
||||
|
||||
#~ msgid "%(member)s had been added"
|
||||
#~ msgstr "%(member)s a bien été ajouté"
|
||||
|
||||
#~ msgid "Disabled Project History"
|
||||
#~ msgstr "Historisation du projet désactivée"
|
||||
|
||||
#~ msgid "Disabled Project History & IP Address Recording"
|
||||
#~ msgstr "Historisation du projet et enregistrement des adresses IP désactivés"
|
||||
|
||||
#~ msgid "Enabled Project History"
|
||||
#~ msgstr "Historisation du projet activée"
|
||||
|
||||
#~ msgid "Disabled IP Address Recording"
|
||||
#~ msgstr "Enregistrement des adresses IP désactivé"
|
||||
|
||||
#~ msgid "Enabled Project History & IP Address Recording"
|
||||
#~ msgstr "Historisation du projet et enregistrement des adresses IP activés"
|
||||
|
||||
#~ msgid "Enabled IP Address Recording"
|
||||
#~ msgstr "Enregistrement des adresses IP activé"
|
||||
|
||||
#~ msgid "History Settings Changed"
|
||||
#~ msgstr "Changement des paramètres d’historisation"
|
||||
|
||||
#~ msgid "changed"
|
||||
#~ msgstr "modifié"
|
||||
|
||||
#~ msgid "from"
|
||||
#~ msgstr "depuis"
|
||||
|
||||
#~ msgid "to"
|
||||
#~ msgstr "vers"
|
||||
|
||||
#~ msgid "Confirm Remove IP Adresses"
|
||||
#~ msgstr "Confirmer la suppression des adresses IP"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Are you sure you want to delete"
|
||||
#~ " all recorded IP addresses from this"
|
||||
#~ " project?\n"
|
||||
#~ " The rest of the project"
|
||||
#~ " history will be unaffected. This "
|
||||
#~ "action cannot be undone."
|
||||
#~ msgstr ""
|
||||
#~ "Êtes vous sûr de supprimer toutes "
|
||||
#~ "les adresses IP enregistrées dans ce "
|
||||
#~ "projet ?\n"
|
||||
#~ "Le reste de l’historique du projet "
|
||||
#~ "restera inchangé. Cette action est "
|
||||
#~ "irréversible."
|
||||
|
||||
#~ msgid "Close"
|
||||
#~ msgstr "Fermer"
|
||||
|
||||
#~ msgid "Confirm Delete"
|
||||
#~ msgstr "Confirmer la suppression"
|
||||
|
||||
#~ msgid "Delete Confirmation"
|
||||
#~ msgstr "Confirmation de suppression"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Are you sure you want to erase "
|
||||
#~ "all history for this project? This "
|
||||
#~ "action cannot be undone."
|
||||
#~ msgstr ""
|
||||
#~ "Êtes vous sûr de supprimer la "
|
||||
#~ "totalité de l’historique de ce projet"
|
||||
#~ " ? Cette action est irréversible."
|
||||
|
|
BIN
ihatemoney/translations/id/LC_MESSAGES/messages.mo
Normal file
BIN
ihatemoney/translations/id/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
|
@ -1,24 +1,26 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-11-15 09:12+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2019-11-16 10:04+0000\n"
|
||||
"Last-Translator: Muhammad Fauzi <fauzi.padlaw@gmail.com>\n"
|
||||
"Language-Team: Indonesian <https://hosted.weblate.org/projects/i-hate-money/"
|
||||
"i-hate-money/id/>\n"
|
||||
"Language: id\n"
|
||||
"Language-Team: Indonesian <https://hosted.weblate.org/projects/i-hate-"
|
||||
"money/i-hate-money/id/>\n"
|
||||
"Plural-Forms: nplurals=1; plural=0\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 3.10-dev\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
"accepted."
|
||||
msgstr ""
|
||||
"Jumlah atau operator tidak valid. Hanya angka dan opertaor +-* yang diterima."
|
||||
"Jumlah atau operator tidak valid. Hanya angka dan opertaor +-* yang "
|
||||
"diterima."
|
||||
|
||||
msgid "Project name"
|
||||
msgstr "Nama proyek"
|
||||
|
@ -29,6 +31,18 @@ msgstr "Kode pribadi"
|
|||
msgid "Email"
|
||||
msgstr "Surel"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Pengidentifikasi proyek"
|
||||
|
||||
|
@ -40,8 +54,8 @@ msgid ""
|
|||
"A project with this identifier (\"%(project)s\") already exists. Please "
|
||||
"choose a new identifier"
|
||||
msgstr ""
|
||||
"Sebuah proyek dengan ID ini (\"%(project)s\") sudah ada. Silakan pilih ID "
|
||||
"baru"
|
||||
"Sebuah proyek dengan ID ini (\"%(project)s\") sudah ada. Silakan pilih ID"
|
||||
" baru"
|
||||
|
||||
msgid "Get in"
|
||||
msgstr "Masuk"
|
||||
|
@ -125,6 +139,15 @@ msgstr "Kirim undangan"
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr "Surel %(email)s tidak valid"
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Proyek"
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr "Terlalu banyak percobaan masuk, silakan coba lagi nanti."
|
||||
|
||||
|
@ -158,6 +181,12 @@ msgstr "Proyek tidak diketahui"
|
|||
msgid "Password successfully reset."
|
||||
msgstr "Kata sandi berhasil diatur ulang."
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr "Proyek berhasil dihapus"
|
||||
|
||||
|
@ -169,8 +198,8 @@ msgid "Your invitations have been sent"
|
|||
msgstr "Undangan Anda telah dikirim"
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgstr "%(member)s telah ditambahkan"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
|
@ -225,9 +254,6 @@ msgstr "?"
|
|||
msgid "Create a new project"
|
||||
msgstr "Buat proyek baru"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Proyek"
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr "Jumlah anggota"
|
||||
|
||||
|
@ -249,6 +275,9 @@ msgstr "ubah"
|
|||
msgid "delete"
|
||||
msgstr "hapus"
|
||||
|
||||
msgid "see"
|
||||
msgstr "lihat"
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr "Dasbor sekarang ini sedang dinonaktifkan."
|
||||
|
||||
|
@ -258,6 +287,12 @@ msgstr "Anda yakin?"
|
|||
msgid "Edit project"
|
||||
msgstr "Ubah proyek"
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr "Unduh data proyek"
|
||||
|
||||
|
@ -279,6 +314,9 @@ msgstr "Tidak bisa mengingat kata sandi?"
|
|||
msgid "Cancel"
|
||||
msgstr "Batalkan"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr "Ubah proyek"
|
||||
|
||||
|
@ -309,6 +347,177 @@ msgstr "Kirim undangan"
|
|||
msgid "Download"
|
||||
msgstr "Unduh"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Siapa?"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Saldo"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr "Atur pembagian harga <br />Anda, dengan mudah"
|
||||
|
||||
|
@ -343,8 +552,8 @@ msgid ""
|
|||
"This access code will be sent to your friends. It is stored as-is by the "
|
||||
"server, so don\\'t reuse a personal password!"
|
||||
msgstr ""
|
||||
"Kode akses ini akan dikirimkan ke teman Anda. Kode ini disimpan dalam bentuk "
|
||||
"teks biasa dalam server, jadi jangan gunakan password Anda!"
|
||||
"Kode akses ini akan dikirimkan ke teman Anda. Kode ini disimpan dalam "
|
||||
"bentuk teks biasa dalam server, jadi jangan gunakan password Anda!"
|
||||
|
||||
msgid "Account manager"
|
||||
msgstr "Pengatur akun"
|
||||
|
@ -358,6 +567,9 @@ msgstr "Atur"
|
|||
msgid "Statistics"
|
||||
msgstr "Statistik"
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Pengaturan"
|
||||
|
||||
|
@ -415,6 +627,12 @@ msgstr "Anda harus mulai dengan menambahkan partisipan"
|
|||
msgid "Add a new bill"
|
||||
msgstr "Tambah tagihan baru"
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr "Kapan?"
|
||||
|
||||
|
@ -441,9 +659,6 @@ msgstr "Semua orang kecuali %(excluded)s"
|
|||
msgid "each"
|
||||
msgstr "setiap"
|
||||
|
||||
msgid "see"
|
||||
msgstr "lihat"
|
||||
|
||||
msgid "No bills"
|
||||
msgstr "Tidak ada tagihan"
|
||||
|
||||
|
@ -466,8 +681,8 @@ msgid ""
|
|||
"A link to reset your password has been sent to you, please check your "
|
||||
"emails."
|
||||
msgstr ""
|
||||
"Tautan atur ulang kata sandi telah dikirim kepada Anda, silakan cek email "
|
||||
"Anda."
|
||||
"Tautan atur ulang kata sandi telah dikirim kepada Anda, silakan cek email"
|
||||
" Anda."
|
||||
|
||||
msgid "Return to home page"
|
||||
msgstr "Kembali ke halaman depan"
|
||||
|
@ -499,7 +714,8 @@ msgstr "Bagikan tautan"
|
|||
|
||||
msgid "You can directly share the following link via your prefered medium"
|
||||
msgstr ""
|
||||
"Anda bisa membagikan tautan secara langsung melalui media yang Anda inginkan"
|
||||
"Anda bisa membagikan tautan secara langsung melalui media yang Anda "
|
||||
"inginkan"
|
||||
|
||||
msgid "Send via Emails"
|
||||
msgstr "Kirim melalui surel"
|
||||
|
@ -510,10 +726,10 @@ msgid ""
|
|||
" creation of this budget management project and we will "
|
||||
"send them an email for you."
|
||||
msgstr ""
|
||||
"Spesifikkan daftar alamat surel (dipisah dengan koma) yang akan Anda kirim "
|
||||
"pemberitahuan tentang\n"
|
||||
" pembuatan dari manajemen anggaran proyek ini dan kami akan "
|
||||
"memngirim mereka sebuah surel."
|
||||
"Spesifikkan daftar alamat surel (dipisah dengan koma) yang akan Anda "
|
||||
"kirim pemberitahuan tentang\n"
|
||||
" pembuatan dari manajemen anggaran proyek ini dan kami "
|
||||
"akan memngirim mereka sebuah surel."
|
||||
|
||||
msgid "Who pays?"
|
||||
msgstr "Siapa membayar?"
|
||||
|
@ -521,14 +737,24 @@ msgstr "Siapa membayar?"
|
|||
msgid "To whom?"
|
||||
msgstr "Kepada siapa?"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Siapa?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr "Dibayar"
|
||||
|
||||
msgid "Spent"
|
||||
msgstr "Dihabiskan"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Saldo"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "%(member)s had been added"
|
||||
#~ msgstr "%(member)s telah ditambahkan"
|
||||
|
||||
#~ msgid "Someone probably"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "cleared the project history."
|
||||
#~ msgstr ""
|
||||
|
||||
|
|
729
ihatemoney/translations/it/LC_MESSAGES/messages.po
Normal file
729
ihatemoney/translations/it/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,729 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-04-28 10:30+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Translate Toolkit 2.5.1\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
"accepted."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Private code"
|
||||
msgstr ""
|
||||
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create the project"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"A project with this identifier (\"%(project)s\") already exists. Please "
|
||||
"choose a new identifier"
|
||||
msgstr ""
|
||||
|
||||
msgid "Get in"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send me the code by email"
|
||||
msgstr ""
|
||||
|
||||
msgid "This project does not exists"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password mismatch"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Reset password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
msgid "What?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Payer"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link"
|
||||
msgstr ""
|
||||
|
||||
msgid "A link to an external document, related to this bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "For whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Submit and add a new one"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bills can't be null"
|
||||
msgstr ""
|
||||
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Weights should be positive"
|
||||
msgstr ""
|
||||
|
||||
msgid "Weight"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
msgid "User name incorrect"
|
||||
msgstr ""
|
||||
|
||||
msgid "This project already have this member"
|
||||
msgstr ""
|
||||
|
||||
msgid "People to notify"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send invites"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "The email %(email)s is not valid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "This admin password is not the right one. Only %(num)d attempts left."
|
||||
msgstr ""
|
||||
|
||||
msgid "You either provided a bad token or no project identifier."
|
||||
msgstr ""
|
||||
|
||||
msgid "This private code is not the right one"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "You have just created '%(project)s' to share your expenses"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(msg_compl)sThe project identifier is %(project)s"
|
||||
msgstr ""
|
||||
|
||||
msgid "No token provided"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid token"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password successfully reset."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "You have been invited to share your expenses for %(project)s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Your invitations have been sent"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"User '%(name)s' has been deactivated. It will still appear in the users "
|
||||
"list until its balance becomes zero."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "User '%(name)s' has been removed"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "User '%(name)s' has been edited"
|
||||
msgstr ""
|
||||
|
||||
msgid "The bill has been added"
|
||||
msgstr ""
|
||||
|
||||
msgid "The bill has been deleted"
|
||||
msgstr ""
|
||||
|
||||
msgid "The bill has been modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sorry, we were unable to find the page you've asked for."
|
||||
msgstr ""
|
||||
|
||||
msgid "The best thing to do is probably to get back to the main page."
|
||||
msgstr ""
|
||||
|
||||
msgid "Back to the list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administration tasks are currently disabled."
|
||||
msgstr ""
|
||||
|
||||
msgid "The project you are trying to access do not exist, do you want to"
|
||||
msgstr ""
|
||||
|
||||
msgid "create it"
|
||||
msgstr ""
|
||||
|
||||
msgid "?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newest bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Oldest bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
|
||||
msgid "edit"
|
||||
msgstr ""
|
||||
|
||||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr ""
|
||||
|
||||
msgid "you sure?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill items"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download the list of bills with owner, amount, reason,... "
|
||||
msgstr ""
|
||||
|
||||
msgid "Settle plans"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download the list of transactions needed to settle the current bills."
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't remember the password?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit this bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add a bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Select all"
|
||||
msgstr ""
|
||||
|
||||
msgid "Select none"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit this member"
|
||||
msgstr ""
|
||||
|
||||
msgid "john.doe@example.com, mary.moe@site.com"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send the invitations"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr ""
|
||||
|
||||
msgid "Try out the demo"
|
||||
msgstr ""
|
||||
|
||||
msgid "You're sharing a house?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Going on holidays with friends?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Simply sharing money with others?"
|
||||
msgstr ""
|
||||
|
||||
msgid "We can help!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in to an existing project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
||||
msgid "can't remember your password?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"This access code will be sent to your friends. It is stored as-is by the "
|
||||
"server, so don\\'t reuse a personal password!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Account manager"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settle"
|
||||
msgstr ""
|
||||
|
||||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Languages"
|
||||
msgstr ""
|
||||
|
||||
msgid "Projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "Start a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Other projects :"
|
||||
msgstr ""
|
||||
|
||||
msgid "switch to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
|
||||
msgid "Mobile Application"
|
||||
msgstr ""
|
||||
|
||||
msgid "Documentation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administation Dashboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "\"I hate money\" is a free software"
|
||||
msgstr ""
|
||||
|
||||
msgid "you can contribute and improve it!"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivate"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invite people"
|
||||
msgstr ""
|
||||
|
||||
msgid "You should start by adding participants"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add a new bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who paid?"
|
||||
msgstr ""
|
||||
|
||||
msgid "For what?"
|
||||
msgstr ""
|
||||
|
||||
msgid "How much?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "Added on %(date)s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Everyone"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "Everyone but %(excluded)s"
|
||||
msgstr ""
|
||||
|
||||
msgid "each"
|
||||
msgstr ""
|
||||
|
||||
msgid "No bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "You probably want to"
|
||||
msgstr ""
|
||||
|
||||
msgid "add a bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "add participants"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password reminder"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"A link to reset your password has been sent to you, please check your "
|
||||
"emails."
|
||||
msgstr ""
|
||||
|
||||
msgid "Return to home page"
|
||||
msgstr ""
|
||||
|
||||
msgid "Your projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "Reset your password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invite people to join this project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Share Identifier & code"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"You can share the project identifier and the private code by any "
|
||||
"communication means."
|
||||
msgstr ""
|
||||
|
||||
msgid "Identifier:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Share the Link"
|
||||
msgstr ""
|
||||
|
||||
msgid "You can directly share the following link via your prefered medium"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send via Emails"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Specify a (comma separated) list of email adresses you want to notify "
|
||||
"about the\n"
|
||||
" creation of this budget management project and we will "
|
||||
"send them an email for you."
|
||||
msgstr ""
|
||||
|
||||
msgid "Who pays?"
|
||||
msgstr ""
|
||||
|
||||
msgid "To whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Spent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
Binary file not shown.
|
@ -1,19 +1,19 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-09-30 23:53+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2019-11-12 09:04+0000\n"
|
||||
"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
|
||||
"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/"
|
||||
"i-hate-money/i-hate-money/nb_NO/>\n"
|
||||
"Language: nb_NO\n"
|
||||
"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/i"
|
||||
"-hate-money/i-hate-money/nb_NO/>\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"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 3.10-dev\n"
|
||||
"Generated-By: Babel 2.7.0\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -31,6 +31,18 @@ msgstr "Privat kode"
|
|||
msgid "Email"
|
||||
msgstr "E-post"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Prosjektidentifikator"
|
||||
|
||||
|
@ -129,6 +141,15 @@ msgstr "Send invitasjoner"
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr "E-posten \"%(email)s\" er ikke gyldig"
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Prosjekt"
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr "For mange mislykkede innloggingsforsøk, prøv igjen senere."
|
||||
|
||||
|
@ -165,6 +186,12 @@ msgstr "Ukjent prosjekt"
|
|||
msgid "Password successfully reset."
|
||||
msgstr "Passord tilbakestilt."
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Project successfully deleted"
|
||||
msgstr "Prosjekt slettet"
|
||||
|
@ -179,8 +206,8 @@ msgid "Your invitations have been sent"
|
|||
msgstr "Invitasjonene dine har blitt sendt"
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgstr "%(member)s lagt til"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
|
@ -237,9 +264,6 @@ msgstr "?"
|
|||
msgid "Create a new project"
|
||||
msgstr "Opprett et nytt prosjekt"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Prosjekt"
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr "Antall medlemmer"
|
||||
|
||||
|
@ -261,6 +285,10 @@ msgstr "rediger"
|
|||
msgid "delete"
|
||||
msgstr "slett"
|
||||
|
||||
#, fuzzy
|
||||
msgid "see"
|
||||
msgstr "se"
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr "Oversikten er for tiden avskrudd."
|
||||
|
||||
|
@ -270,6 +298,12 @@ msgstr "er du sikker?"
|
|||
msgid "Edit project"
|
||||
msgstr "Rediger prosjekt"
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr "Last ned prosjektets data"
|
||||
|
||||
|
@ -294,6 +328,9 @@ msgstr "Husker du ikke passordet?"
|
|||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr "Rediger prosjektet"
|
||||
|
||||
|
@ -325,6 +362,178 @@ msgstr "Send ut invitasjonene"
|
|||
msgid "Download"
|
||||
msgstr "Last nd"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Hvem?"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Balance"
|
||||
msgstr "Kontobalanse"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr "Håndter delte <br />utgifter, enkelt"
|
||||
|
||||
|
@ -376,6 +585,9 @@ msgstr "Gjør opp"
|
|||
msgid "Statistics"
|
||||
msgstr "Statistikk"
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Innstillinger"
|
||||
|
||||
|
@ -436,6 +648,12 @@ msgstr "Du kan starte ved å legge til deltagere"
|
|||
msgid "Add a new bill"
|
||||
msgstr "Legg til en ny regning"
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr "Når?"
|
||||
|
||||
|
@ -462,10 +680,6 @@ msgstr "Alle, unntagen %(excluded)s"
|
|||
msgid "each"
|
||||
msgstr "hver"
|
||||
|
||||
#, fuzzy
|
||||
msgid "see"
|
||||
msgstr "se"
|
||||
|
||||
msgid "No bills"
|
||||
msgstr "Ingen regninger"
|
||||
|
||||
|
@ -546,18 +760,17 @@ msgstr "Hvem betaler?"
|
|||
msgid "To whom?"
|
||||
msgstr "Til hvem?"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Hvem?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr "Betalt"
|
||||
|
||||
msgid "Spent"
|
||||
msgstr "Forbrukt"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Balance"
|
||||
msgstr "Kontobalanse"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The project identifier is used to "
|
||||
|
@ -672,3 +885,6 @@ msgstr "Kontobalanse"
|
|||
#~ "En lenke for å tilbakestille passordet"
|
||||
#~ " har blitt sent til deg per "
|
||||
#~ "e-post."
|
||||
|
||||
#~ msgid "%(member)s had been added"
|
||||
#~ msgstr "%(member)s lagt til"
|
||||
|
|
Binary file not shown.
|
@ -1,19 +1,19 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2019-09-30 23:53+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2019-10-07 22:56+0000\n"
|
||||
"Last-Translator: Heimen Stoffels <vistausss@outlook.com>\n"
|
||||
"Language-Team: Dutch <https://hosted.weblate.org/projects/i-hate-money/"
|
||||
"i-hate-money/nl/>\n"
|
||||
"Language: nl\n"
|
||||
"Language-Team: Dutch <https://hosted.weblate.org/projects/i-hate-money/i"
|
||||
"-hate-money/nl/>\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"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 3.9-dev\n"
|
||||
"Generated-By: Babel 2.7.0\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -29,6 +29,18 @@ msgstr "Privécode"
|
|||
msgid "Email"
|
||||
msgstr "E-mailadres"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Project-id"
|
||||
|
||||
|
@ -123,6 +135,15 @@ msgstr "Uitnodigingen versturen"
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr "Het e-mailadres '%(email)s' is onjuist"
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Project"
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr "Te vaak onjuist ingelogd. Probeer het later opnieuw."
|
||||
|
||||
|
@ -158,6 +179,12 @@ msgstr "Onbekend project"
|
|||
msgid "Password successfully reset."
|
||||
msgstr "Wachtwoord is hersteld."
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr "Project is verwijderd"
|
||||
|
||||
|
@ -169,8 +196,8 @@ msgid "Your invitations have been sent"
|
|||
msgstr "Je uitnodigingen zijn verstuurd"
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgstr "%(member)s is toegevoegd"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
|
@ -225,9 +252,6 @@ msgstr "?"
|
|||
msgid "Create a new project"
|
||||
msgstr "Nieuw project aanmaken"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Project"
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr "Aantal deelnemers"
|
||||
|
||||
|
@ -249,6 +273,9 @@ msgstr "bewerken"
|
|||
msgid "delete"
|
||||
msgstr "verwijderen"
|
||||
|
||||
msgid "see"
|
||||
msgstr "bekijk"
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr "De overzichtspagina is momenteel uitgeschakeld."
|
||||
|
||||
|
@ -258,6 +285,12 @@ msgstr "weet je het zeker?"
|
|||
msgid "Edit project"
|
||||
msgstr "Project aanpassen"
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr "Projectgegevens downloaden"
|
||||
|
||||
|
@ -281,6 +314,9 @@ msgstr "Ben je je wachtwoord vergeten?"
|
|||
msgid "Cancel"
|
||||
msgstr "Annuleren"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr "Project bewerken"
|
||||
|
||||
|
@ -311,6 +347,177 @@ msgstr "Uitnodigingen versturen"
|
|||
msgid "Download"
|
||||
msgstr "Downloaden"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Wie?"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Saldo"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr "Beheer eenvoudig je <br />gedeelde uitgaven"
|
||||
|
||||
|
@ -360,6 +567,9 @@ msgstr "Schikken"
|
|||
msgid "Statistics"
|
||||
msgstr "Statistieken"
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Instellingen"
|
||||
|
||||
|
@ -417,6 +627,12 @@ msgstr "Begin met het toevoegen van deelnemers"
|
|||
msgid "Add a new bill"
|
||||
msgstr "Nieuwe rekening toevoegen"
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr "Wanneer?"
|
||||
|
||||
|
@ -443,9 +659,6 @@ msgstr "Iedereen, behalve %(excluded)s"
|
|||
msgid "each"
|
||||
msgstr "per persoon"
|
||||
|
||||
msgid "see"
|
||||
msgstr "bekijk"
|
||||
|
||||
msgid "No bills"
|
||||
msgstr "Geen rekeningen"
|
||||
|
||||
|
@ -522,128 +735,14 @@ msgstr "Wie betaalt?"
|
|||
msgid "To whom?"
|
||||
msgstr "Aan wie?"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Wie?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr "Betaald"
|
||||
|
||||
msgid "Spent"
|
||||
msgstr "Uitgegeven"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Saldo"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The project identifier is used to "
|
||||
#~ "log in and for the URL of "
|
||||
#~ "the project. We tried to generate "
|
||||
#~ "an identifier for you but a "
|
||||
#~ "project with this identifier already "
|
||||
#~ "exists. Please create a new identifier"
|
||||
#~ " that you will be able to "
|
||||
#~ "remember"
|
||||
#~ msgstr ""
|
||||
#~ "De project-id wordt gebruikt om in"
|
||||
#~ " te loggen en als url van het"
|
||||
#~ " project. We hebben geprobeerd om een"
|
||||
#~ " id voor je te genereren, maar "
|
||||
#~ "er is al een project met deze "
|
||||
#~ "id. Creëer een nieuwe id die je"
|
||||
#~ " makkelijk kunt onthouden."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Not a valid amount or expression.Only"
|
||||
#~ " numbers and + - * / "
|
||||
#~ "operatorsare accepted."
|
||||
#~ msgstr ""
|
||||
#~ "Geen geldig bedrag of geldige expressie."
|
||||
#~ " Alleen getallen en + - * / "
|
||||
#~ "zijn toegestaan."
|
||||
|
||||
#~ msgid "What do you want to download ?"
|
||||
#~ msgstr "Wat wil je downloaden?"
|
||||
|
||||
#~ msgid "bills"
|
||||
#~ msgstr "rekeningen"
|
||||
|
||||
#~ msgid "transactions"
|
||||
#~ msgstr "transacties"
|
||||
|
||||
#~ msgid "Export file format"
|
||||
#~ msgstr "Bestandsformaat voor exporteren"
|
||||
|
||||
#~ msgid "Edit this project"
|
||||
#~ msgstr "Dit project bewerken"
|
||||
|
||||
#~ msgid "Download this project's data"
|
||||
#~ msgstr "Projectgegevens downloaden"
|
||||
|
||||
#~ msgid "Type user name here"
|
||||
#~ msgstr "Typ hier de gebruikersnaam"
|
||||
|
||||
#~ msgid "No, thanks"
|
||||
#~ msgstr "Nee, bedankt"
|
||||
|
||||
#~ msgid "Manage your shared <br>expenses, easily"
|
||||
#~ msgstr "Beheer eenvoudig je gedeelde <br>uitgaven"
|
||||
|
||||
#~ msgid "Log to an existing project"
|
||||
#~ msgstr "Log in op een bestaand project"
|
||||
|
||||
#~ msgid "log in"
|
||||
#~ msgstr "inloggen"
|
||||
|
||||
#~ msgid "or create a new one"
|
||||
#~ msgstr "of creëer een nieuwe"
|
||||
|
||||
#~ msgid "let's get started"
|
||||
#~ msgstr "aan de slag"
|
||||
|
||||
#~ msgid "options"
|
||||
#~ msgstr "opties"
|
||||
|
||||
#~ msgid "Project settings"
|
||||
#~ msgstr "Projectinstellingen"
|
||||
|
||||
#~ msgid "This is a free software"
|
||||
#~ msgstr "Dit is vrije software"
|
||||
|
||||
#~ msgid "Invite people to join this project!"
|
||||
#~ msgstr "Nodig mensen uit voor dit project!"
|
||||
|
||||
#~ msgid "Added on"
|
||||
#~ msgstr "Toegevoegd op"
|
||||
|
||||
#~ msgid "Nothing to list yet. You probably want to"
|
||||
#~ msgstr "Er kan nog geen opsomming worden gemaakt. Voeg"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Specify a (comma separated) list of "
|
||||
#~ "email adresses you want to notify "
|
||||
#~ "about the\n"
|
||||
#~ "creation of this budget management "
|
||||
#~ "project and we will send them an"
|
||||
#~ " email for you."
|
||||
#~ msgstr ""
|
||||
#~ "Geef een kommagescheiden lijst van "
|
||||
#~ "e-mailadressen op. Deze mensen worden op"
|
||||
#~ " de\n"
|
||||
#~ "hoogte gebracht van het bestaan van "
|
||||
#~ "dit project en wij sturen hen een"
|
||||
#~ " e-mail."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If you prefer, you can share the project identifier and the shared\n"
|
||||
#~ "password by other communication means. "
|
||||
#~ "Or even directly share the following "
|
||||
#~ "link:"
|
||||
#~ msgstr ""
|
||||
#~ "Als je wilt, dan kun je de project-id en het gedeelde wachtwoord\n"
|
||||
#~ "delen via andere kanalen. Of deel gewoon de volgende link:"
|
||||
|
||||
#~ msgid "A link to reset your password has been sent to your email."
|
||||
#~ msgstr ""
|
||||
#~ "Er is een link met "
|
||||
#~ "wachtwoordherstelinstructies naar je e-mailadres "
|
||||
#~ "verstuurd."
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
|
768
ihatemoney/translations/ru/LC_MESSAGES/messages.po
Normal file
768
ihatemoney/translations/ru/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,768 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-04-26 19:50+0200\n"
|
||||
"PO-Revision-Date: 2020-04-28 07:11+0000\n"
|
||||
"Last-Translator: Vsevolod <sevauserg.com@gmail.com>\n"
|
||||
"Language-Team: Russian <https://hosted.weblate.org/projects/i-hate-money/"
|
||||
"i-hate-money/ru/>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<="
|
||||
"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.0.2\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
"accepted."
|
||||
msgstr ""
|
||||
"Недопустимая сумма выражения. Принимаются только цифры и операторы + - * / ."
|
||||
|
||||
msgid "Project name"
|
||||
msgstr "Имя проекта"
|
||||
|
||||
msgid "Private code"
|
||||
msgstr "Приватный код"
|
||||
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr "Включить историю проекта"
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr "Использовать отслеживание по IP для истории проекта"
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr "Импортировать ранее экспортированный JSON файл"
|
||||
|
||||
msgid "Import"
|
||||
msgstr "Импортировать"
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Идентификатор проекта"
|
||||
|
||||
msgid "Create the project"
|
||||
msgstr "Создать проект"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"A project with this identifier (\"%(project)s\") already exists. Please "
|
||||
"choose a new identifier"
|
||||
msgstr ""
|
||||
"Проект с идентификатором (\"%(project)s\") уже существует. Пожалуйста, "
|
||||
"выберете новый идентификатор"
|
||||
|
||||
msgid "Get in"
|
||||
msgstr "Войти"
|
||||
|
||||
msgid "Admin password"
|
||||
msgstr "Пароль администратора"
|
||||
|
||||
msgid "Send me the code by email"
|
||||
msgstr "Отправить код мне на Email"
|
||||
|
||||
msgid "This project does not exists"
|
||||
msgstr "Такой проект не существует"
|
||||
|
||||
msgid "Password mismatch"
|
||||
msgstr "Пароли не совпадают"
|
||||
|
||||
msgid "Password"
|
||||
msgstr "Пароль"
|
||||
|
||||
msgid "Password confirmation"
|
||||
msgstr "Подтвердите пароль"
|
||||
|
||||
msgid "Reset password"
|
||||
msgstr "Восстановить пароль"
|
||||
|
||||
msgid "Date"
|
||||
msgstr "Дата"
|
||||
|
||||
msgid "What?"
|
||||
msgstr "Что?"
|
||||
|
||||
msgid "Payer"
|
||||
msgstr "Плательщик"
|
||||
|
||||
msgid "Amount paid"
|
||||
msgstr "Уплаченная сумма"
|
||||
|
||||
msgid "External link"
|
||||
msgstr "Внешняя ссылка"
|
||||
|
||||
msgid "A link to an external document, related to this bill"
|
||||
msgstr "Ссылка на внешний документ, относящийся к этому счёту"
|
||||
|
||||
msgid "For whom?"
|
||||
msgstr "Кому?"
|
||||
|
||||
msgid "Submit"
|
||||
msgstr "Отправить"
|
||||
|
||||
msgid "Submit and add a new one"
|
||||
msgstr "Отправить и добавить новый"
|
||||
|
||||
msgid "Bills can't be null"
|
||||
msgstr "Счета не могут быть нулевыми"
|
||||
|
||||
msgid "Name"
|
||||
msgstr "Имя"
|
||||
|
||||
msgid "Weights should be positive"
|
||||
msgstr "Вес должен быть положительным"
|
||||
|
||||
msgid "Weight"
|
||||
msgstr "Вес"
|
||||
|
||||
msgid "Add"
|
||||
msgstr "Добавить"
|
||||
|
||||
msgid "User name incorrect"
|
||||
msgstr "Неправильное имя пользователя"
|
||||
|
||||
msgid "This project already have this member"
|
||||
msgstr "В этом проекте уже есть такой участник"
|
||||
|
||||
msgid "People to notify"
|
||||
msgstr "Люди для уведомления"
|
||||
|
||||
msgid "Send invites"
|
||||
msgstr "Отправить приглашения"
|
||||
|
||||
#, python-format
|
||||
msgid "The email %(email)s is not valid"
|
||||
msgstr "Email %(email)s не правильный"
|
||||
|
||||
msgid "Participant"
|
||||
msgstr "Участник"
|
||||
|
||||
msgid "Bill"
|
||||
msgstr "Счёт"
|
||||
|
||||
msgid "Project"
|
||||
msgstr "Проект"
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr "Слишком много неудачных попыток входа, попробуйте позже."
|
||||
|
||||
#, python-format
|
||||
msgid "This admin password is not the right one. Only %(num)d attempts left."
|
||||
msgstr ""
|
||||
"Этот пароль администратора неправильный. Осталось только %(num)d попыток."
|
||||
|
||||
msgid "You either provided a bad token or no project identifier."
|
||||
msgstr ""
|
||||
"Вы либо предоставили неверный токен, либо не указали идентификатор проекта."
|
||||
|
||||
msgid "This private code is not the right one"
|
||||
msgstr "Этот приватный код не подходит"
|
||||
|
||||
#, python-format
|
||||
msgid "You have just created '%(project)s' to share your expenses"
|
||||
msgstr "Вы только что создали '%(project)s' , чтобы разделить расходы"
|
||||
|
||||
#, python-format
|
||||
msgid "%(msg_compl)sThe project identifier is %(project)s"
|
||||
msgstr "%(msg_compl)sИдентификатор проекта это %(project)s"
|
||||
|
||||
msgid "No token provided"
|
||||
msgstr "Не предоставлен токен"
|
||||
|
||||
msgid "Invalid token"
|
||||
msgstr "Неправильный токен"
|
||||
|
||||
msgid "Unknown project"
|
||||
msgstr "Неизвестный проект"
|
||||
|
||||
msgid "Password successfully reset."
|
||||
msgstr "Пароль успешно восстановлен."
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr "Проект успешно загружен"
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr "Неправильный JSON"
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr "Проект удалён"
|
||||
|
||||
#, python-format
|
||||
msgid "You have been invited to share your expenses for %(project)s"
|
||||
msgstr "Вас пригласили разделить расходы в проект %(project)s"
|
||||
|
||||
msgid "Your invitations have been sent"
|
||||
msgstr "Ваш код приглашения был отправлен"
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s has been added"
|
||||
msgstr "%(member)s был добавлен"
|
||||
|
||||
#, python-format
|
||||
msgid "%(name)s is part of this project again"
|
||||
msgstr "%(name)s снова часть этого проекта"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"User '%(name)s' has been deactivated. It will still appear in the users "
|
||||
"list until its balance becomes zero."
|
||||
msgstr ""
|
||||
"Пользователь '%(name)s' был деактивирован. Он будет отображаться в списке "
|
||||
"пользователей до тех пор, пока его баланс не станет равным нулю."
|
||||
|
||||
#, python-format
|
||||
msgid "User '%(name)s' has been removed"
|
||||
msgstr "Пользователь '%(name)s' был удалён"
|
||||
|
||||
#, python-format
|
||||
msgid "User '%(name)s' has been edited"
|
||||
msgstr "Пользователь '%(name)s' был изменён"
|
||||
|
||||
msgid "The bill has been added"
|
||||
msgstr "Счёт был добавлен"
|
||||
|
||||
msgid "The bill has been deleted"
|
||||
msgstr "Счёт был удалён"
|
||||
|
||||
msgid "The bill has been modified"
|
||||
msgstr "Счёт был изменён"
|
||||
|
||||
msgid "Sorry, we were unable to find the page you've asked for."
|
||||
msgstr "К сожалению, нам не удалось найти страницу, которую вы запросили."
|
||||
|
||||
msgid "The best thing to do is probably to get back to the main page."
|
||||
msgstr "Лучше всего вернуться на главную страницу."
|
||||
|
||||
msgid "Back to the list"
|
||||
msgstr "Вернутся к списку"
|
||||
|
||||
msgid "Administration tasks are currently disabled."
|
||||
msgstr "Задачи администратора в данный момент отключены."
|
||||
|
||||
msgid "The project you are trying to access do not exist, do you want to"
|
||||
msgstr ""
|
||||
"Проект, к которому вы пытаетесь получить доступ, не существует, вы хотите"
|
||||
|
||||
msgid "create it"
|
||||
msgstr "создать его"
|
||||
|
||||
msgid "?"
|
||||
msgstr "?"
|
||||
|
||||
msgid "Create a new project"
|
||||
msgstr "Создать новый проект"
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr "Число участников"
|
||||
|
||||
msgid "Number of bills"
|
||||
msgstr "Число счетов"
|
||||
|
||||
msgid "Newest bill"
|
||||
msgstr "Новейший счёт"
|
||||
|
||||
msgid "Oldest bill"
|
||||
msgstr "Старейший счёт"
|
||||
|
||||
msgid "Actions"
|
||||
msgstr "Действия"
|
||||
|
||||
msgid "edit"
|
||||
msgstr "изменить"
|
||||
|
||||
msgid "delete"
|
||||
msgstr "удалить"
|
||||
|
||||
msgid "see"
|
||||
msgstr "просмотреть"
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr "Панель инструментов в данный момент отключена."
|
||||
|
||||
msgid "you sure?"
|
||||
msgstr "вы уверены?"
|
||||
|
||||
msgid "Edit project"
|
||||
msgstr "Изменить проект"
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr "Импортировать JSON"
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr "Выбрать файл"
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr "Скачать данные проекта"
|
||||
|
||||
msgid "Bill items"
|
||||
msgstr "Пункты счета"
|
||||
|
||||
msgid "Download the list of bills with owner, amount, reason,... "
|
||||
msgstr "Скачать список счетов с владельцем, суммой, причиной, .. "
|
||||
|
||||
msgid "Settle plans"
|
||||
msgstr "Урегулировать планы"
|
||||
|
||||
msgid "Download the list of transactions needed to settle the current bills."
|
||||
msgstr "Скачать список переводов нужных, чтобы урегулировать данные счета."
|
||||
|
||||
msgid "Can't remember the password?"
|
||||
msgstr "Не помните пароль?"
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr "Отменить"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr "Настройки приватности"
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr "Изменить проект"
|
||||
|
||||
msgid "Edit this bill"
|
||||
msgstr "Изменить счёт"
|
||||
|
||||
msgid "Add a bill"
|
||||
msgstr "Добавить счёт"
|
||||
|
||||
msgid "Select all"
|
||||
msgstr "Выбрать всё"
|
||||
|
||||
msgid "Select none"
|
||||
msgstr "Отменить выбор"
|
||||
|
||||
msgid "Add participant"
|
||||
msgstr "Добавить участника"
|
||||
|
||||
msgid "Edit this member"
|
||||
msgstr "Изменить этого участника"
|
||||
|
||||
msgid "john.doe@example.com, mary.moe@site.com"
|
||||
msgstr "john.doe@example.com, mary.moe@site.com"
|
||||
|
||||
msgid "Send the invitations"
|
||||
msgstr "Отправить приглашения"
|
||||
|
||||
msgid "Download"
|
||||
msgstr "Скачать"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr "История отключенных проектов"
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr "Отключенная история проекта и запись IP-адреса"
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr "Включить историю проекта"
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr "Выключить запись IP-адрессов"
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr "Включить историю проекта и запись IP адрессов"
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr "Включить запись IP адрессов"
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr "Настройки истории изменены"
|
||||
|
||||
msgid "changed"
|
||||
msgstr "изменены"
|
||||
|
||||
msgid "from"
|
||||
msgstr "от"
|
||||
|
||||
msgid "to"
|
||||
msgstr "кому"
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr "Подтвердите удаление IP-адресов"
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
"Вы уверены, что хотите удалить все записанные IP-адреса из этого проекта?\n"
|
||||
" Остальная часть истории проекта не будет затронута. Это "
|
||||
"действие не может быть отменено."
|
||||
|
||||
msgid "Close"
|
||||
msgstr "Закрыть"
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr "Подтвердить удаление"
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr "Подтверждение удаления"
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
"Вы уверены, что хотите стереть историю проекта? Это действие нельзя отменить."
|
||||
|
||||
msgid "Added"
|
||||
msgstr "Добавлен"
|
||||
|
||||
msgid "Removed"
|
||||
msgstr "Удалён"
|
||||
|
||||
msgid "and"
|
||||
msgstr "и"
|
||||
|
||||
msgid "owers list"
|
||||
msgstr "список владельцев"
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "Кто?"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr "Баланс"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <i>У этого проекта история отключена. Новые действия не появятся "
|
||||
"ниже. Вы можете включить историю в</i>\n"
|
||||
" <a href=\"%(url)s\">настройках</a>\n"
|
||||
" "
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <i>В таблице ниже отражены действия, записанные до отключения "
|
||||
"истории проекта. Вы можете\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" data-"
|
||||
"target=\"#confirm-erase\">очистить историю проекта</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
"Некоторые записи ниже содержат IP-адреса, хотя в этом проекте запись IP "
|
||||
"отключена. "
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr "Удалить сохраненные IP-адреса"
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr "Нечего стирать"
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr "Стереть историю проекта"
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr "Нечего стирать"
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr "Удалить сохраненные IP-адреса"
|
||||
|
||||
msgid "Time"
|
||||
msgstr "Время"
|
||||
|
||||
msgid "Event"
|
||||
msgstr "Событие"
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr "Запись IP-адреса может быть включена на странице настроек"
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr "Запись IP-адреса может быть отключена на странице настроек"
|
||||
|
||||
msgid "From IP"
|
||||
msgstr "От IP"
|
||||
|
||||
msgid "added"
|
||||
msgstr "добавлен"
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr "Приватный код проекта изменен"
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr "Проект переименован в"
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr "Контактная почта проекта изменена на"
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr "Настройки проекта изменены"
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr "отключено"
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr "реактивирован"
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr "переименован в"
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr "Внешняя ссылка изменена на"
|
||||
|
||||
msgid "Amount"
|
||||
msgstr "Количество"
|
||||
|
||||
msgid "modified"
|
||||
msgstr "изменено"
|
||||
|
||||
msgid "removed"
|
||||
msgstr "удалено"
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr "изменилось неизвестным образом"
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr "Нечего перечислять"
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr "Кто-то скорее всего стёр историю проекта."
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr "Управляйте своими общими <br />расходами проще"
|
||||
|
||||
msgid "Try out the demo"
|
||||
msgstr "Попробуйте"
|
||||
|
||||
msgid "You're sharing a house?"
|
||||
msgstr "Вы живете в одном доме с другими людьми?"
|
||||
|
||||
msgid "Going on holidays with friends?"
|
||||
msgstr "Собираетесь в отпуск с друзьями?"
|
||||
|
||||
msgid "Simply sharing money with others?"
|
||||
msgstr "Просто делиться деньгами с другими?"
|
||||
|
||||
msgid "We can help!"
|
||||
msgstr "Мы поможем!"
|
||||
|
||||
msgid "Log in to an existing project"
|
||||
msgstr "Войти в существующий проект"
|
||||
|
||||
msgid "Log in"
|
||||
msgstr "Войти"
|
||||
|
||||
msgid "can't remember your password?"
|
||||
msgstr "не помните пароль?"
|
||||
|
||||
msgid "Create"
|
||||
msgstr "Создать"
|
||||
|
||||
msgid ""
|
||||
"This access code will be sent to your friends. It is stored as-is by the "
|
||||
"server, so don\\'t reuse a personal password!"
|
||||
msgstr ""
|
||||
"Этот код доступа будет отправлен вашим друзьям. Он хранится на сервере как "
|
||||
"есть, поэтому не используйте личный пароль!"
|
||||
|
||||
msgid "Account manager"
|
||||
msgstr "Менеджер аккаунтов"
|
||||
|
||||
msgid "Bills"
|
||||
msgstr "Счета"
|
||||
|
||||
msgid "Settle"
|
||||
msgstr "Отрегулировать"
|
||||
|
||||
msgid "Statistics"
|
||||
msgstr "Статистика"
|
||||
|
||||
msgid "History"
|
||||
msgstr "История"
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Настройки"
|
||||
|
||||
msgid "Languages"
|
||||
msgstr "Языки"
|
||||
|
||||
msgid "Projects"
|
||||
msgstr "Проекты"
|
||||
|
||||
msgid "Start a new project"
|
||||
msgstr "Начать новый проект"
|
||||
|
||||
msgid "Other projects :"
|
||||
msgstr "Остальные проекты :"
|
||||
|
||||
msgid "switch to"
|
||||
msgstr "сменён на"
|
||||
|
||||
msgid "Dashboard"
|
||||
msgstr "Панель инструментов"
|
||||
|
||||
msgid "Logout"
|
||||
msgstr "Выйти"
|
||||
|
||||
msgid "Code"
|
||||
msgstr "Код"
|
||||
|
||||
msgid "Mobile Application"
|
||||
msgstr "Мобильное приложение"
|
||||
|
||||
msgid "Documentation"
|
||||
msgstr "Документация"
|
||||
|
||||
msgid "Administation Dashboard"
|
||||
msgstr "Панель инструментов администратора"
|
||||
|
||||
msgid "\"I hate money\" is a free software"
|
||||
msgstr "\" I hate money \" - бесплатная программа"
|
||||
|
||||
msgid "you can contribute and improve it!"
|
||||
msgstr "вы можете способствовать развитию и улучшать её!"
|
||||
|
||||
msgid "deactivate"
|
||||
msgstr "отключить"
|
||||
|
||||
msgid "reactivate"
|
||||
msgstr "включить"
|
||||
|
||||
msgid "Invite people"
|
||||
msgstr "Пригласить людей"
|
||||
|
||||
msgid "You should start by adding participants"
|
||||
msgstr "Вам стоит начать с добавления пользователей"
|
||||
|
||||
msgid "Add a new bill"
|
||||
msgstr "Добавить новый счёт"
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr "Новые счета"
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr "Старые счета"
|
||||
|
||||
msgid "When?"
|
||||
msgstr "Когда?"
|
||||
|
||||
msgid "Who paid?"
|
||||
msgstr "Кто заплатил?"
|
||||
|
||||
msgid "For what?"
|
||||
msgstr "За что?"
|
||||
|
||||
msgid "How much?"
|
||||
msgstr "Сколько?"
|
||||
|
||||
#, python-format
|
||||
msgid "Added on %(date)s"
|
||||
msgstr "Добавлено %(date)s"
|
||||
|
||||
msgid "Everyone"
|
||||
msgstr "Каждый"
|
||||
|
||||
#, python-format
|
||||
msgid "Everyone but %(excluded)s"
|
||||
msgstr "Каждый, кроме %(excluded)s"
|
||||
|
||||
msgid "each"
|
||||
msgstr "каждый"
|
||||
|
||||
msgid "No bills"
|
||||
msgstr "Нет счетов"
|
||||
|
||||
msgid "Nothing to list yet."
|
||||
msgstr "Нечего перечислять еще."
|
||||
|
||||
msgid "You probably want to"
|
||||
msgstr "Возможно вы хотите"
|
||||
|
||||
msgid "add a bill"
|
||||
msgstr "добавить счёт"
|
||||
|
||||
msgid "add participants"
|
||||
msgstr "добавить пользователя"
|
||||
|
||||
msgid "Password reminder"
|
||||
msgstr "Напоминание пароля"
|
||||
|
||||
msgid ""
|
||||
"A link to reset your password has been sent to you, please check your "
|
||||
"emails."
|
||||
msgstr ""
|
||||
"Ссылка для восстановления пароля отправлена, пожалуйста, проверьте Email."
|
||||
|
||||
msgid "Return to home page"
|
||||
msgstr "Вернуться на главную страницу"
|
||||
|
||||
msgid "Your projects"
|
||||
msgstr "Ваши проекты"
|
||||
|
||||
msgid "Reset your password"
|
||||
msgstr "Восстановить пароль"
|
||||
|
||||
msgid "Invite people to join this project"
|
||||
msgstr "Пригласить людей присоединиться к этому проекту"
|
||||
|
||||
msgid "Share Identifier & code"
|
||||
msgstr "Поделиться идентификатором и кодом"
|
||||
|
||||
msgid ""
|
||||
"You can share the project identifier and the private code by any "
|
||||
"communication means."
|
||||
msgstr ""
|
||||
"Вы можете поделиться идентификатором проекта и личным кодом любым способом "
|
||||
"связи."
|
||||
|
||||
msgid "Identifier:"
|
||||
msgstr "Идентификатор:"
|
||||
|
||||
msgid "Share the Link"
|
||||
msgstr "Поделиться ссылкой"
|
||||
|
||||
msgid "You can directly share the following link via your prefered medium"
|
||||
msgstr ""
|
||||
"Вы можете напрямую поделиться следующей ссылкой через любой способ связи"
|
||||
|
||||
msgid "Send via Emails"
|
||||
msgstr "Отправить по почте"
|
||||
|
||||
msgid ""
|
||||
"Specify a (comma separated) list of email adresses you want to notify "
|
||||
"about the\n"
|
||||
" creation of this budget management project and we will "
|
||||
"send them an email for you."
|
||||
msgstr ""
|
||||
"Укажите (разделенный запятыми) список адресов электронной почты, которые вы "
|
||||
"хотите уведомить о\n"
|
||||
" создание этого проекта управления бюджетом, и мы вышлем им "
|
||||
"письмо."
|
||||
|
||||
msgid "Who pays?"
|
||||
msgstr "Кто платит?"
|
||||
|
||||
msgid "To whom?"
|
||||
msgstr "Кому?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr "Оплачено"
|
||||
|
||||
msgid "Spent"
|
||||
msgstr "Потрачено"
|
||||
|
||||
msgid "Expenses by Month"
|
||||
msgstr "Расходы по месяцам"
|
||||
|
||||
msgid "Period"
|
||||
msgstr "Период"
|
Binary file not shown.
|
@ -3,7 +3,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-10-01 21:48+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2019-08-07 13:24+0000\n"
|
||||
"Last-Translator: Mesut Akcan <makcan@gmail.com>\n"
|
||||
"Language: tr\n"
|
||||
|
@ -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.7.0\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -31,6 +31,18 @@ msgstr "Özel kod"
|
|||
msgid "Email"
|
||||
msgstr "E-posta"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Proje tanımlayıcısı"
|
||||
|
||||
|
@ -127,6 +139,15 @@ msgstr ""
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
|
||||
|
@ -160,6 +181,12 @@ msgstr ""
|
|||
msgid "Password successfully reset."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -171,7 +198,7 @@ msgid "Your invitations have been sent"
|
|||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
|
@ -225,9 +252,6 @@ msgstr ""
|
|||
msgid "Create a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr ""
|
||||
|
||||
|
@ -249,6 +273,9 @@ msgstr ""
|
|||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr ""
|
||||
|
||||
|
@ -258,6 +285,12 @@ msgstr ""
|
|||
msgid "Edit project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -279,6 +312,9 @@ msgstr ""
|
|||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr ""
|
||||
|
||||
|
@ -309,6 +345,177 @@ msgstr ""
|
|||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr ""
|
||||
|
||||
|
@ -356,6 +563,9 @@ msgstr ""
|
|||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -413,6 +623,12 @@ msgstr ""
|
|||
msgid "Add a new bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -439,9 +655,6 @@ msgstr ""
|
|||
msgid "each"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "No bills"
|
||||
msgstr ""
|
||||
|
||||
|
@ -510,91 +723,14 @@ msgstr ""
|
|||
msgid "To whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Spent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "What do you want to download ?"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "bills"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "transactions"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Export file format"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Edit this project"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Download this project's data"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Type user name here"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "No, thanks"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Manage your shared <br>expenses, easily"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Log to an existing project"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "log in"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "or create a new one"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "let's get started"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "options"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Project settings"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "This is a free software"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Invite people to join this project!"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Added on"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Nothing to list yet. You probably want to"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Specify a (comma separated) list of "
|
||||
#~ "email adresses you want to notify "
|
||||
#~ "about the\n"
|
||||
#~ "creation of this budget management "
|
||||
#~ "project and we will send them an"
|
||||
#~ " email for you."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If you prefer, you can share the project identifier and the shared\n"
|
||||
#~ "password by other communication means. "
|
||||
#~ "Or even directly share the following "
|
||||
#~ "link:"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "A link to reset your password has been sent to your email."
|
||||
#~ msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
|
BIN
ihatemoney/translations/uk/LC_MESSAGES/messages.mo
Normal file
BIN
ihatemoney/translations/uk/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
|
@ -1,19 +1,20 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-12-05 15:35+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2019-12-08 16:26+0000\n"
|
||||
"Last-Translator: Tymofij Lytvynenko <till.svit@gmail.com>\n"
|
||||
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/i-hate-money/"
|
||||
"i-hate-money/uk/>\n"
|
||||
"Language: uk\n"
|
||||
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/i-hate-"
|
||||
"money/i-hate-money/uk/>\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<="
|
||||
"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 3.10-dev\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -29,6 +30,18 @@ msgstr "Приватний код"
|
|||
msgid "Email"
|
||||
msgstr "Е-пошта"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "Ідентифікатор проєкту"
|
||||
|
||||
|
@ -123,6 +136,15 @@ msgstr ""
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
|
||||
|
@ -156,6 +178,12 @@ msgstr ""
|
|||
msgid "Password successfully reset."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -167,7 +195,7 @@ msgid "Your invitations have been sent"
|
|||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
|
@ -221,9 +249,6 @@ msgstr ""
|
|||
msgid "Create a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr ""
|
||||
|
||||
|
@ -245,6 +270,9 @@ msgstr ""
|
|||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr ""
|
||||
|
||||
|
@ -254,6 +282,12 @@ msgstr ""
|
|||
msgid "Edit project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -275,6 +309,9 @@ msgstr ""
|
|||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr ""
|
||||
|
||||
|
@ -305,6 +342,177 @@ msgstr ""
|
|||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr ""
|
||||
|
||||
|
@ -352,6 +560,9 @@ msgstr ""
|
|||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -409,6 +620,12 @@ msgstr ""
|
|||
msgid "Add a new bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr ""
|
||||
|
||||
|
@ -435,9 +652,6 @@ msgstr ""
|
|||
msgid "each"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "No bills"
|
||||
msgstr ""
|
||||
|
||||
|
@ -506,14 +720,14 @@ msgstr ""
|
|||
msgid "To whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Spent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
|
Binary file not shown.
|
@ -1,19 +1,20 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-10-01 21:48+0200\n"
|
||||
"POT-Creation-Date: 2020-04-25 13:02+0200\n"
|
||||
"PO-Revision-Date: 2020-02-09 12:01+0000\n"
|
||||
"Last-Translator: Muge Niu <mugeniu12138@gmail.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
|
||||
"i-hate-money/i-hate-money/zh_Hans/>\n"
|
||||
"Language: zh_HANS-CN\n"
|
||||
"Language: zh_HANS_CN\n"
|
||||
"Language-Team: Chinese (Simplified) "
|
||||
"<https://hosted.weblate.org/projects/i-hate-money/i-hate-money/zh_Hans/>"
|
||||
"\n"
|
||||
"Plural-Forms: nplurals=1; plural=0\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 3.11-dev\n"
|
||||
"Generated-By: Babel 2.7.0\n"
|
||||
"Generated-By: Babel 2.8.0\n"
|
||||
|
||||
msgid ""
|
||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||
|
@ -29,6 +30,18 @@ msgstr "共享密钥"
|
|||
msgid "Email"
|
||||
msgstr "邮箱"
|
||||
|
||||
msgid "Enable project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use IP tracking for project history"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import previously exported JSON file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project identifier"
|
||||
msgstr "账目名称"
|
||||
|
||||
|
@ -123,6 +136,15 @@ msgstr ""
|
|||
msgid "The email %(email)s is not valid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Participant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Too many failed login attempts, please retry later."
|
||||
msgstr ""
|
||||
|
||||
|
@ -156,6 +178,12 @@ msgstr ""
|
|||
msgid "Password successfully reset."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully uploaded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project successfully deleted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -167,7 +195,7 @@ msgid "Your invitations have been sent"
|
|||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "%(member)s had been added"
|
||||
msgid "%(member)s has been added"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
|
@ -221,9 +249,6 @@ msgstr "?"
|
|||
msgid "Create a new project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of members"
|
||||
msgstr ""
|
||||
|
||||
|
@ -245,6 +270,9 @@ msgstr ""
|
|||
msgid "delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "The Dashboard is currently deactivated."
|
||||
msgstr ""
|
||||
|
||||
|
@ -254,6 +282,12 @@ msgstr ""
|
|||
msgid "Edit project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import JSON"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download project's data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -275,6 +309,9 @@ msgstr ""
|
|||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
msgid "Privacy Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit the project"
|
||||
msgstr ""
|
||||
|
||||
|
@ -305,6 +342,177 @@ msgstr ""
|
|||
msgid "Download"
|
||||
msgstr "下载"
|
||||
|
||||
msgid "Disabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled Project History & IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enabled IP Address Recording"
|
||||
msgstr ""
|
||||
|
||||
msgid "History Settings Changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "from"
|
||||
msgstr ""
|
||||
|
||||
msgid "to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Remove IP Adresses"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to delete all recorded IP addresses from this "
|
||||
"project?\n"
|
||||
" The rest of the project history will be unaffected. This "
|
||||
"action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirm Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Are you sure you want to erase all history for this project? This action "
|
||||
"cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
msgid "owers list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "谁?"
|
||||
|
||||
msgid "Balance"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>This project has history disabled. New actions won't "
|
||||
"appear below. You can enable history on the</i>\n"
|
||||
" <a href=\"%(url)s\">settings page</a>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"\n"
|
||||
" <i>The table below reflects actions recorded prior to "
|
||||
"disabling project history. You can\n"
|
||||
" <a href=\"#\" data-toggle=\"modal\" data-keyboard=\"false\" "
|
||||
"data-target=\"#confirm-erase\">clear project history</a> to remove "
|
||||
"them.</i></p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Some entries below contain IP addresses, even though this project has IP "
|
||||
"recording disabled. "
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete stored IP addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "No history to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clear Project History"
|
||||
msgstr ""
|
||||
|
||||
msgid "No IP Addresses to erase"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete Stored IP Addresses"
|
||||
msgstr ""
|
||||
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be enabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP address recording can be disabled on the settings page"
|
||||
msgstr ""
|
||||
|
||||
msgid "From IP"
|
||||
msgstr ""
|
||||
|
||||
msgid "added"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project private code changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project contact email changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project settings modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "deactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "reactivated"
|
||||
msgstr ""
|
||||
|
||||
msgid "renamed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "External link changed to"
|
||||
msgstr ""
|
||||
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
msgid "modified"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "changed in a unknown way"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Someone probably cleared the project history."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage your shared <br />expenses, easily"
|
||||
msgstr ""
|
||||
|
||||
|
@ -352,6 +560,9 @@ msgstr ""
|
|||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -409,6 +620,12 @@ msgstr ""
|
|||
msgid "Add a new bill"
|
||||
msgstr ""
|
||||
|
||||
msgid "Newer bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "Older bills"
|
||||
msgstr ""
|
||||
|
||||
msgid "When?"
|
||||
msgstr "什么时候?"
|
||||
|
||||
|
@ -435,9 +652,6 @@ msgstr ""
|
|||
msgid "each"
|
||||
msgstr ""
|
||||
|
||||
msgid "see"
|
||||
msgstr ""
|
||||
|
||||
msgid "No bills"
|
||||
msgstr ""
|
||||
|
||||
|
@ -506,107 +720,14 @@ msgstr ""
|
|||
msgid "To whom?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who?"
|
||||
msgstr "谁?"
|
||||
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
msgid "Spent"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balance"
|
||||
msgid "Expenses by Month"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The project identifier is used to "
|
||||
#~ "log in and for the URL of "
|
||||
#~ "the project. We tried to generate "
|
||||
#~ "an identifier for you but a "
|
||||
#~ "project with this identifier already "
|
||||
#~ "exists. Please create a new identifier"
|
||||
#~ " that you will be able to "
|
||||
#~ "remember"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Not a valid amount or expression.Only"
|
||||
#~ " numbers and + - * / "
|
||||
#~ "operatorsare accepted."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "What do you want to download ?"
|
||||
#~ msgstr "你想下载什么?"
|
||||
|
||||
#~ msgid "bills"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "transactions"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Export file format"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Edit this project"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Download this project's data"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Type user name here"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "No, thanks"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Manage your shared <br>expenses, easily"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Log to an existing project"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "log in"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "or create a new one"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "let's get started"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "options"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Project settings"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "This is a free software"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Invite people to join this project!"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Added on"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "Nothing to list yet. You probably want to"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Specify a (comma separated) list of "
|
||||
#~ "email adresses you want to notify "
|
||||
#~ "about the\n"
|
||||
#~ "creation of this budget management "
|
||||
#~ "project and we will send them an"
|
||||
#~ " email for you."
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If you prefer, you can share the project identifier and the shared\n"
|
||||
#~ "password by other communication means. "
|
||||
#~ "Or even directly share the following "
|
||||
#~ "link:"
|
||||
#~ msgstr ""
|
||||
|
||||
#~ msgid "A link to reset your password has been sent to your email."
|
||||
#~ msgstr ""
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
import re
|
||||
import os
|
||||
import ast
|
||||
import operator
|
||||
|
||||
from io import BytesIO, StringIO
|
||||
|
||||
import jinja2
|
||||
from json import dumps, JSONEncoder
|
||||
from flask import redirect, current_app
|
||||
from babel import Locale
|
||||
from werkzeug.routing import HTTPException, RoutingException
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
import csv
|
||||
from datetime import datetime, timedelta
|
||||
from enum import Enum
|
||||
from io import BytesIO, StringIO
|
||||
from json import JSONEncoder, dumps
|
||||
import operator
|
||||
import os
|
||||
import re
|
||||
|
||||
from babel import Locale
|
||||
from flask import current_app, redirect, render_template
|
||||
from flask_babel import get_locale
|
||||
import jinja2
|
||||
from werkzeug.routing import HTTPException, RoutingException
|
||||
|
||||
|
||||
def slugify(value):
|
||||
|
@ -99,7 +98,7 @@ def static_include(filename):
|
|||
|
||||
|
||||
def locale_from_iso(iso_code):
|
||||
return Locale(iso_code)
|
||||
return Locale.parse(iso_code)
|
||||
|
||||
|
||||
def list_of_dicts2json(dict_to_convert):
|
||||
|
@ -257,3 +256,40 @@ def same_bill(bill1, bill2):
|
|||
if bill1[a] != bill2[a]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class FormEnum(Enum):
|
||||
"""Extend builtin Enum class to be seamlessly compatible with WTForms"""
|
||||
|
||||
@classmethod
|
||||
def choices(cls):
|
||||
return [(choice, choice.name) for choice in cls]
|
||||
|
||||
@classmethod
|
||||
def coerce(cls, item):
|
||||
"""Coerce a str or int representation into an Enum object"""
|
||||
if isinstance(item, cls):
|
||||
return item
|
||||
|
||||
# If item is not already a Enum object then it must be
|
||||
# a string or int corresponding to an ID (e.g. '0' or 1)
|
||||
# Either int() or cls() will correctly throw a TypeError if this
|
||||
# is not the case
|
||||
return cls(int(item))
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
|
||||
def render_localized_template(template_name_prefix, **context):
|
||||
"""Like render_template(), but selects the right template according to the
|
||||
current user language. Fallback to English if a template for the
|
||||
current language does not exist.
|
||||
"""
|
||||
fallback = "en"
|
||||
templates = [
|
||||
f"{template_name_prefix}.{lang}.j2"
|
||||
for lang in (get_locale().language, fallback)
|
||||
]
|
||||
# render_template() supports a list of templates to try in order
|
||||
return render_template(templates, **context)
|
||||
|
|
94
ihatemoney/versioning.py
Normal file
94
ihatemoney/versioning.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
from flask import g
|
||||
from sqlalchemy.orm.attributes import get_history
|
||||
from sqlalchemy_continuum import VersioningManager
|
||||
from sqlalchemy_continuum.plugins.flask import fetch_remote_addr
|
||||
|
||||
from ihatemoney.utils import FormEnum
|
||||
|
||||
|
||||
class LoggingMode(FormEnum):
|
||||
"""Represents a project's history preferences."""
|
||||
|
||||
DISABLED = 0
|
||||
ENABLED = 1
|
||||
RECORD_IP = 2
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return cls.ENABLED
|
||||
|
||||
|
||||
class ConditionalVersioningManager(VersioningManager):
|
||||
"""Conditionally enable version tracking based on the given predicate."""
|
||||
|
||||
def __init__(self, tracking_predicate, *args, **kwargs):
|
||||
"""Create version entry iff tracking_predicate() returns True."""
|
||||
super().__init__(*args, **kwargs)
|
||||
self.tracking_predicate = tracking_predicate
|
||||
|
||||
def before_flush(self, session, flush_context, instances):
|
||||
if self.tracking_predicate():
|
||||
return super().before_flush(session, flush_context, instances)
|
||||
else:
|
||||
# At least one call to unit_of_work() needs to be made against the
|
||||
# session object to prevent a KeyError later. This doesn't create
|
||||
# a version or transaction entry
|
||||
self.unit_of_work(session)
|
||||
|
||||
def after_flush(self, session, flush_context):
|
||||
if self.tracking_predicate():
|
||||
return super().after_flush(session, flush_context)
|
||||
else:
|
||||
# At least one call to unit_of_work() needs to be made against the
|
||||
# session object to prevent a KeyError later. This doesn't create
|
||||
# a version or transaction entry
|
||||
self.unit_of_work(session)
|
||||
|
||||
|
||||
def version_privacy_predicate():
|
||||
"""Evaluate if the project of the current session has enabled logging."""
|
||||
logging_enabled = False
|
||||
try:
|
||||
if g.project.logging_preference != LoggingMode.DISABLED:
|
||||
logging_enabled = True
|
||||
|
||||
# If logging WAS enabled prior to this transaction,
|
||||
# we log this one last transaction
|
||||
old_logging_mode = get_history(g.project, "logging_preference")[2]
|
||||
if old_logging_mode and old_logging_mode[0] != LoggingMode.DISABLED:
|
||||
logging_enabled = True
|
||||
except AttributeError:
|
||||
# g.project doesn't exist, it's being created or this action is outside
|
||||
# the scope of a project. Use the default logging mode to decide
|
||||
if LoggingMode.default() != LoggingMode.DISABLED:
|
||||
logging_enabled = True
|
||||
return logging_enabled
|
||||
|
||||
|
||||
def get_ip_if_allowed():
|
||||
"""
|
||||
Get the remote address (IP address) of the current Flask context, if the
|
||||
project's privacy settings allow it. Behind the scenes, this calls back to
|
||||
the FlaskPlugin from SQLAlchemy-Continuum in order to maintain forward
|
||||
compatibility
|
||||
"""
|
||||
ip_logging_allowed = False
|
||||
try:
|
||||
if g.project.logging_preference == LoggingMode.RECORD_IP:
|
||||
ip_logging_allowed = True
|
||||
|
||||
# If ip recording WAS enabled prior to this transaction,
|
||||
# we record the IP for this one last transaction
|
||||
old_logging_mode = get_history(g.project, "logging_preference")[2]
|
||||
if old_logging_mode and old_logging_mode[0] == LoggingMode.RECORD_IP:
|
||||
ip_logging_allowed = True
|
||||
except AttributeError:
|
||||
# g.project doesn't exist, it's being created or this action is outside
|
||||
# the scope of a project. Use the default logging mode to decide
|
||||
if LoggingMode.default() == LoggingMode.RECORD_IP:
|
||||
ip_logging_allowed = True
|
||||
|
||||
if ip_logging_allowed:
|
||||
return fetch_remote_addr()
|
||||
else:
|
||||
return None
|
|
@ -8,55 +8,59 @@ Basically, this blueprint takes care of the authentication and provides
|
|||
some shortcuts to make your life better when coding (see `pull_project`
|
||||
and `add_project_id` for a quick overview)
|
||||
"""
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
import json
|
||||
import os
|
||||
from functools import wraps
|
||||
from smtplib import SMTPRecipientsRefused
|
||||
|
||||
from dateutil.parser import parse
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from flask import (
|
||||
abort,
|
||||
Blueprint,
|
||||
abort,
|
||||
current_app,
|
||||
flash,
|
||||
g,
|
||||
redirect,
|
||||
render_template,
|
||||
request,
|
||||
session,
|
||||
url_for,
|
||||
send_file,
|
||||
send_from_directory,
|
||||
session,
|
||||
url_for,
|
||||
)
|
||||
from flask_babel import get_locale, gettext as _
|
||||
from flask_babel import gettext as _
|
||||
from flask_mail import Message
|
||||
from sqlalchemy import orm
|
||||
from sqlalchemy_continuum import Operation
|
||||
from werkzeug.exceptions import NotFound
|
||||
from werkzeug.security import check_password_hash, generate_password_hash
|
||||
|
||||
from ihatemoney.currency_convertor import CurrencyConverter
|
||||
from ihatemoney.forms import (
|
||||
AdminAuthenticationForm,
|
||||
AuthenticationForm,
|
||||
EditProjectForm,
|
||||
InviteForm,
|
||||
MemberForm,
|
||||
PasswordReminder,
|
||||
ResetPasswordForm,
|
||||
ProjectForm,
|
||||
get_billform_for,
|
||||
ResetPasswordForm,
|
||||
UploadForm,
|
||||
get_billform_for,
|
||||
get_editprojectform_for,
|
||||
)
|
||||
from ihatemoney.models import db, Project, Person, Bill
|
||||
from ihatemoney.history import get_history, get_history_queries
|
||||
from ihatemoney.models import Bill, LoggingMode, Person, Project, db
|
||||
from ihatemoney.utils import (
|
||||
Redirect303,
|
||||
list_of_dicts2json,
|
||||
list_of_dicts2csv,
|
||||
LoginThrottler,
|
||||
Redirect303,
|
||||
get_members,
|
||||
list_of_dicts2csv,
|
||||
list_of_dicts2json,
|
||||
render_localized_template,
|
||||
same_bill,
|
||||
)
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
main = Blueprint("main", __name__)
|
||||
|
||||
|
@ -235,6 +239,8 @@ def authenticate(project_id=None):
|
|||
# add the project on the top of the list
|
||||
session["projects"].insert(0, (project_id, project.name))
|
||||
session[project_id] = True
|
||||
# Set session to permanent to make language choice persist
|
||||
session.permanent = True
|
||||
session.update()
|
||||
setattr(g, "project", project)
|
||||
return redirect(url_for(".list_bills"))
|
||||
|
@ -297,9 +303,7 @@ def create_project():
|
|||
project=g.project.name,
|
||||
)
|
||||
|
||||
message_body = render_template(
|
||||
"reminder_mail.%s.j2" % get_locale().language
|
||||
)
|
||||
message_body = render_localized_template("reminder_mail")
|
||||
|
||||
msg = Message(
|
||||
message_title, body=message_body, recipients=[project.contact_email]
|
||||
|
@ -307,19 +311,10 @@ def create_project():
|
|||
try:
|
||||
current_app.mail.send(msg)
|
||||
except SMTPRecipientsRefused:
|
||||
msg_compl = "Problem sending mail. "
|
||||
# TODO: destroy the project and cancel instead?
|
||||
else:
|
||||
msg_compl = ""
|
||||
flash(_("Error while sending reminder email"), category="danger")
|
||||
|
||||
# redirect the user to the next step (invite)
|
||||
flash(
|
||||
_(
|
||||
"%(msg_compl)sThe project identifier is %(project)s",
|
||||
msg_compl=msg_compl,
|
||||
project=project.id,
|
||||
)
|
||||
)
|
||||
flash(_("The project identifier is %(project)s", project=project.id))
|
||||
return redirect(url_for(".list_bills", project_id=project.id))
|
||||
|
||||
return render_template("create_project.html", form=form)
|
||||
|
@ -333,11 +328,12 @@ def remind_password():
|
|||
# get the project
|
||||
project = Project.query.get(form.id.data)
|
||||
# send a link to reset the password
|
||||
password_reminder = "password_reminder.%s.j2" % get_locale().language
|
||||
current_app.mail.send(
|
||||
Message(
|
||||
"password recovery",
|
||||
body=render_template(password_reminder, project=project),
|
||||
body=render_localized_template(
|
||||
"password_reminder", project=project
|
||||
),
|
||||
recipients=[project.contact_email],
|
||||
)
|
||||
)
|
||||
|
@ -381,37 +377,55 @@ def reset_password():
|
|||
|
||||
@main.route("/<project_id>/edit", methods=["GET", "POST"])
|
||||
def edit_project():
|
||||
edit_form = EditProjectForm()
|
||||
if request.method == "POST":
|
||||
if edit_form.validate():
|
||||
project = edit_form.update(g.project)
|
||||
db.session.add(project)
|
||||
db.session.commit()
|
||||
edit_form = get_editprojectform_for(g.project)
|
||||
import_form = UploadForm()
|
||||
# Import form
|
||||
if import_form.validate_on_submit():
|
||||
try:
|
||||
import_project(import_form.file.data.stream, g.project)
|
||||
flash(_("Project successfully uploaded"))
|
||||
|
||||
return redirect(url_for(".list_bills"))
|
||||
return redirect(url_for("main.list_bills"))
|
||||
except ValueError:
|
||||
flash(_("Invalid JSON"), category="danger")
|
||||
|
||||
# Edit form
|
||||
if edit_form.validate_on_submit():
|
||||
project = edit_form.update(g.project)
|
||||
# Update converted currency
|
||||
if project.default_currency != CurrencyConverter.default:
|
||||
for bill in project.get_bills():
|
||||
|
||||
if bill.original_currency == CurrencyConverter.default:
|
||||
bill.original_currency = project.default_currency
|
||||
|
||||
bill.converted_amount = CurrencyConverter().exchange_currency(
|
||||
bill.amount, bill.original_currency, project.default_currency
|
||||
)
|
||||
db.session.add(bill)
|
||||
|
||||
db.session.add(project)
|
||||
db.session.commit()
|
||||
|
||||
return redirect(url_for("main.list_bills"))
|
||||
else:
|
||||
edit_form.name.data = g.project.name
|
||||
|
||||
if g.project.logging_preference != LoggingMode.DISABLED:
|
||||
edit_form.project_history.data = True
|
||||
if g.project.logging_preference == LoggingMode.RECORD_IP:
|
||||
edit_form.ip_recording.data = True
|
||||
|
||||
edit_form.contact_email.data = g.project.contact_email
|
||||
|
||||
return render_template(
|
||||
"edit_project.html", edit_form=edit_form, current_view="edit_project"
|
||||
"edit_project.html",
|
||||
edit_form=edit_form,
|
||||
import_form=import_form,
|
||||
current_view="edit_project",
|
||||
)
|
||||
|
||||
|
||||
@main.route("/<project_id>/upload_json", methods=["GET", "POST"])
|
||||
def upload_json():
|
||||
form = UploadForm()
|
||||
if form.validate_on_submit():
|
||||
try:
|
||||
import_project(form.file.data.stream, g.project)
|
||||
flash(_("Project successfully uploaded"))
|
||||
except ValueError:
|
||||
flash(_("Invalid JSON"), category="error")
|
||||
return redirect(url_for("main.list_bills"))
|
||||
|
||||
return render_template("upload_json.html", form=form)
|
||||
|
||||
|
||||
def import_project(file, project):
|
||||
json_file = json.load(file)
|
||||
|
||||
|
@ -477,6 +491,7 @@ def import_project(file, project):
|
|||
form.date = parse(b["date"])
|
||||
form.payer = id_dict[b["payer_name"]]
|
||||
form.payed_for = owers_id
|
||||
form.original_currency = b.get("original_currency")
|
||||
|
||||
db.session.add(form.fake_form(bill, project))
|
||||
|
||||
|
@ -510,7 +525,7 @@ def export_project(file, format):
|
|||
|
||||
return send_file(
|
||||
file2export,
|
||||
attachment_filename="%s-%s.%s" % (g.project.id, file, format),
|
||||
attachment_filename=f"{g.project.id}-{file}.{format}",
|
||||
as_attachment=True,
|
||||
)
|
||||
|
||||
|
@ -542,6 +557,7 @@ def demo():
|
|||
name="demonstration",
|
||||
password=generate_password_hash("demo"),
|
||||
contact_email="demo@notmyidea.org",
|
||||
default_currency="EUR",
|
||||
)
|
||||
db.session.add(project)
|
||||
db.session.commit()
|
||||
|
@ -558,11 +574,7 @@ def invite():
|
|||
if request.method == "POST":
|
||||
if form.validate():
|
||||
# send the email
|
||||
|
||||
message_body = render_template(
|
||||
"invitation_mail.%s.j2" % get_locale().language
|
||||
)
|
||||
|
||||
message_body = render_localized_template("invitation_mail")
|
||||
message_title = _(
|
||||
"You have been invited to share your " "expenses for %(project)s",
|
||||
project=g.project.name,
|
||||
|
@ -610,7 +622,7 @@ def add_member():
|
|||
if form.validate():
|
||||
member = form.save(g.project, Person())
|
||||
db.session.commit()
|
||||
flash(_("%(member)s had been added", member=member.name))
|
||||
flash(_("%(member)s has been added", member=member.name))
|
||||
return redirect(url_for(".list_bills"))
|
||||
|
||||
return render_template("add_member.html", form=form)
|
||||
|
@ -740,6 +752,45 @@ def settle_bill():
|
|||
return render_template("settle_bills.html", bills=bills, current_view="settle_bill")
|
||||
|
||||
|
||||
@main.route("/<project_id>/history")
|
||||
def history():
|
||||
"""Query for the version entries associated with this project."""
|
||||
history = get_history(g.project, human_readable_names=True)
|
||||
|
||||
any_ip_addresses = any(event["ip"] for event in history)
|
||||
|
||||
return render_template(
|
||||
"history.html",
|
||||
current_view="history",
|
||||
history=history,
|
||||
any_ip_addresses=any_ip_addresses,
|
||||
LoggingMode=LoggingMode,
|
||||
OperationType=Operation,
|
||||
current_log_pref=g.project.logging_preference,
|
||||
)
|
||||
|
||||
|
||||
@main.route("/<project_id>/erase_history", methods=["POST"])
|
||||
def erase_history():
|
||||
"""Erase all history entries associated with this project."""
|
||||
for query in get_history_queries(g.project):
|
||||
query.delete(synchronize_session="fetch")
|
||||
|
||||
db.session.commit()
|
||||
return redirect(url_for(".history"))
|
||||
|
||||
|
||||
@main.route("/<project_id>/strip_ip_addresses", methods=["POST"])
|
||||
def strip_ip_addresses():
|
||||
"""Strip ip addresses from history entries associated with this project."""
|
||||
for query in get_history_queries(g.project):
|
||||
for version_object in query.all():
|
||||
version_object.transaction.remote_addr = None
|
||||
|
||||
db.session.commit()
|
||||
return redirect(url_for(".history"))
|
||||
|
||||
|
||||
@main.route("/<project_id>/statistics")
|
||||
def statistics():
|
||||
"""Compute what each member has paid and spent and display it"""
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
alembic==1.2.0
|
||||
aniso8601==8.0.0
|
||||
Babel==2.7.0
|
||||
blinker==1.4
|
||||
Click==7.0
|
||||
debts==0.4
|
||||
dnspython==1.16.0
|
||||
email-validator==1.0.4
|
||||
Flask==1.1.1
|
||||
Flask-Babel==0.12.2
|
||||
Flask-Cors==3.0.8
|
||||
Flask-Mail==0.9.1
|
||||
Flask-Migrate==2.5.2
|
||||
Flask-RESTful==0.3.7
|
||||
Flask-Script==2.0.6
|
||||
Flask-SQLAlchemy==2.4.1
|
||||
Flask-WTF==0.14.2
|
||||
idna==2.8
|
||||
itsdangerous==1.1.0
|
||||
Jinja2==2.10.1
|
||||
Mako==1.1.0
|
||||
MarkupSafe==1.1.1
|
||||
python-dateutil==2.8.0
|
||||
pytz==2019.2
|
||||
SQLAlchemy==1.3.8
|
||||
Werkzeug==0.16.0
|
||||
WTForms==2.2.1
|
46
setup.cfg
46
setup.cfg
|
@ -11,9 +11,9 @@ license = Custom BSD Beerware
|
|||
classifiers =
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.5
|
||||
Programming Language :: Python :: 3.6
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Topic :: Internet :: WWW/HTTP
|
||||
Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
||||
|
||||
|
@ -22,28 +22,34 @@ packages = find:
|
|||
include_package_data = True
|
||||
zip_safe = False
|
||||
install_requires =
|
||||
flask
|
||||
flask-wtf
|
||||
flask-sqlalchemy<3.0
|
||||
flask-mail
|
||||
Flask-Migrate
|
||||
Flask-script
|
||||
flask-babel
|
||||
flask-restful
|
||||
jinja2
|
||||
blinker
|
||||
flask-cors
|
||||
itsdangerous
|
||||
email_validator
|
||||
debts
|
||||
blinker==1.4
|
||||
cachetools==4.1.0
|
||||
debts==0.5
|
||||
email_validator==1.0.5
|
||||
Flask-Babel==1.0.0
|
||||
Flask-Cors==3.0.8
|
||||
Flask-Mail==0.9.1
|
||||
Flask-Migrate==2.5.3
|
||||
Flask-RESTful==0.3.8
|
||||
Flask-Script==2.0.6
|
||||
Flask-SQLAlchemy==2.4.1
|
||||
Flask-WTF==0.14.3
|
||||
WTForms==2.2.1
|
||||
Flask==1.1.2
|
||||
itsdangerous==1.1.0
|
||||
Jinja2==2.11.2
|
||||
requests==2.22.0
|
||||
SQLAlchemy-Continuum==1.3.9
|
||||
|
||||
[options.extras_require]
|
||||
dev =
|
||||
zest.releaser
|
||||
tox
|
||||
pytest
|
||||
flake8
|
||||
Flask-Testing
|
||||
black==19.10b0 ; python_version >= '3.6'
|
||||
flake8==3.7.9
|
||||
Flask-Testing==0.8.0
|
||||
isort==4.3.21
|
||||
pytest==5.4.1
|
||||
tox==3.14.6
|
||||
zest.releaser==6.20.1
|
||||
|
||||
[options.entry_points]
|
||||
console_scripts =
|
||||
|
|
17
tox.ini
17
tox.ini
|
@ -1,5 +1,5 @@
|
|||
[tox]
|
||||
envlist = py37,py36,py35,docs,flake8,black
|
||||
envlist = py38,py37,py36,docs,flake8,black
|
||||
skip_missing_interpreters = True
|
||||
|
||||
[testenv]
|
||||
|
@ -9,8 +9,7 @@ commands =
|
|||
py.test --pyargs ihatemoney.tests.tests
|
||||
|
||||
deps =
|
||||
-rdev-requirements.txt
|
||||
-rrequirements.txt
|
||||
-e.[dev]
|
||||
|
||||
# To be sure we are importing ihatemoney pkg from pip-installed version
|
||||
changedir = /tmp
|
||||
|
@ -22,15 +21,13 @@ deps =
|
|||
changedir = {toxinidir}
|
||||
|
||||
[testenv:black]
|
||||
commands = black --check --target-version=py34 .
|
||||
deps =
|
||||
-rdev-requirements.txt
|
||||
commands =
|
||||
black --check --target-version=py34 .
|
||||
isort -c -rc .
|
||||
changedir = {toxinidir}
|
||||
|
||||
[testenv:flake8]
|
||||
commands = flake8 ihatemoney
|
||||
deps =
|
||||
-rdev-requirements.txt
|
||||
changedir = {toxinidir}
|
||||
|
||||
[flake8]
|
||||
|
@ -42,6 +39,6 @@ extend-ignore =
|
|||
|
||||
[travis]
|
||||
python =
|
||||
3.5: py35
|
||||
3.6: py36, docs, black, flake8
|
||||
3.6: py36
|
||||
3.7: py37
|
||||
3.8: py38, docs, black, flake8
|
||||
|
|
Loading…
Reference in a new issue