mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-16 17:21:50 +02:00
Compare commits
45 commits
01d515c07f
...
2647fda43f
Author | SHA1 | Date | |
---|---|---|---|
2647fda43f | |||
![]() |
87112ec9d1 | ||
![]() |
f9552076c3 | ||
![]() |
a5bbaa61f7 | ||
![]() |
967266f7dc | ||
![]() |
9a834c97e3 | ||
bd689f931a | |||
67938eabbc | |||
662ff97795 | |||
![]() |
cfc2ffa671 | ||
![]() |
3a007714bf | ||
4f9cad88bd | |||
![]() |
c2db991ffd | ||
![]() |
794f26f767 | ||
![]() |
85eccb74b2 | ||
4b96e89422 | |||
![]() |
dcb61b62b1 | ||
![]() |
e00c39a62c | ||
![]() |
2f099674ed | ||
![]() |
752c80d29f | ||
![]() |
61ea1f54d2 | ||
![]() |
299c384908 | ||
![]() |
4e9ff9b1ac | ||
![]() |
2aa410c68f | ||
![]() |
7505cbe25a | ||
![]() |
83a60b1289 | ||
![]() |
ce20f9adea | ||
2b21795e94 | |||
![]() |
0b09476865 | ||
![]() |
62fbeee15c | ||
![]() |
56e2ff6900 | ||
![]() |
35ac04be20 | ||
![]() |
a9f211d3f6 | ||
e568bb05cc | |||
86eb9b8662 | |||
6e31a9c8b5 | |||
![]() |
cf77b4c346 | ||
![]() |
6582e2c0c3 | ||
![]() |
6e0a3689b8 | ||
![]() |
710aee9711 | ||
![]() |
eb6e156c32 | ||
![]() |
9ef46e2c5d | ||
4e7496e49d | |||
e5dfbf2f37 | |||
![]() |
3ac1bb8afe |
67 changed files with 4832 additions and 952 deletions
26
.github/workflows/check-doc.yml
vendored
26
.github/workflows/check-doc.yml
vendored
|
@ -1,26 +0,0 @@
|
||||||
name: Check doc
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ 'master', 'stable-*' ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ 'master', 'stable-*' ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
test_doc:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
cache: 'pip'
|
|
||||||
cache-dependency-path: '**/pyproject.toml'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
python -m pip install tox
|
|
||||||
- name: Check we can generate documentation
|
|
||||||
run: tox -e docs
|
|
|
@ -1,33 +1,27 @@
|
||||||
name: Lint & unit tests
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ 'master', 'stable-*' ]
|
branches: [ 'main', 'stable-*' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ 'master', 'stable-*' ]
|
branches: [ 'main', 'stable-*' ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python
|
- name: Install uv and set the python version
|
||||||
uses: actions/setup-python@v4
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
cache: 'pip'
|
|
||||||
cache-dependency-path: '**/pyproject.toml'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
python -m pip install tox
|
|
||||||
- name: Run Lint
|
- name: Run Lint
|
||||||
run: tox -e lint
|
run: make lint
|
||||||
|
|
||||||
test:
|
test:
|
||||||
# Dependency on linting to avoid running our expensive matrix test for nothing
|
# Dependency on linting to avoid running our expensive matrix test for nothing
|
||||||
needs: lint
|
needs: lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
# Use postgresql and MariaDB versions of Debian bookworm
|
# Use postgresql and MariaDB versions of Debian bookworm
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
|
@ -53,10 +47,11 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.7, 3.8, 3.9, "3.10", "3.11", "3.12"]
|
python-version: [3.9, "3.10", "3.11", "3.12"]
|
||||||
dependencies: [normal]
|
dependencies: [normal]
|
||||||
database: [sqlite]
|
database: [sqlite]
|
||||||
# Test other databases with only a few versions of Python (Debian bullseye has 3.9, bookworm has 3.11)
|
# Test other databases with only a few versions of Python
|
||||||
|
# (Debian bullseye has 3.9, bookworm has 3.11)
|
||||||
include:
|
include:
|
||||||
- python-version: 3.9
|
- python-version: 3.9
|
||||||
dependencies: normal
|
dependencies: normal
|
||||||
|
@ -71,9 +66,6 @@ jobs:
|
||||||
dependencies: normal
|
dependencies: normal
|
||||||
database: mariadb
|
database: mariadb
|
||||||
# Try a few variants with the minimal versions supported
|
# Try a few variants with the minimal versions supported
|
||||||
- python-version: 3.7
|
|
||||||
dependencies: minimal
|
|
||||||
database: sqlite
|
|
||||||
- python-version: 3.9
|
- python-version: 3.9
|
||||||
dependencies: minimal
|
dependencies: minimal
|
||||||
database: sqlite
|
database: sqlite
|
||||||
|
@ -95,32 +87,36 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Install uv and set the python version
|
||||||
uses: actions/setup-python@v4
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
cache: 'pip'
|
|
||||||
cache-dependency-path: '**/pyproject.toml'
|
|
||||||
- name: Change dependencies to minimal supported versions
|
- name: Change dependencies to minimal supported versions
|
||||||
run: sed -i -e 's/>=/==/g; s/~=.*==\(.*\)/==\1/g; s/~=/==/g;' pyproject.toml
|
# This sed comment installs the minimal supported version
|
||||||
|
# for all versions except for "requires-python"
|
||||||
|
# This is to detect that the minimum versions are really
|
||||||
|
# supported, in the CI
|
||||||
|
run: sed -i -e '/requires-python/!s/>=/==/g; /requires-python/!s/~=.*==\(.*\)/==\1/g; /requires-python/!s/~=/==/g;' pyproject.toml
|
||||||
if: matrix.dependencies == 'minimal'
|
if: matrix.dependencies == 'minimal'
|
||||||
- name: Install dependencies
|
- name: Run tests
|
||||||
run: |
|
run: uv run --extra dev --extra database pytest .
|
||||||
python -m pip install --upgrade pip
|
|
||||||
python -m pip install tox
|
|
||||||
# Run tox using the version of Python in `PATH`
|
|
||||||
- name: Run Tox with sqlite
|
|
||||||
run: tox -e py
|
|
||||||
if: matrix.database == 'sqlite'
|
|
||||||
env:
|
env:
|
||||||
TESTING_SQLALCHEMY_DATABASE_URI: 'sqlite:///budget.db'
|
# Setup the DATABASE_URI depending on the matrix we are using.
|
||||||
- name: Run Tox with postgresql
|
TESTING_SQLALCHEMY_DATABASE_URI: ${{
|
||||||
run: tox -e py
|
matrix.database == 'sqlite'
|
||||||
if: matrix.database == 'postgresql'
|
&& 'sqlite:///budget.db'
|
||||||
env:
|
|| matrix.database == 'postgresql'
|
||||||
TESTING_SQLALCHEMY_DATABASE_URI: 'postgresql+psycopg2://postgres:ihatemoney@localhost:5432/ihatemoney_ci'
|
&& 'postgresql+psycopg2://postgres:ihatemoney@localhost:5432/ihatemoney_ci'
|
||||||
- name: Run Tox with mariadb
|
|| 'mysql+pymysql://root:ihatemoney@localhost:3306/ihatemoney_ci'
|
||||||
run: tox -e py
|
}}
|
||||||
if: matrix.database == 'mariadb'
|
|
||||||
env:
|
docs:
|
||||||
TESTING_SQLALCHEMY_DATABASE_URI: 'mysql+pymysql://root:ihatemoney@localhost:3306/ihatemoney_ci'
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Install uv and set the python version
|
||||||
|
uses: astral-sh/setup-uv@v4
|
||||||
|
with:
|
||||||
|
python-version: "3.11"
|
||||||
|
- name: Build docs
|
||||||
|
run: make build-docs
|
8
.github/workflows/dockerhub.yml
vendored
8
.github/workflows/dockerhub.yml
vendored
|
@ -3,14 +3,14 @@ name: Docker build
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags: ['*']
|
tags: ['*']
|
||||||
branches: [ 'master', 'stable-*' ]
|
branches: [ 'main', 'stable-*' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ 'master', 'stable-*' ]
|
branches: [ 'main', 'stable-*' ]
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
@ -19,7 +19,7 @@ jobs:
|
||||||
run: docker compose -f docker-compose.test.yml run sut
|
run: docker compose -f docker-compose.test.yml run sut
|
||||||
|
|
||||||
build_upload:
|
build_upload:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
needs: test
|
needs: test
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -5,7 +5,14 @@ This document describes changes between each past release.
|
||||||
## 6.2.0 (unreleased)
|
## 6.2.0 (unreleased)
|
||||||
|
|
||||||
- Add support for python 3.12 (#757)
|
- Add support for python 3.12 (#757)
|
||||||
|
- Migrate from setup.cfg to pyproject.toml (#1243)
|
||||||
|
- Update to wtforms 3.1 (#1248)
|
||||||
|
- Document [repository rules](https://ihatemoney.readthedocs.io/en/latest/contributing.html#repository-rules) (#1253)
|
||||||
|
- Add "reimbursement" bills and allow to create them directly from the "Settle" page (#1290)
|
||||||
|
- Remove support for python 3.7
|
||||||
|
- Replace the black linter by ruff
|
||||||
|
- Replace virtualenv and pip by uv
|
||||||
|
- Remove tox
|
||||||
|
|
||||||
## 6.1.5 (2024-03-19)
|
## 6.1.5 (2024-03-19)
|
||||||
|
|
||||||
|
|
67
Makefile
67
Makefile
|
@ -1,60 +1,40 @@
|
||||||
VIRTUALENV = python3 -m venv
|
VIRTUALENV = uv venv
|
||||||
SPHINX_BUILDDIR = docs/_build
|
|
||||||
VENV := $(shell realpath $${VIRTUAL_ENV-.venv})
|
VENV := $(shell realpath $${VIRTUAL_ENV-.venv})
|
||||||
PYTHON = $(VENV)/bin/python3
|
BIN := uv tool run
|
||||||
|
PIP := uv pip
|
||||||
|
PYTHON = $(BIN)/python3
|
||||||
DEV_STAMP = $(VENV)/.dev_env_installed.stamp
|
DEV_STAMP = $(VENV)/.dev_env_installed.stamp
|
||||||
INSTALL_STAMP = $(VENV)/.install.stamp
|
INSTALL_STAMP = $(VENV)/.install.stamp
|
||||||
TEMPDIR := $(shell mktemp -d)
|
TEMPDIR := $(shell mktemp -d)
|
||||||
ZOPFLIPNG := zopflipng
|
ZOPFLIPNG := zopflipng
|
||||||
MAGICK_MOGRIFY := mogrify
|
MAGICK_MOGRIFY := mogrify
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
all: install ## Alias for install
|
|
||||||
.PHONY: install
|
|
||||||
install: virtualenv pyproject.toml $(INSTALL_STAMP) ## Install dependencies
|
|
||||||
$(INSTALL_STAMP):
|
|
||||||
$(VENV)/bin/pip install -U pip
|
|
||||||
$(VENV)/bin/pip install -e .
|
|
||||||
touch $(INSTALL_STAMP)
|
|
||||||
|
|
||||||
.PHONY: virtualenv
|
.PHONY: virtualenv
|
||||||
virtualenv: $(PYTHON)
|
virtualenv: $(PYTHON)
|
||||||
$(PYTHON):
|
$(PYTHON):
|
||||||
$(VIRTUALENV) $(VENV)
|
$(VIRTUALENV) $(VENV)
|
||||||
|
|
||||||
.PHONY: install-dev
|
|
||||||
install-dev: virtualenv pyproject.toml $(INSTALL_STAMP) $(DEV_STAMP) ## Install development dependencies
|
|
||||||
$(DEV_STAMP): $(PYTHON)
|
|
||||||
$(VENV)/bin/pip install -Ue .[dev]
|
|
||||||
touch $(DEV_STAMP)
|
|
||||||
|
|
||||||
.PHONY: remove-install-stamp
|
|
||||||
remove-install-stamp:
|
|
||||||
rm $(INSTALL_STAMP)
|
|
||||||
|
|
||||||
.PHONY: update
|
|
||||||
update: remove-install-stamp install ## Update the dependencies
|
|
||||||
|
|
||||||
.PHONY: serve
|
.PHONY: serve
|
||||||
serve: install build-translations ## Run the ihatemoney server
|
serve: build-translations ## Run the ihatemoney server
|
||||||
@echo 'Running ihatemoney on http://localhost:5000'
|
@echo 'Running ihatemoney on http://localhost:5000'
|
||||||
FLASK_DEBUG=1 FLASK_APP=ihatemoney.wsgi $(VENV)/bin/flask run --host=0.0.0.0
|
FLASK_DEBUG=1 FLASK_APP=ihatemoney.wsgi uv run flask run --host=0.0.0.0
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: install-dev ## Run the tests
|
test:
|
||||||
$(VENV)/bin/tox
|
uv run --extra dev --extra database pytest .
|
||||||
|
|
||||||
.PHONY: black
|
.PHONY: lint
|
||||||
black: install-dev ## Run the tests
|
lint:
|
||||||
$(VENV)/bin/black --target-version=py37 .
|
uv tool run ruff check .
|
||||||
|
uv tool run vermin --no-tips --violations -t=3.8- .
|
||||||
|
|
||||||
.PHONY: isort
|
.PHONY: format
|
||||||
isort: install-dev ## Run the tests
|
format:
|
||||||
$(VENV)/bin/isort .
|
uv tool run ruff format .
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: install-dev ## Release a new version (see https://ihatemoney.readthedocs.io/en/latest/contributing.html#how-to-release)
|
release: # Release a new version (see https://ihatemoney.readthedocs.io/en/latest/contributing.html#how-to-release)
|
||||||
$(VENV)/bin/fullrelease
|
uv run --extra dev fullreleas
|
||||||
|
|
||||||
.PHONY: compress-showcase
|
.PHONY: compress-showcase
|
||||||
compress-showcase:
|
compress-showcase:
|
||||||
|
@ -72,27 +52,30 @@ compress-assets: compress-showcase ## Compress static assets
|
||||||
|
|
||||||
.PHONY: build-translations
|
.PHONY: build-translations
|
||||||
build-translations: ## Build the translations
|
build-translations: ## Build the translations
|
||||||
$(VENV)/bin/pybabel compile -d ihatemoney/translations
|
uv run --extra dev pybabel compile -d ihatemoney/translations
|
||||||
|
|
||||||
.PHONY: extract-translations
|
.PHONY: extract-translations
|
||||||
extract-translations: ## Extract new translations from source code
|
extract-translations: ## Extract new translations from source code
|
||||||
$(VENV)/bin/pybabel extract --add-comments "I18N:" --strip-comments --omit-header --no-location --mapping-file ihatemoney/babel.cfg -o ihatemoney/messages.pot ihatemoney
|
uv run --extra dev pybabel extract --add-comments "I18N:" --strip-comments --omit-header --no-location --mapping-file ihatemoney/babel.cfg -o ihatemoney/messages.pot ihatemoney
|
||||||
$(VENV)/bin/pybabel update -i ihatemoney/messages.pot -d ihatemoney/translations/
|
uv run --extra dev pybabel update -i ihatemoney/messages.pot -d ihatemoney/translations/
|
||||||
|
|
||||||
.PHONY: create-database-revision
|
.PHONY: create-database-revision
|
||||||
create-database-revision: ## Create a new database revision
|
create-database-revision: ## Create a new database revision
|
||||||
@read -p "Please enter a message describing this revision: " rev_message; \
|
@read -p "Please enter a message describing this revision: " rev_message; \
|
||||||
$(PYTHON) -m ihatemoney.manage db migrate -d ihatemoney/migrations -m "$${rev_message}"
|
uv run python -m ihatemoney.manage db migrate -d ihatemoney/migrations -m "$${rev_message}"
|
||||||
|
|
||||||
.PHONY: create-empty-database-revision
|
.PHONY: create-empty-database-revision
|
||||||
create-empty-database-revision: ## Create an empty database revision
|
create-empty-database-revision: ## Create an empty database revision
|
||||||
@read -p "Please enter a message describing this revision: " rev_message; \
|
@read -p "Please enter a message describing this revision: " rev_message; \
|
||||||
$(PYTHON) -m ihatemoney.manage db revision -d ihatemoney/migrations -m "$${rev_message}"
|
uv run python -m ihatemoney.manage db revision -d ihatemoney/migrations -m "$${rev_message}"
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean: ## Destroy the virtual environment
|
clean: ## Destroy the virtual environment
|
||||||
rm -rf .venv
|
rm -rf .venv
|
||||||
|
|
||||||
|
build-docs:
|
||||||
|
uv run --extra doc sphinx-build -a -n -b html -d docs/_build/doctrees docs docs/_build/html
|
||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
help: ## Show the help indications
|
help: ## Show the help indications
|
||||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
33
README.md
33
README.md
|
@ -22,10 +22,41 @@ highly encouraged to do so.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- **Python**: version 3.7 to 3.12.
|
- **Python**: version 3.8 to 3.12.
|
||||||
- **Backends**: SQLite, PostgreSQL, MariaDB (version 10.3.2 or above),
|
- **Backends**: SQLite, PostgreSQL, MariaDB (version 10.3.2 or above),
|
||||||
Memory.
|
Memory.
|
||||||
|
|
||||||
|
## Current direction (as of 2024)
|
||||||
|
|
||||||
|
Ihatemoney was started in 2011, and we believe the project has reached a certain
|
||||||
|
level of maturity now. The overall energy of contributors is not as high as it
|
||||||
|
used to be.
|
||||||
|
|
||||||
|
In addition, there are now several self-hosted alternatives (for instance
|
||||||
|
[cospend](https://github.com/julien-nc/cospend-nc/tree/main),
|
||||||
|
[spliit](https://github.com/spliit-app/spliit)).
|
||||||
|
|
||||||
|
As maintainers, we believe that the project is still relevant but should gear
|
||||||
|
towards some kind of "maintenance mode":
|
||||||
|
|
||||||
|
* **Simplicity** is now the main goal of the project. It has always been a compass
|
||||||
|
for the project, and the resulting software is appreciated by both users and
|
||||||
|
server administrators. For us, "simplicity" is positive and encompasses both
|
||||||
|
technical aspects (very few javascript code, manageable dependencies, small code
|
||||||
|
size...) and user-visible aspects (straightforward interface, no need to create
|
||||||
|
accounts for people you invite, same web interface on mobile...)
|
||||||
|
|
||||||
|
* **Stability** is prioritized over adding major new features. We found ourselves
|
||||||
|
complexifying the codebase (and the interface) while accepting some
|
||||||
|
contributions. Our goal now is to have a minimal set of features that do most of
|
||||||
|
the job. We believe this will help lower the maintainance burden.
|
||||||
|
|
||||||
|
* **User interface and user experience improvements** are always super welcome !
|
||||||
|
|
||||||
|
It is still possible to propose new features, but they should fit into
|
||||||
|
this new direction. Simplicity of the UI/UX and simplicity of the technical
|
||||||
|
implementation will be the main factors when deciding to accept new features.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Do you wish to contribute to IHateMoney? Fantastic! There's a lot of
|
Do you wish to contribute to IHateMoney? Fantastic! There's a lot of
|
||||||
|
|
|
@ -173,6 +173,14 @@ URL you want.
|
||||||
- **Default value:** `""` (empty string)
|
- **Default value:** `""` (empty string)
|
||||||
- **Production value:** The URL of your chosing.
|
- **Production value:** The URL of your chosing.
|
||||||
|
|
||||||
|
## SITE_NAME
|
||||||
|
|
||||||
|
It is possible to change the name of the site to something at your liking.
|
||||||
|
|
||||||
|
- **Default value:** `"I Hate Money"` (empty string)
|
||||||
|
- **Production value:** The name of your choosing
|
||||||
|
|
||||||
|
|
||||||
## Configuring email sending
|
## Configuring email sending
|
||||||
|
|
||||||
By default, Ihatemoney sends emails using a local SMTP server, but it's
|
By default, Ihatemoney sends emails using a local SMTP server, but it's
|
||||||
|
|
|
@ -1,5 +1,37 @@
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
|
## Current direction (as of 2024)
|
||||||
|
|
||||||
|
Ihatemoney was started in 2011, and we believe the project has reached a certain
|
||||||
|
level of maturity now. The overall energy of contributors is not as high as it
|
||||||
|
used to be.
|
||||||
|
|
||||||
|
In addition, there are now several self-hosted alternatives (for instance
|
||||||
|
[cospend](https://github.com/julien-nc/cospend-nc/tree/main),
|
||||||
|
[spliit](https://github.com/spliit-app/spliit)).
|
||||||
|
|
||||||
|
As maintainers, we believe that the project is still relevant but should gear
|
||||||
|
towards some kind of "maintenance mode":
|
||||||
|
|
||||||
|
* **Simplicity** is now the main goal of the project. It has always been a compass
|
||||||
|
for the project, and the resulting software is appreciated by both users and
|
||||||
|
server administrators. For us, "simplicity" is positive and encompasses both
|
||||||
|
technical aspects (very few javascript code, manageable dependencies, small code
|
||||||
|
size...) and user-visible aspects (straightforward interface, no need to create
|
||||||
|
accounts for people you invite, same web interface on mobile...)
|
||||||
|
|
||||||
|
* **Stability** is prioritized over adding major new features. We found ourselves
|
||||||
|
complexifying the codebase (and the interface) while accepting some
|
||||||
|
contributions. Our goal now is to have a minimal set of features that do most of
|
||||||
|
the job. We believe this will help lower the maintainance burden.
|
||||||
|
|
||||||
|
* **User interface and user experience improvements** are always super welcome !
|
||||||
|
|
||||||
|
It is still possible to propose new features, but they should fit into
|
||||||
|
this new direction. Simplicity of the UI/UX and simplicity of the technical
|
||||||
|
implementation will be the main factors when deciding to accept new features.
|
||||||
|
|
||||||
|
|
||||||
## How to contribute
|
## How to contribute
|
||||||
|
|
||||||
You would like to contribute? First, thanks a bunch! This project is a
|
You would like to contribute? First, thanks a bunch! This project is a
|
||||||
|
@ -46,6 +78,15 @@ Thanks again!
|
||||||
(setup-dev-environment)=
|
(setup-dev-environment)=
|
||||||
## Set up a dev environment
|
## Set up a dev environment
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
In addition to general {ref}`requirements<system-requirements>`, you will need
|
||||||
|
**uv**. It recommended to install uv [system
|
||||||
|
wide](https://docs.astral.sh/uv/getting-started/installation/#standalone-installer)
|
||||||
|
as it is a kind of replacement for pip.
|
||||||
|
|
||||||
|
### Getting the sources
|
||||||
|
|
||||||
You must develop on top of the Git master branch:
|
You must develop on top of the Git master branch:
|
||||||
|
|
||||||
git clone https://github.com/spiral-project/ihatemoney.git
|
git clone https://github.com/spiral-project/ihatemoney.git
|
||||||
|
@ -151,7 +192,7 @@ We are using [black](https://black.readthedocs.io/en/stable/) and
|
||||||
Python files in this project. Be sure to run it locally on your files.
|
Python files in this project. Be sure to run it locally on your files.
|
||||||
To do so, just run:
|
To do so, just run:
|
||||||
|
|
||||||
make black isort
|
make lint
|
||||||
|
|
||||||
You can also integrate them with your dev environment (as a
|
You can also integrate them with your dev environment (as a
|
||||||
*format-on-save* hook, for instance).
|
*format-on-save* hook, for instance).
|
||||||
|
|
|
@ -26,7 +26,7 @@ hub](https://hub.docker.com/r/ihatemoney/ihatemoney/).
|
||||||
This is probably the simplest way to get something running. Once you
|
This is probably the simplest way to get something running. Once you
|
||||||
have Docker installed on your system, just issue :
|
have Docker installed on your system, just issue :
|
||||||
|
|
||||||
docker run -d -p 8000:8000 ihatemoney/ihatemoney
|
docker run -d -p 8000:8000 ihatemoney/ihatemoney:latest
|
||||||
|
|
||||||
Ihatemoney is now available on <http://localhost:8000>.
|
Ihatemoney is now available on <http://localhost:8000>.
|
||||||
|
|
||||||
|
@ -54,6 +54,10 @@ To enable the Admin dashboard, first generate a hashed password with:
|
||||||
|
|
||||||
docker run -it --rm --entrypoint ihatemoney ihatemoney/ihatemoney generate_password_hash
|
docker run -it --rm --entrypoint ihatemoney ihatemoney/ihatemoney generate_password_hash
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
The generated password hash is salted. Which means that the same password will generate a different hash each time. This is normal and expected behavior.
|
||||||
|
:::
|
||||||
|
|
||||||
At the prompt, enter a password to use for the admin dashboard. The
|
At the prompt, enter a password to use for the admin dashboard. The
|
||||||
command will print the hashed password string.
|
command will print the hashed password string.
|
||||||
|
|
||||||
|
@ -62,12 +66,18 @@ Add these additional environment variables to the docker run invocation:
|
||||||
-e ACTIVATE_ADMIN_DASHBOARD=True \
|
-e ACTIVATE_ADMIN_DASHBOARD=True \
|
||||||
-e ADMIN_PASSWORD=<hashed_password_string> \
|
-e ADMIN_PASSWORD=<hashed_password_string> \
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
If you are using a `docker-compose.yml` file and need to include a password hash, use `$$` instead of `$` to escape the dollar sign. This ensures that the hash is treated as a literal string rather than a variable in Bash.
|
||||||
|
:::
|
||||||
|
|
||||||
Additional gunicorn parameters can be passed using the docker `CMD`
|
Additional gunicorn parameters can be passed using the docker `CMD`
|
||||||
parameter. For example, use the following command to add more gunicorn
|
parameter. For example, use the following command to add more gunicorn
|
||||||
workers:
|
workers:
|
||||||
|
|
||||||
docker run -d -p 8000:8000 ihatemoney/ihatemoney -w 3
|
docker run -d -p 8000:8000 ihatemoney/ihatemoney -w 3
|
||||||
|
|
||||||
|
If needed, there is a `docker-compose.yml` file available as an example on the [project repository](https://github.com/spiral-project/ihatemoney/blob/master/docker-compose.yml)
|
||||||
|
|
||||||
(cloud)=
|
(cloud)=
|
||||||
## On a Cloud Provider
|
## On a Cloud Provider
|
||||||
|
|
||||||
|
@ -83,7 +93,7 @@ Some Paas (Platform-as-a-Service), provide a documentation or even a quick insta
|
||||||
|
|
||||||
«Ihatemoney» depends on:
|
«Ihatemoney» depends on:
|
||||||
|
|
||||||
- **Python**: any version from 3.7 to 3.12 will work.
|
- **Python**: any version from 3.8 to 3.12 will work.
|
||||||
- **A database backend**: choose among SQLite, PostgreSQL, MariaDB (>=
|
- **A database backend**: choose among SQLite, PostgreSQL, MariaDB (>=
|
||||||
10.3.2).
|
10.3.2).
|
||||||
- **Virtual environment** (recommended): [python3-venv]{.title-ref}
|
- **Virtual environment** (recommended): [python3-venv]{.title-ref}
|
||||||
|
|
|
@ -3,6 +3,7 @@ DEBUG = SQLACHEMY_ECHO = False
|
||||||
SQLALCHEMY_DATABASE_URI = "sqlite:////tmp/ihatemoney.db"
|
SQLALCHEMY_DATABASE_URI = "sqlite:////tmp/ihatemoney.db"
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
SECRET_KEY = "tralala"
|
SECRET_KEY = "tralala"
|
||||||
|
SITE_NAME = "I Hate Money"
|
||||||
MAIL_DEFAULT_SENDER = "Budget manager <admin@example.com>"
|
MAIL_DEFAULT_SENDER = "Budget manager <admin@example.com>"
|
||||||
SHOW_ADMIN_EMAIL = True
|
SHOW_ADMIN_EMAIL = True
|
||||||
ACTIVATE_DEMO_PROJECT = True
|
ACTIVATE_DEMO_PROJECT = True
|
||||||
|
@ -14,6 +15,7 @@ APPLICATION_ROOT = "/"
|
||||||
ENABLE_CAPTCHA = False
|
ENABLE_CAPTCHA = False
|
||||||
LEGAL_LINK = ""
|
LEGAL_LINK = ""
|
||||||
SUPPORTED_LANGUAGES = [
|
SUPPORTED_LANGUAGES = [
|
||||||
|
"az",
|
||||||
"ca",
|
"ca",
|
||||||
"cs",
|
"cs",
|
||||||
"de",
|
"de",
|
||||||
|
|
|
@ -92,7 +92,6 @@ def get_billform_for(project, set_default=True, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
class CommaDecimalField(DecimalField):
|
class CommaDecimalField(DecimalField):
|
||||||
|
|
||||||
"""A class to deal with comma in Decimal Field"""
|
"""A class to deal with comma in Decimal Field"""
|
||||||
|
|
||||||
def process_formdata(self, value):
|
def process_formdata(self, value):
|
||||||
|
|
|
@ -38,6 +38,9 @@ def history_sort_key(history_item_dict):
|
||||||
|
|
||||||
def describe_version(version_obj):
|
def describe_version(version_obj):
|
||||||
"""Use the base model str() function to describe a version object"""
|
"""Use the base model str() function to describe a version object"""
|
||||||
|
if not version_obj:
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
return parent_class(type(version_obj)).__str__(version_obj)
|
return parent_class(type(version_obj)).__str__(version_obj)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import getpass
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
import datetime
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from flask.cli import FlaskGroup
|
from flask.cli import FlaskGroup
|
||||||
|
@ -93,5 +94,31 @@ def delete_project(project_name):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument("print_emails", default=False)
|
||||||
|
@click.argument("bills", default=0) # default values will get total projects
|
||||||
|
@click.argument("days", default=73000) # approximately 200 years
|
||||||
|
def get_project_count(print_emails, bills, days):
|
||||||
|
"""Count projets with at least x bills and at less than x days old"""
|
||||||
|
projects = [
|
||||||
|
pr
|
||||||
|
for pr in Project.query.all()
|
||||||
|
if pr.get_bills().count() > bills
|
||||||
|
and pr.get_bills()[0].date
|
||||||
|
> datetime.date.today() - datetime.timedelta(days=days)
|
||||||
|
]
|
||||||
|
click.secho("Number of projects: " + str(len(projects)))
|
||||||
|
|
||||||
|
if print_emails:
|
||||||
|
emails = set([pr.contact_email for pr in projects])
|
||||||
|
emails_str = ", ".join(emails)
|
||||||
|
if len(emails) > 1:
|
||||||
|
click.secho("Contact emails: " + emails_str)
|
||||||
|
elif len(emails) == 1:
|
||||||
|
click.secho("Contact email: " + emails_str)
|
||||||
|
else:
|
||||||
|
click.secho("No contact emails found")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
cli()
|
cli()
|
||||||
|
|
|
@ -759,7 +759,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -447,6 +447,10 @@ class Project(db.Model):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return person
|
return person
|
||||||
|
|
||||||
|
def has_member(self, member_id):
|
||||||
|
person = Person.query.get(member_id, self)
|
||||||
|
return person is not None
|
||||||
|
|
||||||
def remove_project(self):
|
def remove_project(self):
|
||||||
# We can't import at top level without circular dependencies
|
# We can't import at top level without circular dependencies
|
||||||
from ihatemoney.history import purge_history
|
from ihatemoney.history import purge_history
|
||||||
|
|
|
@ -103,7 +103,7 @@ def validate_configuration(app):
|
||||||
if "MAIL_DEFAULT_SENDER" not in app.config:
|
if "MAIL_DEFAULT_SENDER" not in app.config:
|
||||||
app.config["MAIL_DEFAULT_SENDER"] = default_settings.DEFAULT_MAIL_SENDER
|
app.config["MAIL_DEFAULT_SENDER"] = default_settings.DEFAULT_MAIL_SENDER
|
||||||
|
|
||||||
if type(app.config["MAIL_DEFAULT_SENDER"]) == tuple:
|
if type(app.config["MAIL_DEFAULT_SENDER"]) is tuple:
|
||||||
(name, address) = app.config["MAIL_DEFAULT_SENDER"]
|
(name, address) = app.config["MAIL_DEFAULT_SENDER"]
|
||||||
app.config["MAIL_DEFAULT_SENDER"] = f"{name} <{address}>"
|
app.config["MAIL_DEFAULT_SENDER"] = f"{name} <{address}>"
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
|
|
|
@ -165,7 +165,6 @@
|
||||||
{% include "display_errors.html" %}
|
{% include "display_errors.html" %}
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ input(form.date, inline=True) }}
|
{{ input(form.date, inline=True) }}
|
||||||
{{ input(form.bill_type, inline=True) }}
|
|
||||||
{{ input(form.what, inline=True) }}
|
{{ input(form.what, inline=True) }}
|
||||||
{{ input(form.payer, inline=True, class="form-control custom-select") }}
|
{{ input(form.payer, inline=True, class="form-control custom-select") }}
|
||||||
<div data-toggle="tooltip" data-placement="top" title='{{ _("Simple operations are allowed, e.g. (18+36.2)/3") }}'>
|
<div data-toggle="tooltip" data-placement="top" title='{{ _("Simple operations are allowed, e.g. (18+36.2)/3") }}'>
|
||||||
|
@ -201,6 +200,7 @@
|
||||||
{% if g.project.default_currency != "XXX" %}
|
{% if g.project.default_currency != "XXX" %}
|
||||||
{{ input(form.original_currency, inline=True, class="form-control custom-select") }}
|
{{ input(form.original_currency, inline=True, class="form-control custom-select") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{{ input(form.bill_type, inline=True) }}
|
||||||
{{ input(form.external_link, inline=True) }}
|
{{ input(form.external_link, inline=True) }}
|
||||||
</details>
|
</details>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="h-100">
|
<html class="h-100">
|
||||||
<head>
|
<head>
|
||||||
<title>{{ _("Account manager") }}{% block title %}{% endblock %}</title>
|
<title>{{ SITE_NAME }} — {{ _("Account manager") }}{% block title %}{% endblock %}</title>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel=stylesheet type=text/css href="{{ url_for("static", filename='css/main.css') }}">
|
<link rel=stylesheet type=text/css href="{{ url_for("static", filename='css/main.css') }}">
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
<i class="icon book">{{ static_include("images/book.svg") | safe }}</i>
|
<i class="icon book">{{ static_include("images/book.svg") | safe }}</i>
|
||||||
</a>
|
</a>
|
||||||
{% if g.show_admin_dashboard_link %}
|
{% if g.show_admin_dashboard_link %}
|
||||||
<a target="_blank" rel="noopener" data-toggle="tooltip" data-placement="top" title="{{ _('Administation Dashboard') }}" href="{{ url_for('main.dashboard') }}">
|
<a target="_blank" rel="noopener" data-toggle="tooltip" data-placement="top" title="{{ _('Administration Dashboard') }}" href="{{ url_for('main.dashboard') }}">
|
||||||
<i class="icon admin">{{ static_include("images/cog.svg") | safe }}</i>
|
<i class="icon admin">{{ static_include("images/cog.svg") | safe }}</i>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
{% extends "sidebar_table_layout.html" %}
|
{% extends "sidebar_table_layout.html" %} {% block sidebar %}
|
||||||
|
<div id="table_overflow">{{ balance_table(show_weight=False) }}</div>
|
||||||
{% block sidebar %}
|
{% endblock %} {% block content %}
|
||||||
<div id="table_overflow">
|
|
||||||
{{ balance_table(show_weight=False) }}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<table id="bill_table" class="split_bills table table-striped">
|
<table id="bill_table" class="split_bills table table-striped">
|
||||||
<thead><tr><th>{{ _("Who pays?") }}</th><th>{{ _("To whom?") }}</th><th>{{ _("How much?") }}</th><th>{{ _("Settled?") }}</th></tr></thead>
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ _("Who pays?") }}</th>
|
||||||
|
<th>{{ _("To whom?") }}</th>
|
||||||
|
<th>{{ _("How much?") }}</th>
|
||||||
|
<th>{{ _("Settled?") }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for transaction in transactions %}
|
{% for transaction in transactions %}
|
||||||
<tr>
|
<tr receiver="{{transaction.receiver.id}}">
|
||||||
<td>{{ transaction.ower }}</td>
|
<td>{{ transaction.ower }}</td>
|
||||||
<td>{{ transaction.receiver }}</td>
|
<td>{{ transaction.receiver }}</td>
|
||||||
<td>{{ transaction.amount|currency }}</td>
|
<td>{{ transaction.amount|currency }}</td>
|
||||||
|
@ -23,8 +23,21 @@
|
||||||
{{ settlement_form.amount(value=transaction.amount) }}
|
{{ settlement_form.amount(value=transaction.amount) }}
|
||||||
{{ settlement_form.sender_id(value=transaction.ower.id) }}
|
{{ settlement_form.sender_id(value=transaction.ower.id) }}
|
||||||
{{ settlement_form.receiver_id(value=transaction.receiver.id) }}
|
{{ settlement_form.receiver_id(value=transaction.receiver.id) }}
|
||||||
<button class="btn btn-primary" type="submit" title="{{ _("Settle") }}">{{ _("Settle") }}</button>
|
<button class="btn btn-primary" type="submit" title="{{ _("Settle") }}">
|
||||||
|
<div
|
||||||
|
data-toggle="tooltip"
|
||||||
|
title='{{ _("Click here to record that the money transfer has been done") }}'
|
||||||
|
>
|
||||||
|
{{ _("Settle") }}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
<a
|
||||||
|
href="{{ url_for('.add_settlement_bill', amount = transaction.amount, sender_id = transaction.ower.id, receiver_id = transaction.receiver.id) }}"
|
||||||
|
class="btn btn-primary"
|
||||||
|
>
|
||||||
|
{{ ("Settle") }}
|
||||||
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2) != 0 %}
|
{%- for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2)|abs > 0.01 %}
|
||||||
<tr id="bal-member-{{ member.id }}" action="{% if member.activated %}delete{% else %}reactivate{% endif %}">
|
<tr id="bal-member-{{ member.id }}" action="{% if member.activated %}delete{% else %}reactivate{% endif %}">
|
||||||
<td class="balance-name">{{ member.name }}
|
<td class="balance-name">{{ member.name }}
|
||||||
{%- if show_weight -%}
|
{%- if show_weight -%}
|
||||||
|
|
|
@ -9,7 +9,6 @@ from ihatemoney.tests.common.ihatemoney_testcase import IhatemoneyTestCase
|
||||||
|
|
||||||
|
|
||||||
class TestAPI(IhatemoneyTestCase):
|
class TestAPI(IhatemoneyTestCase):
|
||||||
|
|
||||||
"""Tests the API"""
|
"""Tests the API"""
|
||||||
|
|
||||||
def api_create(
|
def api_create(
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import datetime
|
from datetime import datetime, timedelta, date
|
||||||
import re
|
import re
|
||||||
from urllib.parse import unquote, urlparse, urlunparse
|
from urllib.parse import unquote, urlparse, urlunparse
|
||||||
|
|
||||||
from flask import session, url_for
|
from flask import session, url_for
|
||||||
from libfaketime import fake_time
|
|
||||||
import pytest
|
import pytest
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
|
|
||||||
|
@ -239,7 +238,10 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
url, data={"password": "pass", "password_confirmation": "pass"}
|
url, data={"password": "pass", "password_confirmation": "pass"}
|
||||||
)
|
)
|
||||||
resp = self.login("raclette", password="pass")
|
resp = self.login("raclette", password="pass")
|
||||||
assert "<title>Account manager - raclette</title>" in resp.data.decode("utf-8")
|
assert (
|
||||||
|
"<title>I Hate Money — Account manager - raclette</title>"
|
||||||
|
in resp.data.decode("utf-8")
|
||||||
|
)
|
||||||
# Test empty and null tokens
|
# Test empty and null tokens
|
||||||
resp = self.client.get("/reset-password")
|
resp = self.client.get("/reset-password")
|
||||||
assert "No token provided" in resp.data.decode("utf-8")
|
assert "No token provided" in resp.data.decode("utf-8")
|
||||||
|
@ -1030,9 +1032,7 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
assert """<thead>
|
assert """<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Project</th>
|
<th>Project</th>
|
||||||
<th>Number of participants</th>""" in resp.data.decode(
|
<th>Number of participants</th>""" in resp.data.decode("utf-8")
|
||||||
"utf-8"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_dashboard_project_deletion(self):
|
def test_dashboard_project_deletion(self):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
@ -1146,7 +1146,7 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
assert re.search(re.compile(regex2, re.DOTALL), response.data.decode("utf-8"))
|
assert re.search(re.compile(regex2, re.DOTALL), response.data.decode("utf-8"))
|
||||||
|
|
||||||
# Check monthly expenses again: it should have a single month and the correct amount
|
# Check monthly expenses again: it should have a single month and the correct amount
|
||||||
august = datetime.date(year=2011, month=8, day=1)
|
august = date(year=2011, month=8, day=1)
|
||||||
assert project.active_months_range() == [august]
|
assert project.active_months_range() == [august]
|
||||||
assert dict(project.monthly_stats[2011]) == {8: 40.0}
|
assert dict(project.monthly_stats[2011]) == {8: 40.0}
|
||||||
|
|
||||||
|
@ -1163,11 +1163,11 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
months = [
|
months = [
|
||||||
datetime.date(year=2011, month=12, day=1),
|
date(year=2011, month=12, day=1),
|
||||||
datetime.date(year=2011, month=11, day=1),
|
date(year=2011, month=11, day=1),
|
||||||
datetime.date(year=2011, month=10, day=1),
|
date(year=2011, month=10, day=1),
|
||||||
datetime.date(year=2011, month=9, day=1),
|
date(year=2011, month=9, day=1),
|
||||||
datetime.date(year=2011, month=8, day=1),
|
date(year=2011, month=8, day=1),
|
||||||
]
|
]
|
||||||
amounts_2011 = {
|
amounts_2011 = {
|
||||||
12: 30.0,
|
12: 30.0,
|
||||||
|
@ -1220,7 +1220,7 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
"amount": "20",
|
"amount": "20",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
months.append(datetime.date(year=2011, month=7, day=1))
|
months.append(date(year=2011, month=7, day=1))
|
||||||
amounts_2011[7] = 20.0
|
amounts_2011[7] = 20.0
|
||||||
assert project.active_months_range() == months
|
assert project.active_months_range() == months
|
||||||
assert dict(project.monthly_stats[2011]) == amounts_2011
|
assert dict(project.monthly_stats[2011]) == amounts_2011
|
||||||
|
@ -1237,7 +1237,7 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
"amount": "30",
|
"amount": "30",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
months.insert(0, datetime.date(year=2012, month=1, day=1))
|
months.insert(0, date(year=2012, month=1, day=1))
|
||||||
amounts_2012 = {1: 30.0}
|
amounts_2012 = {1: 30.0}
|
||||||
assert project.active_months_range() == months
|
assert project.active_months_range() == months
|
||||||
assert dict(project.monthly_stats[2011]) == amounts_2011
|
assert dict(project.monthly_stats[2011]) == amounts_2011
|
||||||
|
@ -1470,8 +1470,8 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
pirate = models.Person.query.filter(models.Person.id == 5).one()
|
pirate = models.Person.query.filter(models.Person.id == 5).one()
|
||||||
assert pirate.name == "pirate"
|
assert pirate.name == "pirate"
|
||||||
|
|
||||||
# Try to add a new bill in another project
|
# Try to add a new bill to another project
|
||||||
self.client.post(
|
resp = self.client.post(
|
||||||
"/raclette/add",
|
"/raclette/add",
|
||||||
data={
|
data={
|
||||||
"date": "2017-01-01",
|
"date": "2017-01-01",
|
||||||
|
@ -1488,7 +1488,7 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
|
|
||||||
# Try to add a new bill in our project that references members of another project.
|
# Try to add a new bill in our project that references members of another project.
|
||||||
# First with invalid payed_for IDs.
|
# First with invalid payed_for IDs.
|
||||||
self.client.post(
|
resp = self.client.post(
|
||||||
"/tartiflette/add",
|
"/tartiflette/add",
|
||||||
data={
|
data={
|
||||||
"date": "2017-01-01",
|
"date": "2017-01-01",
|
||||||
|
@ -1630,7 +1630,7 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
member = models.Person.query.filter(models.Person.id == 1).one_or_none()
|
member = models.Person.query.filter(models.Person.id == 1).one_or_none()
|
||||||
assert member is None
|
assert member is None
|
||||||
|
|
||||||
# test new settle endpoint to add bills with wrong payer / payed_for
|
# test new settle endpoint to add bills with wrong ids
|
||||||
self.client.post("/exit")
|
self.client.post("/exit")
|
||||||
self.client.post(
|
self.client.post(
|
||||||
"/authenticate", data={"id": "tartiflette", "password": "tartiflette"}
|
"/authenticate", data={"id": "tartiflette", "password": "tartiflette"}
|
||||||
|
@ -1962,7 +1962,6 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
"""
|
"""
|
||||||
Tests that the RSS feed output content is expected.
|
Tests that the RSS feed output content is expected.
|
||||||
"""
|
"""
|
||||||
with fake_time("2023-07-25 12:00:00"):
|
|
||||||
self.post_project("raclette", default_currency="EUR")
|
self.post_project("raclette", default_currency="EUR")
|
||||||
self.client.post("/raclette/members/add", data={"name": "george"})
|
self.client.post("/raclette/members/add", data={"name": "george"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "peter"})
|
self.client.post("/raclette/members/add", data={"name": "peter"})
|
||||||
|
@ -2009,12 +2008,10 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
token = project.generate_token("feed")
|
token = project.generate_token("feed")
|
||||||
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
||||||
|
|
||||||
expected_rss_content = f"""<?xml version="1.0" encoding="utf-8"?>
|
content = resp.data.decode()
|
||||||
<rss version="2.0"
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
assert (
|
||||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
f"""<channel>
|
||||||
>
|
|
||||||
<channel>
|
|
||||||
<title>I Hate Money — raclette</title>
|
<title>I Hate Money — raclette</title>
|
||||||
<description>Latest bills from raclette</description>
|
<description>Latest bills from raclette</description>
|
||||||
<atom:link href="http://localhost/raclette/feed/{token}.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="http://localhost/raclette/feed/{token}.xml" rel="self" type="application/rss+xml" />
|
||||||
|
@ -2024,32 +2021,18 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
<guid isPermaLink="false">1</guid>
|
<guid isPermaLink="false">1</guid>
|
||||||
<dc:creator>george</dc:creator>
|
<dc:creator>george</dc:creator>
|
||||||
<description>December 31, 2016 - george, peter, steven : €4.00</description>
|
<description>December 31, 2016 - george, peter, steven : €4.00</description>
|
||||||
<pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
|
"""
|
||||||
</item>
|
in content
|
||||||
<item>
|
)
|
||||||
<title>charcuterie - €15.00</title>
|
|
||||||
<guid isPermaLink="false">2</guid>
|
assert """<title>charcuterie - €15.00</title>""" in content
|
||||||
<dc:creator>peter</dc:creator>
|
assert """<title>vin blanc - €10.00</title>""" in content
|
||||||
<description>December 30, 2016 - george, peter : €7.50</description>
|
|
||||||
<pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<title>vin blanc - €10.00</title>
|
|
||||||
<guid isPermaLink="false">3</guid>
|
|
||||||
<dc:creator>peter</dc:creator>
|
|
||||||
<description>December 29, 2016 - george, peter : €5.00</description>
|
|
||||||
<pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>""" # noqa: E221, E222, E231, E501
|
|
||||||
assert resp.data.decode() == expected_rss_content
|
|
||||||
|
|
||||||
def test_rss_feed_history_disabled(self):
|
def test_rss_feed_history_disabled(self):
|
||||||
"""
|
"""
|
||||||
Tests that RSS feeds is correctly rendered even if the project
|
Tests that RSS feeds is correctly rendered even if the project
|
||||||
history is disabled.
|
history is disabled.
|
||||||
"""
|
"""
|
||||||
with fake_time("2023-07-25 12:00:00"):
|
|
||||||
self.post_project("raclette", default_currency="EUR", project_history=False)
|
self.post_project("raclette", default_currency="EUR", project_history=False)
|
||||||
self.client.post("/raclette/members/add", data={"name": "george"})
|
self.client.post("/raclette/members/add", data={"name": "george"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "peter"})
|
self.client.post("/raclette/members/add", data={"name": "peter"})
|
||||||
|
@ -2096,44 +2079,12 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
token = project.generate_token("feed")
|
token = project.generate_token("feed")
|
||||||
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
||||||
|
|
||||||
expected_rss_content = f"""<?xml version="1.0" encoding="utf-8"?>
|
content = resp.data.decode()
|
||||||
<rss version="2.0"
|
assert """<title>charcuterie - €15.00</title>""" in content
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
assert """<title>vin blanc - €10.00</title>""" in content
|
||||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
|
||||||
>
|
|
||||||
<channel>
|
|
||||||
<title>I Hate Money — raclette</title>
|
|
||||||
<description>Latest bills from raclette</description>
|
|
||||||
<atom:link href="http://localhost/raclette/feed/{token}.xml" rel="self" type="application/rss+xml" />
|
|
||||||
<link>http://localhost/raclette/</link>
|
|
||||||
<item>
|
|
||||||
<title>fromage à raclette - €12.00</title>
|
|
||||||
<guid isPermaLink="false">1</guid>
|
|
||||||
<dc:creator>george</dc:creator>
|
|
||||||
<description>December 31, 2016 - george, peter, steven : €4.00</description>
|
|
||||||
<pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<title>charcuterie - €15.00</title>
|
|
||||||
<guid isPermaLink="false">2</guid>
|
|
||||||
<dc:creator>peter</dc:creator>
|
|
||||||
<description>December 30, 2016 - george, peter : €7.50</description>
|
|
||||||
<pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<title>vin blanc - €10.00</title>
|
|
||||||
<guid isPermaLink="false">3</guid>
|
|
||||||
<dc:creator>peter</dc:creator>
|
|
||||||
<description>December 29, 2016 - george, peter : €5.00</description>
|
|
||||||
<pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>""" # noqa: E221, E222, E231, E501
|
|
||||||
assert resp.data.decode() == expected_rss_content
|
|
||||||
|
|
||||||
def test_rss_if_modified_since_header(self):
|
def test_rss_if_modified_since_header(self):
|
||||||
# Project creation
|
# Project creation
|
||||||
with fake_time("2023-07-26 13:00:00"):
|
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
self.client.post("/raclette/members/add", data={"name": "george"})
|
self.client.post("/raclette/members/add", data={"name": "george"})
|
||||||
project = self.get_project("raclette")
|
project = self.get_project("raclette")
|
||||||
|
@ -2141,22 +2092,33 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
|
|
||||||
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert resp.headers.get("Last-Modified") == "Wed, 26 Jul 2023 13:00:00 UTC"
|
assert "Last-Modified" in resp.headers.keys()
|
||||||
|
last_modified = resp.headers.get("Last-Modified")
|
||||||
|
|
||||||
|
# Get a date 1 hour before the last modified date
|
||||||
|
before = datetime.strptime(
|
||||||
|
last_modified, "%a, %d %b %Y %H:%M:%S %Z"
|
||||||
|
) - timedelta(hours=1)
|
||||||
|
before_str = before.strftime("%a, %d %b %Y %H:%M:%S %Z")
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
headers={"If-Modified-Since": "Tue, 26 Jul 2023 12:00:00 UTC"},
|
headers={"If-Modified-Since": before_str},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
|
||||||
|
after = datetime.strptime(
|
||||||
|
last_modified, "%a, %d %b %Y %H:%M:%S %Z"
|
||||||
|
) + timedelta(hours=1)
|
||||||
|
after_str = after.strftime("%a, %d %b %Y %H:%M:%S %Z")
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
headers={"If-Modified-Since": "Tue, 26 Jul 2023 14:00:00 UTC"},
|
headers={"If-Modified-Since": after_str},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 304
|
assert resp.status_code == 304
|
||||||
|
|
||||||
# Add bill
|
# Add bill
|
||||||
with fake_time("2023-07-27 13:00:00"):
|
|
||||||
self.login("raclette")
|
self.login("raclette")
|
||||||
resp = self.client.post(
|
resp = self.client.post(
|
||||||
"/raclette/add",
|
"/raclette/add",
|
||||||
|
@ -2176,38 +2138,34 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
headers={"If-Modified-Since": "Tue, 27 Jul 2023 12:00:00 UTC"},
|
headers={"If-Modified-Since": before_str},
|
||||||
)
|
)
|
||||||
assert resp.headers.get("Last-Modified") == "Thu, 27 Jul 2023 13:00:00 UTC"
|
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
headers={"If-Modified-Since": "Tue, 27 Jul 2023 14:00:00 UTC"},
|
headers={"If-Modified-Since": after_str},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 304
|
assert resp.status_code == 304
|
||||||
|
|
||||||
def test_rss_etag_headers(self):
|
def test_rss_etag_headers(self):
|
||||||
# Project creation
|
# Project creation
|
||||||
with fake_time("2023-07-26 13:00:00"):
|
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
self.client.post("/raclette/members/add", data={"name": "george"})
|
self.client.post("/raclette/members/add", data={"name": "george"})
|
||||||
project = self.get_project("raclette")
|
project = self.get_project("raclette")
|
||||||
token = project.generate_token("feed")
|
token = project.generate_token("feed")
|
||||||
|
|
||||||
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
resp = self.client.get(f"/raclette/feed/{token}.xml")
|
||||||
assert resp.headers.get("ETag") == build_etag(
|
etag = resp.headers.get("ETag")
|
||||||
project.id, "2023-07-26T13:00:00"
|
|
||||||
)
|
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
headers={
|
headers={
|
||||||
"If-None-Match": build_etag(project.id, "2023-07-26T12:00:00"),
|
"If-None-Match": etag,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 304
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
|
@ -2215,10 +2173,9 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
"If-None-Match": build_etag(project.id, "2023-07-26T13:00:00"),
|
"If-None-Match": build_etag(project.id, "2023-07-26T13:00:00"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 304
|
assert resp.status_code == 200
|
||||||
|
|
||||||
# Add bill
|
# Add bill
|
||||||
with fake_time("2023-07-27 13:00:00"):
|
|
||||||
self.login("raclette")
|
self.login("raclette")
|
||||||
resp = self.client.post(
|
resp = self.client.post(
|
||||||
"/raclette/add",
|
"/raclette/add",
|
||||||
|
@ -2235,20 +2192,19 @@ class TestBudget(IhatemoneyTestCase):
|
||||||
)
|
)
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert "The bill has been added" in resp.data.decode()
|
assert "The bill has been added" in resp.data.decode()
|
||||||
|
etag = resp.headers.get("ETag")
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
headers={
|
headers={"If-None-Match": etag},
|
||||||
"If-None-Match": build_etag(project.id, "2023-07-27T12:00:00"),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
assert resp.headers.get("ETag") == build_etag(project.id, "2023-07-27T13:00:00")
|
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
new_etag = resp.headers.get("ETag")
|
||||||
|
|
||||||
resp = self.client.get(
|
resp = self.client.get(
|
||||||
f"/raclette/feed/{token}.xml",
|
f"/raclette/feed/{token}.xml",
|
||||||
headers={
|
headers={
|
||||||
"If-None-Match": build_etag(project.id, "2023-07-27T13:00:00"),
|
"If-None-Match": new_etag,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert resp.status_code == 304
|
assert resp.status_code == 304
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
from jinja2 import FileSystemBytecodeCache
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ihatemoney.babel_utils import compile_catalogs
|
from ihatemoney.babel_utils import compile_catalogs
|
||||||
|
@ -13,11 +14,19 @@ def babel_catalogs():
|
||||||
compile_catalogs()
|
compile_catalogs()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def jinja_cache_directory(tmp_path_factory):
|
||||||
|
return tmp_path_factory.mktemp("cache")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def app(request: pytest.FixtureRequest):
|
def app(request: pytest.FixtureRequest, jinja_cache_directory):
|
||||||
"""Create the Flask app with database"""
|
"""Create the Flask app with database"""
|
||||||
app = create_app(request.cls)
|
app = create_app(request.cls)
|
||||||
|
|
||||||
|
# Caches the jinja templates so they are compiled only once per test session
|
||||||
|
app.jinja_env.bytecode_cache = FileSystemBytecodeCache(jinja_cache_directory)
|
||||||
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
request.cls.app = app
|
request.cls.app = app
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
SQLALCHEMY_DATABASE_URI = 'sqlite:///budget.db'
|
SQLALCHEMY_DATABASE_URI = 'sqlite:///budget.db'
|
||||||
SQLACHEMY_ECHO = DEBUG
|
SQLACHEMY_ECHO = DEBUG
|
||||||
|
SITE_NAME = "I Hate Money"
|
||||||
|
|
||||||
SECRET_KEY = "supersecret"
|
SECRET_KEY = "supersecret"
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,17 @@ import smtplib
|
||||||
import socket
|
import socket
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
import pytest
|
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
|
|
||||||
from ihatemoney import models
|
from ihatemoney import models
|
||||||
from ihatemoney.currency_convertor import CurrencyConverter
|
from ihatemoney.currency_convertor import CurrencyConverter
|
||||||
from ihatemoney.manage import delete_project, generate_config, password_hash
|
from ihatemoney.manage import (
|
||||||
|
delete_project,
|
||||||
|
generate_config,
|
||||||
|
get_project_count,
|
||||||
|
password_hash,
|
||||||
|
)
|
||||||
from ihatemoney.run import load_configuration
|
from ihatemoney.run import load_configuration
|
||||||
from ihatemoney.tests.common.ihatemoney_testcase import BaseTestCase, IhatemoneyTestCase
|
from ihatemoney.tests.common.ihatemoney_testcase import BaseTestCase, IhatemoneyTestCase
|
||||||
|
|
||||||
|
@ -229,6 +233,65 @@ class TestModels(IhatemoneyTestCase):
|
||||||
pay_each_expected = 10 / 3
|
pay_each_expected = 10 / 3
|
||||||
assert bill.pay_each() == pay_each_expected
|
assert bill.pay_each() == pay_each_expected
|
||||||
|
|
||||||
|
def test_demo_project_count(self):
|
||||||
|
"""Test command the get-project-count"""
|
||||||
|
self.post_project("raclette")
|
||||||
|
|
||||||
|
# add members
|
||||||
|
self.client.post("/raclette/members/add", data={"name": "zorglub", "weight": 2})
|
||||||
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
|
self.client.post("/raclette/members/add", data={"name": "pépé"})
|
||||||
|
|
||||||
|
# create bills
|
||||||
|
self.client.post(
|
||||||
|
"/raclette/add",
|
||||||
|
data={
|
||||||
|
"date": "2011-08-10",
|
||||||
|
"what": "fromage à raclette",
|
||||||
|
"payer": 1,
|
||||||
|
"payed_for": [1, 2, 3],
|
||||||
|
"amount": "10.0",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.client.post(
|
||||||
|
"/raclette/add",
|
||||||
|
data={
|
||||||
|
"date": "2011-08-10",
|
||||||
|
"what": "red wine",
|
||||||
|
"payer": 2,
|
||||||
|
"payed_for": [1],
|
||||||
|
"amount": "20",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert self.get_project("raclette").has_bills()
|
||||||
|
|
||||||
|
# Now check the different parameters
|
||||||
|
runner = self.app.test_cli_runner()
|
||||||
|
result0 = runner.invoke(get_project_count)
|
||||||
|
assert result0.output.strip() == "Number of projects: 1"
|
||||||
|
|
||||||
|
# With more than 1 bill, without printing emails
|
||||||
|
result1 = runner.invoke(get_project_count, "False 1")
|
||||||
|
assert result1.output.strip() == "Number of projects: 1"
|
||||||
|
|
||||||
|
# With more than 2 bill, without printing emails
|
||||||
|
result2 = runner.invoke(get_project_count, "False 2")
|
||||||
|
assert result2.output.strip() == "Number of projects: 0"
|
||||||
|
|
||||||
|
# With more than 0 days old
|
||||||
|
result3 = runner.invoke(get_project_count, "False 0 0")
|
||||||
|
assert result3.output.strip() == "Number of projects: 0"
|
||||||
|
|
||||||
|
result4 = runner.invoke(get_project_count, "False 0 20000")
|
||||||
|
assert result4.output.strip() == "Number of projects: 1"
|
||||||
|
|
||||||
|
# Print emails
|
||||||
|
result5 = runner.invoke(get_project_count, "True")
|
||||||
|
assert "raclette@notmyidea.org" in result5.output
|
||||||
|
|
||||||
|
|
||||||
class TestEmailFailure(IhatemoneyTestCase):
|
class TestEmailFailure(IhatemoneyTestCase):
|
||||||
def test_creation_email_failure_smtp(self):
|
def test_creation_email_failure_smtp(self):
|
||||||
|
@ -401,9 +464,7 @@ class TestCurrencyConverter:
|
||||||
|
|
||||||
def test_failing_remote(self):
|
def test_failing_remote(self):
|
||||||
rates = {}
|
rates = {}
|
||||||
with patch("requests.Response.json", new=lambda _: {}), pytest.warns(
|
with patch("requests.Response.json", new=lambda _: {}):
|
||||||
UserWarning
|
|
||||||
):
|
|
||||||
# we need a non-patched converter, but it seems that MagickMock
|
# we need a non-patched converter, but it seems that MagickMock
|
||||||
# is mocking EVERY instance of the class method. Too bad.
|
# is mocking EVERY instance of the class method. Too bad.
|
||||||
rates = CurrencyConverter.get_rates(self.converter)
|
rates = CurrencyConverter.get_rates(self.converter)
|
||||||
|
|
1155
ihatemoney/translations/az/LC_MESSAGES/messages.po
Normal file
1155
ihatemoney/translations/az/LC_MESSAGES/messages.po
Normal file
File diff suppressed because it is too large
Load diff
|
@ -782,7 +782,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -785,7 +785,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
||||||
"PO-Revision-Date: 2022-09-12 15:25+0000\n"
|
"PO-Revision-Date: 2024-07-03 19:09+0000\n"
|
||||||
"Last-Translator: Maite Guix <maite.guix@gmail.com>\n"
|
"Last-Translator: Quentin PAGÈS <quentinantonin@free.fr>\n"
|
||||||
|
"Language-Team: Catalan <https://hosted.weblate.org/projects/i-hate-money/"
|
||||||
|
"i-hate-money/ca/>\n"
|
||||||
"Language: ca\n"
|
"Language: ca\n"
|
||||||
"Language-Team: Catalan <https://hosted.weblate.org/projects/i-hate-"
|
|
||||||
"money/i-hate-money/ca/>\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1\n"
|
|
||||||
"MIME-Version: 1.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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
|
"X-Generator: Weblate 5.7-dev\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -222,7 +222,7 @@ msgid "{start_object}, {next_object}"
|
||||||
msgstr "{start_object}, {next_object}"
|
msgstr "{start_object}, {next_object}"
|
||||||
|
|
||||||
msgid "No Currency"
|
msgid "No Currency"
|
||||||
msgstr "Sense moneda"
|
msgstr "Cap moneda"
|
||||||
|
|
||||||
#. Form error with only one error
|
#. Form error with only one error
|
||||||
msgid "{prefix}: {error}"
|
msgid "{prefix}: {error}"
|
||||||
|
@ -826,7 +826,7 @@ msgstr "Aplicació mòbil"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentació"
|
msgstr "Documentació"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Panell d'administració"
|
msgstr "Panell d'administració"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
@ -1082,4 +1082,3 @@ msgstr "Període"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Pots compartir directament l'enllaç següent"
|
#~ "Pots compartir directament l'enllaç següent"
|
||||||
#~ " a través del teu mitjà preferit"
|
#~ " a través del teu mitjà preferit"
|
||||||
|
|
||||||
|
|
|
@ -800,7 +800,7 @@ msgstr "Mobilní aplikace"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentace"
|
msgstr "Dokumentace"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Správcovský panel"
|
msgstr "Správcovský panel"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -824,7 +824,7 @@ msgstr "Handy-Applikation"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentation"
|
msgstr "Dokumentation"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Dashboard Administration"
|
msgstr "Dashboard Administration"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -811,7 +811,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
|
|
@ -821,7 +821,7 @@ msgstr "Poŝaparata programo"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentaro"
|
msgstr "Dokumentaro"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Administra panelo"
|
msgstr "Administra panelo"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
|
|
@ -818,7 +818,7 @@ msgstr "Aplicación móvil"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentación"
|
msgstr "Documentación"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Panel de administración"
|
msgstr "Panel de administración"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -815,7 +815,7 @@ msgstr "Aplicación móvil"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentación"
|
msgstr "Documentación"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Panel de administración"
|
msgstr "Panel de administración"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
||||||
"PO-Revision-Date: 2023-03-19 21:40+0000\n"
|
"PO-Revision-Date: 2024-05-23 03:01+0000\n"
|
||||||
"Last-Translator: Sai Mohammad-Hossein Emami <emami@outlook.com>\n"
|
"Last-Translator: Yamin Siahmargooei <yamin8000@yahoo.com>\n"
|
||||||
|
"Language-Team: Persian <https://hosted.weblate.org/projects/i-hate-money/"
|
||||||
|
"i-hate-money/fa/>\n"
|
||||||
"Language: fa\n"
|
"Language: fa\n"
|
||||||
"Language-Team: Persian <https://hosted.weblate.org/projects/i-hate-"
|
|
||||||
"money/i-hate-money/fa/>\n"
|
|
||||||
"Plural-Forms: nplurals=1; plural=0\n"
|
|
||||||
"MIME-Version: 1.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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
"X-Generator: Weblate 5.6-dev\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -125,16 +125,16 @@ msgid "Reset password"
|
||||||
msgstr "بازنشانی گذرواژه"
|
msgstr "بازنشانی گذرواژه"
|
||||||
|
|
||||||
msgid "When?"
|
msgid "When?"
|
||||||
msgstr ""
|
msgstr "چه زمانی؟"
|
||||||
|
|
||||||
msgid "What?"
|
msgid "What?"
|
||||||
msgstr "چی؟"
|
msgstr "چی؟"
|
||||||
|
|
||||||
msgid "Who paid?"
|
msgid "Who paid?"
|
||||||
msgstr ""
|
msgstr "چه کسی پرداخت کرد؟"
|
||||||
|
|
||||||
msgid "How much?"
|
msgid "How much?"
|
||||||
msgstr ""
|
msgstr "چقدر؟"
|
||||||
|
|
||||||
msgid "Currency"
|
msgid "Currency"
|
||||||
msgstr "واحد پولی"
|
msgstr "واحد پولی"
|
||||||
|
@ -180,14 +180,14 @@ msgid "People to notify"
|
||||||
msgstr "افرادی که براشون نوتیفیکیشن ارسال میشه"
|
msgstr "افرادی که براشون نوتیفیکیشن ارسال میشه"
|
||||||
|
|
||||||
msgid "Send the invitations"
|
msgid "Send the invitations"
|
||||||
msgstr ""
|
msgstr "ارسال دعوت نامه ها"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The email %(email)s is not valid"
|
msgid "The email %(email)s is not valid"
|
||||||
msgstr "ایمیل %(email)s نامعتبره"
|
msgstr "ایمیل %(email)s نامعتبره"
|
||||||
|
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr ""
|
msgstr "خروج"
|
||||||
|
|
||||||
msgid "Please check the email configuration of the server."
|
msgid "Please check the email configuration of the server."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -782,7 +782,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
@ -1092,4 +1092,3 @@ msgstr ""
|
||||||
#~ "them an email with the invitation "
|
#~ "them an email with the invitation "
|
||||||
#~ "link."
|
#~ "link."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -824,7 +824,7 @@ msgstr "Application mobile"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentation"
|
msgstr "Documentation"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Panneau d'administration"
|
msgstr "Panneau d'administration"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -788,7 +788,7 @@ msgstr "יישום לנייד"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "דוקומנטציה"
|
msgstr "דוקומנטציה"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -829,7 +829,7 @@ msgstr "मोबाइल एप्लीकेशन"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "प्रलेखन"
|
msgstr "प्रलेखन"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "व्यवस्थापन डैशबोर्ड"
|
msgstr "व्यवस्थापन डैशबोर्ड"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -812,7 +812,7 @@ msgstr "Aplikasi Gawai"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentasi"
|
msgstr "Dokumentasi"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Dasbor Administrasi"
|
msgstr "Dasbor Administrasi"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -817,7 +817,7 @@ msgstr "Applicazione mobile"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentazione"
|
msgstr "Documentazione"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Cruscotto Amministrazione"
|
msgstr "Cruscotto Amministrazione"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
||||||
"PO-Revision-Date: 2020-11-11 16:28+0000\n"
|
"PO-Revision-Date: 2024-06-24 15:09+0000\n"
|
||||||
"Last-Translator: Jwen921 <yangjingwen0921@gmail.com>\n"
|
"Last-Translator: Khang Tran <tranchikhang@outlook.com>\n"
|
||||||
|
"Language-Team: Japanese <https://hosted.weblate.org/projects/i-hate-money/"
|
||||||
|
"i-hate-money/ja/>\n"
|
||||||
"Language: ja\n"
|
"Language: ja\n"
|
||||||
"Language-Team: Japanese <https://hosted.weblate.org/projects/i-hate-"
|
|
||||||
"money/i-hate-money/ja/>\n"
|
|
||||||
"Plural-Forms: nplurals=1; plural=0\n"
|
|
||||||
"MIME-Version: 1.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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
"X-Generator: Weblate 5.6-rc\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -27,19 +27,17 @@ msgstr "無効な入力です。数字と「+ - * / 」の演算子しか入力
|
||||||
msgid "Project name"
|
msgid "Project name"
|
||||||
msgstr "プロジェクトの名前"
|
msgstr "プロジェクトの名前"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Current private code"
|
msgid "Current private code"
|
||||||
msgstr "暗証コード"
|
msgstr "現在の暗証コード"
|
||||||
|
|
||||||
msgid "Enter existing private code to edit project"
|
msgid "Enter existing private code to edit project"
|
||||||
msgstr ""
|
msgstr "プロジェクトを編集するために、暗証コードを入力してください"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "New private code"
|
msgid "New private code"
|
||||||
msgstr "暗証コード"
|
msgstr "新暗証コード"
|
||||||
|
|
||||||
msgid "Enter a new code if you want to change it"
|
msgid "Enter a new code if you want to change it"
|
||||||
msgstr ""
|
msgstr "変更するために、新しい暗証コードを入力してください"
|
||||||
|
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "メールアドレス"
|
msgstr "メールアドレス"
|
||||||
|
@ -54,15 +52,13 @@ msgid "Default Currency"
|
||||||
msgstr "初期設定にする通貨"
|
msgstr "初期設定にする通貨"
|
||||||
|
|
||||||
msgid "Setting a default currency enables currency conversion between bills"
|
msgid "Setting a default currency enables currency conversion between bills"
|
||||||
msgstr ""
|
msgstr "明細通貨変換のため、デフォルトの通貨を設定してください"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Unknown error"
|
msgid "Unknown error"
|
||||||
msgstr "未知のプロジェクト"
|
msgstr "不明エラー"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Invalid private code."
|
msgid "Invalid private code."
|
||||||
msgstr "暗証コード"
|
msgstr "無効な暗証コード。"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"This project cannot be set to 'no currency' because it contains bills in "
|
"This project cannot be set to 'no currency' because it contains bills in "
|
||||||
|
@ -179,7 +175,7 @@ msgid "This project already have this participant"
|
||||||
msgstr "プロジェクトはすでにこのメンバーを含めています"
|
msgstr "プロジェクトはすでにこのメンバーを含めています"
|
||||||
|
|
||||||
msgid "People to notify"
|
msgid "People to notify"
|
||||||
msgstr ""
|
msgstr "通知したい人"
|
||||||
|
|
||||||
msgid "Send the invitations"
|
msgid "Send the invitations"
|
||||||
msgstr "招待状を送る"
|
msgstr "招待状を送る"
|
||||||
|
@ -194,11 +190,12 @@ msgstr "ログアウト"
|
||||||
msgid "Please check the email configuration of the server."
|
msgid "Please check the email configuration of the server."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Please check the email configuration of the server or contact the "
|
"Please check the email configuration of the server or contact the "
|
||||||
"administrator: %(admin_email)s"
|
"administrator: %(admin_email)s"
|
||||||
msgstr "申し訳ございませんが、招待メールを送ったとき、エラーが発生しました。メールアドレスを再度チェックするかまたは管理者に連絡ください。"
|
msgstr "申し訳ございませんが、エラーが発生しました。メールアドレスを再度チェックする"
|
||||||
|
"か、または管理者( %(admin_email)s)に連絡ください"
|
||||||
|
|
||||||
#. List with two items only
|
#. List with two items only
|
||||||
msgid "{dual_object_0} and {dual_object_1}"
|
msgid "{dual_object_0} and {dual_object_1}"
|
||||||
|
@ -271,7 +268,7 @@ msgid "Project settings have been changed successfully."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Unable to parse CSV"
|
msgid "Unable to parse CSV"
|
||||||
msgstr ""
|
msgstr "CSVを読み込むことができません"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Missing attribute: %(attribute)s"
|
msgid "Missing attribute: %(attribute)s"
|
||||||
|
@ -292,7 +289,7 @@ msgid "Error deleting project"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Unable to logout"
|
msgid "Unable to logout"
|
||||||
msgstr ""
|
msgstr "ログアウトできません"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You have been invited to share your expenses for %(project)s"
|
msgid "You have been invited to share your expenses for %(project)s"
|
||||||
|
@ -353,9 +350,8 @@ msgstr ""
|
||||||
msgid "Error deleting project history"
|
msgid "Error deleting project history"
|
||||||
msgstr "プロジェクトの歴史を有効にする"
|
msgstr "プロジェクトの歴史を有効にする"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Deleted project history."
|
msgid "Deleted project history."
|
||||||
msgstr "プロジェクトの歴史を有効にする"
|
msgstr "プロジェクトの歴史を削除しました。"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "Error deleting recorded IP addresses"
|
msgid "Error deleting recorded IP addresses"
|
||||||
|
@ -574,9 +570,8 @@ msgstr ""
|
||||||
msgid "This project has history disabled. New actions won't appear below."
|
msgid "This project has history disabled. New actions won't appear below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "You can enable history on the settings page."
|
msgid "You can enable history on the settings page."
|
||||||
msgstr "設定ページでIPアドレス記録を編集可能にすることができる"
|
msgstr "設定ページでIPアドレス記録を編集可能にすることができる。"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"The table below reflects actions recorded prior to disabling project "
|
"The table below reflects actions recorded prior to disabling project "
|
||||||
|
@ -622,13 +617,13 @@ msgstr "設定ページでIPアドレス記録を編集不可にすることが
|
||||||
msgid "From IP"
|
msgid "From IP"
|
||||||
msgstr "IPから"
|
msgstr "IPから"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Project %(name)s added"
|
msgid "Project %(name)s added"
|
||||||
msgstr "プロジェクトの名前"
|
msgstr "プロジェクト%(name)sが作成されました"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s added"
|
msgid "Bill %(name)s added"
|
||||||
msgstr "明細が追加されました"
|
msgstr "%(name)s明細が追加されました"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s added"
|
msgid "Participant %(name)s added"
|
||||||
|
@ -641,9 +636,9 @@ msgstr "プロジェクトの私用コードが変更された"
|
||||||
msgid "Project renamed to %(new_project_name)s"
|
msgid "Project renamed to %(new_project_name)s"
|
||||||
msgstr "プロジェクト名は%(new_project_name)s"
|
msgstr "プロジェクト名は%(new_project_name)s"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Project contact email changed to %(new_email)s"
|
msgid "Project contact email changed to %(new_email)s"
|
||||||
msgstr "プロジェクトの連絡メールが…に変更された"
|
msgstr "プロジェクトの連絡メールが%(new_email)sに変更されました"
|
||||||
|
|
||||||
msgid "Project settings modified"
|
msgid "Project settings modified"
|
||||||
msgstr "プロジェクトの設定が修正された"
|
msgstr "プロジェクトの設定が修正された"
|
||||||
|
@ -681,9 +676,9 @@ msgstr "日付"
|
||||||
msgid "Amount in %(currency)s"
|
msgid "Amount in %(currency)s"
|
||||||
msgstr "%(currency)sでの金額"
|
msgstr "%(currency)sでの金額"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s modified"
|
msgid "Bill %(name)s modified"
|
||||||
msgstr "明細が変更されました"
|
msgstr "%(name)s明細が変更されました"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s modified"
|
msgid "Participant %(name)s modified"
|
||||||
|
@ -697,17 +692,17 @@ msgstr "ユーザー%(name)sが既に取り除かれました"
|
||||||
msgid "Participant %(name)s removed"
|
msgid "Participant %(name)s removed"
|
||||||
msgstr "ユーザー%(name)sが既に取り除かれました"
|
msgstr "ユーザー%(name)sが既に取り除かれました"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Project %(name)s changed in an unknown way"
|
msgid "Project %(name)s changed in an unknown way"
|
||||||
msgstr "未知の方法で変更された"
|
msgstr "プロジェクト%(name)sが不明な方法で変更されました"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s changed in an unknown way"
|
msgid "Bill %(name)s changed in an unknown way"
|
||||||
msgstr "未知の方法で変更された"
|
msgstr "明細%(name)sが不明な方法で変更されました"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s changed in an unknown way"
|
msgid "Participant %(name)s changed in an unknown way"
|
||||||
msgstr "未知の方法で変更された"
|
msgstr "参加者%(name)sが不明な方法で変更されました"
|
||||||
|
|
||||||
msgid "Nothing to list"
|
msgid "Nothing to list"
|
||||||
msgstr "表示できるものがない"
|
msgstr "表示できるものがない"
|
||||||
|
@ -802,7 +797,7 @@ msgstr "携帯アプリ"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "書類"
|
msgstr "書類"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "管理ダッシュボード"
|
msgstr "管理ダッシュボード"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
@ -904,14 +899,12 @@ msgstr ""
|
||||||
msgid "Send via Emails"
|
msgid "Send via Emails"
|
||||||
msgstr "メールで送る"
|
msgstr "メールで送る"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Specify a list of email adresses (separated by comma) of people you want "
|
"Specify a list of email adresses (separated by comma) of people you want "
|
||||||
"to notify about the creation of this project. We will send them an email "
|
"to notify about the creation of this project. We will send them an email "
|
||||||
"with the invitation link."
|
"with the invitation link."
|
||||||
msgstr ""
|
msgstr "知らせたいメールアドレスのリスト(カンマ区切り)を指定してください。メールで"
|
||||||
"…を知らせたいメールアドレスのリストを特定する(カンマ区切り)\n"
|
"招待リンクを送信します。"
|
||||||
"彼らにこの予算管理プロジェクトの作成をメールでお知らせします。"
|
|
||||||
|
|
||||||
msgid "Share Identifier & code"
|
msgid "Share Identifier & code"
|
||||||
msgstr "名前とコードを共有する"
|
msgstr "名前とコードを共有する"
|
||||||
|
@ -926,9 +919,8 @@ msgstr ""
|
||||||
msgid "Identifier:"
|
msgid "Identifier:"
|
||||||
msgstr "名前:"
|
msgstr "名前:"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Private code:"
|
msgid "Private code:"
|
||||||
msgstr "暗証コード"
|
msgstr "暗証コード:"
|
||||||
|
|
||||||
msgid "the private code was defined when you created the project"
|
msgid "the private code was defined when you created the project"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1109,4 +1101,3 @@ msgstr "期間"
|
||||||
|
|
||||||
#~ msgid "You can directly share the following link via your prefered medium"
|
#~ msgid "You can directly share the following link via your prefered medium"
|
||||||
#~ msgstr "好きの手段で以下のリンクを直接に共有できる"
|
#~ msgstr "好きの手段で以下のリンクを直接に共有できる"
|
||||||
|
|
||||||
|
|
|
@ -793,7 +793,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -793,7 +793,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -855,7 +855,7 @@ msgstr "Mobilprogram"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentasjon"
|
msgstr "Dokumentasjon"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Administrasjonsoversiktspanel"
|
msgstr "Administrasjonsoversiktspanel"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
|
|
@ -814,7 +814,7 @@ msgstr "Mobiele app"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentatie"
|
msgstr "Documentatie"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Administratie-overzicht"
|
msgstr "Administratie-overzicht"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
|
|
932
ihatemoney/translations/oc/LC_MESSAGES/messages.po
Normal file
932
ihatemoney/translations/oc/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,932 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-06-15 16:06+0200\n"
|
||||||
|
"PO-Revision-Date: 2024-07-03 19:09+0000\n"
|
||||||
|
"Last-Translator: Quentin PAGÈS <quentinantonin@free.fr>\n"
|
||||||
|
"Language-Team: Occitan <https://hosted.weblate.org/projects/i-hate-money/"
|
||||||
|
"i-hate-money/oc/>\n"
|
||||||
|
"Language: oc\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 5.7-dev\n"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "You have just created '%(project)s' to share your expenses"
|
||||||
|
msgstr "Venètz de crear « %(project)s » per despartir vòstras despensas"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||||
|
"accepted."
|
||||||
|
msgstr ""
|
||||||
|
"Quantitat o expression non valida. Sonque los nombre e operator +-*/ son "
|
||||||
|
"acceptats."
|
||||||
|
|
||||||
|
msgid "Project name"
|
||||||
|
msgstr "Nom del projècte"
|
||||||
|
|
||||||
|
msgid "Current private code"
|
||||||
|
msgstr "Còdi d’accès actual"
|
||||||
|
|
||||||
|
msgid "Enter existing private code to edit project"
|
||||||
|
msgstr "Picatz lo còdi d’accès existissent per editar lo projècte"
|
||||||
|
|
||||||
|
msgid "New private code"
|
||||||
|
msgstr "Còdi privat novèl"
|
||||||
|
|
||||||
|
msgid "Enter a new code if you want to change it"
|
||||||
|
msgstr "Picatz lo còdi novèl se lo volètz cambiar"
|
||||||
|
|
||||||
|
msgid "Email"
|
||||||
|
msgstr "Adreça electronica"
|
||||||
|
|
||||||
|
msgid "Enable project history"
|
||||||
|
msgstr "Activar l’istoric de projècte"
|
||||||
|
|
||||||
|
msgid "Use IP tracking for project history"
|
||||||
|
msgstr "Reculhir las adreças IP dins l’istoric de projècte"
|
||||||
|
|
||||||
|
msgid "Default Currency"
|
||||||
|
msgstr "Moneda predeterminada"
|
||||||
|
|
||||||
|
msgid "Setting a default currency enables currency conversion between bills"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unknown error"
|
||||||
|
msgstr "Error desconeguda"
|
||||||
|
|
||||||
|
msgid "Invalid private code."
|
||||||
|
msgstr "Còdi d’accès invalid."
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"This project cannot be set to 'no currency' because it contains bills in "
|
||||||
|
"multiple currencies."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Compatible with Cospend"
|
||||||
|
msgstr "Compatible amb Cospend"
|
||||||
|
|
||||||
|
msgid "Project identifier"
|
||||||
|
msgstr "Identificant del projècte"
|
||||||
|
|
||||||
|
msgid "Private code"
|
||||||
|
msgstr "Còdi privat"
|
||||||
|
|
||||||
|
msgid "Create the project"
|
||||||
|
msgstr "Crear lo projècte"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"A project with this identifier (\"%(project)s\") already exists. Please "
|
||||||
|
"choose a new identifier"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Which is a real currency: Euro or Petro dollar?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "euro"
|
||||||
|
msgstr "èuro"
|
||||||
|
|
||||||
|
msgid "Please, validate the captcha to proceed."
|
||||||
|
msgstr "Se vos plai, validatz el captcha per contunhar."
|
||||||
|
|
||||||
|
msgid "Enter private code to confirm deletion"
|
||||||
|
msgstr "Picatz lo còdi d’accès per confirmar la supression"
|
||||||
|
|
||||||
|
msgid "Get in"
|
||||||
|
msgstr "Dintrar"
|
||||||
|
|
||||||
|
msgid "Admin password"
|
||||||
|
msgstr "Senhal d’administracion"
|
||||||
|
|
||||||
|
msgid "Send me the code by email"
|
||||||
|
msgstr "Mandatz-me lo còdi per corrièl"
|
||||||
|
|
||||||
|
msgid "This project does not exists"
|
||||||
|
msgstr "Aqueste projècte existís pas"
|
||||||
|
|
||||||
|
msgid "Password mismatch"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Password"
|
||||||
|
msgstr "Senhal"
|
||||||
|
|
||||||
|
msgid "Password confirmation"
|
||||||
|
msgstr "Confirmacion del senhla"
|
||||||
|
|
||||||
|
msgid "Reset password"
|
||||||
|
msgstr "Reïnicializar lo senhal"
|
||||||
|
|
||||||
|
msgid "When?"
|
||||||
|
msgstr "Quand ?"
|
||||||
|
|
||||||
|
msgid "What?"
|
||||||
|
msgstr "Qué ?"
|
||||||
|
|
||||||
|
msgid "Who paid?"
|
||||||
|
msgstr "Qual paguèt ?"
|
||||||
|
|
||||||
|
msgid "How much?"
|
||||||
|
msgstr "Quant ?"
|
||||||
|
|
||||||
|
msgid "Currency"
|
||||||
|
msgstr "Moneda"
|
||||||
|
|
||||||
|
msgid "External link"
|
||||||
|
msgstr "Ligam extèrne"
|
||||||
|
|
||||||
|
msgid "A link to an external document, related to this bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "For whom?"
|
||||||
|
msgstr "Per qual ?"
|
||||||
|
|
||||||
|
msgid "Submit"
|
||||||
|
msgstr "Enviar"
|
||||||
|
|
||||||
|
msgid "Submit and add a new one"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Project default: %(currency)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nom"
|
||||||
|
|
||||||
|
msgid "Weights should be positive"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Weight"
|
||||||
|
msgstr "Pes"
|
||||||
|
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "Apondre"
|
||||||
|
|
||||||
|
msgid "The participant name is invalid"
|
||||||
|
msgstr "Lo nom del participant es incorrècte"
|
||||||
|
|
||||||
|
msgid "This project already have this participant"
|
||||||
|
msgstr "Aqueste projècte a ja aqueste participant"
|
||||||
|
|
||||||
|
msgid "People to notify"
|
||||||
|
msgstr "Personas de convidar"
|
||||||
|
|
||||||
|
msgid "Send the invitations"
|
||||||
|
msgstr "Enviar las invitacions"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "The email %(email)s is not valid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr "Desconnexion"
|
||||||
|
|
||||||
|
msgid "Please check the email configuration of the server."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"Please check the email configuration of the server or contact the "
|
||||||
|
"administrator: %(admin_email)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. List with two items only
|
||||||
|
msgid "{dual_object_0} and {dual_object_1}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Last two items of a list with more than 3 items
|
||||||
|
msgid "{previous_object}, and {end_object}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Two items in a middle of a list with more than 5 objects
|
||||||
|
msgid "{previous_object}, {next_object}"
|
||||||
|
msgstr "{previous_object}, {next_object}"
|
||||||
|
|
||||||
|
#. First two items of a list with more than 3 items
|
||||||
|
msgid "{start_object}, {next_object}"
|
||||||
|
msgstr "{start_object}, {next_object}"
|
||||||
|
|
||||||
|
msgid "No Currency"
|
||||||
|
msgstr "Cap de moneda"
|
||||||
|
|
||||||
|
#. Form error with only one error
|
||||||
|
msgid "{prefix}: {error}"
|
||||||
|
msgstr "{prefix} : {error}"
|
||||||
|
|
||||||
|
#. Form error with a list of errors
|
||||||
|
msgid "{prefix}:<br />{errors}"
|
||||||
|
msgstr "{prefix} :<br />{errors}"
|
||||||
|
|
||||||
|
msgid "Too many failed login attempts."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "This admin password is not the right one. Only %(num)d attempts left."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Provided token is invalid"
|
||||||
|
msgstr "Aqueste geton es invalid"
|
||||||
|
|
||||||
|
msgid "This private code is not the right one"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "A reminder email has just been sent to you"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"We tried to send you an reminder email, but there was an error. You can "
|
||||||
|
"still use the project normally."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Sorry, there was an error while sending you an email with password reset "
|
||||||
|
"instructions."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "No token provided"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Invalid token"
|
||||||
|
msgstr "Geton invalid"
|
||||||
|
|
||||||
|
msgid "Unknown project"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Password successfully reset."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Project settings have been changed successfully."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unable to parse CSV"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Missing attribute: %(attribute)s"
|
||||||
|
msgstr "Atribut mancant : %(attribute)s"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Cannot add bills in multiple currencies to a project without default "
|
||||||
|
"currency"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Project successfully uploaded"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Project successfully deleted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Error deleting project"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unable to logout"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "You have been invited to share your expenses for %(project)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Your invitations have been sent"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Sorry, there was an error while trying to send the invitation emails."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "%(member)s has been added"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Error activating participant"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s is part of this project again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Error removing participant"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"Participant '%(name)s' has been deactivated. It will still appear in the "
|
||||||
|
"list until its balance reach zero."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant '%(name)s' has been removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant '%(name)s' has been modified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "The bill has been added"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Error deleting bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "The bill has been deleted"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "The bill has been modified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "%(lang)s is not a supported language"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Error deleting project history"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Deleted project history."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Error deleting recorded IP addresses"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Deleted recorded IP addresses in project history."
|
||||||
|
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 "Authentication"
|
||||||
|
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 "Project"
|
||||||
|
msgstr "Projècte"
|
||||||
|
|
||||||
|
msgid "Number of participants"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Number of bills"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Newest bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Oldest bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Actions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "edit"
|
||||||
|
msgstr "modifica"
|
||||||
|
|
||||||
|
msgid "Delete project"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "show"
|
||||||
|
msgstr "mostrar"
|
||||||
|
|
||||||
|
msgid "The Dashboard is currently deactivated."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Download Mobile Application"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Get it on"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Edit project"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Import project"
|
||||||
|
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 "Anullar"
|
||||||
|
|
||||||
|
msgid "Privacy Settings"
|
||||||
|
msgstr "Paramètres de confidencialitat"
|
||||||
|
|
||||||
|
msgid "Save changes"
|
||||||
|
msgstr "Enregistrar las modificacions"
|
||||||
|
|
||||||
|
msgid "This will remove all bills and participants in this project!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Import previously exported project"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Choose file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Edit this bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Add a bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Simple operations are allowed, e.g. (18+36.2)/3"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Everyone"
|
||||||
|
msgstr "Tot lo monde"
|
||||||
|
|
||||||
|
msgid "No one"
|
||||||
|
msgstr "Degun"
|
||||||
|
|
||||||
|
msgid "More options"
|
||||||
|
msgstr "Mai d'opcions"
|
||||||
|
|
||||||
|
msgid "Add participant"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Edit this participant"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "john.doe@example.com, mary.moe@site.com"
|
||||||
|
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 ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s: %(property_name)s changed from %(before)s to %(after)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s: %(property_name)s changed to %(after)s"
|
||||||
|
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 "Confirm deletion"
|
||||||
|
msgstr "Confirmar la supression"
|
||||||
|
|
||||||
|
msgid "Close"
|
||||||
|
msgstr "Tampar"
|
||||||
|
|
||||||
|
msgid "Delete Confirmation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Are you sure you want to erase all history for this project? This action "
|
||||||
|
"cannot be undone."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s: added %(owers_list_str)s to owers list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s: removed %(owers_list_str)s from owers list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "This project has history disabled. New actions won't appear below."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "You can enable history on the settings page."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"The table below reflects actions recorded prior to disabling project "
|
||||||
|
"history."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "You can clear the project history to remove them."
|
||||||
|
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 IP Addresses to erase"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Delete Stored IP Addresses"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "No history to erase"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Clear Project History"
|
||||||
|
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 ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Project %(name)s added"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s added"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s added"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Project private code changed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Project renamed to %(new_project_name)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Project contact email changed to %(new_email)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Project settings modified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s deactivated"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s reactivated"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s renamed to %(new_name)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s renamed to %(new_description)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s: weight changed from %(old_weight)s to %(new_weight)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Payer"
|
||||||
|
msgstr "Pagaire"
|
||||||
|
|
||||||
|
msgid "Amount"
|
||||||
|
msgstr "Soma"
|
||||||
|
|
||||||
|
msgid "Date"
|
||||||
|
msgstr "Data"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Amount in %(currency)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s modified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s modified"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s removed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Project %(name)s changed in an unknown way"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Bill %(name)s changed in an unknown way"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Participant %(name)s changed in an unknown way"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Nothing to list"
|
||||||
|
msgstr "Pas res a listar"
|
||||||
|
|
||||||
|
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 "Connexion"
|
||||||
|
|
||||||
|
msgid "can't remember your password?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Crear"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Don\\'t reuse a personal password. Choose a private code and send it to "
|
||||||
|
"your friends"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Account manager"
|
||||||
|
msgstr "Gestionari de compte"
|
||||||
|
|
||||||
|
msgid "Bills"
|
||||||
|
msgstr "Facturas"
|
||||||
|
|
||||||
|
msgid "Settle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Statistics"
|
||||||
|
msgstr "Estatisticas"
|
||||||
|
|
||||||
|
msgid "Languages"
|
||||||
|
msgstr "Lengas"
|
||||||
|
|
||||||
|
msgid "Projects"
|
||||||
|
msgstr "Projèctes"
|
||||||
|
|
||||||
|
msgid "Start a new project"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "RSS Feed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Other projects :"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "switch to"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Dashboard"
|
||||||
|
msgstr "Panèl d’administracion"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Please retry after %(date)s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Code"
|
||||||
|
msgstr "Còdi"
|
||||||
|
|
||||||
|
msgid "Mobile Application"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Documentation"
|
||||||
|
msgstr "Documentacion"
|
||||||
|
|
||||||
|
msgid "Administration Dashboard"
|
||||||
|
msgstr "Panèl d’administracion"
|
||||||
|
|
||||||
|
msgid "Legal information"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "\"I hate money\" is free software"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "you can contribute and improve it!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "%(amount)s each"
|
||||||
|
msgstr "%(amount)s cadun"
|
||||||
|
|
||||||
|
msgid "you sure?"
|
||||||
|
msgstr "O volètz vertadièrament ?"
|
||||||
|
|
||||||
|
msgid "Invite people"
|
||||||
|
msgstr "Convidar de monde"
|
||||||
|
|
||||||
|
msgid "Newer bills"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Older bills"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "You should start by adding participants"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Add a new bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "For what?"
|
||||||
|
msgstr "Per qué ?"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Added on %(date)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-format
|
||||||
|
msgid "Everyone but %(excluded)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "delete"
|
||||||
|
msgstr "suprimir"
|
||||||
|
|
||||||
|
msgid "No bills"
|
||||||
|
msgstr "Cap de factura"
|
||||||
|
|
||||||
|
msgid "Nothing to list yet."
|
||||||
|
msgstr "Pas res a listar pel moment."
|
||||||
|
|
||||||
|
msgid "Add your first bill"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Add the first participant"
|
||||||
|
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 an invitation link"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"The easiest way to invite people is to give them the following invitation"
|
||||||
|
" link.<br />They will be able to access the project, manage participants,"
|
||||||
|
" add/edit/delete bills. However, they will not have access to important "
|
||||||
|
"settings such as changing the private code or deleting the whole project."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Scan QR code"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use a mobile device with a compatible app."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Send via Emails"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Specify a list of email adresses (separated by comma) of people you want "
|
||||||
|
"to notify about the creation of this project. We will send them an email "
|
||||||
|
"with the invitation link."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Share Identifier & code"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"You can share the project identifier and the private code by any "
|
||||||
|
"communication means.<br />Anyone with the private code will have access "
|
||||||
|
"to the full project, including changing settings such as the private code"
|
||||||
|
" or project email address, or even deleting the whole project."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Identifier:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Private code:"
|
||||||
|
msgstr "Còdi privat :"
|
||||||
|
|
||||||
|
msgid "the private code was defined when you created the project"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Who pays?"
|
||||||
|
msgstr "Qual paga ?"
|
||||||
|
|
||||||
|
msgid "To whom?"
|
||||||
|
msgstr "A qual ?"
|
||||||
|
|
||||||
|
msgid "Who?"
|
||||||
|
msgstr "Qual ?"
|
||||||
|
|
||||||
|
msgid "Balance"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "deactivate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "reactivate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Paid"
|
||||||
|
msgstr "Pagat"
|
||||||
|
|
||||||
|
msgid "Spent"
|
||||||
|
msgstr "Despensat"
|
||||||
|
|
||||||
|
msgid "Expenses by Month"
|
||||||
|
msgstr "Despensas per mes"
|
||||||
|
|
||||||
|
msgid "Period"
|
||||||
|
msgstr "Periòde"
|
|
@ -812,7 +812,7 @@ msgstr "Aplikacja mobilna"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentacja"
|
msgstr "Dokumentacja"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Kokpit administracyjny"
|
msgstr "Kokpit administracyjny"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
||||||
"PO-Revision-Date: 2023-05-05 00:47+0000\n"
|
"PO-Revision-Date: 2024-05-10 07:26+0000\n"
|
||||||
"Last-Translator: MurkBRA <anjo1077@gmail.com>\n"
|
"Last-Translator: Gesiane Pajarinen <gesianef@hotmail.com>\n"
|
||||||
|
"Language-Team: Portuguese <https://hosted.weblate.org/projects/i-hate-money/"
|
||||||
|
"i-hate-money/pt/>\n"
|
||||||
"Language: pt\n"
|
"Language: pt\n"
|
||||||
"Language-Team: Portuguese <https://hosted.weblate.org/projects/i-hate-"
|
|
||||||
"money/i-hate-money/pt/>\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=n > 1\n"
|
|
||||||
"MIME-Version: 1.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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||||
|
"X-Generator: Weblate 5.5.4-rc\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -34,7 +34,7 @@ msgid "Current private code"
|
||||||
msgstr "Código privado novo"
|
msgstr "Código privado novo"
|
||||||
|
|
||||||
msgid "Enter existing private code to edit project"
|
msgid "Enter existing private code to edit project"
|
||||||
msgstr ""
|
msgstr "Insira o código privado existente para editar o projeto"
|
||||||
|
|
||||||
msgid "New private code"
|
msgid "New private code"
|
||||||
msgstr "Código privado novo"
|
msgstr "Código privado novo"
|
||||||
|
@ -71,7 +71,7 @@ msgstr ""
|
||||||
" em várias moedas."
|
" em várias moedas."
|
||||||
|
|
||||||
msgid "Compatible with Cospend"
|
msgid "Compatible with Cospend"
|
||||||
msgstr ""
|
msgstr "Compatível com Cospend"
|
||||||
|
|
||||||
msgid "Project identifier"
|
msgid "Project identifier"
|
||||||
msgstr "Identificador do projeto"
|
msgstr "Identificador do projeto"
|
||||||
|
@ -192,7 +192,7 @@ msgid "Logout"
|
||||||
msgstr "Sair"
|
msgstr "Sair"
|
||||||
|
|
||||||
msgid "Please check the email configuration of the server."
|
msgid "Please check the email configuration of the server."
|
||||||
msgstr ""
|
msgstr "Verifique a configuração de e-mail do servidor."
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
|
@ -279,14 +279,14 @@ msgid "Password successfully reset."
|
||||||
msgstr "Palavra-passe redefinida corretamente."
|
msgstr "Palavra-passe redefinida corretamente."
|
||||||
|
|
||||||
msgid "Project settings have been changed successfully."
|
msgid "Project settings have been changed successfully."
|
||||||
msgstr ""
|
msgstr "As configurações do projeto foram alteradas com sucesso."
|
||||||
|
|
||||||
msgid "Unable to parse CSV"
|
msgid "Unable to parse CSV"
|
||||||
msgstr ""
|
msgstr "Não foi possível processar o CSV"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Missing attribute: %(attribute)s"
|
msgid "Missing attribute: %(attribute)s"
|
||||||
msgstr ""
|
msgstr "Faltando o atributo: %(attribute)s"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Cannot add bills in multiple currencies to a project without default "
|
"Cannot add bills in multiple currencies to a project without default "
|
||||||
|
@ -305,7 +305,7 @@ msgid "Error deleting project"
|
||||||
msgstr "Erro ao apagar o projeto"
|
msgstr "Erro ao apagar o projeto"
|
||||||
|
|
||||||
msgid "Unable to logout"
|
msgid "Unable to logout"
|
||||||
msgstr ""
|
msgstr "Não é possível sair"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You have been invited to share your expenses for %(project)s"
|
msgid "You have been invited to share your expenses for %(project)s"
|
||||||
|
@ -365,7 +365,7 @@ msgstr "A fatura foi modificada"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(lang)s is not a supported language"
|
msgid "%(lang)s is not a supported language"
|
||||||
msgstr ""
|
msgstr "Não temos configuração para o idioma %(lang)s"
|
||||||
|
|
||||||
msgid "Error deleting project history"
|
msgid "Error deleting project history"
|
||||||
msgstr "Erro ao apagar o histórico do projeto"
|
msgstr "Erro ao apagar o histórico do projeto"
|
||||||
|
@ -476,7 +476,7 @@ msgid "Privacy Settings"
|
||||||
msgstr "Configurações de Privacidade"
|
msgstr "Configurações de Privacidade"
|
||||||
|
|
||||||
msgid "Save changes"
|
msgid "Save changes"
|
||||||
msgstr ""
|
msgstr "Salvar as alterações"
|
||||||
|
|
||||||
msgid "This will remove all bills and participants in this project!"
|
msgid "This will remove all bills and participants in this project!"
|
||||||
msgstr "Isso removerá todas as faturas e os participantes deste projeto!"
|
msgstr "Isso removerá todas as faturas e os participantes deste projeto!"
|
||||||
|
@ -495,7 +495,7 @@ msgid "Add a bill"
|
||||||
msgstr "Adicionar uma fatura"
|
msgstr "Adicionar uma fatura"
|
||||||
|
|
||||||
msgid "Simple operations are allowed, e.g. (18+36.2)/3"
|
msgid "Simple operations are allowed, e.g. (18+36.2)/3"
|
||||||
msgstr ""
|
msgstr "Operações simples são permitidas, por ex. (18+36,2)/3"
|
||||||
|
|
||||||
msgid "Everyone"
|
msgid "Everyone"
|
||||||
msgstr "Todos"
|
msgstr "Todos"
|
||||||
|
@ -587,6 +587,7 @@ msgstr "Fatura %(name)s: removido %(owers_list_str)s da lista de proprietários"
|
||||||
|
|
||||||
msgid "This project has history disabled. New actions won't appear below."
|
msgid "This project has history disabled. New actions won't appear below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Este projeto tem o histórico desativado. Novas ações não aparecerão abaixo."
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "You can enable history on the settings page."
|
msgid "You can enable history on the settings page."
|
||||||
|
@ -596,6 +597,8 @@ msgid ""
|
||||||
"The table below reflects actions recorded prior to disabling project "
|
"The table below reflects actions recorded prior to disabling project "
|
||||||
"history."
|
"history."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"A tabela abaixo contém as ações registradas antes da desativação do "
|
||||||
|
"histórico do projeto."
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "You can clear the project history to remove them."
|
msgid "You can clear the project history to remove them."
|
||||||
|
@ -796,7 +799,7 @@ msgid "Settings"
|
||||||
msgstr "Configurações"
|
msgstr "Configurações"
|
||||||
|
|
||||||
msgid "RSS Feed"
|
msgid "RSS Feed"
|
||||||
msgstr ""
|
msgstr "RSS Feed"
|
||||||
|
|
||||||
msgid "Other projects :"
|
msgid "Other projects :"
|
||||||
msgstr "Outros projetos:"
|
msgstr "Outros projetos:"
|
||||||
|
@ -809,7 +812,7 @@ msgstr "Painel de controle"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please retry after %(date)s."
|
msgid "Please retry after %(date)s."
|
||||||
msgstr ""
|
msgstr "Por favor, tente novamente após %(date)s."
|
||||||
|
|
||||||
msgid "Code"
|
msgid "Code"
|
||||||
msgstr "Código"
|
msgstr "Código"
|
||||||
|
@ -820,7 +823,7 @@ msgstr "Aplicação Mobile"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentação"
|
msgstr "Documentação"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Painel de Administração"
|
msgstr "Painel de Administração"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
@ -905,7 +908,7 @@ msgid "Invite people to join this project"
|
||||||
msgstr "Convide pessoas para participar deste projeto"
|
msgstr "Convide pessoas para participar deste projeto"
|
||||||
|
|
||||||
msgid "Share an invitation link"
|
msgid "Share an invitation link"
|
||||||
msgstr ""
|
msgstr "Compartilhe um link do convite"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"The easiest way to invite people is to give them the following invitation"
|
"The easiest way to invite people is to give them the following invitation"
|
||||||
|
@ -913,12 +916,17 @@ msgid ""
|
||||||
" add/edit/delete bills. However, they will not have access to important "
|
" add/edit/delete bills. However, they will not have access to important "
|
||||||
"settings such as changing the private code or deleting the whole project."
|
"settings such as changing the private code or deleting the whole project."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"A maneira mais fácil de convidar as pessoas é compartilhando o seguinte link "
|
||||||
|
"do convite.<br />Eles poderão acessar o projeto, gerenciar participantes, "
|
||||||
|
"adicionar/editar/excluir contas. No entanto, eles não terão acesso a "
|
||||||
|
"configurações importantes, como alterar o código privado ou excluir todo o "
|
||||||
|
"projeto."
|
||||||
|
|
||||||
msgid "Scan QR code"
|
msgid "Scan QR code"
|
||||||
msgstr ""
|
msgstr "Escanear o código QR"
|
||||||
|
|
||||||
msgid "Use a mobile device with a compatible app."
|
msgid "Use a mobile device with a compatible app."
|
||||||
msgstr ""
|
msgstr "Use um telefone celular ou tablet com um aplicativo compatível."
|
||||||
|
|
||||||
msgid "Send via Emails"
|
msgid "Send via Emails"
|
||||||
msgstr "Enviar via E-mails"
|
msgstr "Enviar via E-mails"
|
||||||
|
@ -943,6 +951,11 @@ msgid ""
|
||||||
"to the full project, including changing settings such as the private code"
|
"to the full project, including changing settings such as the private code"
|
||||||
" or project email address, or even deleting the whole project."
|
" or project email address, or even deleting the whole project."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Você pode compartilhar o identificador do projeto e o código privado por "
|
||||||
|
"qualquer meio de comunicação.<br />Qualquer pessoa com o código privado terá "
|
||||||
|
"acesso a todo o projeto, incluindo a alteração de configurações como o "
|
||||||
|
"código privado ou o endereço do e-mail, ou até mesmo a exclusão de todo o "
|
||||||
|
"projeto."
|
||||||
|
|
||||||
msgid "Identifier:"
|
msgid "Identifier:"
|
||||||
msgstr "Identificador:"
|
msgstr "Identificador:"
|
||||||
|
@ -952,7 +965,7 @@ msgid "Private code:"
|
||||||
msgstr "Código privado"
|
msgstr "Código privado"
|
||||||
|
|
||||||
msgid "the private code was defined when you created the project"
|
msgid "the private code was defined when you created the project"
|
||||||
msgstr ""
|
msgstr "o código privado foi definido quando você criou o projeto"
|
||||||
|
|
||||||
msgid "Who pays?"
|
msgid "Who pays?"
|
||||||
msgstr "Quem paga?"
|
msgstr "Quem paga?"
|
||||||
|
@ -1140,4 +1153,3 @@ msgstr "Período"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
#~ "Pode compartilhar diretamente o seguinte "
|
#~ "Pode compartilhar diretamente o seguinte "
|
||||||
#~ "ligação através do seu meio preferido"
|
#~ "ligação através do seu meio preferido"
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
||||||
"PO-Revision-Date: 2023-05-05 00:47+0000\n"
|
"PO-Revision-Date: 2024-05-10 07:26+0000\n"
|
||||||
"Last-Translator: MurkBRA <anjo1077@gmail.com>\n"
|
"Last-Translator: Gesiane Pajarinen <gesianef@hotmail.com>\n"
|
||||||
|
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
|
||||||
|
"i-hate-money/i-hate-money/pt_BR/>\n"
|
||||||
"Language: pt_BR\n"
|
"Language: pt_BR\n"
|
||||||
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/i"
|
|
||||||
"-hate-money/i-hate-money/pt_BR/>\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=n > 1\n"
|
|
||||||
"MIME-Version: 1.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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||||
|
"X-Generator: Weblate 5.5.4-rc\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -23,24 +23,23 @@ msgid ""
|
||||||
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
"Not a valid amount or expression. Only numbers and + - * / operators are "
|
||||||
"accepted."
|
"accepted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Expressão ou montante inválido. Apenas números e os operadores +=*/ são "
|
"Expressão ou quantia inválida. Apenas números e os operadores +=*/ são "
|
||||||
"aceitos."
|
"aceitos."
|
||||||
|
|
||||||
msgid "Project name"
|
msgid "Project name"
|
||||||
msgstr "Nome do projeto"
|
msgstr "Nome do projeto"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Current private code"
|
msgid "Current private code"
|
||||||
msgstr "Código privado novo"
|
msgstr "Código privado atual"
|
||||||
|
|
||||||
msgid "Enter existing private code to edit project"
|
msgid "Enter existing private code to edit project"
|
||||||
msgstr ""
|
msgstr "Insira o código privado para editar o projeto"
|
||||||
|
|
||||||
msgid "New private code"
|
msgid "New private code"
|
||||||
msgstr "Código privado novo"
|
msgstr "Novo código privado"
|
||||||
|
|
||||||
msgid "Enter a new code if you want to change it"
|
msgid "Enter a new code if you want to change it"
|
||||||
msgstr "Insira um novo código se quiser alterá-lo"
|
msgstr "Digite um novo código se quiser mudá-lo"
|
||||||
|
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "E-mail"
|
msgstr "E-mail"
|
||||||
|
@ -67,11 +66,11 @@ msgid ""
|
||||||
"This project cannot be set to 'no currency' because it contains bills in "
|
"This project cannot be set to 'no currency' because it contains bills in "
|
||||||
"multiple currencies."
|
"multiple currencies."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"O projeto não pode ser definido como 'sem moeda' porque contém contas em "
|
"Esse projeto não pode ser configurado como 'sem moeda' porque ele tem "
|
||||||
"várias moedas."
|
"faturas em moedas diferentes."
|
||||||
|
|
||||||
msgid "Compatible with Cospend"
|
msgid "Compatible with Cospend"
|
||||||
msgstr ""
|
msgstr "Compatível com Cospend"
|
||||||
|
|
||||||
msgid "Project identifier"
|
msgid "Project identifier"
|
||||||
msgstr "Identificador do projeto"
|
msgstr "Identificador do projeto"
|
||||||
|
@ -148,7 +147,7 @@ msgid "A link to an external document, related to this bill"
|
||||||
msgstr "Link para um documento externo, relacionado à essa conta"
|
msgstr "Link para um documento externo, relacionado à essa conta"
|
||||||
|
|
||||||
msgid "For whom?"
|
msgid "For whom?"
|
||||||
msgstr "Para quem?"
|
msgstr "Por quem?"
|
||||||
|
|
||||||
msgid "Submit"
|
msgid "Submit"
|
||||||
msgstr "Enviar"
|
msgstr "Enviar"
|
||||||
|
@ -173,10 +172,10 @@ msgid "Add"
|
||||||
msgstr "Adicionar"
|
msgstr "Adicionar"
|
||||||
|
|
||||||
msgid "The participant name is invalid"
|
msgid "The participant name is invalid"
|
||||||
msgstr "'%(name)s' não é um usuário válido"
|
msgstr "O nome do participante não é válido"
|
||||||
|
|
||||||
msgid "This project already have this participant"
|
msgid "This project already have this participant"
|
||||||
msgstr "'%(name)s' já está no projeto"
|
msgstr "Este participante já está no projeto"
|
||||||
|
|
||||||
msgid "People to notify"
|
msgid "People to notify"
|
||||||
msgstr "Pessoas para notificar"
|
msgstr "Pessoas para notificar"
|
||||||
|
@ -192,16 +191,15 @@ msgid "Logout"
|
||||||
msgstr "Sair"
|
msgstr "Sair"
|
||||||
|
|
||||||
msgid "Please check the email configuration of the server."
|
msgid "Please check the email configuration of the server."
|
||||||
msgstr ""
|
msgstr "Verifique a configuração de e-mail do servidor."
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Please check the email configuration of the server or contact the "
|
"Please check the email configuration of the server or contact the "
|
||||||
"administrator: %(admin_email)s"
|
"administrator: %(admin_email)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Desculpe, houve um erro ao enviar os convites via e-mail. Por favor, "
|
"Verifique a configuração de e-mail do servidor ou entre em contato com o "
|
||||||
"confira a configuração de email do servidor ou entre em contato com um "
|
"administrador: %(admin_email)s"
|
||||||
"administrador."
|
|
||||||
|
|
||||||
#. List with two items only
|
#. List with two items only
|
||||||
msgid "{dual_object_0} and {dual_object_1}"
|
msgid "{dual_object_0} and {dual_object_1}"
|
||||||
|
@ -230,18 +228,17 @@ msgstr "{prefix}: {error}"
|
||||||
msgid "{prefix}:<br />{errors}"
|
msgid "{prefix}:<br />{errors}"
|
||||||
msgstr "{prefix}:<br />{errors}"
|
msgstr "{prefix}:<br />{errors}"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Too many failed login attempts."
|
msgid "Too many failed login attempts."
|
||||||
msgstr "Muitas tentativas de login falhas, por favor, tente novamente mais tarde."
|
msgstr "Muitas tentativas de login falhas."
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "This admin password is not the right one. Only %(num)d attempts left."
|
msgid "This admin password is not the right one. Only %(num)d attempts left."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Esta senha de administrador não é a correta. Apenas %(num)d tentativas "
|
"Esta senha de administrador não está correta. Apenas %(num)d tentativas "
|
||||||
"restantes."
|
"restantes."
|
||||||
|
|
||||||
msgid "Provided token is invalid"
|
msgid "Provided token is invalid"
|
||||||
msgstr "Token invalido"
|
msgstr "O token fornecido é inválido"
|
||||||
|
|
||||||
msgid "This private code is not the right one"
|
msgid "This private code is not the right one"
|
||||||
msgstr "Este código privado não é o correto"
|
msgstr "Este código privado não é o correto"
|
||||||
|
@ -253,17 +250,15 @@ msgid ""
|
||||||
"We tried to send you an reminder email, but there was an error. You can "
|
"We tried to send you an reminder email, but there was an error. You can "
|
||||||
"still use the project normally."
|
"still use the project normally."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Nós tentamos te enviar um email de lembrete, mas aconteceu um erro. Você "
|
"Tentamos te enviar um email de lembrete, mas aconteceu um erro. Você pode "
|
||||||
"pode continuar usando o projeto normalmente."
|
"continuar usando o projeto normalmente."
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Sorry, there was an error while sending you an email with password reset "
|
"Sorry, there was an error while sending you an email with password reset "
|
||||||
"instructions."
|
"instructions."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Desculpe, houve um erro ao te enviar um email com as instruções de "
|
"Desculpe, houve um erro ao te enviar um email com as instruções de "
|
||||||
"redefinição de senha. Por favor, confira a configuração de e-mail do "
|
"redefinição de senha."
|
||||||
"servidor ou entre em contato com um administrador."
|
|
||||||
|
|
||||||
msgid "No token provided"
|
msgid "No token provided"
|
||||||
msgstr "Nenhum token fornecido"
|
msgstr "Nenhum token fornecido"
|
||||||
|
@ -275,37 +270,36 @@ msgid "Unknown project"
|
||||||
msgstr "Projeto desconhecido"
|
msgstr "Projeto desconhecido"
|
||||||
|
|
||||||
msgid "Password successfully reset."
|
msgid "Password successfully reset."
|
||||||
msgstr "Senha redefinida corretamente."
|
msgstr "Senha redefinida com sucesso."
|
||||||
|
|
||||||
msgid "Project settings have been changed successfully."
|
msgid "Project settings have been changed successfully."
|
||||||
msgstr ""
|
msgstr "As configurações do projeto foram alteradas com sucesso."
|
||||||
|
|
||||||
msgid "Unable to parse CSV"
|
msgid "Unable to parse CSV"
|
||||||
msgstr ""
|
msgstr "Não foi possível processar o CSV"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Missing attribute: %(attribute)s"
|
msgid "Missing attribute: %(attribute)s"
|
||||||
msgstr ""
|
msgstr "Faltando o atributo: %(attribute)s"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Cannot add bills in multiple currencies to a project without default "
|
"Cannot add bills in multiple currencies to a project without default "
|
||||||
"currency"
|
"currency"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Não é possível adicionar contas em várias moedas a um projeto sem moeda "
|
"Não é possível adicionar contas em várias moedas em um projeto sem moeda "
|
||||||
"padrão"
|
"padrão"
|
||||||
|
|
||||||
msgid "Project successfully uploaded"
|
msgid "Project successfully uploaded"
|
||||||
msgstr "Projeto enviado corretamente"
|
msgstr "Projeto enviado com sucesso"
|
||||||
|
|
||||||
msgid "Project successfully deleted"
|
msgid "Project successfully deleted"
|
||||||
msgstr "Projeto deletado com sucesso"
|
msgstr "Projeto deletado com sucesso"
|
||||||
|
|
||||||
msgid "Error deleting project"
|
msgid "Error deleting project"
|
||||||
msgstr "Erro ao excluir o projeto"
|
msgstr "Erro ao deletar o projeto"
|
||||||
|
|
||||||
msgid "Unable to logout"
|
msgid "Unable to logout"
|
||||||
msgstr ""
|
msgstr "Não é possível sair"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You have been invited to share your expenses for %(project)s"
|
msgid "You have been invited to share your expenses for %(project)s"
|
||||||
|
@ -314,76 +308,73 @@ msgstr "Você foi convidado a compartilhar suas despesas com %(project)s"
|
||||||
msgid "Your invitations have been sent"
|
msgid "Your invitations have been sent"
|
||||||
msgstr "Seus convites foram enviados"
|
msgstr "Seus convites foram enviados"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Sorry, there was an error while trying to send the invitation emails."
|
msgid "Sorry, there was an error while trying to send the invitation emails."
|
||||||
msgstr ""
|
msgstr "Desculpe, houve um erro ao enviar os convites via e-mail."
|
||||||
"Desculpe, houve um erro ao enviar os convites via e-mail. Por favor, "
|
|
||||||
"confira a configuração de email do servidor ou entre em contato com um "
|
|
||||||
"administrador."
|
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(member)s has been added"
|
msgid "%(member)s has been added"
|
||||||
msgstr "%(member)s foram adicionados"
|
msgstr "%(member)s foi adicionado(a)"
|
||||||
|
|
||||||
msgid "Error activating participant"
|
msgid "Error activating participant"
|
||||||
msgstr "Erro ao ativar usuário"
|
msgstr "Erro ao ativar participante"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s is part of this project again"
|
msgid "%(name)s is part of this project again"
|
||||||
msgstr "%(name)s faz parte deste projeto novamente"
|
msgstr "%(name)s faz parte deste projeto novamente"
|
||||||
|
|
||||||
msgid "Error removing participant"
|
msgid "Error removing participant"
|
||||||
msgstr "Erro ao remover usuário"
|
msgstr "Erro ao remover participante"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Participant '%(name)s' has been deactivated. It will still appear in the "
|
"Participant '%(name)s' has been deactivated. It will still appear in the "
|
||||||
"list until its balance reach zero."
|
"list until its balance reach zero."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Usuário '%(name)s' foi desativado. Ele continuará aparecendo na lista de "
|
"O participante '%(name)s' foi desativado. Ele continuará aparecendo na lista "
|
||||||
"usuários até que seu saldo seja zero."
|
"de usuários até que seu saldo seja zero."
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Participant '%(name)s' has been removed"
|
msgid "Participant '%(name)s' has been removed"
|
||||||
msgstr "Usuário '%(name)s' foi removido"
|
msgstr "Participante '%(name)s' foi removido(a)"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Participant '%(name)s' has been modified"
|
msgid "Participant '%(name)s' has been modified"
|
||||||
msgstr "Usuário '%(name)s' foi removido"
|
msgstr "Participante '%(name)s' foi alterado(a)"
|
||||||
|
|
||||||
msgid "The bill has been added"
|
msgid "The bill has been added"
|
||||||
msgstr "A conta foi adicionada"
|
msgstr "A conta foi adicionada"
|
||||||
|
|
||||||
msgid "Error deleting bill"
|
msgid "Error deleting bill"
|
||||||
msgstr "Erro ao excluir conta"
|
msgstr "Erro ao excluir a conta"
|
||||||
|
|
||||||
msgid "The bill has been deleted"
|
msgid "The bill has been deleted"
|
||||||
msgstr "A conta foi deletada"
|
msgstr "A conta foi deletada"
|
||||||
|
|
||||||
msgid "The bill has been modified"
|
msgid "The bill has been modified"
|
||||||
msgstr "A conta foi modificada"
|
msgstr "A conta foi alterada"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(lang)s is not a supported language"
|
msgid "%(lang)s is not a supported language"
|
||||||
msgstr ""
|
msgstr "Não temos configuração para o idioma %(lang)s"
|
||||||
|
|
||||||
msgid "Error deleting project history"
|
msgid "Error deleting project history"
|
||||||
msgstr "Erro ao deletar o histórico do projeto"
|
msgstr "Erro ao deletar o histórico do projeto"
|
||||||
|
|
||||||
msgid "Deleted project history."
|
msgid "Deleted project history."
|
||||||
msgstr "Histórico do projeto apagado."
|
msgstr "Histórico do projeto deletado."
|
||||||
|
|
||||||
msgid "Error deleting recorded IP addresses"
|
msgid "Error deleting recorded IP addresses"
|
||||||
msgstr "Erro ao excluir endereços IP salvos"
|
msgstr "Erro ao deletar endereços IP salvos"
|
||||||
|
|
||||||
msgid "Deleted recorded IP addresses in project history."
|
msgid "Deleted recorded IP addresses in project history."
|
||||||
msgstr "Endereços IP salvos no histórico de projeto deletados."
|
msgstr "Endereços de IP registrados deletados no histórico do projeto."
|
||||||
|
|
||||||
msgid "Sorry, we were unable to find the page you've asked for."
|
msgid "Sorry, we were unable to find the page you've asked for."
|
||||||
msgstr "Desculpe, não foi possível encontrar a página que você solicitou."
|
msgstr "Desculpe, não foi possível encontrar a página que você solicitou."
|
||||||
|
|
||||||
msgid "The best thing to do is probably to get back to the main page."
|
msgid "The best thing to do is probably to get back to the main page."
|
||||||
msgstr "É provável que a melhor coisa a fazer seja voltar para a página inicial."
|
msgstr ""
|
||||||
|
"Provavelmente, a melhor coisa a fazer seja voltar para a página inicial."
|
||||||
|
|
||||||
msgid "Back to the list"
|
msgid "Back to the list"
|
||||||
msgstr "Voltar para a lista"
|
msgstr "Voltar para a lista"
|
||||||
|
@ -398,7 +389,7 @@ msgid "The project you are trying to access do not exist, do you want to"
|
||||||
msgstr "O projeto que você está tentando acessar não existe, você quer"
|
msgstr "O projeto que você está tentando acessar não existe, você quer"
|
||||||
|
|
||||||
msgid "create it"
|
msgid "create it"
|
||||||
msgstr "Criar"
|
msgstr "criar"
|
||||||
|
|
||||||
msgid "?"
|
msgid "?"
|
||||||
msgstr "?"
|
msgstr "?"
|
||||||
|
@ -410,7 +401,7 @@ msgid "Project"
|
||||||
msgstr "Projeto"
|
msgstr "Projeto"
|
||||||
|
|
||||||
msgid "Number of participants"
|
msgid "Number of participants"
|
||||||
msgstr "Número de usuários"
|
msgstr "Número de participantes"
|
||||||
|
|
||||||
msgid "Number of bills"
|
msgid "Number of bills"
|
||||||
msgstr "Número de contas"
|
msgstr "Número de contas"
|
||||||
|
@ -428,29 +419,28 @@ msgid "edit"
|
||||||
msgstr "editar"
|
msgstr "editar"
|
||||||
|
|
||||||
msgid "Delete project"
|
msgid "Delete project"
|
||||||
msgstr "Excluir projeto"
|
msgstr "Deletar projeto"
|
||||||
|
|
||||||
msgid "show"
|
msgid "show"
|
||||||
msgstr "exibir"
|
msgstr "mostrar"
|
||||||
|
|
||||||
msgid "The Dashboard is currently deactivated."
|
msgid "The Dashboard is currently deactivated."
|
||||||
msgstr "O Painel de Controle atualmente está desativado."
|
msgstr "O Painel de Controle atualmente está desativado."
|
||||||
|
|
||||||
msgid "Download Mobile Application"
|
msgid "Download Mobile Application"
|
||||||
msgstr "Baixar o APP"
|
msgstr "Baixar o aplicativo"
|
||||||
|
|
||||||
msgid "Get it on"
|
msgid "Get it on"
|
||||||
msgstr "Pegue agora"
|
msgstr "Comece"
|
||||||
|
|
||||||
msgid "Edit project"
|
msgid "Edit project"
|
||||||
msgstr "Editar projeto"
|
msgstr "Editar projeto"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Import project"
|
msgid "Import project"
|
||||||
msgstr "Editar projeto"
|
msgstr "Importar projeto"
|
||||||
|
|
||||||
msgid "Download project's data"
|
msgid "Download project's data"
|
||||||
msgstr "Baixar dados do projeto"
|
msgstr "Baixar os dados do projeto"
|
||||||
|
|
||||||
msgid "Bill items"
|
msgid "Bill items"
|
||||||
msgstr "Itens da conta"
|
msgstr "Itens da conta"
|
||||||
|
@ -474,14 +464,13 @@ msgid "Privacy Settings"
|
||||||
msgstr "Configurações de Privacidade"
|
msgstr "Configurações de Privacidade"
|
||||||
|
|
||||||
msgid "Save changes"
|
msgid "Save changes"
|
||||||
msgstr ""
|
msgstr "Salvar as alterações"
|
||||||
|
|
||||||
msgid "This will remove all bills and participants in this project!"
|
msgid "This will remove all bills and participants in this project!"
|
||||||
msgstr "Isso vai remover todas as contas e participantes desse projeto!"
|
msgstr "Isso vai remover todas as faturas e participantes desse projeto!"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Import previously exported project"
|
msgid "Import previously exported project"
|
||||||
msgstr "Importar arquivo JSON exportado anteriormente"
|
msgstr "Importar projeto que foi exportado anteriormente"
|
||||||
|
|
||||||
msgid "Choose file"
|
msgid "Choose file"
|
||||||
msgstr "Escolher arquivo"
|
msgstr "Escolher arquivo"
|
||||||
|
@ -493,7 +482,7 @@ msgid "Add a bill"
|
||||||
msgstr "Adicionar uma conta"
|
msgstr "Adicionar uma conta"
|
||||||
|
|
||||||
msgid "Simple operations are allowed, e.g. (18+36.2)/3"
|
msgid "Simple operations are allowed, e.g. (18+36.2)/3"
|
||||||
msgstr ""
|
msgstr "Operações simples são permitidas, por ex. (18+36,2)/3"
|
||||||
|
|
||||||
msgid "Everyone"
|
msgid "Everyone"
|
||||||
msgstr "Todos"
|
msgstr "Todos"
|
||||||
|
@ -508,7 +497,7 @@ msgid "Add participant"
|
||||||
msgstr "Adicionar participante"
|
msgstr "Adicionar participante"
|
||||||
|
|
||||||
msgid "Edit this participant"
|
msgid "Edit this participant"
|
||||||
msgstr "Editar usuário"
|
msgstr "Editar participante"
|
||||||
|
|
||||||
msgid "john.doe@example.com, mary.moe@site.com"
|
msgid "john.doe@example.com, mary.moe@site.com"
|
||||||
msgstr "john.doe@example.com, mary.moe@site.com"
|
msgstr "john.doe@example.com, mary.moe@site.com"
|
||||||
|
@ -517,22 +506,22 @@ msgid "Download"
|
||||||
msgstr "Baixar"
|
msgstr "Baixar"
|
||||||
|
|
||||||
msgid "Disabled Project History"
|
msgid "Disabled Project History"
|
||||||
msgstr "Histórico do Projeto Desativado"
|
msgstr "Histórico de Projeto Desativado"
|
||||||
|
|
||||||
msgid "Disabled Project History & IP Address Recording"
|
msgid "Disabled Project History & IP Address Recording"
|
||||||
msgstr "Histórico do Projeto Desativado & Gravação de Endereço IP"
|
msgstr "Histórico de Projeto Desativado & Registro de Endereços de IP"
|
||||||
|
|
||||||
msgid "Enabled Project History"
|
msgid "Enabled Project History"
|
||||||
msgstr "Histórico do Projeto Ativado"
|
msgstr "Histórico de Projeto Ativado"
|
||||||
|
|
||||||
msgid "Disabled IP Address Recording"
|
msgid "Disabled IP Address Recording"
|
||||||
msgstr "Gravação do Endereço IP Desativada"
|
msgstr "Registro de Endereços de IP Desativados"
|
||||||
|
|
||||||
msgid "Enabled Project History & IP Address Recording"
|
msgid "Enabled Project History & IP Address Recording"
|
||||||
msgstr "Histórico do Projeto Ativado & Gravação do Endereço IP"
|
msgstr "Histórico de Projeto Ativado & Registro de Endereços de IP"
|
||||||
|
|
||||||
msgid "Enabled IP Address Recording"
|
msgid "Enabled IP Address Recording"
|
||||||
msgstr "Gravação do Endereço IP Ativada"
|
msgstr "Registro de Endereços de IP Ativado"
|
||||||
|
|
||||||
msgid "History Settings Changed"
|
msgid "History Settings Changed"
|
||||||
msgstr "Configurações do Histórico Alteradas"
|
msgstr "Configurações do Histórico Alteradas"
|
||||||
|
@ -554,13 +543,13 @@ msgid ""
|
||||||
" The rest of the project history will be unaffected. This "
|
" The rest of the project history will be unaffected. This "
|
||||||
"action cannot be undone."
|
"action cannot be undone."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Você tem certeza que deseja deletar todos os endereços IP gravados deste "
|
"Tem certeza que deseja deletar todos os endereços IP gravados neste projeto?"
|
||||||
"projeto?\n"
|
"\n"
|
||||||
" O resto do histórico do projeto não será afetado. Esta "
|
" O resto do histórico do projeto não será afetado. Esta ação "
|
||||||
"ação não pode ser desfeita."
|
"não pode ser desfeita."
|
||||||
|
|
||||||
msgid "Confirm deletion"
|
msgid "Confirm deletion"
|
||||||
msgstr "Confirmar exclusão"
|
msgstr "Confirmar a exclusão"
|
||||||
|
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr "Fechar"
|
msgstr "Fechar"
|
||||||
|
@ -577,27 +566,28 @@ msgstr ""
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s: added %(owers_list_str)s to owers list"
|
msgid "Bill %(name)s: added %(owers_list_str)s to owers list"
|
||||||
msgstr "Conta %(name)s: adicionou %(owers_list_str)s a lista de devedores"
|
msgstr "Conta %(name)s: adicionados %(owers_list_str)s à lista de proprietários"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s: removed %(owers_list_str)s from owers list"
|
msgid "Bill %(name)s: removed %(owers_list_str)s from owers list"
|
||||||
msgstr "Conta %(name)s: removeu %(owers_list_str)s da lista de devedores"
|
msgstr "Conta %(name)s: removidos %(owers_list_str)s da lista de proprietários"
|
||||||
|
|
||||||
msgid "This project has history disabled. New actions won't appear below."
|
msgid "This project has history disabled. New actions won't appear below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Este projeto tem o histórico desativado. Novas ações não aparecerão abaixo."
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "You can enable history on the settings page."
|
msgid "You can enable history on the settings page."
|
||||||
msgstr "A gravação do endereço IP pode ser ativada na página de configurações"
|
msgstr "Você pode ativar o histórico na página de configurações."
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"The table below reflects actions recorded prior to disabling project "
|
"The table below reflects actions recorded prior to disabling project "
|
||||||
"history."
|
"history."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"A tabela abaixo contém as ações registradas antes da desativação do "
|
||||||
|
"histórico do projeto."
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "You can clear the project history to remove them."
|
msgid "You can clear the project history to remove them."
|
||||||
msgstr "Alguém provavelmente limpou o histórico do projeto."
|
msgstr "Você pode limpar o histórico do projeto para removê-los."
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Some entries below contain IP addresses, even though this project has IP "
|
"Some entries below contain IP addresses, even though this project has IP "
|
||||||
|
@ -613,7 +603,7 @@ msgid "No IP Addresses to erase"
|
||||||
msgstr "Não há endereços IP para apagar"
|
msgstr "Não há endereços IP para apagar"
|
||||||
|
|
||||||
msgid "Delete Stored IP Addresses"
|
msgid "Delete Stored IP Addresses"
|
||||||
msgstr "Deletar endereços IP salvos"
|
msgstr "Deletar Endereços IP Salvos"
|
||||||
|
|
||||||
msgid "No history to erase"
|
msgid "No history to erase"
|
||||||
msgstr "Não há histórico para apagar"
|
msgstr "Não há histórico para apagar"
|
||||||
|
@ -622,7 +612,7 @@ msgid "Clear Project History"
|
||||||
msgstr "Limpar Histórico do Projeto"
|
msgstr "Limpar Histórico do Projeto"
|
||||||
|
|
||||||
msgid "Time"
|
msgid "Time"
|
||||||
msgstr "Tempo"
|
msgstr "Data e hora"
|
||||||
|
|
||||||
msgid "Event"
|
msgid "Event"
|
||||||
msgstr "Evento"
|
msgstr "Evento"
|
||||||
|
@ -634,7 +624,7 @@ msgid "IP address recording can be disabled on the settings page"
|
||||||
msgstr "A gravação do endereço IP pode ser desativada na página de configurações"
|
msgstr "A gravação do endereço IP pode ser desativada na página de configurações"
|
||||||
|
|
||||||
msgid "From IP"
|
msgid "From IP"
|
||||||
msgstr "Do IP"
|
msgstr "IP"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Project %(name)s added"
|
msgid "Project %(name)s added"
|
||||||
|
@ -646,7 +636,7 @@ msgstr "Conta %(name)s adicionada"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s added"
|
msgid "Participant %(name)s added"
|
||||||
msgstr "Usuário %(name)s adicionado"
|
msgstr "Participante %(name)s adicionado(a)"
|
||||||
|
|
||||||
msgid "Project private code changed"
|
msgid "Project private code changed"
|
||||||
msgstr "Código privado do projeto alterado"
|
msgstr "Código privado do projeto alterado"
|
||||||
|
@ -664,15 +654,15 @@ msgstr "Configurações do projeto alteradas"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s deactivated"
|
msgid "Participant %(name)s deactivated"
|
||||||
msgstr "Usuário %(name)s desativado"
|
msgstr "Participante %(name)s desativado"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s reactivated"
|
msgid "Participant %(name)s reactivated"
|
||||||
msgstr "Usuário %(name)s reativado"
|
msgstr "Participante %(name)s reativado"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s renamed to %(new_name)s"
|
msgid "Participant %(name)s renamed to %(new_name)s"
|
||||||
msgstr "Usuário %(name)s renomeado para %(new_name)s"
|
msgstr "Participante %(name)s renomeado para %(new_name)s"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s renamed to %(new_description)s"
|
msgid "Bill %(name)s renamed to %(new_description)s"
|
||||||
|
@ -680,7 +670,8 @@ msgstr "Conta %(name)s renomeada para %(new_description)s"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s: weight changed from %(old_weight)s to %(new_weight)s"
|
msgid "Participant %(name)s: weight changed from %(old_weight)s to %(new_weight)s"
|
||||||
msgstr "Usuário %(name)s: a carga mudou de %(old_weight)s para %(new_weight)s"
|
msgstr ""
|
||||||
|
"Participante %(name)s: o peso mudou de %(old_weight)s para %(new_weight)s"
|
||||||
|
|
||||||
msgid "Payer"
|
msgid "Payer"
|
||||||
msgstr "Pagador"
|
msgstr "Pagador"
|
||||||
|
@ -697,40 +688,40 @@ msgstr "Quantia em %(currency)s"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s modified"
|
msgid "Bill %(name)s modified"
|
||||||
msgstr "Conta %(name)s modificada"
|
msgstr "Conta %(name)s alterada"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s modified"
|
msgid "Participant %(name)s modified"
|
||||||
msgstr "Usuário %(name)s modificado"
|
msgstr "Participante %(name)s foi alterado(a)"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s removed"
|
msgid "Bill %(name)s removed"
|
||||||
msgstr "Conta '%(name)s' foi removida"
|
msgstr "Conta '%(name)s' foi removida"
|
||||||
|
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s removed"
|
msgid "Participant %(name)s removed"
|
||||||
msgstr "Usuário '%(name)s' foi removido"
|
msgstr "Participante '%(name)s' foi removido"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Project %(name)s changed in an unknown way"
|
msgid "Project %(name)s changed in an unknown way"
|
||||||
msgstr "Projeto %(name)s modificado de maneira desconhecida"
|
msgstr "Projeto %(name)s alterado de maneira desconhecida"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Bill %(name)s changed in an unknown way"
|
msgid "Bill %(name)s changed in an unknown way"
|
||||||
msgstr "Conta %(name)s modificado de maneira desconhecida"
|
msgstr "Conta %(name)s alterada de maneira desconhecida"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Participant %(name)s changed in an unknown way"
|
msgid "Participant %(name)s changed in an unknown way"
|
||||||
msgstr "Participante %(name)s modificado de maneira desconhecida"
|
msgstr "Participante %(name)s alterado(a) de maneira desconhecida"
|
||||||
|
|
||||||
msgid "Nothing to list"
|
msgid "Nothing to list"
|
||||||
msgstr "Nada a listar"
|
msgstr "Nada para listar"
|
||||||
|
|
||||||
msgid "Someone probably cleared the project history."
|
msgid "Someone probably cleared the project history."
|
||||||
msgstr "Alguém provavelmente limpou o histórico do projeto."
|
msgstr "Alguém provavelmente limpou o histórico do projeto."
|
||||||
|
|
||||||
msgid "Manage your shared <br />expenses, easily"
|
msgid "Manage your shared <br />expenses, easily"
|
||||||
msgstr "Modifique suas despesas <br />compartilhadas, facilmente"
|
msgstr "Gerencie suas despesas <br /> compartilhadas com facilidade"
|
||||||
|
|
||||||
msgid "Try out the demo"
|
msgid "Try out the demo"
|
||||||
msgstr "Experimente a demonstração"
|
msgstr "Experimente a demonstração"
|
||||||
|
@ -748,13 +739,13 @@ msgid "We can help!"
|
||||||
msgstr "Nós podemos ajudar!"
|
msgstr "Nós podemos ajudar!"
|
||||||
|
|
||||||
msgid "Log in to an existing project"
|
msgid "Log in to an existing project"
|
||||||
msgstr "Conecte-se em um projeto existente"
|
msgstr "Faça login em um projeto existente"
|
||||||
|
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr "Conecte-se"
|
msgstr "Login"
|
||||||
|
|
||||||
msgid "can't remember your password?"
|
msgid "can't remember your password?"
|
||||||
msgstr "não consegue se lembrar da sua senha?"
|
msgstr "não lembra sua senha?"
|
||||||
|
|
||||||
msgid "Create"
|
msgid "Create"
|
||||||
msgstr "Criar"
|
msgstr "Criar"
|
||||||
|
@ -773,13 +764,13 @@ msgid "Bills"
|
||||||
msgstr "Contas"
|
msgstr "Contas"
|
||||||
|
|
||||||
msgid "Settle"
|
msgid "Settle"
|
||||||
msgstr "Estabelecer"
|
msgstr "Pagamentos"
|
||||||
|
|
||||||
msgid "Statistics"
|
msgid "Statistics"
|
||||||
msgstr "Estatísticas"
|
msgstr "Estatísticas"
|
||||||
|
|
||||||
msgid "Languages"
|
msgid "Languages"
|
||||||
msgstr "Linguagens"
|
msgstr "Idiomas"
|
||||||
|
|
||||||
msgid "Projects"
|
msgid "Projects"
|
||||||
msgstr "Projetos"
|
msgstr "Projetos"
|
||||||
|
@ -794,7 +785,7 @@ msgid "Settings"
|
||||||
msgstr "Configurações"
|
msgstr "Configurações"
|
||||||
|
|
||||||
msgid "RSS Feed"
|
msgid "RSS Feed"
|
||||||
msgstr ""
|
msgstr "Feed RSS"
|
||||||
|
|
||||||
msgid "Other projects :"
|
msgid "Other projects :"
|
||||||
msgstr "Outros projetos:"
|
msgstr "Outros projetos:"
|
||||||
|
@ -807,18 +798,18 @@ msgstr "Painel de controle"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please retry after %(date)s."
|
msgid "Please retry after %(date)s."
|
||||||
msgstr ""
|
msgstr "Por favor, tente novamente após %(date)s."
|
||||||
|
|
||||||
msgid "Code"
|
msgid "Code"
|
||||||
msgstr "Código"
|
msgstr "Código"
|
||||||
|
|
||||||
msgid "Mobile Application"
|
msgid "Mobile Application"
|
||||||
msgstr "Aplicação Mobile"
|
msgstr "Aplicativo"
|
||||||
|
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Documentação"
|
msgstr "Documentação"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Painel de Administração"
|
msgstr "Painel de Administração"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
@ -847,7 +838,7 @@ msgid "Older bills"
|
||||||
msgstr "Contas mais antigas"
|
msgstr "Contas mais antigas"
|
||||||
|
|
||||||
msgid "You should start by adding participants"
|
msgid "You should start by adding participants"
|
||||||
msgstr "Você deveria começar adicionando pessoas"
|
msgstr "Comece adicionando participantes"
|
||||||
|
|
||||||
msgid "Add a new bill"
|
msgid "Add a new bill"
|
||||||
msgstr "Adicionar uma nova conta"
|
msgstr "Adicionar uma nova conta"
|
||||||
|
@ -872,13 +863,11 @@ msgstr "Sem contas"
|
||||||
msgid "Nothing to list yet."
|
msgid "Nothing to list yet."
|
||||||
msgstr "Nada para listar ainda."
|
msgstr "Nada para listar ainda."
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Add your first bill"
|
msgid "Add your first bill"
|
||||||
msgstr "adicionar uma conta"
|
msgstr "Adicione sua primeira conta"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Add the first participant"
|
msgid "Add the first participant"
|
||||||
msgstr "Editar usuário"
|
msgstr "Adicione o primeiro participante"
|
||||||
|
|
||||||
msgid "Password reminder"
|
msgid "Password reminder"
|
||||||
msgstr "Lembrete de senha"
|
msgstr "Lembrete de senha"
|
||||||
|
@ -903,7 +892,7 @@ msgid "Invite people to join this project"
|
||||||
msgstr "Convide pessoas para participar deste projeto"
|
msgstr "Convide pessoas para participar deste projeto"
|
||||||
|
|
||||||
msgid "Share an invitation link"
|
msgid "Share an invitation link"
|
||||||
msgstr ""
|
msgstr "Compartilhe um link do convite"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"The easiest way to invite people is to give them the following invitation"
|
"The easiest way to invite people is to give them the following invitation"
|
||||||
|
@ -911,26 +900,29 @@ msgid ""
|
||||||
" add/edit/delete bills. However, they will not have access to important "
|
" add/edit/delete bills. However, they will not have access to important "
|
||||||
"settings such as changing the private code or deleting the whole project."
|
"settings such as changing the private code or deleting the whole project."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"A maneira mais fácil de convidar as pessoas é enviando o seguinte link para "
|
||||||
|
"convite.<br />Eles poderão acessar o projeto, gerenciar participantes, "
|
||||||
|
"adicionar/editar/excluir contas. No entanto, eles não terão acesso às "
|
||||||
|
"configurações importantes, como alterar o código privado ou excluir todo o "
|
||||||
|
"projeto."
|
||||||
|
|
||||||
msgid "Scan QR code"
|
msgid "Scan QR code"
|
||||||
msgstr ""
|
msgstr "Escaneie o QR code"
|
||||||
|
|
||||||
msgid "Use a mobile device with a compatible app."
|
msgid "Use a mobile device with a compatible app."
|
||||||
msgstr ""
|
msgstr "Use um telefone celular ou tablet com um aplicativo compatível."
|
||||||
|
|
||||||
msgid "Send via Emails"
|
msgid "Send via Emails"
|
||||||
msgstr "Enviar via E-mails"
|
msgstr "Enviar via E-mails"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Specify a list of email adresses (separated by comma) of people you want "
|
"Specify a list of email adresses (separated by comma) of people you want "
|
||||||
"to notify about the creation of this project. We will send them an email "
|
"to notify about the creation of this project. We will send them an email "
|
||||||
"with the invitation link."
|
"with the invitation link."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Especifica uma lista de endereços de email (separados por vírgula) que "
|
"Especifique uma lista de e-mails (separados por vírgula) das pessoas que "
|
||||||
"você quer notificar acerca da\n"
|
"você deseja notificar sobre a criação deste projeto. Enviaremos um e-mail "
|
||||||
" criação deste projeto de gestão de saldo e nós iremos "
|
"para eles com o link do convite."
|
||||||
"enviar um email por si."
|
|
||||||
|
|
||||||
msgid "Share Identifier & code"
|
msgid "Share Identifier & code"
|
||||||
msgstr "Compartilhar Identificador & código"
|
msgstr "Compartilhar Identificador & código"
|
||||||
|
@ -941,16 +933,19 @@ msgid ""
|
||||||
"to the full project, including changing settings such as the private code"
|
"to the full project, including changing settings such as the private code"
|
||||||
" or project email address, or even deleting the whole project."
|
" or project email address, or even deleting the whole project."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Você pode compartilhar o identificador do projeto e o código privado por "
|
||||||
|
"qualquer meio de comunicação.<br />Qualquer pessoa com o código privado terá "
|
||||||
|
"acesso a todo o projeto e poderá alterar as configurações como o código "
|
||||||
|
"privado ou o e-mail, ou até mesmo a exclusão de todo o projeto."
|
||||||
|
|
||||||
msgid "Identifier:"
|
msgid "Identifier:"
|
||||||
msgstr "Identificador:"
|
msgstr "Identificador:"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Private code:"
|
msgid "Private code:"
|
||||||
msgstr "Código privado"
|
msgstr "Código privado:"
|
||||||
|
|
||||||
msgid "the private code was defined when you created the project"
|
msgid "the private code was defined when you created the project"
|
||||||
msgstr ""
|
msgstr "o código privado foi definido quando você criou o projeto"
|
||||||
|
|
||||||
msgid "Who pays?"
|
msgid "Who pays?"
|
||||||
msgstr "Quem paga?"
|
msgstr "Quem paga?"
|
||||||
|
@ -1140,4 +1135,3 @@ msgstr "Período"
|
||||||
#~ "Você pode compartilhar diretamente o "
|
#~ "Você pode compartilhar diretamente o "
|
||||||
#~ "seguinte link através do seu meio "
|
#~ "seguinte link através do seu meio "
|
||||||
#~ "preferido"
|
#~ "preferido"
|
||||||
|
|
||||||
|
|
|
@ -816,7 +816,7 @@ msgstr "Мобильное приложение"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Документация"
|
msgstr "Документация"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Панель инструментов администратора"
|
msgstr "Панель инструментов администратора"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -783,7 +783,7 @@ msgstr "Mobilna Aplikacija"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentacija"
|
msgstr "Dokumentacija"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -818,7 +818,7 @@ msgstr "Mobilapplikation"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Dokumentation"
|
msgstr "Dokumentation"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Översiktspanel för administration"
|
msgstr "Översiktspanel för administration"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -809,7 +809,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
"POT-Creation-Date: 2023-07-29 14:24+0200\n"
|
||||||
"PO-Revision-Date: 2022-10-04 14:19+0000\n"
|
"PO-Revision-Date: 2024-05-13 07:00+0000\n"
|
||||||
"Last-Translator: Sharan J <sharanjs1999@gmail.com>\n"
|
"Last-Translator: Harshini K <harshinikondepudi@gmail.com>\n"
|
||||||
|
"Language-Team: Telugu <https://hosted.weblate.org/projects/i-hate-money/"
|
||||||
|
"i-hate-money/te/>\n"
|
||||||
"Language: te\n"
|
"Language: te\n"
|
||||||
"Language-Team: Telugu <https://hosted.weblate.org/projects/i-hate-money/i"
|
|
||||||
"-hate-money/te/>\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1\n"
|
|
||||||
"MIME-Version: 1.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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
|
"X-Generator: Weblate 5.5.5-dev\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
|
@ -35,7 +35,7 @@ msgid "Current private code"
|
||||||
msgstr "కొత్త ప్రైవేట్ కోడ్"
|
msgstr "కొత్త ప్రైవేట్ కోడ్"
|
||||||
|
|
||||||
msgid "Enter existing private code to edit project"
|
msgid "Enter existing private code to edit project"
|
||||||
msgstr ""
|
msgstr "ప్రాజెక్ట్ను సవరించడానికి ఇప్పటికీ ఉన్న ప్రైవేట్ కోడ్ ని ఎంటర్ చేయండి"
|
||||||
|
|
||||||
msgid "New private code"
|
msgid "New private code"
|
||||||
msgstr "కొత్త ప్రైవేట్ కోడ్"
|
msgstr "కొత్త ప్రైవేట్ కోడ్"
|
||||||
|
@ -75,7 +75,7 @@ msgstr ""
|
||||||
" చెయ్యడం కుదరదు."
|
" చెయ్యడం కుదరదు."
|
||||||
|
|
||||||
msgid "Compatible with Cospend"
|
msgid "Compatible with Cospend"
|
||||||
msgstr ""
|
msgstr "కాస్పెండ్ తో అనుకూలమైనది"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "Project identifier"
|
msgid "Project identifier"
|
||||||
|
@ -136,16 +136,16 @@ msgid "Reset password"
|
||||||
msgstr "పాస్ వర్డ్ రీసెట్ చేయి"
|
msgstr "పాస్ వర్డ్ రీసెట్ చేయి"
|
||||||
|
|
||||||
msgid "When?"
|
msgid "When?"
|
||||||
msgstr ""
|
msgstr "ఎప్పుడు?"
|
||||||
|
|
||||||
msgid "What?"
|
msgid "What?"
|
||||||
msgstr "ఏమిటి?"
|
msgstr "ఏమిటి?"
|
||||||
|
|
||||||
msgid "Who paid?"
|
msgid "Who paid?"
|
||||||
msgstr ""
|
msgstr "ఎవరు చెల్లించారు?"
|
||||||
|
|
||||||
msgid "How much?"
|
msgid "How much?"
|
||||||
msgstr ""
|
msgstr "ఎంత?"
|
||||||
|
|
||||||
msgid "Currency"
|
msgid "Currency"
|
||||||
msgstr "కరెన్సీ"
|
msgstr "కరెన్సీ"
|
||||||
|
@ -817,7 +817,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
@ -1063,4 +1063,3 @@ msgstr ""
|
||||||
#~ "them an email with the invitation "
|
#~ "them an email with the invitation "
|
||||||
#~ "link."
|
#~ "link."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -778,7 +778,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -811,7 +811,7 @@ msgstr "Telefon Uygulaması"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "Belgelendirme"
|
msgstr "Belgelendirme"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "Yönetici Gösterge Paneli"
|
msgstr "Yönetici Gösterge Paneli"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -791,7 +791,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -776,7 +776,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -775,7 +775,7 @@ msgstr ""
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -779,7 +779,7 @@ msgstr "手机软件"
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr "文件"
|
msgstr "文件"
|
||||||
|
|
||||||
msgid "Administation Dashboard"
|
msgid "Administration Dashboard"
|
||||||
msgstr "管理面板"
|
msgstr "管理面板"
|
||||||
|
|
||||||
msgid "Legal information"
|
msgid "Legal information"
|
||||||
|
|
|
@ -84,7 +84,6 @@ def flash_email_error(error_message, category="danger"):
|
||||||
|
|
||||||
|
|
||||||
class Redirect303(HTTPException, RoutingException):
|
class Redirect303(HTTPException, RoutingException):
|
||||||
|
|
||||||
"""Raise if the map requests a redirect. This is for example the case if
|
"""Raise if the map requests a redirect. This is for example the case if
|
||||||
`strict_slashes` are activated and an url that requires a trailing slash.
|
`strict_slashes` are activated and an url that requires a trailing slash.
|
||||||
|
|
||||||
|
@ -102,7 +101,6 @@ class Redirect303(HTTPException, RoutingException):
|
||||||
|
|
||||||
|
|
||||||
class PrefixedWSGI(object):
|
class PrefixedWSGI(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Wrap the application in this middleware and configure the
|
Wrap the application in this middleware and configure the
|
||||||
front-end server to add these headers, to let you quietly bind
|
front-end server to add these headers, to let you quietly bind
|
||||||
|
|
|
@ -8,6 +8,7 @@ Basically, this blueprint takes care of the authentication and provides
|
||||||
some shortcuts to make your life better when coding (see `pull_project`
|
some shortcuts to make your life better when coding (see `pull_project`
|
||||||
and `add_project_id` for a quick overview)
|
and `add_project_id` for a quick overview)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -137,6 +138,11 @@ def set_show_admin_dashboard_link(endpoint, values):
|
||||||
g.logout_form = LogoutForm()
|
g.logout_form = LogoutForm()
|
||||||
|
|
||||||
|
|
||||||
|
@main.context_processor
|
||||||
|
def add_template_variables():
|
||||||
|
return {"SITE_NAME": current_app.config.get("SITE_NAME")}
|
||||||
|
|
||||||
|
|
||||||
@main.url_value_preprocessor
|
@main.url_value_preprocessor
|
||||||
def pull_project(endpoint, values):
|
def pull_project(endpoint, values):
|
||||||
"""When a request contains a project_id value, transform it directly
|
"""When a request contains a project_id value, transform it directly
|
||||||
|
@ -868,13 +874,18 @@ def add_settlement_bill():
|
||||||
)
|
)
|
||||||
return redirect(url_for(".settle_bill"))
|
return redirect(url_for(".settle_bill"))
|
||||||
|
|
||||||
# TODO: check that sender and receiver ID are valid and part of this project
|
# Ensure that the sender and receiver ID are valid and part of this project
|
||||||
|
receiver_id = form.receiver_id.data
|
||||||
|
sender_id = form.sender_id.data
|
||||||
|
|
||||||
|
if not g.project.has_member(sender_id):
|
||||||
|
return redirect(url_for(".settle_bill"))
|
||||||
|
|
||||||
settlement = Bill(
|
settlement = Bill(
|
||||||
amount=form.amount.data,
|
amount=form.amount.data,
|
||||||
date=datetime.datetime.today(),
|
date=datetime.datetime.today(),
|
||||||
owers=[Person.query.get(form.receiver_id.data)],
|
owers=[Person.query.get(receiver_id, g.project.id)],
|
||||||
payer_id=form.sender_id.data,
|
payer_id=sender_id,
|
||||||
project_default_currency=g.project.default_currency,
|
project_default_currency=g.project.default_currency,
|
||||||
bill_type=BillType.REIMBURSEMENT,
|
bill_type=BillType.REIMBURSEMENT,
|
||||||
what=_("Settlement"),
|
what=_("Settlement"),
|
||||||
|
@ -884,6 +895,7 @@ def add_settlement_bill():
|
||||||
db.session.add(settlement)
|
db.session.add(settlement)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
flash(_("Settlement bill has been successfully added"), category="success")
|
||||||
return redirect(url_for(".settle_bill"))
|
return redirect(url_for(".settle_bill"))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ build-backend = "hatchling.build"
|
||||||
[project]
|
[project]
|
||||||
name = "ihatemoney"
|
name = "ihatemoney"
|
||||||
version = "6.2.0.dev0"
|
version = "6.2.0.dev0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
description = "A simple shared budget manager web application."
|
description = "A simple shared budget manager web application."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = {file = "LICENSE"}
|
license = {file = "LICENSE"}
|
||||||
|
@ -15,8 +16,6 @@ keywords = ["web", "budget"]
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Programming Language :: Python",
|
"Programming Language :: Python",
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3.7",
|
|
||||||
"Programming Language :: Python :: 3.8",
|
|
||||||
"Programming Language :: Python :: 3.9",
|
"Programming Language :: Python :: 3.9",
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
|
@ -27,11 +26,12 @@ classifiers = [
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"blinker>=1.4,<2",
|
"blinker>=1.4,<2",
|
||||||
"cachetools>=4.1,<5",
|
"cachetools>=4.1,<6",
|
||||||
"debts>=0.5,<1",
|
"debts>=0.5,<1",
|
||||||
"email_validator>=1.0,<3",
|
"email_validator>=1.0,<3",
|
||||||
|
"Flask>=2,<4",
|
||||||
"Flask-Babel>=1.0,<4",
|
"Flask-Babel>=1.0,<4",
|
||||||
"Flask-Cors>=3.0.8,<4",
|
"Flask-Cors>=3.0.8,<6",
|
||||||
"Flask-Limiter>=2.6,<3",
|
"Flask-Limiter>=2.6,<3",
|
||||||
"Flask-Mail>=0.9.1,<1",
|
"Flask-Mail>=0.9.1,<1",
|
||||||
"Flask-Migrate>=2.5.3,<5", # Not following semantic versioning (e.g. https://github.com/miguelgrinberg/flask-migrate/commit/1af28ba273de6c88544623b8dc02dd539340294b)
|
"Flask-Migrate>=2.5.3,<5", # Not following semantic versioning (e.g. https://github.com/miguelgrinberg/flask-migrate/commit/1af28ba273de6c88544623b8dc02dd539340294b)
|
||||||
|
@ -39,41 +39,34 @@ dependencies = [
|
||||||
"Flask-SQLAlchemy>=2.4,<3",
|
"Flask-SQLAlchemy>=2.4,<3",
|
||||||
"Flask-Talisman>=0.8,<2",
|
"Flask-Talisman>=0.8,<2",
|
||||||
"Flask-WTF>=0.14.3,<2",
|
"Flask-WTF>=0.14.3,<2",
|
||||||
"WTForms>=2.3.3,<3.2",
|
|
||||||
"Flask>=2,<3",
|
|
||||||
"Werkzeug>=2,<3",
|
|
||||||
"itsdangerous>=2,<3",
|
"itsdangerous>=2,<3",
|
||||||
"Jinja2>=3,<4",
|
"Jinja2>=3,<4",
|
||||||
"qrcode>=7.1,<8",
|
|
||||||
"requests>=2.25,<3",
|
|
||||||
"SQLAlchemy-Continuum>=1.3.12,<2",
|
|
||||||
"SQLAlchemy>=1.3.0,<1.5", # New 1.4 changes API, see #728
|
|
||||||
"python-dateutil",
|
"python-dateutil",
|
||||||
]
|
"qrcode>=7.1,<9",
|
||||||
|
"requests>=2.25,<3",
|
||||||
|
"SQLAlchemy>=1.3.0,<1.5",
|
||||||
|
"SQLAlchemy-Continuum>=1.3.12,<2", # New 1.4 changes API, see #728
|
||||||
|
"Werkzeug>=2,<3",
|
||||||
|
"WTForms>=2.3.3,<3.3",]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
database = [
|
database = [
|
||||||
# Python 3.11 support starts in 2.9.2
|
# Python 3.11 support starts in 2.9.2
|
||||||
"psycopg2-binary>=2.9.2,<3",
|
"psycopg2-binary>=2.9.2,<2.9.11",
|
||||||
"PyMySQL>=0.9,<1.1",
|
"PyMySQL>=0.9,<1.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
dev = [
|
dev = [
|
||||||
"black==23.3.0",
|
"ruff==0.8.4",
|
||||||
"flake8==5.0.4",
|
|
||||||
"isort==5.11.5",
|
"isort==5.11.5",
|
||||||
"vermin==1.5.2",
|
"vermin==1.6.0",
|
||||||
"pytest>=6.2.5",
|
"pytest>=6.2.5",
|
||||||
"pytest-flask>=1.2.0",
|
"pytest-flask>=1.2.0",
|
||||||
"pytest-libfaketime>=0.1.2",
|
|
||||||
"tox>=3.14.6",
|
|
||||||
"zest.releaser>=6.20.1",
|
"zest.releaser>=6.20.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
doc = [
|
doc = [
|
||||||
"Sphinx>=7.0.1,<8",
|
"Sphinx>=7.0.1,<9",
|
||||||
"docutils==0.20.1",
|
"docutils==0.20.1",
|
||||||
"myst-parser>=2,<3",
|
"myst-parser>=2,<5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
@ -107,3 +100,7 @@ include = [
|
||||||
"README.md",
|
"README.md",
|
||||||
"SECURITY.md",
|
"SECURITY.md",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
exclude = ["ihatemoney/migrations"]
|
||||||
|
|
41
tox.ini
41
tox.ini
|
@ -1,41 +0,0 @@
|
||||||
[tox]
|
|
||||||
isolated_build = true
|
|
||||||
envlist = py312,py311,py310,py39,py38,py37,lint,docs
|
|
||||||
skip_missing_interpreters = True
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
passenv = TESTING_SQLALCHEMY_DATABASE_URI
|
|
||||||
|
|
||||||
commands =
|
|
||||||
python --version
|
|
||||||
py.test --pyargs ihatemoney.tests {posargs}
|
|
||||||
|
|
||||||
deps =
|
|
||||||
-e.[database,dev]
|
|
||||||
|
|
||||||
# To be sure we are importing ihatemoney pkg from pip-installed version
|
|
||||||
changedir = /tmp
|
|
||||||
|
|
||||||
[testenv:lint]
|
|
||||||
commands =
|
|
||||||
black --check --target-version=py37 .
|
|
||||||
isort --check --profile black .
|
|
||||||
flake8 ihatemoney
|
|
||||||
vermin --no-tips --violations -t=3.7- .
|
|
||||||
deps =
|
|
||||||
-e.[dev]
|
|
||||||
changedir = {toxinidir}
|
|
||||||
|
|
||||||
[testenv:docs]
|
|
||||||
commands =
|
|
||||||
sphinx-build -a -n -b html -d docs/_build/doctrees docs docs/_build/html
|
|
||||||
deps =
|
|
||||||
-e.[doc]
|
|
||||||
changedir = {toxinidir}
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
exclude = migrations
|
|
||||||
max_line_length = 100
|
|
||||||
extend-ignore =
|
|
||||||
# See https://github.com/PyCQA/pycodestyle/issues/373
|
|
||||||
E203,
|
|
Loading…
Reference in a new issue