Merge branch 'develop' into beta
This commit is contained in:
commit
9ecb087cd6
@ -1,4 +1,4 @@
|
||||
node_modules
|
||||
**/node_modules
|
||||
npm-debug.log
|
||||
Dockerfile*
|
||||
docker-compose*
|
||||
@ -12,6 +12,21 @@ LICENSE
|
||||
.env.template
|
||||
.github
|
||||
.idea
|
||||
.prettierignore
|
||||
LICENSE.md
|
||||
docs
|
||||
update.sh
|
||||
update.sh
|
||||
.pytest_cache
|
||||
cookbook/tests
|
||||
mediafiles
|
||||
staticfiles
|
||||
db.sqlite3
|
||||
pytest.ini
|
||||
vue/**/*.vue
|
||||
vue/**/*.ts
|
||||
**/.openapi-generator
|
||||
mkdocs.yml
|
||||
vue/babel.config*
|
||||
vue/package.json
|
||||
vue/tsconfig.json
|
||||
vue/src/utils/openapi
|
||||
|
@ -3,6 +3,9 @@
|
||||
DEBUG=0
|
||||
SQL_DEBUG=0
|
||||
|
||||
# HTTP port to bind to
|
||||
# TANDOOR_PORT=8080
|
||||
|
||||
# hosts the application can run under e.g. recipes.mydomain.com,cooking.mydomain.com,...
|
||||
ALLOWED_HOSTS=*
|
||||
|
||||
@ -146,7 +149,12 @@ REVERSE_PROXY_AUTH=0
|
||||
#AUTH_LDAP_BIND_DN=
|
||||
#AUTH_LDAP_BIND_PASSWORD=
|
||||
#AUTH_LDAP_USER_SEARCH_BASE_DN=
|
||||
#AUTH_LDAP_TLS_CACERTFILE=
|
||||
|
||||
# Enables exporting PDF (see export docs)
|
||||
# Disabled by default, uncomment to enable
|
||||
# ENABLE_PDF_EXPORT=1
|
||||
|
||||
# Recipe exports are cached for a certain time by default, adjust time if needed
|
||||
# EXPORT_FILE_CACHE_DURATION=600
|
||||
|
||||
|
8
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
8
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -29,11 +29,3 @@ body:
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Add any other context or screenshots about the feature request here."
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "Contribute"
|
||||
description: "Are you willing and able to help develop this feature?"
|
||||
options:
|
||||
- label: "Yes"
|
||||
- label: "Partly"
|
||||
- label: "No"
|
||||
|
@ -6,11 +6,17 @@ Please have a look at the [list of pull requests](https://github.com/vabene1111/
|
||||
a complete list of contributions.
|
||||
Below are some of the larger contributions made yet.
|
||||
|
||||
|
||||
- @tourn provided the serving feature and **several** other improvements!
|
||||
- @l0c4lh057 provided a much improved ingredient text parser in [#277](https://github.com/vabene1111/recipes/pull/277)
|
||||
- @sebimarkgraf added nutritional information [#199](https://github.com/vabene1111/recipes/pull/199)
|
||||
- @cazier added reverse proxy authentication [#88](https://github.com/vabene1111/recipes/pull/88)
|
||||
- [vabene1111]
|
||||
- [Kaibu]
|
||||
- [smilerz]
|
||||
- [MaxJa4] Docker builds and other improvements
|
||||
- [tourn] provided the serving feature and **several** other improvements!
|
||||
- [l0c4lh057] provided a much improved ingredient text parser in [#277](https://github.com/vabene1111/recipes/pull/277)
|
||||
- [sebimarkgraf] added nutritional information [#199](https://github.com/vabene1111/recipes/pull/199)
|
||||
- [cazier] added reverse proxy authentication [#88](https://github.com/vabene1111/recipes/pull/88)
|
||||
- [murphy83] added support for IPv6 #1490
|
||||
- [TheHaf] added custom serving size component #1411
|
||||
- [lostlont] added LDAP support #960
|
||||
|
||||
## Translations
|
||||
|
||||
@ -30,6 +36,7 @@ Below are some of the larger contributions made yet.
|
||||
### German
|
||||
[eTaurus](https://www.transifex.com/user/profile/eTaurus/)
|
||||
[l0c4lh057](https://www.transifex.com/user/profile/l0c4lh057/)
|
||||
[hyperbit00]
|
||||
|
||||
### Hungarian
|
||||
[igazka](https://www.transifex.com/user/profile/igazka/)
|
||||
@ -60,4 +67,4 @@ Below are some of the larger contributions made yet.
|
||||
|
||||
### Vietnamese
|
||||
|
||||
[vuongtrunghieu](https://www.transifex.com/user/profile/vuongtrunghieu/)
|
||||
[vuongtrunghieu](https://www.transifex.com/user/profile/vuongtrunghieu/)
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM python:3.9-alpine3.12
|
||||
FROM python:3.10-alpine3.15
|
||||
|
||||
#Install all dependencies.
|
||||
RUN apk add --no-cache postgresql-libs gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography
|
||||
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography
|
||||
|
||||
#Print all logs without buffering it.
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
@ -16,6 +16,7 @@ WORKDIR /opt/recipes
|
||||
COPY requirements.txt ./
|
||||
|
||||
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev libressl-dev libffi-dev cargo openssl-dev openldap-dev && \
|
||||
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
|
||||
python -m venv venv && \
|
||||
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
|
||||
venv/bin/pip install wheel==0.36.2 && \
|
||||
|
53
boot.sh
53
boot.sh
@ -1,12 +1,61 @@
|
||||
#!/bin/sh
|
||||
source venv/bin/activate
|
||||
|
||||
echo "Updating database"
|
||||
TANDOOR_PORT="${TANDOOR_PORT:-8080}"
|
||||
NGINX_CONF_FILE=/opt/recipes/nginx/conf.d/Recipes.conf
|
||||
|
||||
display_warning() {
|
||||
echo "[WARNING]"
|
||||
echo -e "$1"
|
||||
}
|
||||
|
||||
echo "Checking configuration..."
|
||||
|
||||
# Nginx config file must exist if gunicorn is not active
|
||||
if [ ! -f "$NGINX_CONF_FILE" ] && [ $GUNICORN_MEDIA -eq 0 ]; then
|
||||
display_warning "Nginx configuration file could not be found at the default location!\nPath: ${NGINX_CONF_FILE}"
|
||||
fi
|
||||
|
||||
# SECRET_KEY must be set in .env file
|
||||
if [ -z "${SECRET_KEY}" ]; then
|
||||
display_warning "The environment variable 'SECRET_KEY' is not set but REQUIRED for running Tandoor!"
|
||||
fi
|
||||
|
||||
# POSTGRES_PASSWORD must be set in .env file
|
||||
if [ -z "${POSTGRES_PASSWORD}" ]; then
|
||||
display_warning "The environment variable 'POSTGRES_PASSWORD' is not set but REQUIRED for running Tandoor!"
|
||||
fi
|
||||
|
||||
echo "Waiting for database to be ready..."
|
||||
|
||||
attempt=0
|
||||
max_attempts=20
|
||||
while pg_isready --host=${POSTGRES_HOST} -q; status=$?; attempt=$((attempt+1)); [ $status -ne 0 ] && [ $attempt -le $max_attempts ]; do
|
||||
sleep 5
|
||||
done
|
||||
|
||||
if [ $attempt -gt $max_attempts ]; then
|
||||
echo -e "\nDatabase not reachable. Maximum attempts exceeded."
|
||||
echo "Please check logs above - misconfiguration is very likely."
|
||||
echo "Make sure the DB container is up and POSTGRES_HOST is set properly."
|
||||
echo "Shutting down container."
|
||||
exit 1 # exit with error to make the container stop
|
||||
fi
|
||||
|
||||
echo "Database is ready"
|
||||
|
||||
echo "Migrating database"
|
||||
|
||||
|
||||
python manage.py migrate
|
||||
|
||||
echo "Generating static files"
|
||||
|
||||
python manage.py collectstatic_js_reverse
|
||||
python manage.py collectstatic --noinput
|
||||
|
||||
echo "Done"
|
||||
|
||||
chmod -R 755 /opt/recipes/mediafiles
|
||||
|
||||
exec gunicorn -b :8080 --access-logfile - --error-logfile - --log-level INFO recipes.wsgi
|
||||
exec gunicorn -b :$TANDOOR_PORT --access-logfile - --error-logfile - --log-level INFO recipes.wsgi
|
@ -179,6 +179,7 @@ class ImportForm(ImportExportBase):
|
||||
class ExportForm(ImportExportBase):
|
||||
recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=Recipe.objects.none(), required=False)
|
||||
all = forms.BooleanField(required=False)
|
||||
custom_filter = forms.IntegerField(required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
space = kwargs.pop('space')
|
||||
|
@ -205,9 +205,9 @@ class CustomIsShared(permissions.BasePermission):
|
||||
return request.user.is_authenticated
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
# temporary hack to make old shopping list work with new shopping list
|
||||
if obj.__class__.__name__ == 'ShoppingList':
|
||||
return is_object_shared(request.user, obj) or obj.created_by in list(request.user.get_shopping_share())
|
||||
# # temporary hack to make old shopping list work with new shopping list
|
||||
# if obj.__class__.__name__ in ['ShoppingList', 'ShoppingListEntry']:
|
||||
# return is_object_shared(request.user, obj) or obj.created_by in list(request.user.get_shopping_share())
|
||||
return is_object_shared(request.user, obj)
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
import random
|
||||
import re
|
||||
from html import unescape
|
||||
from unicodedata import decomposition
|
||||
|
||||
from django.utils.dateparse import parse_duration
|
||||
from isodate import parse_duration as iso_parse_duration
|
||||
@ -116,7 +117,7 @@ def get_from_scraper(scrape, request):
|
||||
'id': random.randrange(10000, 99999)
|
||||
},
|
||||
'note': note,
|
||||
'original': x
|
||||
'original_text': x
|
||||
}
|
||||
)
|
||||
except Exception:
|
||||
@ -132,7 +133,7 @@ def get_from_scraper(scrape, request):
|
||||
'id': random.randrange(10000, 99999)
|
||||
},
|
||||
'note': '',
|
||||
'original': x
|
||||
'original_text': x
|
||||
}
|
||||
)
|
||||
recipe_json['recipeIngredient'] = ingredients
|
||||
@ -198,7 +199,7 @@ def parse_ingredients(ingredients):
|
||||
'id': random.randrange(10000, 99999)
|
||||
},
|
||||
'note': note,
|
||||
'original': x
|
||||
'original_text': x
|
||||
}
|
||||
)
|
||||
except Exception:
|
||||
@ -214,7 +215,7 @@ def parse_ingredients(ingredients):
|
||||
'id': random.randrange(10000, 99999)
|
||||
},
|
||||
'note': '',
|
||||
'original': x
|
||||
'original_text': x
|
||||
}
|
||||
)
|
||||
|
||||
@ -332,7 +333,7 @@ def parse_keywords(keyword_json, space):
|
||||
kw = normalize_string(kw)
|
||||
if len(kw) != 0:
|
||||
if k := Keyword.objects.filter(name=kw, space=space).first():
|
||||
keywords.append({'id': str(k.id), 'text': str(k)})
|
||||
keywords.append({'id': str(k.id), 'text': str(k.name)})
|
||||
else:
|
||||
keywords.append({'id': random.randrange(1111111, 9999999, 1), 'text': kw})
|
||||
|
||||
|
@ -8,7 +8,7 @@ from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from cookbook.helper.HelperFunctions import Round, str2bool
|
||||
from cookbook.models import (Ingredient, ShoppingListEntry, ShoppingListRecipe,
|
||||
from cookbook.models import (Ingredient, MealPlan, Recipe, ShoppingListEntry, ShoppingListRecipe,
|
||||
SupermarketCategoryRelation)
|
||||
from recipes import settings
|
||||
|
||||
@ -35,121 +35,279 @@ def shopping_helper(qs, request):
|
||||
qs = qs.filter(Q(checked=False) | Q(completed_at__gte=week_ago))
|
||||
supermarket_order = ['checked'] + supermarket_order
|
||||
|
||||
return qs.order_by(*supermarket_order).select_related('unit', 'food', 'ingredient', 'created_by', 'list_recipe', 'list_recipe__mealplan', 'list_recipe__recipe')
|
||||
return qs.distinct().order_by(*supermarket_order).select_related('unit', 'food', 'ingredient', 'created_by', 'list_recipe', 'list_recipe__mealplan', 'list_recipe__recipe')
|
||||
|
||||
|
||||
# TODO refactor as class
|
||||
def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None, ingredients=None, created_by=None, space=None, append=False):
|
||||
"""
|
||||
Creates ShoppingListRecipe and associated ShoppingListEntrys from a recipe or a meal plan with a recipe
|
||||
:param list_recipe: Modify an existing ShoppingListRecipe
|
||||
:param recipe: Recipe to use as list of ingredients. One of [recipe, mealplan] are required
|
||||
:param mealplan: alternatively use a mealplan recipe as source of ingredients
|
||||
:param servings: Optional: Number of servings to use to scale shoppinglist. If servings = 0 an existing recipe list will be deleted
|
||||
:param ingredients: Ingredients, list of ingredient IDs to include on the shopping list. When not provided all ingredients will be used
|
||||
:param append: If False will remove any entries not included with ingredients, when True will append ingredients to the shopping list
|
||||
"""
|
||||
r = recipe or getattr(mealplan, 'recipe', None) or getattr(list_recipe, 'recipe', None)
|
||||
if not r:
|
||||
raise ValueError(_("You must supply a recipe or mealplan"))
|
||||
class RecipeShoppingEditor():
|
||||
def __init__(self, user, space, **kwargs):
|
||||
self.created_by = user
|
||||
self.space = space
|
||||
self._kwargs = {**kwargs}
|
||||
|
||||
created_by = created_by or getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', None)
|
||||
if not created_by:
|
||||
raise ValueError(_("You must supply a created_by"))
|
||||
self.mealplan = self._kwargs.get('mealplan', None)
|
||||
if type(self.mealplan) in [int, float]:
|
||||
self.mealplan = MealPlan.objects.filter(id=self.mealplan, space=self.space)
|
||||
self.id = self._kwargs.get('id', None)
|
||||
|
||||
try:
|
||||
servings = float(servings)
|
||||
except (ValueError, TypeError):
|
||||
servings = getattr(mealplan, 'servings', 1.0)
|
||||
self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space)
|
||||
|
||||
servings_factor = servings / r.servings
|
||||
if self._shopping_list_recipe:
|
||||
# created_by needs to be sticky to original creator as it is 'their' shopping list
|
||||
# changing shopping list created_by can shift some items to new owner which may not share in the other direction
|
||||
self.created_by = getattr(self._shopping_list_recipe.entries.first(), 'created_by', self.created_by)
|
||||
|
||||
shared_users = list(created_by.get_shopping_share())
|
||||
shared_users.append(created_by)
|
||||
if list_recipe:
|
||||
created = False
|
||||
else:
|
||||
list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings)
|
||||
created = True
|
||||
self.recipe = getattr(self._shopping_list_recipe, 'recipe', None) or self._kwargs.get('recipe', None) or getattr(self.mealplan, 'recipe', None)
|
||||
if type(self.recipe) in [int, float]:
|
||||
self.recipe = Recipe.objects.filter(id=self.recipe, space=self.space)
|
||||
|
||||
related_step_ing = []
|
||||
if servings == 0 and not created:
|
||||
list_recipe.delete()
|
||||
return []
|
||||
elif ingredients:
|
||||
ingredients = Ingredient.objects.filter(pk__in=ingredients, space=space)
|
||||
else:
|
||||
ingredients = Ingredient.objects.filter(step__recipe=r, space=space)
|
||||
try:
|
||||
self.servings = float(self._kwargs.get('servings', None))
|
||||
except (ValueError, TypeError):
|
||||
self.servings = getattr(self._shopping_list_recipe, 'servings', None) or getattr(self.mealplan, 'servings', None) or getattr(self.recipe, 'servings', None)
|
||||
|
||||
if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
|
||||
ingredients = ingredients.exclude(food__onhand_users__id__in=[x.id for x in shared_users])
|
||||
@property
|
||||
def _recipe_servings(self):
|
||||
return getattr(self.recipe, 'servings', None) or getattr(getattr(self.mealplan, 'recipe', None), 'servings', None) or getattr(getattr(self._shopping_list_recipe, 'recipe', None), 'servings', None)
|
||||
|
||||
if related := created_by.userpreference.mealplan_autoinclude_related:
|
||||
# TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans
|
||||
related_recipes = r.get_related_recipes()
|
||||
@property
|
||||
def _servings_factor(self):
|
||||
return Decimal(self.servings)/Decimal(self._recipe_servings)
|
||||
|
||||
for x in related_recipes:
|
||||
# related recipe is a Step serving size is driven by recipe serving size
|
||||
# TODO once/if Steps can have a serving size this needs to be refactored
|
||||
if exclude_onhand:
|
||||
# if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior
|
||||
related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]).values_list('id', flat=True)
|
||||
else:
|
||||
related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True)
|
||||
@property
|
||||
def _shared_users(self):
|
||||
return [*list(self.created_by.get_shopping_share()), self.created_by]
|
||||
|
||||
x_ing = []
|
||||
if ingredients.filter(food__recipe=x).exists():
|
||||
for ing in ingredients.filter(food__recipe=x):
|
||||
if exclude_onhand:
|
||||
x_ing = Ingredient.objects.filter(step__recipe=x, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users])
|
||||
else:
|
||||
x_ing = Ingredient.objects.filter(step__recipe=x, space=space)
|
||||
for i in [x for x in x_ing]:
|
||||
ShoppingListEntry.objects.create(
|
||||
list_recipe=list_recipe,
|
||||
food=i.food,
|
||||
unit=i.unit,
|
||||
ingredient=i,
|
||||
amount=i.amount * Decimal(servings_factor),
|
||||
created_by=created_by,
|
||||
space=space,
|
||||
)
|
||||
# dont' add food to the shopping list that are actually recipes that will be added as ingredients
|
||||
ingredients = ingredients.exclude(food__recipe=x)
|
||||
@staticmethod
|
||||
def get_shopping_list_recipe(id, user, space):
|
||||
return ShoppingListRecipe.objects.filter(id=id).filter(Q(shoppinglist__space=space) | Q(entries__space=space)).filter(
|
||||
Q(shoppinglist__created_by=user)
|
||||
| Q(shoppinglist__shared=user)
|
||||
| Q(entries__created_by=user)
|
||||
| Q(entries__created_by__in=list(user.get_shopping_share()))
|
||||
).prefetch_related('entries').first()
|
||||
|
||||
add_ingredients = list(ingredients.values_list('id', flat=True)) + related_step_ing
|
||||
if not append:
|
||||
existing_list = ShoppingListEntry.objects.filter(list_recipe=list_recipe)
|
||||
# delete shopping list entries not included in ingredients
|
||||
existing_list.exclude(ingredient__in=ingredients).delete()
|
||||
# add shopping list entries that did not previously exist
|
||||
add_ingredients = set(add_ingredients) - set(existing_list.values_list('ingredient__id', flat=True))
|
||||
add_ingredients = Ingredient.objects.filter(id__in=add_ingredients, space=space)
|
||||
def get_recipe_ingredients(self, id, exclude_onhand=False):
|
||||
if exclude_onhand:
|
||||
return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space).exclude(food__onhand_users__id__in=[x.id for x in self._shared_users])
|
||||
else:
|
||||
return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space)
|
||||
|
||||
# if servings have changed, update the ShoppingListRecipe and existing Entries
|
||||
if servings <= 0:
|
||||
servings = 1
|
||||
@property
|
||||
def _include_related(self):
|
||||
return self.created_by.userpreference.mealplan_autoinclude_related
|
||||
|
||||
if not created and list_recipe.servings != servings:
|
||||
update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True))
|
||||
list_recipe.servings = servings
|
||||
list_recipe.save()
|
||||
for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients):
|
||||
sle.amount = sle.ingredient.amount * Decimal(servings_factor)
|
||||
@property
|
||||
def _exclude_onhand(self):
|
||||
return self.created_by.userpreference.mealplan_autoexclude_onhand
|
||||
|
||||
def create(self, **kwargs):
|
||||
ingredients = kwargs.get('ingredients', None)
|
||||
exclude_onhand = not ingredients and self._exclude_onhand
|
||||
if servings := kwargs.get('servings', None):
|
||||
self.servings = float(servings)
|
||||
|
||||
if mealplan := kwargs.get('mealplan', None):
|
||||
self.mealplan = mealplan
|
||||
self.recipe = mealplan.recipe
|
||||
elif recipe := kwargs.get('recipe', None):
|
||||
self.recipe = recipe
|
||||
|
||||
if not self.servings:
|
||||
self.servings = getattr(self.mealplan, 'servings', None) or getattr(self.recipe, 'servings', 1.0)
|
||||
|
||||
self._shopping_list_recipe = ShoppingListRecipe.objects.create(recipe=self.recipe, mealplan=self.mealplan, servings=self.servings)
|
||||
|
||||
if ingredients:
|
||||
self._add_ingredients(ingredients=ingredients)
|
||||
else:
|
||||
if self._include_related:
|
||||
related = self.recipe.get_related_recipes()
|
||||
self._add_ingredients(self.get_recipe_ingredients(self.recipe.id, exclude_onhand=exclude_onhand).exclude(food__recipe__in=related))
|
||||
for r in related:
|
||||
self._add_ingredients(self.get_recipe_ingredients(r.id, exclude_onhand=exclude_onhand).exclude(food__recipe__in=related))
|
||||
else:
|
||||
self._add_ingredients(self.get_recipe_ingredients(self.recipe.id, exclude_onhand=exclude_onhand))
|
||||
|
||||
return True
|
||||
|
||||
def add(self, **kwargs):
|
||||
return
|
||||
|
||||
def edit(self, servings=None, ingredients=None, **kwargs):
|
||||
if servings:
|
||||
self.servings = servings
|
||||
|
||||
self._delete_ingredients(ingredients=ingredients)
|
||||
if self.servings != self._shopping_list_recipe.servings:
|
||||
self.edit_servings()
|
||||
self._add_ingredients(ingredients=ingredients)
|
||||
return True
|
||||
|
||||
def edit_servings(self, servings=None, **kwargs):
|
||||
if servings:
|
||||
self.servings = servings
|
||||
if id := kwargs.get('id', None):
|
||||
self._shopping_list_recipe = self.get_shopping_list_recipe(id, self.created_by, self.space)
|
||||
if not self.servings:
|
||||
raise ValueError(_("You must supply a servings size"))
|
||||
|
||||
if self._shopping_list_recipe.servings == self.servings:
|
||||
return True
|
||||
|
||||
for sle in ShoppingListEntry.objects.filter(list_recipe=self._shopping_list_recipe):
|
||||
sle.amount = sle.ingredient.amount * Decimal(self._servings_factor)
|
||||
sle.save()
|
||||
self._shopping_list_recipe.servings = self.servings
|
||||
self._shopping_list_recipe.save()
|
||||
return True
|
||||
|
||||
# add any missing Entries
|
||||
for i in [x for x in add_ingredients if x.food]:
|
||||
def delete(self, **kwargs):
|
||||
try:
|
||||
self._shopping_list_recipe.delete()
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
ShoppingListEntry.objects.create(
|
||||
list_recipe=list_recipe,
|
||||
food=i.food,
|
||||
unit=i.unit,
|
||||
ingredient=i,
|
||||
amount=i.amount * Decimal(servings_factor),
|
||||
created_by=created_by,
|
||||
space=space,
|
||||
)
|
||||
def _add_ingredients(self, ingredients=None):
|
||||
if not ingredients:
|
||||
return
|
||||
elif type(ingredients) == list:
|
||||
ingredients = Ingredient.objects.filter(id__in=ingredients)
|
||||
existing = self._shopping_list_recipe.entries.filter(ingredient__in=ingredients).values_list('ingredient__pk', flat=True)
|
||||
add_ingredients = ingredients.exclude(id__in=existing)
|
||||
|
||||
# return all shopping list items
|
||||
return list_recipe
|
||||
for i in [x for x in add_ingredients if x.food]:
|
||||
ShoppingListEntry.objects.create(
|
||||
list_recipe=self._shopping_list_recipe,
|
||||
food=i.food,
|
||||
unit=i.unit,
|
||||
ingredient=i,
|
||||
amount=i.amount * Decimal(self._servings_factor),
|
||||
created_by=self.created_by,
|
||||
space=self.space,
|
||||
)
|
||||
|
||||
# deletes shopping list entries not in ingredients list
|
||||
def _delete_ingredients(self, ingredients=None):
|
||||
if not ingredients:
|
||||
return
|
||||
to_delete = self._shopping_list_recipe.entries.exclude(ingredient__in=ingredients)
|
||||
ShoppingListEntry.objects.filter(id__in=to_delete).delete()
|
||||
self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space)
|
||||
|
||||
|
||||
# # TODO refactor as class
|
||||
# def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None, ingredients=None, created_by=None, space=None, append=False):
|
||||
# """
|
||||
# Creates ShoppingListRecipe and associated ShoppingListEntrys from a recipe or a meal plan with a recipe
|
||||
# :param list_recipe: Modify an existing ShoppingListRecipe
|
||||
# :param recipe: Recipe to use as list of ingredients. One of [recipe, mealplan] are required
|
||||
# :param mealplan: alternatively use a mealplan recipe as source of ingredients
|
||||
# :param servings: Optional: Number of servings to use to scale shoppinglist. If servings = 0 an existing recipe list will be deleted
|
||||
# :param ingredients: Ingredients, list of ingredient IDs to include on the shopping list. When not provided all ingredients will be used
|
||||
# :param append: If False will remove any entries not included with ingredients, when True will append ingredients to the shopping list
|
||||
# """
|
||||
# r = recipe or getattr(mealplan, 'recipe', None) or getattr(list_recipe, 'recipe', None)
|
||||
# if not r:
|
||||
# raise ValueError(_("You must supply a recipe or mealplan"))
|
||||
|
||||
# created_by = created_by or getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', None)
|
||||
# if not created_by:
|
||||
# raise ValueError(_("You must supply a created_by"))
|
||||
|
||||
# try:
|
||||
# servings = float(servings)
|
||||
# except (ValueError, TypeError):
|
||||
# servings = getattr(mealplan, 'servings', 1.0)
|
||||
|
||||
# servings_factor = servings / r.servings
|
||||
|
||||
# shared_users = list(created_by.get_shopping_share())
|
||||
# shared_users.append(created_by)
|
||||
# if list_recipe:
|
||||
# created = False
|
||||
# else:
|
||||
# list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings)
|
||||
# created = True
|
||||
|
||||
# related_step_ing = []
|
||||
# if servings == 0 and not created:
|
||||
# list_recipe.delete()
|
||||
# return []
|
||||
# elif ingredients:
|
||||
# ingredients = Ingredient.objects.filter(pk__in=ingredients, space=space)
|
||||
# else:
|
||||
# ingredients = Ingredient.objects.filter(step__recipe=r, food__ignore_shopping=False, space=space)
|
||||
|
||||
# if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
|
||||
# ingredients = ingredients.exclude(food__onhand_users__id__in=[x.id for x in shared_users])
|
||||
|
||||
# if related := created_by.userpreference.mealplan_autoinclude_related:
|
||||
# # TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans
|
||||
# related_recipes = r.get_related_recipes()
|
||||
|
||||
# for x in related_recipes:
|
||||
# # related recipe is a Step serving size is driven by recipe serving size
|
||||
# # TODO once/if Steps can have a serving size this needs to be refactored
|
||||
# if exclude_onhand:
|
||||
# # if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior
|
||||
# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]).values_list('id', flat=True)
|
||||
# else:
|
||||
# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True)
|
||||
|
||||
# x_ing = []
|
||||
# if ingredients.filter(food__recipe=x).exists():
|
||||
# for ing in ingredients.filter(food__recipe=x):
|
||||
# if exclude_onhand:
|
||||
# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users])
|
||||
# else:
|
||||
# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__ignore_shopping=True)
|
||||
# for i in [x for x in x_ing]:
|
||||
# ShoppingListEntry.objects.create(
|
||||
# list_recipe=list_recipe,
|
||||
# food=i.food,
|
||||
# unit=i.unit,
|
||||
# ingredient=i,
|
||||
# amount=i.amount * Decimal(servings_factor),
|
||||
# created_by=created_by,
|
||||
# space=space,
|
||||
# )
|
||||
# # dont' add food to the shopping list that are actually recipes that will be added as ingredients
|
||||
# ingredients = ingredients.exclude(food__recipe=x)
|
||||
|
||||
# add_ingredients = list(ingredients.values_list('id', flat=True)) + related_step_ing
|
||||
# if not append:
|
||||
# existing_list = ShoppingListEntry.objects.filter(list_recipe=list_recipe)
|
||||
# # delete shopping list entries not included in ingredients
|
||||
# existing_list.exclude(ingredient__in=ingredients).delete()
|
||||
# # add shopping list entries that did not previously exist
|
||||
# add_ingredients = set(add_ingredients) - set(existing_list.values_list('ingredient__id', flat=True))
|
||||
# add_ingredients = Ingredient.objects.filter(id__in=add_ingredients, space=space)
|
||||
|
||||
# # if servings have changed, update the ShoppingListRecipe and existing Entries
|
||||
# if servings <= 0:
|
||||
# servings = 1
|
||||
|
||||
# if not created and list_recipe.servings != servings:
|
||||
# update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True))
|
||||
# list_recipe.servings = servings
|
||||
# list_recipe.save()
|
||||
# for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients):
|
||||
# sle.amount = sle.ingredient.amount * Decimal(servings_factor)
|
||||
# sle.save()
|
||||
|
||||
# # add any missing Entries
|
||||
# for i in [x for x in add_ingredients if x.food]:
|
||||
|
||||
# ShoppingListEntry.objects.create(
|
||||
# list_recipe=list_recipe,
|
||||
# food=i.food,
|
||||
# unit=i.unit,
|
||||
# ingredient=i,
|
||||
# amount=i.amount * Decimal(servings_factor),
|
||||
# created_by=created_by,
|
||||
# space=space,
|
||||
# )
|
||||
|
||||
# # return all shopping list items
|
||||
# return list_recipe
|
||||
|
@ -1,11 +1,14 @@
|
||||
from gettext import gettext as _
|
||||
|
||||
import bleach
|
||||
import markdown as md
|
||||
from bleach_allowlist import markdown_attrs, markdown_tags
|
||||
from jinja2 import Template, TemplateSyntaxError, UndefinedError
|
||||
from markdown.extensions.tables import TableExtension
|
||||
|
||||
from cookbook.helper.mdx_attributes import MarkdownFormatExtension
|
||||
from cookbook.helper.mdx_urlize import UrlizeExtension
|
||||
from jinja2 import Template, TemplateSyntaxError, UndefinedError
|
||||
from gettext import gettext as _
|
||||
from markdown.extensions.tables import TableExtension
|
||||
|
||||
|
||||
class IngredientObject(object):
|
||||
amount = ""
|
||||
|
@ -2,14 +2,14 @@ import re
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient
|
||||
from cookbook.models import Ingredient, Recipe, Step
|
||||
|
||||
|
||||
class ChefTap(Integration):
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
print("testing", zip_info_object.filename)
|
||||
return re.match(r'^cheftap_export/([A-Za-z\d\w\s-])+.txt$', zip_info_object.filename) or re.match(r'^([A-Za-z\d\w\s-])+.txt$', zip_info_object.filename)
|
||||
return re.match(r'^cheftap_export/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.txt$', zip_info_object.filename) or re.match(r'^([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.txt$', zip_info_object.filename)
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
source_url = ''
|
||||
@ -45,11 +45,11 @@ class ChefTap(Integration):
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in ingredients:
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
|
@ -5,14 +5,14 @@ from zipfile import ZipFile
|
||||
from cookbook.helper.image_processing import get_filetype
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class Chowdown(Integration):
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
print("testing", zip_info_object.filename)
|
||||
return re.match(r'^(_)*recipes/([A-Za-z\d\s-])+.md$', zip_info_object.filename)
|
||||
return re.match(r'^(_)*recipes/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.md$', zip_info_object.filename)
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
ingredient_mode = False
|
||||
@ -60,12 +60,13 @@ class Chowdown(Integration):
|
||||
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in ingredients:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
))
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
for f in self.files:
|
||||
|
@ -2,6 +2,7 @@ import base64
|
||||
import gzip
|
||||
import json
|
||||
import re
|
||||
from gettext import gettext as _
|
||||
from io import BytesIO
|
||||
|
||||
import requests
|
||||
@ -11,8 +12,7 @@ from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.helper.recipe_html_import import get_recipe_from_source
|
||||
from cookbook.helper.recipe_url_import import iso_duration_to_minutes
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from gettext import gettext as _
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class CookBookApp(Integration):
|
||||
@ -51,11 +51,11 @@ class CookBookApp(Integration):
|
||||
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in recipe_json['recipeIngredient']:
|
||||
f = ingredient_parser.get_food(ingredient['ingredient']['text'])
|
||||
u = ingredient_parser.get_unit(ingredient['unit']['text'])
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=ingredient['amount'], note=ingredient['note'], space=self.request.space,
|
||||
))
|
||||
f = ingredient_parser.get_food(ingredient['ingredient']['text'])
|
||||
u = ingredient_parser.get_unit(ingredient['unit']['text'])
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=ingredient['amount'], note=ingredient['note'], space=self.request.space,
|
||||
))
|
||||
|
||||
if len(images) > 0:
|
||||
try:
|
||||
|
@ -8,7 +8,7 @@ from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.helper.recipe_html_import import get_recipe_from_source
|
||||
from cookbook.helper.recipe_url_import import iso_duration_to_minutes, parse_servings
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
from recipes.settings import DEBUG
|
||||
|
||||
|
||||
@ -41,11 +41,11 @@ class CopyMeThat(Integration):
|
||||
for ingredient in file.find_all("li", {"class": "recipeIngredient"}):
|
||||
if ingredient.text == "":
|
||||
continue
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient.text.strip())
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient.text.strip(), space=self.request.space,
|
||||
))
|
||||
|
||||
for s in file.find_all("li", {"class": "instruction"}):
|
||||
|
@ -32,11 +32,12 @@ class Default(Integration):
|
||||
return None
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
|
||||
export = RecipeExportSerializer(recipe).data
|
||||
|
||||
return 'recipe.json', JSONRenderer().render(export).decode("utf-8")
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
export_zip_stream = BytesIO()
|
||||
export_zip_obj = ZipFile(export_zip_stream, 'w')
|
||||
|
||||
@ -50,13 +51,20 @@ class Default(Integration):
|
||||
recipe_stream.write(data)
|
||||
recipe_zip_obj.writestr(filename, recipe_stream.getvalue())
|
||||
recipe_stream.close()
|
||||
|
||||
try:
|
||||
recipe_zip_obj.writestr(f'image{get_filetype(r.image.file.name)}', r.image.file.read())
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
recipe_zip_obj.close()
|
||||
|
||||
export_zip_obj.writestr(str(r.pk) + '.zip', recipe_zip_stream.getvalue())
|
||||
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(r)
|
||||
el.save()
|
||||
|
||||
export_zip_obj.close()
|
||||
|
||||
return [[ 'export.zip', export_zip_stream.getvalue() ]]
|
||||
return [[ self.get_export_file_name(), export_zip_stream.getvalue() ]]
|
@ -4,7 +4,7 @@ from io import BytesIO
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient
|
||||
from cookbook.models import Ingredient, Recipe, Step
|
||||
|
||||
|
||||
class Domestica(Integration):
|
||||
@ -37,11 +37,11 @@ class Domestica(Integration):
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in file['ingredients'].split('\n'):
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
import time
|
||||
import datetime
|
||||
import json
|
||||
import traceback
|
||||
import uuid
|
||||
from io import BytesIO, StringIO
|
||||
from zipfile import BadZipFile, ZipFile
|
||||
from django.core.cache import cache
|
||||
import datetime
|
||||
|
||||
from bs4 import Tag
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
@ -18,6 +21,7 @@ from cookbook.forms import ImportExportBase
|
||||
from cookbook.helper.image_processing import get_filetype, handle_image
|
||||
from cookbook.models import Keyword, Recipe
|
||||
from recipes.settings import DEBUG
|
||||
from recipes.settings import EXPORT_FILE_CACHE_DURATION
|
||||
|
||||
|
||||
class Integration:
|
||||
@ -61,35 +65,44 @@ class Integration:
|
||||
space=request.space
|
||||
)
|
||||
|
||||
def do_export(self, recipes):
|
||||
"""
|
||||
Perform the export based on a list of recipes
|
||||
:param recipes: list of recipe objects
|
||||
:return: HttpResponse with the file of the requested export format that is directly downloaded (When that format involve multiple files they are zipped together)
|
||||
"""
|
||||
|
||||
files = self.get_files_from_recipes(recipes, self.request.COOKIES)
|
||||
|
||||
if len(files) == 1:
|
||||
filename, file = files[0]
|
||||
export_filename = filename
|
||||
export_file = file
|
||||
def do_export(self, recipes, el):
|
||||
|
||||
else:
|
||||
export_filename = "export.zip"
|
||||
export_stream = BytesIO()
|
||||
export_obj = ZipFile(export_stream, 'w')
|
||||
with scope(space=self.request.space):
|
||||
el.total_recipes = len(recipes)
|
||||
el.cache_duration = EXPORT_FILE_CACHE_DURATION
|
||||
el.save()
|
||||
|
||||
for filename, file in files:
|
||||
export_obj.writestr(filename, file)
|
||||
files = self.get_files_from_recipes(recipes, el, self.request.COOKIES)
|
||||
|
||||
export_obj.close()
|
||||
export_file = export_stream.getvalue()
|
||||
if len(files) == 1:
|
||||
filename, file = files[0]
|
||||
export_filename = filename
|
||||
export_file = file
|
||||
|
||||
else:
|
||||
#zip the files if there is more then one file
|
||||
export_filename = self.get_export_file_name()
|
||||
export_stream = BytesIO()
|
||||
export_obj = ZipFile(export_stream, 'w')
|
||||
|
||||
for filename, file in files:
|
||||
export_obj.writestr(filename, file)
|
||||
|
||||
export_obj.close()
|
||||
export_file = export_stream.getvalue()
|
||||
|
||||
|
||||
cache.set('export_file_'+str(el.pk), {'filename': export_filename, 'file': export_file}, EXPORT_FILE_CACHE_DURATION)
|
||||
el.running = False
|
||||
el.save()
|
||||
|
||||
response = HttpResponse(export_file, content_type='application/force-download')
|
||||
response['Content-Disposition'] = 'attachment; filename="' + export_filename + '"'
|
||||
return response
|
||||
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
"""
|
||||
Since zipfile.namelist() returns all files in all subdirectories this function allows filtering of files
|
||||
@ -126,7 +139,7 @@ class Integration:
|
||||
for d in data_list:
|
||||
recipe = self.get_recipe_from_file(d)
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -151,7 +164,7 @@ class Integration:
|
||||
else:
|
||||
recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename)))
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -159,14 +172,14 @@ class Integration:
|
||||
traceback.print_exc()
|
||||
self.handle_exception(e, log=il, message=f'-------------------- \nERROR \n{e}\n--------------------\n')
|
||||
import_zip.close()
|
||||
elif '.json' in f['name'] or '.txt' in f['name'] or '.mmf' in f['name']:
|
||||
elif '.json' in f['name'] or '.txt' in f['name'] or '.mmf' in f['name'] or '.rk' in f['name']:
|
||||
data_list = self.split_recipe_file(f['file'])
|
||||
il.total_recipes += len(data_list)
|
||||
for d in data_list:
|
||||
try:
|
||||
recipe = self.get_recipe_from_file(d)
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -183,7 +196,7 @@ class Integration:
|
||||
try:
|
||||
recipe = self.get_recipe_from_file(d)
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -193,7 +206,7 @@ class Integration:
|
||||
else:
|
||||
recipe = self.get_recipe_from_file(f['file'])
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
except BadZipFile:
|
||||
il.msg += 'ERROR ' + _(
|
||||
@ -260,7 +273,7 @@ class Integration:
|
||||
"""
|
||||
raise NotImplementedError('Method not implemented in integration')
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
"""
|
||||
Takes a list of recipe object and converts it to a array containing each file.
|
||||
Each file is represented as an array [filename, data] where data is a string of the content of the file.
|
||||
@ -279,3 +292,10 @@ class Integration:
|
||||
log.msg += exception.msg
|
||||
if DEBUG:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def get_export_file_name(self, format='zip'):
|
||||
return "export_{}.{}".format(datetime.datetime.now().strftime("%Y-%m-%d"), format)
|
||||
|
||||
def get_recipe_processed_msg(self, recipe):
|
||||
return f'{recipe.pk} - {recipe.name} \n'
|
||||
|
@ -6,13 +6,13 @@ from zipfile import ZipFile
|
||||
from cookbook.helper.image_processing import get_filetype
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient
|
||||
from cookbook.models import Ingredient, Recipe, Step
|
||||
|
||||
|
||||
class Mealie(Integration):
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
return re.match(r'^recipes/([A-Za-z\d-])+/([A-Za-z\d-])+.json$', zip_info_object.filename)
|
||||
return re.match(r'^recipes/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.json$', zip_info_object.filename)
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
recipe_json = json.loads(file.getvalue().decode("utf-8"))
|
||||
@ -45,12 +45,14 @@ class Mealie(Integration):
|
||||
u = ingredient_parser.get_unit(ingredient['unit'])
|
||||
amount = ingredient['quantity']
|
||||
note = ingredient['note']
|
||||
original_text = None
|
||||
else:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient['note'])
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient['note'])
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
original_text = ingredient['note']
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=original_text, space=self.request.space,
|
||||
))
|
||||
except Exception:
|
||||
pass
|
||||
@ -60,7 +62,8 @@ class Mealie(Integration):
|
||||
if '.zip' in f['name']:
|
||||
import_zip = ZipFile(f['file'])
|
||||
try:
|
||||
self.import_recipe_image(recipe, BytesIO(import_zip.read(f'recipes/{recipe_json["slug"]}/images/min-original.webp')), filetype=get_filetype(f'recipes/{recipe_json["slug"]}/images/original'))
|
||||
self.import_recipe_image(recipe, BytesIO(import_zip.read(f'recipes/{recipe_json["slug"]}/images/min-original.webp')),
|
||||
filetype=get_filetype(f'recipes/{recipe_json["slug"]}/images/original'))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
@ -2,7 +2,7 @@ import re
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class MealMaster(Integration):
|
||||
@ -45,11 +45,11 @@ class MealMaster(Integration):
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in ingredients:
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
|
@ -7,7 +7,7 @@ from cookbook.helper.image_processing import get_filetype
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.helper.recipe_url_import import iso_duration_to_minutes
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class NextcloudCookbook(Integration):
|
||||
@ -57,11 +57,11 @@ class NextcloudCookbook(Integration):
|
||||
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in recipe_json['recipeIngredient']:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
|
@ -2,7 +2,7 @@ import json
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient
|
||||
from cookbook.models import Ingredient, Recipe, Step
|
||||
|
||||
|
||||
class OpenEats(Integration):
|
||||
|
@ -2,12 +2,12 @@ import base64
|
||||
import gzip
|
||||
import json
|
||||
import re
|
||||
from gettext import gettext as _
|
||||
from io import BytesIO
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from gettext import gettext as _
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class Paprika(Integration):
|
||||
@ -70,11 +70,11 @@ class Paprika(Integration):
|
||||
try:
|
||||
for ingredient in recipe_json['ingredients'].split('\n'):
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
@ -11,22 +11,25 @@ from cookbook.helper.image_processing import get_filetype
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.serializer import RecipeExportSerializer
|
||||
|
||||
import django.core.management.commands.runserver as runserver
|
||||
from cookbook.models import ExportLog
|
||||
from asgiref.sync import sync_to_async
|
||||
|
||||
import django.core.management.commands.runserver as runserver
|
||||
import logging
|
||||
|
||||
class PDFexport(Integration):
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
|
||||
async def get_files_from_recipes_async(self, recipes, cookie):
|
||||
async def get_files_from_recipes_async(self, recipes, el, cookie):
|
||||
cmd = runserver.Command()
|
||||
|
||||
browser = await launch(
|
||||
handleSIGINT=False,
|
||||
handleSIGTERM=False,
|
||||
handleSIGHUP=False,
|
||||
ignoreHTTPSErrors=True
|
||||
ignoreHTTPSErrors=True,
|
||||
)
|
||||
|
||||
cookies = {'domain': cmd.default_addr, 'name': 'sessionid', 'value': cookie['sessionid'], }
|
||||
@ -39,17 +42,28 @@ class PDFexport(Integration):
|
||||
}
|
||||
}
|
||||
|
||||
page = await browser.newPage()
|
||||
await page.emulateMedia('print')
|
||||
await page.setCookie(cookies)
|
||||
|
||||
files = []
|
||||
for recipe in recipes:
|
||||
await page.goto('http://' + cmd.default_addr + ':' + cmd.default_port + '/view/recipe/' + str(recipe.id), {'waitUntil': 'networkidle0', })
|
||||
|
||||
page = await browser.newPage()
|
||||
await page.emulateMedia('print')
|
||||
await page.setCookie(cookies)
|
||||
|
||||
await page.goto('http://'+cmd.default_addr+':'+cmd.default_port+'/view/recipe/'+str(recipe.id), {'waitUntil': 'domcontentloaded'})
|
||||
await page.waitForSelector('#printReady');
|
||||
|
||||
files.append([recipe.name + '.pdf', await page.pdf(options)])
|
||||
await page.close();
|
||||
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(recipe)
|
||||
await sync_to_async(el.save, thread_sensitive=True)()
|
||||
|
||||
|
||||
await browser.close()
|
||||
return files
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
return asyncio.run(self.get_files_from_recipes_async(recipes, cookie))
|
||||
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
return asyncio.run(self.get_files_from_recipes_async(recipes, el, cookie))
|
||||
|
@ -1,6 +1,6 @@
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient
|
||||
from cookbook.models import Ingredient, Recipe, Step
|
||||
|
||||
|
||||
class Pepperplate(Integration):
|
||||
@ -41,11 +41,11 @@ class Pepperplate(Integration):
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in ingredients:
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
|
@ -4,7 +4,7 @@ import requests
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class Plantoeat(Integration):
|
||||
@ -56,11 +56,11 @@ class Plantoeat(Integration):
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in ingredients:
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
import re
|
||||
import imghdr
|
||||
import json
|
||||
import requests
|
||||
import re
|
||||
from io import BytesIO
|
||||
from zipfile import ZipFile
|
||||
import imghdr
|
||||
|
||||
import requests
|
||||
|
||||
from cookbook.helper.image_processing import get_filetype
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class RecetteTek(Integration):
|
||||
@ -58,11 +59,11 @@ class RecetteTek(Integration):
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in file['ingredients'].split('\n'):
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(food)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
except Exception as e:
|
||||
print(recipe.name, ': failed to parse recipe ingredients ', str(e))
|
||||
|
@ -1,12 +1,13 @@
|
||||
import re
|
||||
from bs4 import BeautifulSoup
|
||||
from io import BytesIO
|
||||
from zipfile import ZipFile
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.helper.recipe_url_import import parse_servings, iso_duration_to_minutes
|
||||
from cookbook.helper.recipe_url_import import iso_duration_to_minutes, parse_servings
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class RecipeKeeper(Integration):
|
||||
@ -45,11 +46,11 @@ class RecipeKeeper(Integration):
|
||||
for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
|
||||
if ingredient.text == "":
|
||||
continue
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient.text.strip())
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
|
||||
for s in file.find("div", {"itemprop": "recipeDirections"}).find_all("p"):
|
||||
|
@ -5,7 +5,7 @@ import requests
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient
|
||||
from cookbook.models import Ingredient, Recipe, Step
|
||||
|
||||
|
||||
class RecipeSage(Integration):
|
||||
@ -31,7 +31,7 @@ class RecipeSage(Integration):
|
||||
except Exception as e:
|
||||
print('failed to parse yield or time ', str(e))
|
||||
|
||||
ingredient_parser = IngredientParser(self.request,True)
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
ingredients_added = False
|
||||
for s in file['recipeInstructions']:
|
||||
step = Step.objects.create(
|
||||
@ -41,11 +41,11 @@ class RecipeSage(Integration):
|
||||
ingredients_added = True
|
||||
|
||||
for ingredient in file['recipeIngredient']:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
@ -88,12 +88,16 @@ class RecipeSage(Integration):
|
||||
|
||||
return data
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
json_list = []
|
||||
for r in recipes:
|
||||
json_list.append(self.get_file_from_recipe(r))
|
||||
|
||||
return [['export.json', json.dumps(json_list)]]
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(r)
|
||||
el.save()
|
||||
|
||||
return [[self.get_export_file_name('json'), json.dumps(json_list)]]
|
||||
|
||||
def split_recipe_file(self, file):
|
||||
return json.loads(file.read().decode("utf-8"))
|
||||
|
@ -1,6 +1,6 @@
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
||||
|
||||
|
||||
class RezKonv(Integration):
|
||||
@ -44,11 +44,11 @@ class RezKonv(Integration):
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in ingredients:
|
||||
if len(ingredient.strip()) > 0:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
@ -60,9 +60,14 @@ class RezKonv(Integration):
|
||||
def split_recipe_file(self, file):
|
||||
recipe_list = []
|
||||
current_recipe = ''
|
||||
|
||||
encoding_list = ['windows-1250', 'latin-1'] #TODO build algorithm to try trough encodings and fail if none work, use for all importers
|
||||
encoding = 'windows-1250'
|
||||
for fl in file.readlines():
|
||||
line = fl.decode("windows-1250")
|
||||
try:
|
||||
line = fl.decode(encoding)
|
||||
except UnicodeDecodeError:
|
||||
encoding = 'latin-1'
|
||||
line = fl.decode(encoding)
|
||||
if line.startswith('=====') and 'rezkonv' in line.lower():
|
||||
if current_recipe != '':
|
||||
recipe_list.append(current_recipe)
|
||||
|
@ -2,7 +2,7 @@ from django.utils.translation import gettext as _
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Ingredient
|
||||
from cookbook.models import Ingredient, Recipe, Step
|
||||
|
||||
|
||||
class Saffron(Integration):
|
||||
@ -47,11 +47,11 @@ class Saffron(Integration):
|
||||
|
||||
ingredient_parser = IngredientParser(self.request, True)
|
||||
for ingredient in ingredients:
|
||||
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(ingredient)
|
||||
amount, unit, food, note = ingredient_parser.parse(ingredient)
|
||||
f = ingredient_parser.get_food(food)
|
||||
u = ingredient_parser.get_unit(unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
@ -76,7 +76,7 @@ class Saffron(Integration):
|
||||
|
||||
for i in s.ingredients.all():
|
||||
recipeIngredient.append(f'{float(i.amount)} {i.unit} {i.food}')
|
||||
|
||||
|
||||
data += "Ingredients: \n"
|
||||
for ingredient in recipeIngredient:
|
||||
data += ingredient+"\n"
|
||||
@ -87,10 +87,14 @@ class Saffron(Integration):
|
||||
|
||||
return recipe.name+'.txt', data
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
files = []
|
||||
for r in recipes:
|
||||
filename, data = self.get_file_from_recipe(r)
|
||||
files.append([ filename, data ])
|
||||
files.append([filename, data])
|
||||
|
||||
return files
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(r)
|
||||
el.save()
|
||||
|
||||
return files
|
||||
|
Binary file not shown.
@ -13,7 +13,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2020-06-02 19:28+0000\n"
|
||||
"Last-Translator: Miguel Canteras <mcanteras@gmail.com>, 2021\n"
|
||||
"Language-Team: Catalan (https://www.transifex.com/django-recipes/"
|
||||
@ -309,7 +309,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:445
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
@ -367,7 +367,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -522,42 +522,38 @@ msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
"No pots interaccionar amb aquest objecte ja que no és de la teva propietat!"
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "Has de proporcionar com a mínim una recepta o un títol."
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
#: .\cookbook\helper\template_helper.py:63
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Imported new recipe!"
|
||||
msgid "Imported %s recipes."
|
||||
@ -580,7 +576,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -609,7 +604,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -671,101 +666,80 @@ msgstr "Gran"
|
||||
msgid "New"
|
||||
msgstr "Nova"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Text"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "Temps"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "ID d'Arxiu"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Recepta"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Food"
|
||||
msgid "Food Alias"
|
||||
msgstr "Menjar"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Units"
|
||||
msgid "Unit Alias"
|
||||
msgstr "Unitats"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Keywords"
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Paraules clau"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1132,8 +1106,8 @@ msgstr "Edició per lots"
|
||||
msgid "History"
|
||||
msgstr "Historial"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1228,7 +1202,6 @@ msgstr "El camí ha de tenir el format següent"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1275,7 +1248,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr "Llibres de Receptes"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "Exporta Receptes"
|
||||
|
||||
@ -1399,19 +1372,12 @@ msgstr "Importar Receptes"
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "Registre de Receptes de Cuina"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Recepta"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "Tots els camps són opcionals i es poden deixar buits."
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "Valoració"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "Tanca"
|
||||
@ -1520,7 +1486,9 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "o bé deixant una línia en blanc entremig."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1543,8 +1511,12 @@ msgid "Lists"
|
||||
msgstr "Llistes"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
"Les llistes es poden ordenar o desordenades. És <b> important deixar una "
|
||||
@ -1821,7 +1793,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1846,7 +1818,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1876,7 +1848,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2159,7 +2131,9 @@ msgid "Finished"
|
||||
msgstr "Acabat"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
#, fuzzy
|
||||
#| msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr ""
|
||||
"Estàs fora de línia, és possible que la llista de compra no es sincronitzi."
|
||||
|
||||
@ -2458,6 +2432,16 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Text"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "ID d'Arxiu"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr "Introduïu l'URL del lloc web"
|
||||
@ -2646,180 +2630,181 @@ msgstr "Problemes de GitHub"
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr "Especificació de marcatge de receptes"
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
#, fuzzy
|
||||
#| msgid "Parameter filter_list incorrectly formatted"
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr "El paràmetre filter_list té un format incorrecte"
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr "Sincronització correcte"
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "Error de sincronització amb emmagatzematge"
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
"El lloc sol·licitat proporcionava dades malformades i no es pot llegir."
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr "No s'ha pogut trobar la pàgina sol·licitada."
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
@ -2827,28 +2812,28 @@ msgstr ""
|
||||
"El lloc sol·licitat no proporciona cap format de dades reconegut des d’on "
|
||||
"importar la recepta."
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
#: .\cookbook\views\api.py:1118
|
||||
#, fuzzy
|
||||
#| msgid "The requested page could not be found."
|
||||
msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "No s'ha pogut trobar la pàgina sol·licitada."
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2909,20 +2894,16 @@ msgstr "Canvis desats!"
|
||||
msgid "Error saving changes!"
|
||||
msgstr "Error al desar canvis!"
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr "Importa Registre"
|
||||
@ -3045,7 +3026,7 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
@ -3055,44 +3036,56 @@ msgstr ""
|
||||
"Si heu oblidat les vostres credencials de superusuari, consulteu la "
|
||||
"documentació de django sobre com restablir les contrasenyes."
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr "Les contrasenyes no coincideixen!"
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr "L'usuari s'ha creat, si us plau inicieu la sessió!"
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr "S'ha proporcionat un enllaç d'invitació mal format."
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
#, fuzzy
|
||||
#| msgid "You are not logged in and therefore cannot view this page!"
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr "No heu iniciat la sessió i, per tant, no podeu veure aquesta pàgina."
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr "L'enllaç d'invitació no és vàlid o ja s'ha utilitzat."
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "Temps"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "Registre de Receptes de Cuina"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "Tots els camps són opcionals i es poden deixar buits."
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "Valoració"
|
||||
|
||||
#~ msgid "New Unit"
|
||||
#~ msgstr "Nova Unitat"
|
||||
|
||||
|
Binary file not shown.
@ -14,17 +14,17 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"PO-Revision-Date: 2022-01-20 22:47+0000\n"
|
||||
"Last-Translator: Sebastian Weber <tandoor@web3r.de>\n"
|
||||
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/de/>\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2022-02-06 21:31+0000\n"
|
||||
"Last-Translator: David Laukamp <dlkmp@live.de>\n"
|
||||
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/recipes-"
|
||||
"backend/de/>\n"
|
||||
"Language: de\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 4.8\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
|
||||
#: .\cookbook\filters.py:23 .\cookbook\templates\forms\ingredients.html:34
|
||||
#: .\cookbook\templates\space.html:50 .\cookbook\templates\stats.html:28
|
||||
@ -104,22 +104,17 @@ msgid ""
|
||||
"Enables support for fractions in ingredient amounts (e.g. convert decimals "
|
||||
"to fractions automatically)"
|
||||
msgstr ""
|
||||
"Unterstützung für Brüche in Zutaten aktivieren. Dadurch werden Dezimalzahlen "
|
||||
"mit Brüchen ersetzt, z.B. 0.5 mit ½."
|
||||
"Unterstützung für Brüche in Zutaten aktivieren (dadurch werden Dezimalzahlen "
|
||||
"automatisch mit Brüchen ersetzt)"
|
||||
|
||||
#: .\cookbook\forms.py:78
|
||||
msgid "Display nutritional energy amounts in joules instead of calories"
|
||||
msgstr "Nährwerte in Joule statt Kalorien anzeigen"
|
||||
|
||||
#: .\cookbook\forms.py:79
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Users with whom newly created meal plan/shopping list entries should be "
|
||||
#| "shared by default."
|
||||
msgid "Users with whom newly created meal plans should be shared by default."
|
||||
msgstr ""
|
||||
"Nutzer, mit denen neue Pläne und Einkaufslisten standardmäßig geteilt werden "
|
||||
"sollen."
|
||||
"Nutzer, mit denen neue Essenspläne standardmäßig geteilt werden sollen."
|
||||
|
||||
#: .\cookbook\forms.py:80
|
||||
msgid "Users with whom to share shopping lists."
|
||||
@ -157,11 +152,11 @@ msgstr "Navigationsleiste wird oben angeheftet."
|
||||
|
||||
#: .\cookbook\forms.py:90 .\cookbook\forms.py:496
|
||||
msgid "Automatically add meal plan ingredients to shopping list."
|
||||
msgstr ""
|
||||
msgstr "Fügt die Zutaten des Speiseplans automatisch zur Einkaufsliste hinzu."
|
||||
|
||||
#: .\cookbook\forms.py:91
|
||||
msgid "Exclude ingredients that are on hand."
|
||||
msgstr ""
|
||||
msgstr "Zutaten, die vorrätig sind, ausschließen."
|
||||
|
||||
#: .\cookbook\forms.py:108
|
||||
msgid ""
|
||||
@ -298,9 +293,13 @@ msgstr ""
|
||||
"A. führen niedrigere Werte zum ignorieren von mehr Tippfehlern)."
|
||||
|
||||
#: .\cookbook\forms.py:445
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Select type method of search. Click <a href=\"/docs/search/\">here</a> "
|
||||
#| "for full desciption of choices."
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
"Suchmethode auswählen. Klicke <a href=\"/docs/search/\">hier</a> für eine "
|
||||
"Auflistung der Optionen."
|
||||
@ -319,8 +318,7 @@ msgid ""
|
||||
"degrade search quality depending on language"
|
||||
msgstr ""
|
||||
"Felder bei welchen Akzente ignoriert werden. Das aktivieren dieser Option "
|
||||
"kann die Suchqualität abhängig von der Sprache verbessern oder "
|
||||
"verschlechtern."
|
||||
"kann die Suchqualität je nach Sprache verbessern oder verschlechtern"
|
||||
|
||||
#: .\cookbook\forms.py:450
|
||||
msgid ""
|
||||
@ -372,7 +370,9 @@ msgid "Partial Match"
|
||||
msgstr "Teilweise Übereinstimmung"
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
#, fuzzy
|
||||
#| msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr "Beginnt mit"
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -388,82 +388,93 @@ msgid ""
|
||||
"Users will see all items you add to your shopping list. They must add you "
|
||||
"to see items on their list."
|
||||
msgstr ""
|
||||
"Die Benutzer sehen alle Artikel, die Sie auf Ihre Einkaufsliste setzen. Die "
|
||||
"Benutzer müssen Sie hinzufügen, damit Sie Artikel auf der Liste der Benutzer "
|
||||
"sehen können."
|
||||
|
||||
#: .\cookbook\forms.py:497
|
||||
msgid ""
|
||||
"When adding a meal plan to the shopping list (manually or automatically), "
|
||||
"include all related recipes."
|
||||
msgstr ""
|
||||
"Wenn Sie einen Essensplan zur Einkaufsliste hinzufügen (manuell oder "
|
||||
"automatisch), fügen Sie alle zugehörigen Rezepte hinzu."
|
||||
|
||||
#: .\cookbook\forms.py:498
|
||||
msgid ""
|
||||
"When adding a meal plan to the shopping list (manually or automatically), "
|
||||
"exclude ingredients that are on hand."
|
||||
msgstr ""
|
||||
"Wenn Sie einen Essensplan zur Einkaufsliste hinzufügen (manuell oder "
|
||||
"automatisch), schließen Sie Zutaten aus, die Sie gerade zur Hand haben."
|
||||
|
||||
#: .\cookbook\forms.py:499
|
||||
msgid "Default number of hours to delay a shopping list entry."
|
||||
msgstr ""
|
||||
"Voreingestellte Anzahl von Stunden für die Verzögerung eines "
|
||||
"Einkaufslisteneintrags."
|
||||
|
||||
#: .\cookbook\forms.py:500
|
||||
msgid "Filter shopping list to only include supermarket categories."
|
||||
msgstr ""
|
||||
"Nur für den Supermarkt konfigurierte Kategorien in Einkaufsliste anzeigen."
|
||||
|
||||
#: .\cookbook\forms.py:501
|
||||
msgid "Days of recent shopping list entries to display."
|
||||
msgstr ""
|
||||
"Tage der letzten Einträge in der Einkaufsliste, die angezeigt werden sollen."
|
||||
|
||||
#: .\cookbook\forms.py:502
|
||||
msgid "Mark food 'On Hand' when checked off shopping list."
|
||||
msgstr ""
|
||||
"Lebensmittel als vorrätig markieren, wenn es in der Einkaufliste abgehakt "
|
||||
"wurde."
|
||||
|
||||
#: .\cookbook\forms.py:503
|
||||
msgid "Delimiter to use for CSV exports."
|
||||
msgstr ""
|
||||
msgstr "Separator für CSV-Export."
|
||||
|
||||
#: .\cookbook\forms.py:504
|
||||
msgid "Prefix to add when copying list to the clipboard."
|
||||
msgstr ""
|
||||
msgstr "Zusatz wird der in die Zwischenablage kopierten Liste vorangestellt."
|
||||
|
||||
#: .\cookbook\forms.py:508
|
||||
#, fuzzy
|
||||
#| msgid "New Shopping List"
|
||||
msgid "Share Shopping List"
|
||||
msgstr "Neue Einkaufsliste"
|
||||
msgstr "Einkaufsliste teilen"
|
||||
|
||||
#: .\cookbook\forms.py:509
|
||||
msgid "Autosync"
|
||||
msgstr ""
|
||||
msgstr "Automatischer Abgleich"
|
||||
|
||||
#: .\cookbook\forms.py:510
|
||||
msgid "Auto Add Meal Plan"
|
||||
msgstr ""
|
||||
msgstr "automatisch dem Menüplan hinzufügen"
|
||||
|
||||
#: .\cookbook\forms.py:511
|
||||
msgid "Exclude On Hand"
|
||||
msgstr ""
|
||||
msgstr "Ausgenommen Vorrätiges"
|
||||
|
||||
#: .\cookbook\forms.py:512
|
||||
msgid "Include Related"
|
||||
msgstr ""
|
||||
msgstr "dazugehörend"
|
||||
|
||||
#: .\cookbook\forms.py:513
|
||||
msgid "Default Delay Hours"
|
||||
msgstr ""
|
||||
msgstr "Standardmäßige Verzögerung in Stunden"
|
||||
|
||||
#: .\cookbook\forms.py:514
|
||||
#, fuzzy
|
||||
#| msgid "Select Supermarket"
|
||||
msgid "Filter to Supermarket"
|
||||
msgstr "Supermarkt auswählen"
|
||||
msgstr "Supermarkt filtern"
|
||||
|
||||
#: .\cookbook\forms.py:515
|
||||
msgid "Recent Days"
|
||||
msgstr ""
|
||||
msgstr "Vergangene Tage"
|
||||
|
||||
#: .\cookbook\forms.py:516
|
||||
msgid "CSV Delimiter"
|
||||
msgstr ""
|
||||
msgstr "CSV Trennzeichen"
|
||||
|
||||
#: .\cookbook\forms.py:517 .\cookbook\templates\shopping_list.html:322
|
||||
msgid "List Prefix"
|
||||
@ -471,27 +482,24 @@ msgstr "Listenpräfix"
|
||||
|
||||
#: .\cookbook\forms.py:518
|
||||
msgid "Auto On Hand"
|
||||
msgstr ""
|
||||
msgstr "Automatisch als vorrätig markieren"
|
||||
|
||||
#: .\cookbook\forms.py:528
|
||||
msgid "Reset Food Inheritance"
|
||||
msgstr ""
|
||||
msgstr "Lebensmittelvererbung zurücksetzen"
|
||||
|
||||
#: .\cookbook\forms.py:529
|
||||
msgid "Reset all food to inherit the fields configured."
|
||||
msgstr ""
|
||||
"Alle Lebensmittel zurücksetzen, um die konfigurierten Felder zu übernehmen."
|
||||
|
||||
#: .\cookbook\forms.py:541
|
||||
#, fuzzy
|
||||
#| msgid "Food that should be replaced."
|
||||
msgid "Fields on food that should be inherited by default."
|
||||
msgstr "Zutat, die ersetzt werden soll."
|
||||
msgstr "Zutaten, die standardmäßig übernommen werden sollen."
|
||||
|
||||
#: .\cookbook\forms.py:542
|
||||
#, fuzzy
|
||||
#| msgid "Show recently viewed recipes on search page."
|
||||
msgid "Show recipe counts on search filters"
|
||||
msgstr "Zuletzt angeschaute Rezepte bei der Suche anzeigen."
|
||||
msgstr "Rezeptanzahl im Suchfiltern anzeigen"
|
||||
|
||||
#: .\cookbook\helper\AllAuthCustomAdapter.py:36
|
||||
msgid ""
|
||||
@ -525,26 +533,22 @@ msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
"Du kannst mit diesem Objekt nicht interagieren, da es dir nicht gehört!"
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
msgstr "Es muss die Abfrage oder der Hash_Key angeben werden"
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgstr "Mindestens ein Rezept oder ein Titel müssen angegeben werden."
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
msgstr ""
|
||||
#| msgid "You must supply a created_by"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "Die Angabe der Verfassers ist notwendig"
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
#: .\cookbook\helper\template_helper.py:63
|
||||
msgid "Could not parse template code."
|
||||
msgstr "Konnte den Template code nicht verarbeiten."
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
@ -552,7 +556,7 @@ msgstr ""
|
||||
"Importer erwartet eine .zip Datei. Hast du den richtigen Importer-Typ für "
|
||||
"deine Daten ausgewählt?"
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
@ -560,11 +564,11 @@ msgstr ""
|
||||
"Ein unerwarteter Fehler trat beim Importieren auf. Bitte stelle sicher, dass "
|
||||
"die hochgeladene Datei gültig ist."
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr "Die folgenden Rezepte wurden ignoriert da sie bereits existieren:"
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr "%s Rezepte importiert."
|
||||
@ -582,7 +586,6 @@ msgid "Source"
|
||||
msgstr "Quelle"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -611,7 +614,9 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr "Generiert den Index für die Rezept-Volltextsuche neu"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
#, fuzzy
|
||||
#| msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
"Nur PostgreSQL Datenbanken verwenden Volltextsuche, kein Index muss neu "
|
||||
"generiert werden"
|
||||
@ -677,93 +682,75 @@ msgstr "Groß"
|
||||
msgid "New"
|
||||
msgstr "Neu"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr " ist Teil eines Rezepts und kann nicht gelöscht werden"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Text"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "Zeit"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "Datei"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Rezept"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr "Einfach"
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr "Satz"
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr "Web"
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr "Rohdaten"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Food Alias"
|
||||
msgstr "Lebensmittel Alias"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr "Einheiten Alias"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Stichwort Alias"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
msgstr "Ein Benutzername ist notwendig"
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr "Datei-Uploads sind in diesem Space nicht aktiviert."
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr "Du hast Dein Datei-Uploadlimit erreicht."
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
msgstr "Bestehende Einkaufliste, die aktualisiert werden soll"
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
"Menge des Lebensmittels, welches der Einkaufsliste hinzugefügt werden soll"
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
msgstr "ID der Einheit, die für die Einkaufsliste verwendet werden soll"
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1125,8 +1112,8 @@ msgstr "Massenbearbeitung"
|
||||
msgid "History"
|
||||
msgstr "Verlauf"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1219,7 +1206,6 @@ msgstr "Der Pfad muss folgendes Format haben"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1262,7 +1248,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr "Rezeptbuch"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "Rezepte exportieren"
|
||||
|
||||
@ -1332,11 +1318,11 @@ msgstr "Abbrechen"
|
||||
|
||||
#: .\cookbook\templates\generic\edit_template.html:32
|
||||
msgid "View"
|
||||
msgstr "Anschauen"
|
||||
msgstr "Ansicht"
|
||||
|
||||
#: .\cookbook\templates\generic\edit_template.html:36
|
||||
msgid "Delete original file"
|
||||
msgstr "Original löschen"
|
||||
msgstr "Originaldatei löschen"
|
||||
|
||||
#: .\cookbook\templates\generic\list_template.html:6
|
||||
#: .\cookbook\templates\generic\list_template.html:22
|
||||
@ -1390,19 +1376,12 @@ msgstr "Rezepte importieren"
|
||||
msgid "Import"
|
||||
msgstr "Importieren"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "Kochen protokollieren"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Rezept"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "Alle Felder sind optional und können leer gelassen werden."
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "Bewertung"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
@ -1511,7 +1490,9 @@ msgstr "Zeilenumbrüche entstehen durch zwei Leerzeichen am ende einer Zeile"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "oder durch eine leere Zeile dazwischen."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1534,8 +1515,12 @@ msgid "Lists"
|
||||
msgstr "Listen"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
"Liste können sortiert oder unsortiert sein. Es ist <b>wichtig das eine leere "
|
||||
@ -1832,10 +1817,19 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:29
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Simple searches ignore punctuation and common words such as "
|
||||
#| "'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
#| " Searching for 'apple or flour' will return any recipe that "
|
||||
#| "includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
#| "selected for a full text search.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1867,13 +1861,30 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:39
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Web searches simulate functionality found on many web search "
|
||||
#| "sites supporting special syntax.\n"
|
||||
#| " Placing quotes around several words will convert those words "
|
||||
#| "into a phrase.\n"
|
||||
#| " 'or' is recongized as searching for the word (or phrase) "
|
||||
#| "immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
#| " '-' is recognized as searching for recipes that do not "
|
||||
#| "include the word (or phrase) that comes immediately after. \n"
|
||||
#| " For example searching for 'apple pie' or cherry -butter will "
|
||||
#| "return any recipe that includes the phrase 'apple pie' or the word "
|
||||
#| "'cherry' \n"
|
||||
#| " in any field included in the full text search but exclude any "
|
||||
#| "recipe that has the word 'butter' in any field included.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Web searches simulate functionality found on many web search "
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1913,6 +1924,19 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:59
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Another approach to searching that also requires Postgresql "
|
||||
#| "is fuzzy search or trigram similarity. A trigram is a group of three "
|
||||
#| "consecutive characters.\n"
|
||||
#| " For example searching for 'apple' will create x trigrams "
|
||||
#| "'app', 'ppl', 'ple' and will create a score of how closely words match "
|
||||
#| "the generated trigrams.\n"
|
||||
#| " One benefit of searching trigams is that a search for "
|
||||
#| "'sandwich' will find mispelled words such as 'sandwhich' that would be "
|
||||
#| "missed by other methods.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Another approach to searching that also requires Postgresql is "
|
||||
@ -1922,7 +1946,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2045,10 +2069,8 @@ msgid "Search-Settings"
|
||||
msgstr "Sucheinstellungen"
|
||||
|
||||
#: .\cookbook\templates\settings.html:56
|
||||
#, fuzzy
|
||||
#| msgid "Search-Settings"
|
||||
msgid "Shopping-Settings"
|
||||
msgstr "Sucheinstellungen"
|
||||
msgstr "Einstellungen Einkaufsliste"
|
||||
|
||||
#: .\cookbook\templates\settings.html:65
|
||||
msgid "Name Settings"
|
||||
@ -2161,10 +2183,8 @@ msgid "Perfect for large Databases"
|
||||
msgstr "Ideal für große Datenbanken"
|
||||
|
||||
#: .\cookbook\templates\settings.html:207
|
||||
#, fuzzy
|
||||
#| msgid "Shopping List"
|
||||
msgid "Shopping Settings"
|
||||
msgstr "Einkaufsliste"
|
||||
msgstr "Einstellungen Einkaufsliste"
|
||||
|
||||
#: .\cookbook\templates\setup.html:6 .\cookbook\templates\system.html:5
|
||||
msgid "Cookbook Setup"
|
||||
@ -2245,7 +2265,9 @@ msgid "Finished"
|
||||
msgstr "Erledigt"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
#, fuzzy
|
||||
#| msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr "Du bist offline, die Einkaufsliste wird ggf. nicht synchronisiert."
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2539,6 +2561,14 @@ msgstr "URL"
|
||||
msgid "App"
|
||||
msgstr "Anwendung"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Text"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "Datei"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr "Webseite-URL eingeben"
|
||||
@ -2713,208 +2743,211 @@ msgstr "GitHub-Issues"
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr "Rezept-Markup-Spezifikation"
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr "Der Parameter updated_at ist falsch formatiert"
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr "Kein {self.basename} mit der ID {pk} existiert"
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr "Zusammenführen mit selben Objekt nicht möglich!"
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr "Kein {self.basename} mit der ID {target} existiert"
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr "Zusammenführen mit untergeordnetem Objekt nicht möglich!"
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr "{source.name} wurde erfolgreich mit {target.name} zusammengeführt"
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
"Beim zusammenführen von {source.name} mit {target.name} ist ein Fehler "
|
||||
"aufgetreten"
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr "{child.name} wurde erfolgreich zur Wurzel verschoben."
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr "Fehler aufgetreten beim verschieben von "
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr "Ein Element kann nicht in sich selbst verschoben werden!"
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr "Kein {self.basename} mit ID {parent} existiert"
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
"{child.name} wurde erfolgreich zum Überelement {parent.name} verschoben"
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
msgstr "{obj.name} wurde von der Einkaufsliste entfernt."
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
msgstr "{obj.name} wurde der Einkaufsliste hinzugefügt."
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
msgstr "ID der Einheit, die ein Rezept haben sollte."
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
msgstr "Bewertung, die ein Rezept haben sollte. [ 0 - 5]"
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr "Diese Funktion ist in dieser Version von Tandoor noch nicht verfügbar!"
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr "Synchronisation erfolgreich!"
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "Fehler beim Synchronisieren"
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr "Nichts zu tun."
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
"Die angefragte Seite hat ungültige Daten zurückgegeben oder die Daten "
|
||||
"konnten nicht verarbeitet werden."
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr "Die angefragte Seite konnte nicht gefunden werden."
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
msgstr ""
|
||||
"Die angefragte Seite stellt keine bekannten Datenformate zur Verfügung."
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
msgstr "Verbindung fehlgeschlagen."
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
#, fuzzy
|
||||
#| msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "Es konnten keine nutzbaren Daten gefunden werden."
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr "Ich konnte nichts zu tun finden."
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr "Du hast die maximale Anzahl an Rezepten für Deinen Space erreicht."
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr "Du hast mehr Benutzer in Deinem Space als erlaubt."
|
||||
@ -2975,19 +3008,17 @@ msgstr "Änderungen gespeichert!"
|
||||
msgid "Error saving changes!"
|
||||
msgstr "Fehler beim Speichern der Daten!"
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr "Importieren ist für diesen Anbieter noch nicht implementiert"
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr "Exportieren ist für diesen Anbieter noch nicht implementiert"
|
||||
"Der PDF-Exporter ist in dieser Instanz nicht aktiviert, da er sich noch in "
|
||||
"einem experimentellen Zustand befindet."
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
@ -3118,7 +3149,7 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr "Die \"Ungenaue\" Suche ist mit diesem Suchtyp nicht kompatibel!"
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
@ -3127,33 +3158,33 @@ msgstr ""
|
||||
"Die Setup-Seite kann nur für den ersten Nutzer verwendet werden. Zum "
|
||||
"Zurücksetzen von Passwörtern bitte der Django-Dokumentation folgen."
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr "Passwörter stimmen nicht überein!"
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr "Benutzer wurde erstellt, bitte einloggen!"
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr "Fehlerhafter Einladungslink angegeben!"
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr ""
|
||||
"Du bist bereits Mitglied eines Space, daher kannst du diesem Space nicht "
|
||||
"beitreten."
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr "Space erfolgreich beigetreten."
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr "Einladungslink ungültig oder bereits genutzt!"
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
@ -3161,7 +3192,7 @@ msgstr ""
|
||||
"Das melden von Links ist in dieser Instanz nicht aktiviert. Bitte "
|
||||
"kontaktieren sie den Seitenadministrator um Probleme zu melden."
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
@ -3169,6 +3200,24 @@ msgstr ""
|
||||
"Dieser Link wurde deaktiviert! Bitte kontaktieren sie den "
|
||||
"Seitenadministrator für weitere Informationen."
|
||||
|
||||
#~ msgid "You must supply a recipe or mealplan"
|
||||
#~ msgstr "Mindestens ein Rezept oder ein Essensplan müssen angegeben werden"
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "Zeit"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "Kochen protokollieren"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "Alle Felder sind optional und können leer gelassen werden."
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "Bewertung"
|
||||
|
||||
#~ msgid "Exporting is not implemented for this provider"
|
||||
#~ msgstr "Exportieren ist für diesen Anbieter noch nicht implementiert"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "No {self.basename} with id {child} exists"
|
||||
#~ msgstr "Kein {self.basename} mit ID {child} existiert"
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -260,7 +260,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:445
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
@ -316,7 +316,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -458,16 +458,12 @@ msgstr ""
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
msgid "You must supply a servings size"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
@ -475,23 +471,23 @@ msgstr ""
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr ""
|
||||
@ -509,7 +505,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -538,7 +533,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -600,93 +595,74 @@ msgstr ""
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Food Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Keyword Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1031,8 +1007,8 @@ msgstr ""
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1121,7 +1097,6 @@ msgstr ""
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1162,7 +1137,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr ""
|
||||
|
||||
@ -1280,19 +1255,12 @@ msgstr ""
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
@ -1383,7 +1351,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1407,7 +1375,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
|
||||
@ -1669,7 +1637,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1694,7 +1662,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1724,7 +1692,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -1983,7 +1951,7 @@ msgid "Finished"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2241,6 +2209,14 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr ""
|
||||
@ -2403,202 +2379,203 @@ msgstr ""
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
msgid "No usable data could be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2656,20 +2633,16 @@ msgstr ""
|
||||
msgid "Error saving changes!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr ""
|
||||
@ -2786,44 +2759,44 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
"on how to reset passwords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
|
Binary file not shown.
@ -14,7 +14,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2020-06-02 19:28+0000\n"
|
||||
"Last-Translator: Miguel Canteras <mcanteras@gmail.com>, 2021\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/django-recipes/"
|
||||
@ -316,7 +316,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:445
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
@ -374,7 +374,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -528,26 +528,22 @@ msgstr "¡No tienes los permisos necesarios para ver esta página!"
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr "¡No puede interactuar con este objeto ya que no es de tu propiedad!"
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "Debe proporcionar al menos una receta o un título."
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
#: .\cookbook\helper\template_helper.py:63
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
@ -555,17 +551,17 @@ msgstr ""
|
||||
"El importador esperaba un fichero.zip. ¿Has escogido el tipo de importador "
|
||||
"correcto para tus datos?"
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Imported new recipe!"
|
||||
msgid "Imported %s recipes."
|
||||
@ -588,7 +584,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -617,7 +612,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -679,101 +674,80 @@ msgstr "Grande"
|
||||
msgid "New"
|
||||
msgstr "Nuevo"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Texto"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "Tiempo"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "ID de Fichero"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Receta"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Food"
|
||||
msgid "Food Alias"
|
||||
msgstr "Comida"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Units"
|
||||
msgid "Unit Alias"
|
||||
msgstr "Unidades"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Keywords"
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Palabras clave"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1147,8 +1121,8 @@ msgstr "Edición Masiva"
|
||||
msgid "History"
|
||||
msgstr "Historial"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1243,7 +1217,6 @@ msgstr "La ruta debe tener el siguiente formato"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1290,7 +1263,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr "Libros de recetas"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "Exportar recetas"
|
||||
|
||||
@ -1417,19 +1390,12 @@ msgstr "Importar recetas"
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "Registrar receta cocinada"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Receta"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "Todos los campos son opcionales y pueden dejarse vacíos."
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "Calificación"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
@ -1540,7 +1506,9 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "o dejando una línea en blanco entre ellos."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1563,8 +1531,12 @@ msgid "Lists"
|
||||
msgstr "Listas"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
"Las listas pueden ser ordenadas o no ordenadas. <b>¡Es importante dejar una "
|
||||
@ -1852,7 +1824,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1877,7 +1849,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1907,7 +1879,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2192,7 +2164,9 @@ msgid "Finished"
|
||||
msgstr "Completada"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
#, fuzzy
|
||||
#| msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr "Estás desconectado, la lista de la compra no se sincronizará."
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2505,6 +2479,16 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Texto"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "ID de Fichero"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr "Introduce la URL del sitio web"
|
||||
@ -2693,185 +2677,186 @@ msgstr "Propuestas de GitHub"
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr "Especificación de anotaciones de la receta"
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
#, fuzzy
|
||||
#| msgid "Parameter filter_list incorrectly formatted"
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr "Parámetro filter_list formateado incorrectamente"
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr "¡No se puede unir con el mismo objeto!"
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
#, fuzzy
|
||||
#| msgid "Cannot merge with the same object!"
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr "¡No se puede unir con el mismo objeto!"
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
#, fuzzy
|
||||
#| msgid "This feature is not available in the demo version!"
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr "¡Esta funcionalidad no está disponible en la versión demo!"
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr "¡Sincronización exitosa!"
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "Error de sincronización con el almacenamiento"
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
"El sitio solicitado proporcionó datos con formato incorrecto y no se puede "
|
||||
"leer."
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr "La página solicitada no pudo ser encontrada."
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
@ -2879,28 +2864,28 @@ msgstr ""
|
||||
"El sitio solicitado no proporciona ningún formato de datos reconocido para "
|
||||
"importar la receta."
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
#: .\cookbook\views\api.py:1118
|
||||
#, fuzzy
|
||||
#| msgid "The requested page could not be found."
|
||||
msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "La página solicitada no pudo ser encontrada."
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2960,20 +2945,16 @@ msgstr "¡Cambios guardados!"
|
||||
msgid "Error saving changes!"
|
||||
msgstr "¡Error al guardar los cambios!"
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr "La importación no está implementada para este proveedor"
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr "La exportación no está implementada para este proveedor"
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr "Importar registro"
|
||||
@ -3096,7 +3077,7 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
@ -3106,44 +3087,59 @@ msgstr ""
|
||||
"usuario. Si has olvidado tus credenciales de superusuario, por favor "
|
||||
"consulta la documentación de django sobre cómo restablecer las contraseñas."
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr "¡Las contraseñas no coinciden!"
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr "El usuario ha sido creado, ¡inicie sesión!"
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr "¡Se proporcionó un enlace de invitación con formato incorrecto!"
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
#, fuzzy
|
||||
#| msgid "You are not logged in and therefore cannot view this page!"
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr "¡No ha iniciado sesión y por lo tanto no puede ver esta página!"
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr "¡El enlace de invitación no es válido o ya se ha utilizado!"
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "Tiempo"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "Registrar receta cocinada"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "Todos los campos son opcionales y pueden dejarse vacíos."
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "Calificación"
|
||||
|
||||
#~ msgid "Exporting is not implemented for this provider"
|
||||
#~ msgstr "La exportación no está implementada para este proveedor"
|
||||
|
||||
#~ msgid "New Unit"
|
||||
#~ msgstr "Nueva Unidad"
|
||||
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2020-06-02 19:28+0000\n"
|
||||
"Last-Translator: igazka <igazka100@gmail.com>, 2020\n"
|
||||
"Language-Team: Hungarian (Hungary) (https://www.transifex.com/django-recipes/"
|
||||
@ -271,7 +271,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:445
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
@ -327,7 +327,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -471,16 +471,12 @@ msgstr ""
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
msgid "You must supply a servings size"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
@ -488,23 +484,23 @@ msgstr ""
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr ""
|
||||
@ -522,7 +518,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -551,7 +546,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -613,99 +608,78 @@ msgstr ""
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Szöveg"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "Fájl ID:"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "New Food"
|
||||
msgid "Food Alias"
|
||||
msgstr "Új Étel"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Keywords"
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Kulcsszavak"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1054,8 +1028,8 @@ msgstr ""
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1144,7 +1118,6 @@ msgstr ""
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1185,7 +1158,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr ""
|
||||
|
||||
@ -1303,19 +1276,12 @@ msgstr ""
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
@ -1406,7 +1372,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1430,7 +1396,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
|
||||
@ -1692,7 +1658,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1717,7 +1683,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1747,7 +1713,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2006,7 +1972,7 @@ msgid "Finished"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2264,6 +2230,16 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Szöveg"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "Fájl ID:"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr ""
|
||||
@ -2428,202 +2404,203 @@ msgstr ""
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
msgid "No usable data could be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2681,20 +2658,16 @@ msgstr ""
|
||||
msgid "Error saving changes!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr ""
|
||||
@ -2811,44 +2784,44 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
"on how to reset passwords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
|
Binary file not shown.
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2022-01-17 07:56+0000\n"
|
||||
"Last-Translator: Oliver Cervera <olivercervera@yahoo.it>\n"
|
||||
"Language-Team: Italian <http://translate.tandoor.dev/projects/tandoor/"
|
||||
@ -297,9 +297,13 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:445
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Select type method of search. Click <a href=\"/docs/search/\">here</a> "
|
||||
#| "for full desciption of choices."
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
"Seleziona il metodo di ricerca. Clicca <a href=\"/docs/search/\">qui</a> "
|
||||
"per avere maggiori informazioni."
|
||||
@ -357,7 +361,9 @@ msgid "Partial Match"
|
||||
msgstr "Corrispondenza parziale"
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
#, fuzzy
|
||||
#| msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr "Inizia con"
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -509,26 +515,22 @@ msgstr "Non hai i permessi necessari per visualizzare questa pagina!"
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr "Non puoi interagire con questo oggetto perché non ne hai i diritti!"
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "Devi fornire almeno una ricetta o un titolo."
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
#: .\cookbook\helper\template_helper.py:63
|
||||
msgid "Could not parse template code."
|
||||
msgstr "Impossibile elaborare il codice del template."
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
@ -536,7 +538,7 @@ msgstr ""
|
||||
"La procedura di import necessita di un file .zip. Hai scelto il tipo di "
|
||||
"importazione corretta per i tuoi dati?"
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
@ -544,11 +546,11 @@ msgstr ""
|
||||
"Un errore imprevisto si è verificato durante l'importazione. Assicurati di "
|
||||
"aver caricato un file valido."
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr "Le seguenti ricette sono state ignorate perché già esistenti:"
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr "Importate %s ricette."
|
||||
@ -566,7 +568,6 @@ msgid "Source"
|
||||
msgstr "Fonte"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -595,7 +596,9 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr "Ricostruisce l'indice di ricerca full text per la ricetta"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
#, fuzzy
|
||||
#| msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
"Solo i database Postgres usano l'indice di ricerca full text, non ci sono "
|
||||
"indici da ricostruire"
|
||||
@ -661,93 +664,74 @@ msgstr "Grande"
|
||||
msgid "New"
|
||||
msgstr "Nuovo"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr " è parte dello step di una ricetta e non può essere eliminato"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Testo"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "Tempo"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "File"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Ricetta"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr "Semplice"
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr "Frase"
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr "Web"
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr "Raw"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Food Alias"
|
||||
msgstr "Alias Alimento"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr "Alias Unità"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Alias Parola Chiave"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr "Il caricamento dei file non è abilitato in questa istanza."
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr "Hai raggiungo il limite per il caricamento dei file."
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1109,8 +1093,8 @@ msgstr "Modifica in blocco"
|
||||
msgid "History"
|
||||
msgstr "Cronologia"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1203,7 +1187,6 @@ msgstr "Il percorso deve essere nel formato seguente"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1246,7 +1229,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr "Libri di Ricette"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "Esporta Ricette"
|
||||
|
||||
@ -1370,19 +1353,12 @@ msgstr "Importa Ricette"
|
||||
msgid "Import"
|
||||
msgstr "Importa"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "Aggiungi al registro delle ricette cucinate"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Ricetta"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "Tutti i campi sono opzionali e possono essere lasciati vuoti."
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "Valutazione"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "Chiudi"
|
||||
@ -1492,7 +1468,9 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "o lasciando una riga vuota in mezzo."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1515,8 +1493,12 @@ msgid "Lists"
|
||||
msgstr "Liste"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
"Le liste possono essere ordinate o no. È <b>importante lasciare una riga "
|
||||
@ -1805,7 +1787,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1830,7 +1812,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1860,7 +1842,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2137,7 +2119,9 @@ msgid "Finished"
|
||||
msgstr "Completato"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
#, fuzzy
|
||||
#| msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr "Sei offline: la lista della spesa potrebbe non sincronizzarsi."
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2423,6 +2407,14 @@ msgstr "URL"
|
||||
msgid "App"
|
||||
msgstr "App"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Testo"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "File"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr "Inserisci l'indirizzo del sito web"
|
||||
@ -2596,181 +2588,182 @@ msgstr "Issues (Problemi aperti) su GitHub"
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr "Specifica di Markup della ricetta"
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr "Il parametro updated_at non è formattato correttamente"
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr "Non esiste nessun {self.basename} con id {pk}"
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr "Non è possibile unirlo con lo stesso oggetto!"
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr "Non esiste nessun {self.basename} con id {target}"
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr "Non è possibile unirlo con un oggetto secondario!"
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr "{source.name} è stato unito con successo a {target.name}"
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
"Si è verificato un errore durante l'unione di {source.name} con {target.name}"
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr "{child.name} è stato spostato con successo alla radice."
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr "Si è verificato un errore durante lo spostamento "
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr "Non è possibile muovere un oggetto a sé stesso!"
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr "Non esiste nessun {self.basename} con id {parent}"
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr "{child.name} è stato spostato con successo al primario {parent.name}"
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
"Questa funzione non è ancora disponibile nella versione hostata di Tandor!"
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr "Sincronizzazione completata con successo!"
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "Errore di sincronizzazione con questo backend"
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr "Nulla da fare."
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
"Il sito richiesto ha fornito dati in formato non corretto e non può essere "
|
||||
"letto."
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr "La pagina richiesta non è stata trovata."
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
@ -2778,26 +2771,28 @@ msgstr ""
|
||||
"Il sito richiesto non fornisce un formato di dati riconosciuto da cui "
|
||||
"importare la ricetta."
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
#, fuzzy
|
||||
#| msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "Nessuna informazione utilizzabile è stata trovata."
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr "Non è stato trovato nulla da fare."
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr "Hai raggiunto il numero massimo di ricette nella tua istanza."
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr "Hai più utenti di quanti permessi nella tua istanza."
|
||||
@ -2860,20 +2855,16 @@ msgstr "Modifiche salvate!"
|
||||
msgid "Error saving changes!"
|
||||
msgstr "Si è verificato un errore durante il salvataggio delle modifiche!"
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr "Questo provider non permette l'importazione"
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr "Questo provider non permette l'esportazione"
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr "Registro importazioni"
|
||||
@ -3002,7 +2993,7 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr "La ricerca Fuzzy non è compatibile con questo metodo di ricerca!"
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
@ -3012,32 +3003,32 @@ msgstr ""
|
||||
"utente! Se hai dimenticato le credenziali del tuo super utente controlla la "
|
||||
"documentazione di Django per resettare le password."
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr "Le password non combaciano!"
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr "L'utente è stato creato e ora può essere usato per il login!"
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr "È stato fornito un link di invito non valido!"
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr ""
|
||||
"Sei già membro di una istanza e quindi non puoi entrare in quest'altra."
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr "Sei entrato a far parte di questa istanza."
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr "Il link di invito non è valido o è stato già usato!"
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
@ -3045,7 +3036,7 @@ msgstr ""
|
||||
"La segnalazione dei link di condivisione non è abilitata per questa istanza. "
|
||||
"Notifica l'amministratore per segnalare i problemi."
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
@ -3053,6 +3044,21 @@ msgstr ""
|
||||
"Il link per la condivisione delle ricette è stato disabilitato! Per maggiori "
|
||||
"informazioni contatta l'amministratore."
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "Tempo"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "Aggiungi al registro delle ricette cucinate"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "Tutti i campi sono opzionali e possono essere lasciati vuoti."
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "Valutazione"
|
||||
|
||||
#~ msgid "Exporting is not implemented for this provider"
|
||||
#~ msgstr "Questo provider non permette l'esportazione"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "No {self.basename} with id {child} exists"
|
||||
#~ msgstr "Non esiste nessun {self.basename} con id {child}"
|
||||
|
Binary file not shown.
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2020-06-02 19:28+0000\n"
|
||||
"Last-Translator: vabene1111 <vabene1234@googlemail.com>, 2021\n"
|
||||
"Language-Team: Latvian (https://www.transifex.com/django-recipes/"
|
||||
@ -302,7 +302,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:445
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
@ -360,7 +360,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -512,42 +512,38 @@ msgstr "Jums nav nepieciešamo atļauju, lai apskatītu šo lapu!"
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr "Jūs nevarat mainīt šo objektu, jo tas nepieder jums!"
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "Jums jānorāda vismaz recepte vai nosaukums."
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
#: .\cookbook\helper\template_helper.py:63
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Imported new recipe!"
|
||||
msgid "Imported %s recipes."
|
||||
@ -570,7 +566,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -599,7 +594,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -661,101 +656,80 @@ msgstr "Liels"
|
||||
msgid "New"
|
||||
msgstr "Jauns"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Teskts"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "Laiks"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "Faila ID"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Recepte"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Food"
|
||||
msgid "Food Alias"
|
||||
msgstr "Ēdiens"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Units"
|
||||
msgid "Unit Alias"
|
||||
msgstr "Vienības"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Keywords"
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Atslēgvārdi"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1122,8 +1096,8 @@ msgstr "Rediģēt vairākus"
|
||||
msgid "History"
|
||||
msgstr "Vēsture"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1217,7 +1191,6 @@ msgstr "Ceļam jābūt šādā formātā"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1264,7 +1237,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr "Recepšu grāmatas"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "Eksportēt receptes"
|
||||
|
||||
@ -1391,19 +1364,12 @@ msgstr "Importēt receptes"
|
||||
msgid "Import"
|
||||
msgstr "Importēt"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "Saglabāt recepšu pagatavošanu žurnālā"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Recepte"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "Visi lauki nav obligāti, un tos var atstāt tukšus."
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "Vērtējums"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "Aizvērt"
|
||||
@ -1517,7 +1483,9 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "vai atstājot tukšu rindu starp tekstu."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1540,8 +1508,12 @@ msgid "Lists"
|
||||
msgstr "Saraksti"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
"Saraksti var tikt numurēti vai nenumurēti. Ir <b>svarīgi atstāt tukšu rindu "
|
||||
@ -1817,7 +1789,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1842,7 +1814,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1872,7 +1844,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2155,7 +2127,9 @@ msgid "Finished"
|
||||
msgstr "Pabeigts"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
#, fuzzy
|
||||
#| msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr "Jūs esat bezsaistē. Iepirkumu saraksts netiek sinhronizēts."
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2457,6 +2431,16 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Teskts"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "Faila ID"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr "Ievadiet vietnes URL"
|
||||
@ -2645,179 +2629,180 @@ msgstr "GitHub Issues"
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr "Recepšu Markup specifikācija"
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
#, fuzzy
|
||||
#| msgid "Parameter filter_list incorrectly formatted"
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr "Parametrs filter_list ir nepareizi formatēts"
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr "Sinhronizācija ir veiksmīga!"
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "Sinhronizējot ar krātuvi, radās kļūda"
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr "Pieprasītā vietne sniedza nepareizus datus, kurus nevar nolasīt."
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr "Pieprasīto lapu nevarēja atrast."
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
@ -2825,28 +2810,28 @@ msgstr ""
|
||||
"Pieprasītajā vietnē nav norādīts atzīts datu formāts, no kura varētu "
|
||||
"importēt recepti."
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
#: .\cookbook\views\api.py:1118
|
||||
#, fuzzy
|
||||
#| msgid "The requested page could not be found."
|
||||
msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "Pieprasīto lapu nevarēja atrast."
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2907,20 +2892,16 @@ msgstr "Izmaiņas saglabātas!"
|
||||
msgid "Error saving changes!"
|
||||
msgstr "Saglabājot izmaiņas, radās kļūda!"
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr "Importēšanas žurnāls"
|
||||
@ -3041,7 +3022,7 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
@ -3051,44 +3032,56 @@ msgstr ""
|
||||
"aizmirsis sava superlietotāja informāciju, lūdzu, skatiet Django "
|
||||
"dokumentāciju par paroļu atiestatīšanu."
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr "Paroles nesakrīt!"
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr "Lietotājs ir izveidots, lūdzu, piesakieties!"
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr "Nepareiza uzaicinājuma saite!"
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
#, fuzzy
|
||||
#| msgid "You are not logged in and therefore cannot view this page!"
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr "Jūs neesat pieteicies un tāpēc nevarat skatīt šo lapu!"
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr "Uzaicinājuma saite nav derīga vai jau izmantota!"
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "Laiks"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "Saglabāt recepšu pagatavošanu žurnālā"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "Visi lauki nav obligāti, un tos var atstāt tukšus."
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "Vērtējums"
|
||||
|
||||
#~ msgid "New Unit"
|
||||
#~ msgstr "Jaunā vienība"
|
||||
|
||||
|
Binary file not shown.
@ -12,9 +12,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"PO-Revision-Date: 2021-11-14 14:06+0000\n"
|
||||
"Last-Translator: Job Putters <me@ixbitz.com>\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2022-02-09 01:31+0000\n"
|
||||
"Last-Translator: Jesse <jesse.kamps@pm.me>\n"
|
||||
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/recipes-"
|
||||
"backend/nl/>\n"
|
||||
"Language: nl\n"
|
||||
@ -22,7 +22,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.8\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
|
||||
#: .\cookbook\filters.py:23 .\cookbook\templates\forms\ingredients.html:34
|
||||
#: .\cookbook\templates\space.html:50 .\cookbook\templates\stats.html:28
|
||||
@ -110,20 +110,14 @@ msgid "Display nutritional energy amounts in joules instead of calories"
|
||||
msgstr "Geef energiewaardes weer in joules in plaats van calorieën"
|
||||
|
||||
#: .\cookbook\forms.py:79
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Users with whom newly created meal plan/shopping list entries should be "
|
||||
#| "shared by default."
|
||||
msgid "Users with whom newly created meal plans should be shared by default."
|
||||
msgstr ""
|
||||
"Gebruikers waarmee een nieuw maaltijdplan/boodschappenlijst standaard "
|
||||
"gedeeld moeten worden."
|
||||
"Gebruikers waarmee een nieuwe maaltijdplannen standaard gedeeld moeten "
|
||||
"worden."
|
||||
|
||||
#: .\cookbook\forms.py:80
|
||||
#, fuzzy
|
||||
#| msgid "Try the new shopping list"
|
||||
msgid "Users with whom to share shopping lists."
|
||||
msgstr "Probeer de nieuwe boodschappenlijst"
|
||||
msgstr "Gebruikers waarmee boodschappenlijsten gedeeld moeten worden."
|
||||
|
||||
#: .\cookbook\forms.py:82
|
||||
msgid "Show recently viewed recipes on search page."
|
||||
@ -156,11 +150,11 @@ msgstr "Zet de navbar vast aan de bovenkant van de pagina."
|
||||
|
||||
#: .\cookbook\forms.py:90 .\cookbook\forms.py:496
|
||||
msgid "Automatically add meal plan ingredients to shopping list."
|
||||
msgstr ""
|
||||
msgstr "Zet maaltijdplan ingrediënten automatisch op boodschappenlijst."
|
||||
|
||||
#: .\cookbook\forms.py:91
|
||||
msgid "Exclude ingredients that are on hand."
|
||||
msgstr ""
|
||||
msgstr "Sluit ingrediënten die op voorraad zijn uit."
|
||||
|
||||
#: .\cookbook\forms.py:108
|
||||
msgid ""
|
||||
@ -297,9 +291,13 @@ msgstr ""
|
||||
"(lage waarden betekenen bijvoorbeeld dat meer typefouten genegeerd worden)."
|
||||
|
||||
#: .\cookbook\forms.py:445
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Select type method of search. Click <a href=\"/docs/search/\">here</a> "
|
||||
#| "for full desciption of choices."
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
"Selecteer zoekmethode. Klik <a href=\"/docs/search/\">hier</a> voor een "
|
||||
"beschrijving van de keuzes."
|
||||
@ -370,7 +368,9 @@ msgid "Partial Match"
|
||||
msgstr "Gedeeltelijke overeenkomst"
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
#, fuzzy
|
||||
#| msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr "Begint met"
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -386,82 +386,87 @@ msgid ""
|
||||
"Users will see all items you add to your shopping list. They must add you "
|
||||
"to see items on their list."
|
||||
msgstr ""
|
||||
"Gebruikers zien alle items die je op je boodschappenlijst zet. Ze moeten "
|
||||
"jou toevoegen om items op hun lijst te zien."
|
||||
|
||||
#: .\cookbook\forms.py:497
|
||||
msgid ""
|
||||
"When adding a meal plan to the shopping list (manually or automatically), "
|
||||
"include all related recipes."
|
||||
msgstr ""
|
||||
"Als een maaltijdplan aan de boodschappenlijst toegevoegd wordt (handmatig of "
|
||||
"automatisch), neem dan alle recepten op."
|
||||
|
||||
#: .\cookbook\forms.py:498
|
||||
msgid ""
|
||||
"When adding a meal plan to the shopping list (manually or automatically), "
|
||||
"exclude ingredients that are on hand."
|
||||
msgstr ""
|
||||
"Als een maaltijdplan aan de boodschappenlijst toegevoegd wordt (handmatig of "
|
||||
"automatisch), sluit ingrediënten die op voorraad zijn dan uit."
|
||||
|
||||
#: .\cookbook\forms.py:499
|
||||
msgid "Default number of hours to delay a shopping list entry."
|
||||
msgstr ""
|
||||
msgstr "Standaard aantal uren om een boodschappenlijst item te vertragen."
|
||||
|
||||
#: .\cookbook\forms.py:500
|
||||
msgid "Filter shopping list to only include supermarket categories."
|
||||
msgstr ""
|
||||
msgstr "Filter boodschappenlijst om alleen supermarktcategorieën te bevatten."
|
||||
|
||||
#: .\cookbook\forms.py:501
|
||||
msgid "Days of recent shopping list entries to display."
|
||||
msgstr ""
|
||||
msgstr "Dagen van recente boodschappenlijst items weer te geven."
|
||||
|
||||
#: .\cookbook\forms.py:502
|
||||
msgid "Mark food 'On Hand' when checked off shopping list."
|
||||
msgstr ""
|
||||
"Markeer eten 'Op voorraad' wanneer het van het boodschappenlijstje is "
|
||||
"afgevinkt."
|
||||
|
||||
#: .\cookbook\forms.py:503
|
||||
msgid "Delimiter to use for CSV exports."
|
||||
msgstr ""
|
||||
msgstr "Scheidingsteken te gebruiken voor CSV exports."
|
||||
|
||||
#: .\cookbook\forms.py:504
|
||||
msgid "Prefix to add when copying list to the clipboard."
|
||||
msgstr ""
|
||||
"Toe te voegen Voorvoegsel bij het kopiëren van een lijst naar het klembord."
|
||||
|
||||
#: .\cookbook\forms.py:508
|
||||
#, fuzzy
|
||||
#| msgid "New Shopping List"
|
||||
msgid "Share Shopping List"
|
||||
msgstr "Nieuwe boodschappenlijst"
|
||||
msgstr "Deel boodschappenlijst"
|
||||
|
||||
#: .\cookbook\forms.py:509
|
||||
msgid "Autosync"
|
||||
msgstr ""
|
||||
msgstr "Autosync"
|
||||
|
||||
#: .\cookbook\forms.py:510
|
||||
msgid "Auto Add Meal Plan"
|
||||
msgstr ""
|
||||
msgstr "Voeg maaltijdplan automatisch toe"
|
||||
|
||||
#: .\cookbook\forms.py:511
|
||||
msgid "Exclude On Hand"
|
||||
msgstr ""
|
||||
msgstr "Sluit op voorraad uit"
|
||||
|
||||
#: .\cookbook\forms.py:512
|
||||
msgid "Include Related"
|
||||
msgstr ""
|
||||
msgstr "Neem gerelateerde op"
|
||||
|
||||
#: .\cookbook\forms.py:513
|
||||
msgid "Default Delay Hours"
|
||||
msgstr ""
|
||||
msgstr "Standaard vertraging in uren"
|
||||
|
||||
#: .\cookbook\forms.py:514
|
||||
#, fuzzy
|
||||
#| msgid "Select Supermarket"
|
||||
msgid "Filter to Supermarket"
|
||||
msgstr "Selecteer supermarkt"
|
||||
msgstr "Filter op supermarkt"
|
||||
|
||||
#: .\cookbook\forms.py:515
|
||||
msgid "Recent Days"
|
||||
msgstr ""
|
||||
msgstr "Afgelopen dagen"
|
||||
|
||||
#: .\cookbook\forms.py:516
|
||||
msgid "CSV Delimiter"
|
||||
msgstr ""
|
||||
msgstr "CSV scheidingsteken"
|
||||
|
||||
#: .\cookbook\forms.py:517 .\cookbook\templates\shopping_list.html:322
|
||||
msgid "List Prefix"
|
||||
@ -469,27 +474,23 @@ msgstr "Lijst voorvoegsel"
|
||||
|
||||
#: .\cookbook\forms.py:518
|
||||
msgid "Auto On Hand"
|
||||
msgstr ""
|
||||
msgstr "Auto op voorraad"
|
||||
|
||||
#: .\cookbook\forms.py:528
|
||||
msgid "Reset Food Inheritance"
|
||||
msgstr ""
|
||||
msgstr "Herstel Ingrediënt overname"
|
||||
|
||||
#: .\cookbook\forms.py:529
|
||||
msgid "Reset all food to inherit the fields configured."
|
||||
msgstr ""
|
||||
msgstr "Herstel alle ingrediënten om de geconfigureerde velden over te nemen."
|
||||
|
||||
#: .\cookbook\forms.py:541
|
||||
#, fuzzy
|
||||
#| msgid "Food that should be replaced."
|
||||
msgid "Fields on food that should be inherited by default."
|
||||
msgstr "Te vervangen Ingrediënt."
|
||||
msgstr "Velden van ingrediënten die standaard overgenomen moeten worden."
|
||||
|
||||
#: .\cookbook\forms.py:542
|
||||
#, fuzzy
|
||||
#| msgid "Show recently viewed recipes on search page."
|
||||
msgid "Show recipe counts on search filters"
|
||||
msgstr "Geef recent bekeken recepten op de zoekpagina weer."
|
||||
msgstr "Toon recepten teller bij zoekfilters"
|
||||
|
||||
#: .\cookbook\helper\AllAuthCustomAdapter.py:36
|
||||
msgid ""
|
||||
@ -523,33 +524,29 @@ msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
"Interactie met dit object is niet mogelijk omdat je niet de eigenaar bent!"
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
msgstr "Er moet een queryset of hash_key opgegeven worden"
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgstr "Je moet minimaal één recept of titel te specificeren."
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
msgstr ""
|
||||
#| msgid "You must supply a created_by"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "Je moet een created_by aanleveren"
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
#: .\cookbook\helper\template_helper.py:63
|
||||
msgid "Could not parse template code."
|
||||
msgstr "Sjablooncode kon niet verwerkt worden."
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
"De importtool verwachtte een .zip bestand. Heb je het juiste type gekozen?"
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
@ -557,11 +554,11 @@ msgstr ""
|
||||
"Er is een onverwachte fout opgetreden tijdens het importeren. Controleer of "
|
||||
"u een geldig bestand hebt geüpload."
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr "De volgende recepten zijn genegeerd omdat ze al bestonden:"
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr "%s recepten geïmporteerd."
|
||||
@ -579,7 +576,6 @@ msgid "Source"
|
||||
msgstr "Bron"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -608,7 +604,9 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr "Herbouwt de volledige tekst zoekindex van Recept"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
#, fuzzy
|
||||
#| msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
"Alleen Postgress databases gebruiken volledige tekst zoekmethoden, geen "
|
||||
"index aanwezig om te herbouwen"
|
||||
@ -674,93 +672,76 @@ msgstr "Groot"
|
||||
msgid "New"
|
||||
msgstr "Nieuw"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr " is deel van een receptstap en kan niet verwijderd worden"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Tekst"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "Tijd"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "Bestand"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Recept"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr "Simpel"
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr "Zin"
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr "Web"
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr "Rauw"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Food Alias"
|
||||
msgstr "Ingrediënt alias"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr "Eenheid alias"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Etiket alias"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
msgstr "Een gebruiker is verplicht"
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr "Bestandsuploads zijn niet ingeschakeld voor deze Ruimte."
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr "U heeft de uploadlimiet bereikt."
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
msgstr "Bestaande boodschappenlijst is bijgewerkt"
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
"Lijst van ingrediënten ID's van het toe te voegen recept, als deze niet "
|
||||
"opgegeven worden worden alle ingrediënten toegevoegd."
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1121,8 +1102,8 @@ msgstr "Batchbewerking"
|
||||
msgid "History"
|
||||
msgstr "Geschiedenis"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1215,7 +1196,6 @@ msgstr "Het pad dient het volgende format te hebben"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1258,7 +1238,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr "Kookboeken"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "Recepten exporteren"
|
||||
|
||||
@ -1383,19 +1363,12 @@ msgstr "Recepten importeren"
|
||||
msgid "Import"
|
||||
msgstr "Importeer"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "logboek recept koken"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Recept"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "Alle velden zijn optioneel en mogen leeg gelaten worden."
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "Beoordeling"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "Sluiten"
|
||||
@ -1507,7 +1480,9 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "of door een witregel te gebruiken."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1530,8 +1505,12 @@ msgid "Lists"
|
||||
msgstr "Lijsten"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
"Lijsten zijn geordend en ongeordend mogelijk. Het is <b>belangrijk om een "
|
||||
@ -1827,10 +1806,19 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:29
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Simple searches ignore punctuation and common words such as "
|
||||
#| "'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
#| " Searching for 'apple or flour' will return any recipe that "
|
||||
#| "includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
#| "selected for a full text search.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1863,13 +1851,30 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:39
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Web searches simulate functionality found on many web search "
|
||||
#| "sites supporting special syntax.\n"
|
||||
#| " Placing quotes around several words will convert those words "
|
||||
#| "into a phrase.\n"
|
||||
#| " 'or' is recongized as searching for the word (or phrase) "
|
||||
#| "immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
#| " '-' is recognized as searching for recipes that do not "
|
||||
#| "include the word (or phrase) that comes immediately after. \n"
|
||||
#| " For example searching for 'apple pie' or cherry -butter will "
|
||||
#| "return any recipe that includes the phrase 'apple pie' or the word "
|
||||
#| "'cherry' \n"
|
||||
#| " in any field included in the full text search but exclude any "
|
||||
#| "recipe that has the word 'butter' in any field included.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Web searches simulate functionality found on many web search "
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1908,6 +1913,19 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:59
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Another approach to searching that also requires Postgresql "
|
||||
#| "is fuzzy search or trigram similarity. A trigram is a group of three "
|
||||
#| "consecutive characters.\n"
|
||||
#| " For example searching for 'apple' will create x trigrams "
|
||||
#| "'app', 'ppl', 'ple' and will create a score of how closely words match "
|
||||
#| "the generated trigrams.\n"
|
||||
#| " One benefit of searching trigams is that a search for "
|
||||
#| "'sandwich' will find mispelled words such as 'sandwhich' that would be "
|
||||
#| "missed by other methods.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Another approach to searching that also requires Postgresql is "
|
||||
@ -1917,7 +1935,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2245,7 +2263,9 @@ msgid "Finished"
|
||||
msgstr "Afgerond"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
#, fuzzy
|
||||
#| msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr "Je bent offline, de boodschappenlijst synchroniseert mogelijk niet."
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2541,6 +2561,14 @@ msgstr "URL"
|
||||
msgid "App"
|
||||
msgstr "App"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Tekst"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "Bestand"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr "Vul website URL in"
|
||||
@ -2716,181 +2744,182 @@ msgstr "GitHub issues"
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr "Recept opmaak specificatie"
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr "Parameter updatet_at is onjuist geformateerd"
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr "Er bestaat geen {self.basename} met id {pk}"
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr "Kan niet met hetzelfde object samenvoegen!"
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr "Er bestaat geen {self.basename} met id {target}"
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr "Kan niet met kindobject samenvoegen!"
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr "{source.name} is succesvol samengevoegd met {target.name}"
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
"Er is een error opgetreden bij het samenvoegen van {source.name} met {target."
|
||||
"name}"
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr "{child.name} is succesvol verplaatst naar het hoogste niveau."
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr "Er is een error opgetreden bij het verplaatsen "
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr "Kan object niet verplaatsen naar zichzelf!"
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr "Er bestaat geen {self.basename} met id {parent}"
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr "{child.name} is succesvol verplaatst naar {parent.name}"
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr "Deze optie is nog niet beschikbaar in de gehoste versie van Tandoor!"
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr "Synchronisatie succesvol!"
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "Er is een fout opgetreden bij het synchroniseren met Opslag"
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr "Niks te doen."
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
"De opgevraagde site heeft misvormde data verstrekt en kan niet gelezen "
|
||||
"worden."
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr "De opgevraagde pagina kon niet gevonden worden."
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
@ -2898,26 +2927,28 @@ msgstr ""
|
||||
"De opgevraagde site biedt geen bekend gegevensformaat aan om het recept van "
|
||||
"te importeren."
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
#, fuzzy
|
||||
#| msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "Er is geen bruikbare data gevonden."
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr "Ik kon niks vinden om te doen."
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr "Je hebt het maximaal aantal recepten voor jouw ruimte bereikt."
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr "Je hebt meer gebruikers dan toegestaan in jouw ruimte."
|
||||
@ -2977,20 +3008,16 @@ msgstr "Wijzigingen opgeslagen!"
|
||||
msgid "Error saving changes!"
|
||||
msgstr "Fout bij het opslaan van de wijzigingen!"
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr "Importeren is voor deze provider niet geïmplementeerd"
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr "Exporteren is voor deze provider niet geïmplementeerd"
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr "Import logboek"
|
||||
@ -3117,7 +3144,7 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr "'Fuzzy' zoeken is niet te gebruiken met deze zoekmethode!"
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
@ -3128,31 +3155,31 @@ msgstr ""
|
||||
"documentatie raad moeten plegen voor een methode om je wachtwoord te "
|
||||
"resetten."
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr "Wachtwoorden komen niet overeen!"
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr "Gebruiker is gecreëerd, Log in alstublieft!"
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr "Onjuiste uitnodigingslink opgegeven!"
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr "Je bent al lid van een ruimte en kan daardoor niet toetreden tot deze."
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr "Succesvol toegetreden tot ruimte."
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr "De uitnodigingslink is niet valide of al gebruikt!"
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
@ -3160,7 +3187,7 @@ msgstr ""
|
||||
"Het rapporteren van gedeelde links is niet geactiveerd voor deze instantie. "
|
||||
"Rapporteer problemen bij de beheerder van de pagina."
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
@ -3168,6 +3195,24 @@ msgstr ""
|
||||
"Links voor het delen van recepten zijn gedeactiveerd. Neem contact op met de "
|
||||
"paginabeheerder voor aanvullende informatie."
|
||||
|
||||
#~ msgid "You must supply a recipe or mealplan"
|
||||
#~ msgstr "Je moet een recept of maaltijdplan aanleveren"
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "Tijd"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "logboek recept koken"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "Alle velden zijn optioneel en mogen leeg gelaten worden."
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "Beoordeling"
|
||||
|
||||
#~ msgid "Exporting is not implemented for this provider"
|
||||
#~ msgstr "Exporteren is voor deze provider niet geïmplementeerd"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "No {self.basename} with id {child} exists"
|
||||
#~ msgstr "Er bestaat geen {self.basename} met id {child}"
|
||||
|
Binary file not shown.
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2021-11-12 20:06+0000\n"
|
||||
"Last-Translator: Henrique Silva <hds@mailbox.org>\n"
|
||||
"Language-Team: Portuguese <http://translate.tandoor.dev/projects/tandoor/"
|
||||
@ -294,9 +294,13 @@ msgstr ""
|
||||
"ignorados)."
|
||||
|
||||
#: .\cookbook\forms.py:445
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Select type method of search. Click <a href=\"/docs/search/\">here</a> "
|
||||
#| "for full desciption of choices."
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
"Selecionar o método de pesquisa. Uma descrição completa das opções pode ser "
|
||||
"encontrada <a href=\"/docs/search/\">aqui</a>."
|
||||
@ -360,7 +364,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -512,42 +516,38 @@ msgstr "Sem permissões para aceder a esta página!"
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "É necessário inserir uma receita ou um título."
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
#: .\cookbook\helper\template_helper.py:63
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Import Recipes"
|
||||
msgid "Imported %s recipes."
|
||||
@ -568,7 +568,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -597,7 +596,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -659,101 +658,80 @@ msgstr "Grande"
|
||||
msgid "New"
|
||||
msgstr "Novo"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Texto"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "Tempo"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "ID the ficheiro"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Receita"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "New Food"
|
||||
msgid "Food Alias"
|
||||
msgstr "Novo Prato"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Units"
|
||||
msgid "Unit Alias"
|
||||
msgstr "Unidades"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
#, fuzzy
|
||||
#| msgid "Keywords"
|
||||
msgid "Keyword Alias"
|
||||
msgstr "Palavras-chave"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1110,8 +1088,8 @@ msgstr "Editor em massa"
|
||||
msgid "History"
|
||||
msgstr "Histórico"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1202,7 +1180,6 @@ msgstr "O caminho deve estar no seguinte formato"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1249,7 +1226,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr "Livros de Receitas"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "Exportar Receitas"
|
||||
|
||||
@ -1372,19 +1349,12 @@ msgstr "Importar Receitas"
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "Registro Receita Cooking"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "Receita"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "Todos os campos são opcionais e podem ser deixados vazios. "
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "Classificação "
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "Fechar"
|
||||
@ -1485,7 +1455,9 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "ou deixando uma linha em branco no meio."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1508,8 +1480,12 @@ msgid "Lists"
|
||||
msgstr "Listas"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
"As listas podem ser ordenadas ou não ordenadas. É <b>importante deixar uma "
|
||||
@ -1783,7 +1759,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1808,7 +1784,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1838,7 +1814,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2115,7 +2091,7 @@ msgid "Finished"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2377,6 +2353,16 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "Texto"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
#, fuzzy
|
||||
#| msgid "File ID"
|
||||
msgid "File"
|
||||
msgstr "ID the ficheiro"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr ""
|
||||
@ -2555,202 +2541,203 @@ msgstr ""
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
msgstr "Esta página não contém uma receita que eu consiga entender."
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
msgid "No usable data could be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2808,20 +2795,16 @@ msgstr ""
|
||||
msgid "Error saving changes!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr ""
|
||||
@ -2940,51 +2923,63 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
"on how to reset passwords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
#, fuzzy
|
||||
#| msgid "You are not logged in and therefore cannot view this page!"
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr "Autenticação necessária para aceder a esta página!"
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "Tempo"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "Registro Receita Cooking"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "Todos os campos são opcionais e podem ser deixados vazios. "
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "Classificação "
|
||||
|
||||
#~ msgid "New Unit"
|
||||
#~ msgstr "Nova Unidade"
|
||||
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -260,7 +260,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:445
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
@ -316,7 +316,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -458,16 +458,12 @@ msgstr ""
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
msgid "You must supply a servings size"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
@ -475,23 +471,23 @@ msgstr ""
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr ""
|
||||
@ -509,7 +505,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -538,7 +533,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -600,93 +595,74 @@ msgstr ""
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Food Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Keyword Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1031,8 +1007,8 @@ msgstr ""
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1121,7 +1097,6 @@ msgstr ""
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1162,7 +1137,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr ""
|
||||
|
||||
@ -1280,19 +1255,12 @@ msgstr ""
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
@ -1383,7 +1351,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1407,7 +1375,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
|
||||
@ -1669,7 +1637,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1694,7 +1662,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1724,7 +1692,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -1983,7 +1951,7 @@ msgid "Finished"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2241,6 +2209,14 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr ""
|
||||
@ -2403,202 +2379,203 @@ msgstr ""
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
msgid "No usable data could be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2656,20 +2633,16 @@ msgstr ""
|
||||
msgid "Error saving changes!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr ""
|
||||
@ -2786,44 +2759,44 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
"on how to reset passwords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
|
Binary file not shown.
@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
|
||||
"PO-Revision-Date: 2021-11-16 06:06+0000\n"
|
||||
"Last-Translator: Luka <storek00@gmail.com>\n"
|
||||
"PO-Revision-Date: 2022-02-02 15:31+0000\n"
|
||||
"Last-Translator: Mario Dvorsek <mario.dvorsek@gmail.com>\n"
|
||||
"Language-Team: Slovenian <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/sl/>\n"
|
||||
"Language: sl\n"
|
||||
@ -18,7 +18,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
|
||||
"%100==4 ? 2 : 3;\n"
|
||||
"X-Generator: Weblate 4.8\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
|
||||
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
|
||||
#: .\cookbook\templates\forms\ingredients.html:34
|
||||
@ -33,47 +33,47 @@ msgstr "Privzeta enota"
|
||||
|
||||
#: .\cookbook\forms.py:55
|
||||
msgid "Use fractions"
|
||||
msgstr ""
|
||||
msgstr "Uporabi ulomke/frakcije"
|
||||
|
||||
#: .\cookbook\forms.py:56
|
||||
msgid "Use KJ"
|
||||
msgstr ""
|
||||
msgstr "Uporabi KJ"
|
||||
|
||||
#: .\cookbook\forms.py:57
|
||||
msgid "Theme"
|
||||
msgstr ""
|
||||
msgstr "Tema"
|
||||
|
||||
#: .\cookbook\forms.py:58
|
||||
msgid "Navbar color"
|
||||
msgstr ""
|
||||
msgstr "Barva navigacijske vrstice"
|
||||
|
||||
#: .\cookbook\forms.py:59
|
||||
msgid "Sticky navbar"
|
||||
msgstr ""
|
||||
msgstr "Lepljiva navigacijska vrstica"
|
||||
|
||||
#: .\cookbook\forms.py:60
|
||||
msgid "Default page"
|
||||
msgstr ""
|
||||
msgstr "Privzeta stran"
|
||||
|
||||
#: .\cookbook\forms.py:61
|
||||
msgid "Show recent recipes"
|
||||
msgstr ""
|
||||
msgstr "Prikaži nedavne recepte"
|
||||
|
||||
#: .\cookbook\forms.py:62
|
||||
msgid "Search style"
|
||||
msgstr ""
|
||||
msgstr "Vrsta iskalnika"
|
||||
|
||||
#: .\cookbook\forms.py:63
|
||||
msgid "Plan sharing"
|
||||
msgstr ""
|
||||
msgstr "Deli planer"
|
||||
|
||||
#: .\cookbook\forms.py:64
|
||||
msgid "Ingredient decimal places"
|
||||
msgstr ""
|
||||
msgstr "Decimalno mesto pri sestavini"
|
||||
|
||||
#: .\cookbook\forms.py:65
|
||||
msgid "Shopping list auto sync period"
|
||||
msgstr ""
|
||||
msgstr "Čas avtomatske sinhronizacije pri nakupovalnem listku"
|
||||
|
||||
#: .\cookbook\forms.py:66 .\cookbook\templates\recipe_view.html:21
|
||||
#: .\cookbook\templates\space.html:62 .\cookbook\templates\stats.html:47
|
||||
@ -85,38 +85,44 @@ msgid ""
|
||||
"Color of the top navigation bar. Not all colors work with all themes, just "
|
||||
"try them out!"
|
||||
msgstr ""
|
||||
"Barva zgornje vrstice za krmarjenje. Ne delujejo vse barve z vsemi temami!"
|
||||
|
||||
#: .\cookbook\forms.py:72
|
||||
msgid "Default Unit to be used when inserting a new ingredient into a recipe."
|
||||
msgstr ""
|
||||
"Privzeta enota, ki se uporablja pri vstavljanju nove sestavine v recept."
|
||||
|
||||
#: .\cookbook\forms.py:74
|
||||
msgid ""
|
||||
"Enables support for fractions in ingredient amounts (e.g. convert decimals "
|
||||
"to fractions automatically)"
|
||||
msgstr ""
|
||||
"Omogoča podporo ulomkom/frakcijam v količinah sestavin (npr. samodejno "
|
||||
"pretvori decimalke v ulomke)"
|
||||
|
||||
#: .\cookbook\forms.py:76
|
||||
msgid "Display nutritional energy amounts in joules instead of calories"
|
||||
msgstr ""
|
||||
msgstr "Prikazuj hranilne energijske količine v joules namesto v kalorijah"
|
||||
|
||||
#: .\cookbook\forms.py:78
|
||||
msgid ""
|
||||
"Users with whom newly created meal plan/shopping list entries should be "
|
||||
"shared by default."
|
||||
msgstr ""
|
||||
"Uporabniki, s katerimi je privzeto deljen novo ustvarjen načrt ali "
|
||||
"nakupovalni listek."
|
||||
|
||||
#: .\cookbook\forms.py:80
|
||||
msgid "Show recently viewed recipes on search page."
|
||||
msgstr ""
|
||||
msgstr "Prikaži nedavno videne recepte na iskalniku."
|
||||
|
||||
#: .\cookbook\forms.py:81
|
||||
msgid "Number of decimals to round ingredients."
|
||||
msgstr ""
|
||||
msgstr "Število decimalk, ki so zaokrožene pri sestavinah."
|
||||
|
||||
#: .\cookbook\forms.py:82
|
||||
msgid "If you want to be able to create and see comments underneath recipes."
|
||||
msgstr ""
|
||||
msgstr "V primeru, da želite ustvariti in videti komentarje pod recepti."
|
||||
|
||||
#: .\cookbook\forms.py:84
|
||||
msgid ""
|
||||
@ -125,21 +131,28 @@ msgid ""
|
||||
"Useful when shopping with multiple people but might use a little bit of "
|
||||
"mobile data. If lower than instance limit it is reset when saving."
|
||||
msgstr ""
|
||||
"Nastavitev na 0 bo onemogočila avtomatsko sinhronizacijo. V pogledu "
|
||||
"nakupovalnega listka, se seznam osvežuje vsake toliko sekund, če nekdo drug "
|
||||
"naredi spremembo. To je najbolj uporabno, če nakupovalni listek delimo z "
|
||||
"večimi osebami. Paziti je potrebno, saj porabi nekaj podatkov v mobilnem "
|
||||
"omrežju."
|
||||
|
||||
#: .\cookbook\forms.py:87
|
||||
msgid "Makes the navbar stick to the top of the page."
|
||||
msgstr ""
|
||||
msgstr "Nastavi navigacijsko vrstico na vrh strani."
|
||||
|
||||
#: .\cookbook\forms.py:103
|
||||
msgid ""
|
||||
"Both fields are optional. If none are given the username will be displayed "
|
||||
"instead"
|
||||
msgstr ""
|
||||
"Obe polji sta opcijski. V primeru, da ju pustimo prazni bo prikazano "
|
||||
"uporabniško ime"
|
||||
|
||||
#: .\cookbook\forms.py:124 .\cookbook\forms.py:289
|
||||
#: .\cookbook\templates\url_import.html:158
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
msgstr "Ime"
|
||||
|
||||
#: .\cookbook\forms.py:125 .\cookbook\forms.py:290
|
||||
#: .\cookbook\templates\space.html:39 .\cookbook\templates\stats.html:24
|
||||
@ -150,47 +163,51 @@ msgstr "Ključne besede"
|
||||
|
||||
#: .\cookbook\forms.py:126
|
||||
msgid "Preparation time in minutes"
|
||||
msgstr ""
|
||||
msgstr "Priprava v minutah"
|
||||
|
||||
#: .\cookbook\forms.py:127
|
||||
msgid "Waiting time (cooking/baking) in minutes"
|
||||
msgstr ""
|
||||
msgstr "Čas čakanja v minutah"
|
||||
|
||||
#: .\cookbook\forms.py:128 .\cookbook\forms.py:259 .\cookbook\forms.py:291
|
||||
msgid "Path"
|
||||
msgstr ""
|
||||
msgstr "Pot"
|
||||
|
||||
#: .\cookbook\forms.py:129
|
||||
msgid "Storage UID"
|
||||
msgstr ""
|
||||
msgstr "UID shrambe"
|
||||
|
||||
#: .\cookbook\forms.py:157
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
msgstr "Privzeto"
|
||||
|
||||
#: .\cookbook\forms.py:168 .\cookbook\templates\url_import.html:94
|
||||
msgid ""
|
||||
"To prevent duplicates recipes with the same name as existing ones are "
|
||||
"ignored. Check this box to import everything."
|
||||
msgstr ""
|
||||
"V primeru, da želite preprečiti dvojnike receptov z enakim imenom kot so "
|
||||
"obstoječi. Če želite uvoziti vse, potrdite to polje."
|
||||
|
||||
#: .\cookbook\forms.py:190
|
||||
msgid "Add your comment: "
|
||||
msgstr ""
|
||||
msgstr "Dodaj komentar: "
|
||||
|
||||
#: .\cookbook\forms.py:205
|
||||
msgid "Leave empty for dropbox and enter app password for nextcloud."
|
||||
msgstr ""
|
||||
msgstr "Pusti prazno za dropbox in vnesi geslo za nextcloud."
|
||||
|
||||
#: .\cookbook\forms.py:212
|
||||
msgid "Leave empty for nextcloud and enter api token for dropbox."
|
||||
msgstr ""
|
||||
msgstr "Pusti prazno za nextcloud in vnesi API žeton za dropbox."
|
||||
|
||||
#: .\cookbook\forms.py:221
|
||||
msgid ""
|
||||
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
|
||||
"php/webdav/</code> is added automatically)"
|
||||
msgstr ""
|
||||
"Pusti prazno za dropbox in vnesi URL za nextcloud (<code>/remote.php/webdav/"
|
||||
"</code> je dodano avtomatsko)"
|
||||
|
||||
#: .\cookbook\forms.py:258 .\cookbook\views\edit.py:166
|
||||
msgid "Storage"
|
||||
@ -198,33 +215,35 @@ msgstr "Shramba"
|
||||
|
||||
#: .\cookbook\forms.py:260
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
msgstr "Aktivno"
|
||||
|
||||
#: .\cookbook\forms.py:265
|
||||
msgid "Search String"
|
||||
msgstr ""
|
||||
msgstr "Iskalni niz"
|
||||
|
||||
#: .\cookbook\forms.py:292
|
||||
msgid "File ID"
|
||||
msgstr ""
|
||||
msgstr "ID datoteke"
|
||||
|
||||
#: .\cookbook\forms.py:313
|
||||
msgid "You must provide at least a recipe or a title."
|
||||
msgstr ""
|
||||
msgstr "Vpisati moraš vsaj recept ali naslov."
|
||||
|
||||
#: .\cookbook\forms.py:326
|
||||
msgid "You can list default users to share recipes with in the settings."
|
||||
msgstr ""
|
||||
msgstr "Seznam uporabnikov za deljenje receptov lahko vidiš v nastavitvah."
|
||||
|
||||
#: .\cookbook\forms.py:327
|
||||
msgid ""
|
||||
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
|
||||
"\">docs here</a>"
|
||||
msgstr ""
|
||||
"Lahko uporabiš \"markdown\", da urediš to polje. Preveri <a href=\"/docs/"
|
||||
"markdown/\">tukaj</a>"
|
||||
|
||||
#: .\cookbook\forms.py:353
|
||||
msgid "Maximum number of users for this space reached."
|
||||
msgstr ""
|
||||
msgstr "Maksimalno število uporabnikov za ta prostor je doseženo."
|
||||
|
||||
#: .\cookbook\forms.py:359
|
||||
msgid "Email address already taken!"
|
||||
@ -235,56 +254,71 @@ msgid ""
|
||||
"An email address is not required but if present the invite link will be sent "
|
||||
"to the user."
|
||||
msgstr ""
|
||||
"E-poštni naslov ni potreben, vendar če je vnešeno, bo povabilo poslano do "
|
||||
"uporabnika."
|
||||
|
||||
#: .\cookbook\forms.py:382
|
||||
msgid "Name already taken."
|
||||
msgstr ""
|
||||
msgstr "Ime je že zasedeno."
|
||||
|
||||
#: .\cookbook\forms.py:393
|
||||
msgid "Accept Terms and Privacy"
|
||||
msgstr ""
|
||||
msgstr "Sprejmi pogoje uporabe"
|
||||
|
||||
#: .\cookbook\forms.py:425
|
||||
msgid ""
|
||||
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
|
||||
"g. low values mean more typos are ignored)."
|
||||
msgstr ""
|
||||
"Določa, kakšno je iskanje, če uporablja trigram podobnost ujemanje (npr. "
|
||||
"nizke vrednosti pomenijo več, tipkanje se prezre)."
|
||||
|
||||
#: .\cookbook\forms.py:435
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
msgstr ""
|
||||
"Izberi metodo iskanja. Klikni <a href=\"/docs/search/\">tukaj</a> za "
|
||||
"prikaz vseh izbir."
|
||||
|
||||
#: .\cookbook\forms.py:436
|
||||
msgid ""
|
||||
"Use fuzzy matching on units, keywords and ingredients when editing and "
|
||||
"importing recipes."
|
||||
msgstr ""
|
||||
"Pri urejanju in uvozu receptov uporabite mehka ujemanja na enotah, ključnih "
|
||||
"besedah in sestavinah."
|
||||
|
||||
#: .\cookbook\forms.py:438
|
||||
msgid ""
|
||||
"Fields to search ignoring accents. Selecting this option can improve or "
|
||||
"degrade search quality depending on language"
|
||||
msgstr ""
|
||||
"Polja za iskanje prezrtih naglasov. Če izberete to možnost, lahko izboljšate "
|
||||
"ali poslabšate kakovost iskanja, odvisno od jezika"
|
||||
|
||||
#: .\cookbook\forms.py:440
|
||||
msgid ""
|
||||
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
|
||||
"'pie' and 'piece' and 'soapie')"
|
||||
msgstr ""
|
||||
"Polja za iskanje delnih ujemajev. (npr. iskanje \"Pie\" vrne \"pie\" in "
|
||||
"\"piece\" in \"soapie\")"
|
||||
|
||||
#: .\cookbook\forms.py:442
|
||||
msgid ""
|
||||
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
|
||||
"will return 'salad' and 'sandwich')"
|
||||
msgstr ""
|
||||
"Polja za iskanje začetka ujemanja besed. (npr. iskanje \"sa\" vrne \"salad\" "
|
||||
"in \"sandwich\")"
|
||||
|
||||
#: .\cookbook\forms.py:444
|
||||
msgid ""
|
||||
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
|
||||
"Note: this option will conflict with 'web' and 'raw' methods of search."
|
||||
msgstr ""
|
||||
"Polja za \"mehko\" iskanje. (npr. iskanje \"recpie\" bo našlo \"recipe\".)"
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
msgid ""
|
||||
|
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2020-06-02 19:28+0000\n"
|
||||
"Last-Translator: Emre S, 2020\n"
|
||||
"Language-Team: Turkish (https://www.transifex.com/django-recipes/"
|
||||
@ -275,7 +275,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:445
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
@ -331,7 +331,7 @@ msgid "Partial Match"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -475,16 +475,12 @@ msgstr ""
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
msgid "You must supply a servings size"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
@ -492,23 +488,23 @@ msgstr ""
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr ""
|
||||
@ -526,7 +522,6 @@ msgid "Source"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -555,7 +550,7 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -617,93 +612,74 @@ msgstr ""
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Food Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Keyword Alias"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
|
||||
@ -1048,8 +1024,8 @@ msgstr ""
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1138,7 +1114,6 @@ msgstr ""
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1179,7 +1154,7 @@ msgstr ""
|
||||
msgid "Recipe Books"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr ""
|
||||
|
||||
@ -1297,19 +1272,12 @@ msgstr ""
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
@ -1400,7 +1368,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1424,7 +1392,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr ""
|
||||
|
||||
@ -1686,7 +1654,7 @@ msgstr ""
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
@ -1711,7 +1679,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1741,7 +1709,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -2000,7 +1968,7 @@ msgid "Finished"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2258,6 +2226,14 @@ msgstr ""
|
||||
msgid "App"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr ""
|
||||
@ -2420,202 +2396,203 @@ msgstr ""
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
msgid "No usable data could be found."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
@ -2673,20 +2650,16 @@ msgstr ""
|
||||
msgid "Error saving changes!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr ""
|
||||
@ -2803,44 +2776,44 @@ msgstr ""
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
"on how to reset passwords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
|
Binary file not shown.
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||
"PO-Revision-Date: 2022-01-22 03:30+0000\n"
|
||||
"Last-Translator: 糖多 <1365143958@qq.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <http://translate.tandoor.dev/projects/"
|
||||
@ -184,7 +184,9 @@ msgstr "默认"
|
||||
msgid ""
|
||||
"To prevent duplicates recipes with the same name as existing ones are "
|
||||
"ignored. Check this box to import everything."
|
||||
msgstr "为防止重复,忽略与现有同名的菜谱。选中此框可导入所有内容(危险操作,请先备份)。"
|
||||
msgstr ""
|
||||
"为防止重复,忽略与现有同名的菜谱。选中此框可导入所有内容(危险操作,请先备"
|
||||
"份)。"
|
||||
|
||||
#: .\cookbook\forms.py:197
|
||||
msgid "Add your comment: "
|
||||
@ -202,7 +204,9 @@ msgstr "Nextcloud 留空并输入 Dropbox API 令牌。"
|
||||
msgid ""
|
||||
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
|
||||
"php/webdav/</code> is added automatically)"
|
||||
msgstr "Dropbox 留空并输入基础 Nextcloud 网址(<code>/remote.php/webdav/</code> 会自动添加)"
|
||||
msgstr ""
|
||||
"Dropbox 留空并输入基础 Nextcloud 网址(<code>/remote.php/webdav/</code> 会自"
|
||||
"动添加)"
|
||||
|
||||
#: .\cookbook\forms.py:266 .\cookbook\views\edit.py:166
|
||||
msgid "Storage"
|
||||
@ -232,7 +236,8 @@ msgstr "你可以在设置中列出默认用户来分享菜谱。"
|
||||
msgid ""
|
||||
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
|
||||
"\">docs here</a>"
|
||||
msgstr "可以使用 Markdown 设置此字段格式。<a href=\"/docs/markdown/\">查看文档</a>"
|
||||
msgstr ""
|
||||
"可以使用 Markdown 设置此字段格式。<a href=\"/docs/markdown/\">查看文档</a>"
|
||||
|
||||
#: .\cookbook\forms.py:363
|
||||
msgid "Maximum number of users for this space reached."
|
||||
@ -260,14 +265,17 @@ msgstr "接受条款及隐私政策"
|
||||
msgid ""
|
||||
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
|
||||
"g. low values mean more typos are ignored)."
|
||||
msgstr "确定使用三元图相似性匹配时搜索的模糊程度(例如,较低的值意味着忽略更多的打字错误)。"
|
||||
msgstr ""
|
||||
"确定使用三元图相似性匹配时搜索的模糊程度(例如,较低的值意味着忽略更多的打字"
|
||||
"错误)。"
|
||||
|
||||
#: .\cookbook\forms.py:445
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full desciption of choices."
|
||||
msgstr "选择搜索类型方法。<a href=\"/docs/search/\">点击此处</a> 查看选项的完整说明。"
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
"选择搜索类型方法。<a href=\"/docs/search/\">点击此处</a> 查看选项的完整说明。"
|
||||
|
||||
#: .\cookbook\forms.py:446
|
||||
msgid ""
|
||||
@ -297,7 +305,9 @@ msgstr "用于搜索开头匹配的字段。(如搜索“sa”会返回“sala
|
||||
msgid ""
|
||||
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
|
||||
"Note: this option will conflict with 'web' and 'raw' methods of search."
|
||||
msgstr "“模糊”搜索字段。(例如搜索“recpie”将会找到“recipe”。)注意:此选项将与“web”和“raw”搜索方法冲突。"
|
||||
msgstr ""
|
||||
"“模糊”搜索字段。(例如搜索“recpie”将会找到“recipe”。)注意:此选项将"
|
||||
"与“web”和“raw”搜索方法冲突。"
|
||||
|
||||
#: .\cookbook\forms.py:456
|
||||
msgid ""
|
||||
@ -322,7 +332,9 @@ msgid "Partial Match"
|
||||
msgstr "部分匹配"
|
||||
|
||||
#: .\cookbook\forms.py:464
|
||||
msgid "Starts Wtih"
|
||||
#, fuzzy
|
||||
#| msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr "起始于"
|
||||
|
||||
#: .\cookbook\forms.py:465
|
||||
@ -337,7 +349,9 @@ msgstr "全文"
|
||||
msgid ""
|
||||
"Users will see all items you add to your shopping list. They must add you "
|
||||
"to see items on their list."
|
||||
msgstr "用户将看到你添加到购物清单中的所有商品。他们必须将你添加到列表才能看到他们清单上的项目。"
|
||||
msgstr ""
|
||||
"用户将看到你添加到购物清单中的所有商品。他们必须将你添加到列表才能看到他们清"
|
||||
"单上的项目。"
|
||||
|
||||
#: .\cookbook\forms.py:497
|
||||
msgid ""
|
||||
@ -467,16 +481,14 @@ msgstr "你没有必要的权限来查看这个页面!"
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr "你不能与此对象交互,因为它不属于你!"
|
||||
|
||||
#: .\cookbook\helper\recipe_search.py:473
|
||||
#: .\cookbook\helper\recipe_search.py:486
|
||||
msgid "One of queryset or hash_key must be provided"
|
||||
msgstr "必须提供 queryset 或 hash_key 之一"
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:54
|
||||
msgid "You must supply a recipe or mealplan"
|
||||
msgstr "你必须提供菜谱或膳食计划"
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:58
|
||||
msgid "You must supply a created_by"
|
||||
#: .\cookbook\helper\shopping_helper.py:148
|
||||
#, fuzzy
|
||||
#| msgid "You must supply a created_by"
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "你必须提供创建者"
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:61
|
||||
@ -484,23 +496,23 @@ msgstr "你必须提供创建者"
|
||||
msgid "Could not parse template code."
|
||||
msgstr "无法解析模板代码。"
|
||||
|
||||
#: .\cookbook\integration\integration.py:200
|
||||
#: .\cookbook\integration\integration.py:213
|
||||
msgid ""
|
||||
"Importer expected a .zip file. Did you choose the correct importer type for "
|
||||
"your data ?"
|
||||
msgstr "需要一个 .zip 文件。你是否为数据选择了正确的导入器类型?"
|
||||
|
||||
#: .\cookbook\integration\integration.py:203
|
||||
#: .\cookbook\integration\integration.py:216
|
||||
msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr "在导入过程中发生了一个意外的错误。请确认你已经上传了一个有效的文件。"
|
||||
|
||||
#: .\cookbook\integration\integration.py:208
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr "以下菜谱被忽略了,因为它们已经存在了:"
|
||||
|
||||
#: .\cookbook\integration\integration.py:212
|
||||
#: .\cookbook\integration\integration.py:225
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr "导入了%s菜谱。"
|
||||
@ -518,7 +530,6 @@ msgid "Source"
|
||||
msgstr "来源"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:18
|
||||
#: .\cookbook\templates\url_import.html:231
|
||||
#: .\cookbook\templates\url_import.html:462
|
||||
msgid "Servings"
|
||||
@ -547,7 +558,9 @@ msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr "在菜谱上重建全文搜索索引"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
#, fuzzy
|
||||
#| msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr "仅 Postgress 数据库使用全文搜索,没有重建索引"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
@ -609,93 +622,74 @@ msgstr "大"
|
||||
msgid "New"
|
||||
msgstr "新"
|
||||
|
||||
#: .\cookbook\models.py:512
|
||||
#: .\cookbook\models.py:513
|
||||
msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr " 是菜谱步骤的一部分,不能删除"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "文本"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
msgid "Time"
|
||||
msgstr "时间"
|
||||
|
||||
#: .\cookbook\models.py:586 .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "文件"
|
||||
|
||||
#: .\cookbook\models.py:586
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "菜谱"
|
||||
|
||||
#: .\cookbook\models.py:1041 .\cookbook\templates\search_info.html:28
|
||||
#: .\cookbook\models.py:1065 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
msgstr "简明"
|
||||
|
||||
#: .\cookbook\models.py:1042 .\cookbook\templates\search_info.html:33
|
||||
#: .\cookbook\models.py:1066 .\cookbook\templates\search_info.html:33
|
||||
msgid "Phrase"
|
||||
msgstr "短语"
|
||||
|
||||
#: .\cookbook\models.py:1043 .\cookbook\templates\search_info.html:38
|
||||
#: .\cookbook\models.py:1067 .\cookbook\templates\search_info.html:38
|
||||
msgid "Web"
|
||||
msgstr "网络"
|
||||
|
||||
#: .\cookbook\models.py:1044 .\cookbook\templates\search_info.html:47
|
||||
#: .\cookbook\models.py:1068 .\cookbook\templates\search_info.html:47
|
||||
msgid "Raw"
|
||||
msgstr "原始"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Food Alias"
|
||||
msgstr "食物别名"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Unit Alias"
|
||||
msgstr "单位别名"
|
||||
|
||||
#: .\cookbook\models.py:1082
|
||||
#: .\cookbook\models.py:1106
|
||||
msgid "Keyword Alias"
|
||||
msgstr "关键词别名"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
#: .\cookbook\serializer.py:180
|
||||
msgid "A user is required"
|
||||
msgstr "需要一个用户"
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
#: .\cookbook\serializer.py:200
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr "未为此空间启用文件上传。"
|
||||
|
||||
#: .\cookbook\serializer.py:206
|
||||
#: .\cookbook\serializer.py:211
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr "你已达到文件上传的限制。"
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
#: .\cookbook\serializer.py:977
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr "要更新现有的购物清单"
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
#: .\cookbook\serializer.py:979
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr "要添加的菜谱中材料识别符列表,不提供则添加所有材料。"
|
||||
|
||||
#: .\cookbook\serializer.py:965
|
||||
#: .\cookbook\serializer.py:980
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr "提供一个菜谱列表识别符或份数为0将删除该购物清单。"
|
||||
|
||||
#: .\cookbook\serializer.py:973
|
||||
#: .\cookbook\serializer.py:988
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr "要添加到购物清单中的食物数量"
|
||||
|
||||
#: .\cookbook\serializer.py:974
|
||||
#: .\cookbook\serializer.py:989
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr "用于购物清单的单位识别符"
|
||||
|
||||
#: .\cookbook\serializer.py:975
|
||||
#: .\cookbook\serializer.py:990
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr "当设置为 true 时,将从活动的购物列表中删除所有食物。"
|
||||
|
||||
@ -789,7 +783,9 @@ msgstr "警告:"
|
||||
msgid ""
|
||||
"You currently do not have any e-mail address set up. You should really add "
|
||||
"an e-mail address so you can receive notifications, reset your password, etc."
|
||||
msgstr "你目前没有设置任何电子邮件地址。你真的应该添加一个电子邮件地址,这样你就可以收到通知,重置你的密码等等。"
|
||||
msgstr ""
|
||||
"你目前没有设置任何电子邮件地址。你真的应该添加一个电子邮件地址,这样你就可以"
|
||||
"收到通知,重置你的密码等等。"
|
||||
|
||||
#: .\cookbook\templates\account\email.html:64
|
||||
msgid "Add E-mail Address"
|
||||
@ -817,8 +813,8 @@ msgid ""
|
||||
" ."
|
||||
msgstr ""
|
||||
"请确认\n"
|
||||
" <a href=\"mailto:%(email)s\">%(email)s</a> 是用户 %(user_display)s "
|
||||
"的电子邮件地址\n"
|
||||
" <a href=\"mailto:%(email)s\">%(email)s</a> 是用户 "
|
||||
"%(user_display)s 的电子邮件地址\n"
|
||||
" ."
|
||||
|
||||
#: .\cookbook\templates\account\email_confirm.html:22
|
||||
@ -940,7 +936,8 @@ msgid ""
|
||||
"password reset</a>."
|
||||
msgstr ""
|
||||
"密码重置链接无效,可能是因为它已经被使用。\n"
|
||||
" 请重新请求 <a href=\"%(passwd_reset_url)s\">重设密码</a>。"
|
||||
" 请重新请求 <a href=\"%(passwd_reset_url)s\">重设密码</"
|
||||
"a>。"
|
||||
|
||||
#: .\cookbook\templates\account\password_reset_from_key.html:33
|
||||
msgid "change password"
|
||||
@ -1053,8 +1050,8 @@ msgstr "批量编辑"
|
||||
msgid "History"
|
||||
msgstr "历史"
|
||||
|
||||
#: .\cookbook\templates\base.html:228 .\cookbook\templates\export.html:14
|
||||
#: .\cookbook\templates\export.html:20
|
||||
#: .\cookbook\templates\base.html:228
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\shopping_list.html:310
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
@ -1143,7 +1140,6 @@ msgstr "路径必须采用以下格式"
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\include\log_cooking.html:30
|
||||
#: .\cookbook\templates\settings.html:70 .\cookbook\templates\settings.html:112
|
||||
#: .\cookbook\templates\settings.html:130
|
||||
#: .\cookbook\templates\settings.html:202
|
||||
@ -1184,7 +1180,7 @@ msgstr "这可能需要几分钟,取决于同步的菜谱数量,请等待。
|
||||
msgid "Recipe Books"
|
||||
msgstr "菜谱书"
|
||||
|
||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||
#: .\cookbook\templates\export.html:8 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr "导出菜谱"
|
||||
|
||||
@ -1306,19 +1302,12 @@ msgstr "导入菜谱"
|
||||
msgid "Import"
|
||||
msgstr "导入"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:9
|
||||
msgid "Log Recipe Cooking"
|
||||
msgstr "菜谱烹饪记录"
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:7
|
||||
#: .\cookbook\views\delete.py:39 .\cookbook\views\edit.py:260
|
||||
#: .\cookbook\views\new.py:53
|
||||
msgid "Recipe"
|
||||
msgstr "菜谱"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:15
|
||||
msgid "All fields are optional and can be left empty."
|
||||
msgstr "所有字段都是可选的,可以留空。"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:21
|
||||
msgid "Rating"
|
||||
msgstr "评分"
|
||||
|
||||
#: .\cookbook\templates\include\log_cooking.html:29
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:18
|
||||
msgid "Close"
|
||||
msgstr "关闭"
|
||||
@ -1345,7 +1334,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <b>密码和令牌</b>字段在数据库中存储为<b>明文</b>。\n"
|
||||
" 这是必要的,因为它们需要发出应用程序接口请求,但这也增加了被窃取的风险。<br/>\n"
|
||||
" 这是必要的,因为它们需要发出应用程序接口请求,但这也增加了被窃取的风"
|
||||
"险。<br/>\n"
|
||||
" 为了限制可能的损害,可以使用访问受限的令牌或帐户。\n"
|
||||
" "
|
||||
|
||||
@ -1400,8 +1390,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Markdown 是轻量标记语言,很方便格式化纯文本。\n"
|
||||
" 本站使用 <a href=\"https://python-markdown.github.io/\" target=\"_blank\""
|
||||
">Python Markdown</a> 库转换你的文本信息成好看的 HTML。\n"
|
||||
" 本站使用 <a href=\"https://python-markdown.github.io/\" target="
|
||||
"\"_blank\">Python Markdown</a> 库转换你的文本信息成好看的 HTML。\n"
|
||||
" 完整的 Markdown 文档可 <a href=\"https://daringfireball.net/projects/"
|
||||
"markdown/syntax\" target=\"_blank\">点击这里</a> 查看。\n"
|
||||
" 下面可以找到一个不完整但很可能够用的文档。\n"
|
||||
@ -1422,7 +1412,9 @@ msgstr "通过在行尾后添加两个空格插入换行符"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line inbetween."
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "或者在中间留一个空行。"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
@ -1445,8 +1437,12 @@ msgid "Lists"
|
||||
msgstr "列表"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
msgstr "列表可以是有序或无序的。重要的是 <b>在列表前留下一个空行!</b>"
|
||||
|
||||
@ -1486,7 +1482,9 @@ msgstr "图片和链接"
|
||||
msgid ""
|
||||
"Links can be formatted with Markdown. This application also allows to paste "
|
||||
"links directly into markdown fields without any formatting."
|
||||
msgstr "链接可以使用 Markdown 格式化。此应用程序还允许粘贴链接到 markdown 字段而无需格式化。"
|
||||
msgstr ""
|
||||
"链接可以使用 Markdown 格式化。此应用程序还允许粘贴链接到 markdown 字段而无需"
|
||||
"格式化。"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:132
|
||||
#: .\cookbook\templates\markdown_info.html:145
|
||||
@ -1504,8 +1502,8 @@ msgid ""
|
||||
"\"noreferrer noopener\" target=\"_blank\">this one.</a>"
|
||||
msgstr ""
|
||||
"Markdown 表格难以手写。推荐使用像 <a href=\"https://www.tablesgenerator.com/"
|
||||
"markdown_tables\" rel=\"noreferrer noopener\" target=\"_blank\">这个</a> "
|
||||
"的表格编辑器。"
|
||||
"markdown_tables\" rel=\"noreferrer noopener\" target=\"_blank\">这个</a> 的表"
|
||||
"格编辑器。"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:155
|
||||
#: .\cookbook\templates\markdown_info.html:157
|
||||
@ -1604,7 +1602,9 @@ msgstr "加入一个现有的空间。"
|
||||
msgid ""
|
||||
"To join an existing space either enter your invite token or click on the "
|
||||
"invite link the space owner send you."
|
||||
msgstr "要加入一个现有的空间,要么输入你的邀请令牌,要么单击空间所有者发送给你的邀请链接。"
|
||||
msgstr ""
|
||||
"要加入一个现有的空间,要么输入你的邀请令牌,要么单击空间所有者发送给你的邀请"
|
||||
"链接。"
|
||||
|
||||
#: .\cookbook\templates\no_space_info.html:48
|
||||
#: .\cookbook\templates\no_space_info.html:56
|
||||
@ -1631,7 +1631,9 @@ msgstr "你目前处于离线状态!"
|
||||
msgid ""
|
||||
"The recipes listed below are available for offline viewing because you have "
|
||||
"recently viewed them. Keep in mind that data might be outdated."
|
||||
msgstr "下面列出的菜谱可以离线查看,因为你最近已经查看过了。请记住,数据可能是过时的。"
|
||||
msgstr ""
|
||||
"下面列出的菜谱可以离线查看,因为你最近已经查看过了。请记住,数据可能是过时"
|
||||
"的。"
|
||||
|
||||
#: .\cookbook\templates\recipe_view.html:26
|
||||
msgid "by"
|
||||
@ -1690,7 +1692,8 @@ msgstr ""
|
||||
"\n"
|
||||
" 创造最佳的搜索体验非常复杂,并且对您的个人配置有很大影响。\n"
|
||||
" 改变任何搜索设置都可能对搜索结果的速度和质量产生重大影响。\n"
|
||||
" 只有在数据库使用 Postgres 时,才可以使用搜索方法、卦和全文搜索配置。\n"
|
||||
" 只有在数据库使用 Postgres 时,才可以使用搜索方法、卦和全文搜索配"
|
||||
"置。\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:19
|
||||
@ -1712,25 +1715,39 @@ msgid ""
|
||||
" "
|
||||
msgstr ""
|
||||
" \n"
|
||||
" 全文搜索尝试规范化提供的单词以匹配常见变体。例如:“forked”、“forking”、“forks”都将归为“fork”。\n"
|
||||
" 下面将介绍几种可用的方法,可以控制搜索多个单词时搜索行为的反应。\n"
|
||||
" 关于这些操作的完整技术细节可以在 <a href=https://www.postgresql.org/docs/current/"
|
||||
"textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES>Postgresql的网站</a> 上查看。\n"
|
||||
" 全文搜索尝试规范化提供的单词以匹配常见变体。例"
|
||||
"如:“forked”、“forking”、“forks”都将归为“fork”。\n"
|
||||
" 下面将介绍几种可用的方法,可以控制搜索多个单词时搜索行为的反"
|
||||
"应。\n"
|
||||
" 关于这些操作的完整技术细节可以在 <a href=https://www.postgresql."
|
||||
"org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-"
|
||||
"QUERIES>Postgresql的网站</a> 上查看。\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:29
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Simple searches ignore punctuation and common words such as "
|
||||
#| "'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
#| " Searching for 'apple or flour' will return any recipe that "
|
||||
#| "includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
#| "selected for a full text search.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
"'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
"'the', 'a', 'and'. And will treat separate words as required.\n"
|
||||
" Searching for 'apple or flour' will return any recipe that "
|
||||
"includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
"selected for a full text search.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
" \n"
|
||||
" 简单搜索会忽略标点符号和常用词,如“the”、“a”、“and”。并将根据需要处理单独的单词。\n"
|
||||
" 搜索“apple or flour”将会在全文搜索中返回任意包含“apple”和“flour”的菜谱。\n"
|
||||
" 简单搜索会忽略标点符号和常用词,如“the”、“a”、“and”。并将根据需要"
|
||||
"处理单独的单词。\n"
|
||||
" 搜索“apple or flour”将会在全文搜索中返回任意包"
|
||||
"含“apple”和“flour”的菜谱。\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:34
|
||||
@ -1751,7 +1768,7 @@ msgid ""
|
||||
"sites supporting special syntax.\n"
|
||||
" Placing quotes around several words will convert those words "
|
||||
"into a phrase.\n"
|
||||
" 'or' is recongized as searching for the word (or phrase) "
|
||||
" 'or' is recognized as searching for the word (or phrase) "
|
||||
"immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
" '-' is recognized as searching for recipes that do not include "
|
||||
"the word (or phrase) that comes immediately after. \n"
|
||||
@ -1781,7 +1798,7 @@ msgid ""
|
||||
"'ppl', 'ple' and will create a score of how closely words match the "
|
||||
"generated trigrams.\n"
|
||||
" One benefit of searching trigams is that a search for 'sandwich' "
|
||||
"will find mispelled words such as 'sandwhich' that would be missed by other "
|
||||
"will find misspelled words such as 'sandwhich' that would be missed by other "
|
||||
"methods.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
@ -1895,7 +1912,9 @@ msgstr "应用程序接口令牌"
|
||||
msgid ""
|
||||
"You can use both basic authentication and token based authentication to "
|
||||
"access the REST API."
|
||||
msgstr "您可以使用基本身份验证和基于令牌的身份验证来访问表现层状态转换应用程序接口(REST API)。"
|
||||
msgstr ""
|
||||
"您可以使用基本身份验证和基于令牌的身份验证来访问表现层状态转换应用程序接口"
|
||||
"(REST API)。"
|
||||
|
||||
#: .\cookbook\templates\settings.html:160
|
||||
msgid ""
|
||||
@ -1917,13 +1936,16 @@ msgstr "根据个人偏好,有许多选项可以配置搜索。"
|
||||
msgid ""
|
||||
"Usually you do <b>not need</b> to configure any of them and can just stick "
|
||||
"with either the default or one of the following presets."
|
||||
msgstr "通常你 <b>不需要</b> 配置它们中的任何一个,只需使用默认设置或以下预设值之一。"
|
||||
msgstr ""
|
||||
"通常你 <b>不需要</b> 配置它们中的任何一个,只需使用默认设置或以下预设值之一。"
|
||||
|
||||
#: .\cookbook\templates\settings.html:175
|
||||
msgid ""
|
||||
"If you do want to configure the search you can read about the different "
|
||||
"options <a href=\"/docs/search/\">here</a>."
|
||||
msgstr "如果你想要配置搜索,可以在 <a href=\"/docs/search/\">这里</a> 阅读不同的选项。"
|
||||
msgstr ""
|
||||
"如果你想要配置搜索,可以在 <a href=\"/docs/search/\">这里</a> 阅读不同的选"
|
||||
"项。"
|
||||
|
||||
#: .\cookbook\templates\settings.html:180
|
||||
msgid "Fuzzy"
|
||||
@ -1934,7 +1956,9 @@ msgid ""
|
||||
"Find what you need even if your search or the recipe contains typos. Might "
|
||||
"return more results than needed to make sure you find what you are looking "
|
||||
"for."
|
||||
msgstr "即使你的搜索或菜谱中有拼写错误,也要找到你需要的东西。可能会返回比需要更多的结果,以确保你找到所需的内容。"
|
||||
msgstr ""
|
||||
"即使你的搜索或菜谱中有拼写错误,也要找到你需要的东西。可能会返回比需要更多的"
|
||||
"结果,以确保你找到所需的内容。"
|
||||
|
||||
#: .\cookbook\templates\settings.html:182
|
||||
msgid "This is the default behavior"
|
||||
@ -1953,7 +1977,8 @@ msgstr "精确"
|
||||
msgid ""
|
||||
"Allows fine control over search results but might not return results if too "
|
||||
"many spelling mistakes are made."
|
||||
msgstr "允许对搜索结果进行精细控制,但如果出现太多拼写错误,则可能不会返回结果。"
|
||||
msgstr ""
|
||||
"允许对搜索结果进行精细控制,但如果出现太多拼写错误,则可能不会返回结果。"
|
||||
|
||||
#: .\cookbook\templates\settings.html:190
|
||||
msgid "Perfect for large Databases"
|
||||
@ -2042,7 +2067,9 @@ msgid "Finished"
|
||||
msgstr "完成"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:267
|
||||
msgid "You are offline, shopping list might not syncronize."
|
||||
#, fuzzy
|
||||
#| msgid "You are offline, shopping list might not syncronize."
|
||||
msgid "You are offline, shopping list might not synchronize."
|
||||
msgstr "你已离线,购物清单可能无法同步。"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:318
|
||||
@ -2203,10 +2230,10 @@ msgid ""
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Django Recipes 是一个开源应用程序。\n"
|
||||
" 你可以在 <a href=\"https://github.com/vabene1111/recipes\">GitHub</a> "
|
||||
"中找到。\n"
|
||||
" 更新日志在 <a href=\"https://github.com/vabene1111/recipes/releases\""
|
||||
">这里</a>。\n"
|
||||
" 你可以在 <a href=\"https://github.com/vabene1111/recipes\">GitHub</"
|
||||
"a> 中找到。\n"
|
||||
" 更新日志在 <a href=\"https://github.com/vabene1111/recipes/releases"
|
||||
"\">这里</a>。\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\system.html:48
|
||||
@ -2233,8 +2260,8 @@ msgid ""
|
||||
" "
|
||||
msgstr ""
|
||||
"<b>不推荐</b> 使用 gunicorn/python 提供媒体文件。\n"
|
||||
" 请按照 <a href=\"https://github.com/vabene1111/recipes/releases/tag/"
|
||||
"0.8.1\">这里</a> 描述的步骤操作更新安装。\n"
|
||||
" 请按照 <a href=\"https://github.com/vabene1111/recipes/releases/"
|
||||
"tag/0.8.1\">这里</a> 描述的步骤操作更新安装。\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\system.html:57 .\cookbook\templates\system.html:73
|
||||
@ -2311,6 +2338,14 @@ msgstr "链接"
|
||||
msgid "App"
|
||||
msgstr "应用程序"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:44
|
||||
msgid "Text"
|
||||
msgstr "文本"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:46
|
||||
msgid "File"
|
||||
msgstr "文件"
|
||||
|
||||
#: .\cookbook\templates\url_import.html:64
|
||||
msgid "Enter website URL"
|
||||
msgstr "输入网站链接"
|
||||
@ -2473,202 +2508,205 @@ msgstr "GitHub 问题"
|
||||
msgid "Recipe Markup Specification"
|
||||
msgstr "菜谱标记规范"
|
||||
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:170
|
||||
#: .\cookbook\views\api.py:88 .\cookbook\views\api.py:174
|
||||
msgid "Parameter updated_at incorrectly formatted"
|
||||
msgstr "参数 updated_at 格式不正确"
|
||||
|
||||
#: .\cookbook\views\api.py:190 .\cookbook\views\api.py:291
|
||||
#: .\cookbook\views\api.py:194 .\cookbook\views\api.py:295
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {pk} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:194
|
||||
#: .\cookbook\views\api.py:198
|
||||
msgid "Cannot merge with the same object!"
|
||||
msgstr "无法与同一对象合并!"
|
||||
|
||||
#: .\cookbook\views\api.py:201
|
||||
#: .\cookbook\views\api.py:205
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {target} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:206
|
||||
#: .\cookbook\views\api.py:210
|
||||
msgid "Cannot merge with child object!"
|
||||
msgstr "无法与子对象合并!"
|
||||
|
||||
#: .\cookbook\views\api.py:239
|
||||
#: .\cookbook\views\api.py:243
|
||||
#, python-brace-format
|
||||
msgid "{source.name} was merged successfully with {target.name}"
|
||||
msgstr "{source.name} 已成功与 {target.name} 合并"
|
||||
|
||||
#: .\cookbook\views\api.py:244
|
||||
#: .\cookbook\views\api.py:248
|
||||
#, python-brace-format
|
||||
msgid "An error occurred attempting to merge {source.name} with {target.name}"
|
||||
msgstr "视图合并 {source.name} 和 {target.name} 时出错"
|
||||
|
||||
#: .\cookbook\views\api.py:300
|
||||
#: .\cookbook\views\api.py:304
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to the root."
|
||||
msgstr "{child.name} 已成功移动到根目录。"
|
||||
|
||||
#: .\cookbook\views\api.py:303 .\cookbook\views\api.py:321
|
||||
#: .\cookbook\views\api.py:307 .\cookbook\views\api.py:325
|
||||
msgid "An error occurred attempting to move "
|
||||
msgstr "尝试移动时出错 "
|
||||
|
||||
#: .\cookbook\views\api.py:306
|
||||
#: .\cookbook\views\api.py:310
|
||||
msgid "Cannot move an object to itself!"
|
||||
msgstr "无法将对象移动到自身!"
|
||||
|
||||
#: .\cookbook\views\api.py:312
|
||||
#: .\cookbook\views\api.py:316
|
||||
#, python-brace-format
|
||||
msgid "No {self.basename} with id {parent} exists"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:318
|
||||
#: .\cookbook\views\api.py:322
|
||||
#, python-brace-format
|
||||
msgid "{child.name} was moved successfully to parent {parent.name}"
|
||||
msgstr "{child.name} 成功移动到父节点 {parent.name}"
|
||||
|
||||
#: .\cookbook\views\api.py:470
|
||||
#: .\cookbook\views\api.py:474
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr "{obj.name} 已从购物清单中删除。"
|
||||
|
||||
#: .\cookbook\views\api.py:475 .\cookbook\views\api.py:726
|
||||
#: .\cookbook\views\api.py:479 .\cookbook\views\api.py:729
|
||||
#: .\cookbook\views\api.py:742
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr "{obj.name} 已添加到购物清单中。"
|
||||
|
||||
#: .\cookbook\views\api.py:587
|
||||
#: .\cookbook\views\api.py:591
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:588
|
||||
#: .\cookbook\views\api.py:592
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:631
|
||||
#: .\cookbook\views\api.py:635
|
||||
msgid ""
|
||||
"Query string matched (fuzzy) against recipe name. In the future also "
|
||||
"fulltext search."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:632
|
||||
#: .\cookbook\views\api.py:636
|
||||
msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:633
|
||||
#: .\cookbook\views\api.py:637
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:634
|
||||
#: .\cookbook\views\api.py:638
|
||||
msgid "ID of unit a recipe should have."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:635
|
||||
#: .\cookbook\views\api.py:639
|
||||
msgid "Rating a recipe should have. [0 - 5]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:636
|
||||
#: .\cookbook\views\api.py:640
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:637
|
||||
#: .\cookbook\views\api.py:641
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided keywords."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:638
|
||||
#: .\cookbook\views\api.py:642
|
||||
msgid ""
|
||||
"If recipe should have all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided foods."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:639
|
||||
#: .\cookbook\views\api.py:643
|
||||
msgid ""
|
||||
"If recipe should be in all (AND=false) or any (OR=<b>true</b>) of the "
|
||||
"provided books."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:640
|
||||
#: .\cookbook\views\api.py:644
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:641
|
||||
#: .\cookbook\views\api.py:645
|
||||
msgid "Returns the results in randomized order. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:642
|
||||
#: .\cookbook\views\api.py:646
|
||||
msgid "Returns new results first in search results. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:768
|
||||
#: .\cookbook\views\api.py:784
|
||||
msgid ""
|
||||
"Returns the shopping list entry with a primary key of id. Multiple values "
|
||||
"allowed."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:771
|
||||
#: .\cookbook\views\api.py:787
|
||||
msgid ""
|
||||
"Filter shopping list entries on checked. [true, false, both, <b>recent</"
|
||||
"b>]<br> - recent includes unchecked items and recently completed items."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:773
|
||||
#: .\cookbook\views\api.py:789
|
||||
msgid "Returns the shopping list entries sorted by supermarket category order."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:922 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\api.py:949 .\cookbook\views\data.py:42
|
||||
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
|
||||
msgid "This feature is not yet available in the hosted version of tandoor!"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:944
|
||||
#: .\cookbook\views\api.py:971
|
||||
msgid "Sync successful!"
|
||||
msgstr "同步成功!"
|
||||
|
||||
#: .\cookbook\views\api.py:949
|
||||
#: .\cookbook\views\api.py:976
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "与存储同步时出错"
|
||||
|
||||
#: .\cookbook\views\api.py:1028
|
||||
#: .\cookbook\views\api.py:1055
|
||||
msgid "Nothing to do."
|
||||
msgstr "无事可做。"
|
||||
|
||||
#: .\cookbook\views\api.py:1043
|
||||
#: .\cookbook\views\api.py:1070
|
||||
msgid "The requested site provided malformed data and cannot be read."
|
||||
msgstr "请求的站点提供了格式错误的数据,无法读取。"
|
||||
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#: .\cookbook\views\api.py:1077
|
||||
msgid "The requested page could not be found."
|
||||
msgstr "找不到请求的页面。"
|
||||
|
||||
#: .\cookbook\views\api.py:1068
|
||||
#: .\cookbook\views\api.py:1095
|
||||
msgid ""
|
||||
"The requested site does not provide any recognized data format to import the "
|
||||
"recipe from."
|
||||
msgstr "请求的站点未提供任何可识别的数据格式,无法从中导入菜谱。"
|
||||
|
||||
#: .\cookbook\views\api.py:1082
|
||||
#: .\cookbook\views\api.py:1109
|
||||
msgid "Connection Refused."
|
||||
msgstr "连接被拒绝。"
|
||||
|
||||
#: .\cookbook\views\api.py:1091
|
||||
msgid "No useable data could be found."
|
||||
#: .\cookbook\views\api.py:1118
|
||||
#, fuzzy
|
||||
#| msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "找不到可用的数据。"
|
||||
|
||||
#: .\cookbook\views\api.py:1107
|
||||
#: .\cookbook\views\api.py:1134
|
||||
msgid "I couldn't find anything to do."
|
||||
msgstr "无所事事。"
|
||||
|
||||
#: .\cookbook\views\data.py:34 .\cookbook\views\data.py:129
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:80
|
||||
#: .\cookbook\views\edit.py:49 .\cookbook\views\import_export.py:81
|
||||
#: .\cookbook\views\new.py:33
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr "你已经达到了空间的菜谱的最大数量。"
|
||||
|
||||
#: .\cookbook\views\data.py:38 .\cookbook\views\data.py:133
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:84
|
||||
#: .\cookbook\views\edit.py:53 .\cookbook\views\import_export.py:85
|
||||
#: .\cookbook\views\new.py:37
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr "你的空间中的用户数超过了允许的数量。"
|
||||
@ -2726,20 +2764,16 @@ msgstr "更改已保存!"
|
||||
msgid "Error saving changes!"
|
||||
msgstr "保存更改时出错!"
|
||||
|
||||
#: .\cookbook\views\import_export.py:106
|
||||
#: .\cookbook\views\import_export.py:107 .\cookbook\views\import_export.py:143
|
||||
msgid "Importing is not implemented for this provider"
|
||||
msgstr "此提供程序未实现导入"
|
||||
|
||||
#: .\cookbook\views\import_export.py:127
|
||||
#: .\cookbook\views\import_export.py:130
|
||||
msgid ""
|
||||
"The PDF Exporter is not enabled on this instance as it is still in an "
|
||||
"experimental state."
|
||||
msgstr "此实例上未启用 PDF 导出器,因为它仍处于实验状态。"
|
||||
|
||||
#: .\cookbook\views\import_export.py:132
|
||||
msgid "Exporting is not implemented for this provider"
|
||||
msgstr "此提供程序未实现导出"
|
||||
|
||||
#: .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr "导入日志"
|
||||
@ -2856,49 +2890,69 @@ msgstr "要使用此搜索方法,至少选择一个全文搜索字段!"
|
||||
msgid "Fuzzy search is not compatible with this search method!"
|
||||
msgstr "模糊搜索与此搜索方法不兼容!"
|
||||
|
||||
#: .\cookbook\views\views.py:470
|
||||
#: .\cookbook\views\views.py:473
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first user! If you have "
|
||||
"forgotten your superuser credentials please consult the django documentation "
|
||||
"on how to reset passwords."
|
||||
msgstr "设置页面只能用于创建第一个用户!如果您忘记了超级用户凭据,请参阅 Django 文档,了解如何重置密码。"
|
||||
msgstr ""
|
||||
"设置页面只能用于创建第一个用户!如果您忘记了超级用户凭据,请参阅 Django 文"
|
||||
"档,了解如何重置密码。"
|
||||
|
||||
#: .\cookbook\views\views.py:477
|
||||
#: .\cookbook\views\views.py:480
|
||||
msgid "Passwords dont match!"
|
||||
msgstr "密码不匹配!"
|
||||
|
||||
#: .\cookbook\views\views.py:493
|
||||
#: .\cookbook\views\views.py:496
|
||||
msgid "User has been created, please login!"
|
||||
msgstr "用户已创建,请登录!"
|
||||
|
||||
#: .\cookbook\views\views.py:509
|
||||
#: .\cookbook\views\views.py:512
|
||||
msgid "Malformed Invite Link supplied!"
|
||||
msgstr "提供了格式错误的邀请链接!"
|
||||
|
||||
#: .\cookbook\views\views.py:516
|
||||
#: .\cookbook\views\views.py:519
|
||||
msgid "You are already member of a space and therefore cannot join this one."
|
||||
msgstr "你已是空间的成员,因此未能加入。"
|
||||
|
||||
#: .\cookbook\views\views.py:527
|
||||
#: .\cookbook\views\views.py:530
|
||||
msgid "Successfully joined space."
|
||||
msgstr "成功加入空间。"
|
||||
|
||||
#: .\cookbook\views\views.py:533
|
||||
#: .\cookbook\views\views.py:536
|
||||
msgid "Invite Link not valid or already used!"
|
||||
msgstr "邀请链接无效或已使用!"
|
||||
|
||||
#: .\cookbook\views\views.py:614
|
||||
#: .\cookbook\views\views.py:617
|
||||
msgid ""
|
||||
"Reporting share links is not enabled for this instance. Please notify the "
|
||||
"page administrator to report problems."
|
||||
msgstr "未为此实例启用报告共享链接。请通知页面管理员报告问题。"
|
||||
|
||||
#: .\cookbook\views\views.py:620
|
||||
#: .\cookbook\views\views.py:623
|
||||
msgid ""
|
||||
"Recipe sharing link has been disabled! For additional information please "
|
||||
"contact the page administrator."
|
||||
msgstr "菜谱共享链接已被禁用!有关更多信息,请与页面管理员联系。"
|
||||
|
||||
#~ msgid "You must supply a recipe or mealplan"
|
||||
#~ msgstr "你必须提供菜谱或膳食计划"
|
||||
|
||||
#~ msgid "Time"
|
||||
#~ msgstr "时间"
|
||||
|
||||
#~ msgid "Log Recipe Cooking"
|
||||
#~ msgstr "菜谱烹饪记录"
|
||||
|
||||
#~ msgid "All fields are optional and can be left empty."
|
||||
#~ msgstr "所有字段都是可选的,可以留空。"
|
||||
|
||||
#~ msgid "Rating"
|
||||
#~ msgstr "评分"
|
||||
|
||||
#~ msgid "Exporting is not implemented for this provider"
|
||||
#~ msgstr "此提供程序未实现导出"
|
||||
|
||||
#~ msgid "New Unit"
|
||||
#~ msgstr "新单位"
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
from django.contrib.postgres.aggregates import StringAgg
|
||||
from django.contrib.postgres.search import (
|
||||
SearchQuery, SearchRank, SearchVector,
|
||||
)
|
||||
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.utils import translation
|
||||
|
@ -140,5 +140,10 @@ class Migration(migrations.Migration):
|
||||
old_name='ignore_shopping',
|
||||
new_name='food_onhand',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='space',
|
||||
name='show_facet_count',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.RunPython(copy_values_to_sle),
|
||||
]
|
||||
|
@ -10,9 +10,10 @@ class Migration(migrations.Migration):
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='space',
|
||||
name='show_facet_count',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
# migrations.AddField(
|
||||
# model_name='space',
|
||||
# name='show_facet_count',
|
||||
# field=models.BooleanField(default=False),
|
||||
# ),
|
||||
# removed due to quick fix in 0159 migration to maintain correct order
|
||||
]
|
||||
|
20
cookbook/migrations/0168_add_unit_searchfields.py
Normal file
20
cookbook/migrations/0168_add_unit_searchfields.py
Normal file
@ -0,0 +1,20 @@
|
||||
from django.db import migrations
|
||||
|
||||
from cookbook.models import SearchFields
|
||||
|
||||
|
||||
def create_searchfields(apps, schema_editor):
|
||||
SearchFields.objects.create(name='Units', field='steps__ingredients__unit__name')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0167_userpreference_left_handed'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
create_searchfields
|
||||
),
|
||||
]
|
35
cookbook/migrations/0169_exportlog.py
Normal file
35
cookbook/migrations/0169_exportlog.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Generated by Django 3.2.11 on 2022-02-03 15:03
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
import cookbook.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0168_add_unit_searchfields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ExportLog',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('type', models.CharField(max_length=32)),
|
||||
('running', models.BooleanField(default=True)),
|
||||
('msg', models.TextField(default='')),
|
||||
('total_recipes', models.IntegerField(default=0)),
|
||||
('exported_recipes', models.IntegerField(default=0)),
|
||||
('cache_duration', models.IntegerField(default=0)),
|
||||
('possibly_not_expired', models.BooleanField(default=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
]
|
66
cookbook/migrations/0170_auto_20220207_1848.py
Normal file
66
cookbook/migrations/0170_auto_20220207_1848.py
Normal file
@ -0,0 +1,66 @@
|
||||
# Generated by Django 3.2.11 on 2022-02-07 17:48
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
import cookbook.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0169_exportlog'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='child_inherit_fields',
|
||||
field=models.ManyToManyField(blank=True, related_name='child_inherit', to='cookbook.FoodInheritField'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute',
|
||||
field=models.ManyToManyField(blank=True, related_name='_cookbook_food_substitute_+', to='cookbook.Food'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute_children',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute_siblings',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ingredient',
|
||||
name='unit',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.unit'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CustomFilter',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('type', models.CharField(choices=[('RECIPE', 'Recipe'), ('FOOD', 'Food'), ('KEYWORD', 'Keyword')], default=('RECIPE', 'Recipe'), max_length=128)),
|
||||
('search', models.TextField()),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('shared', models.ManyToManyField(blank=True, related_name='f_shared_with', to=settings.AUTH_USER_MODEL)),
|
||||
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='recipebook',
|
||||
name='filter',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.customfilter'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='customfilter',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'name'), name='cf_unique_name_per_space'),
|
||||
),
|
||||
]
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.12 on 2022-02-15 00:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0170_auto_20220207_1848'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='searchpreference',
|
||||
name='trigram_threshold',
|
||||
field=models.DecimalField(decimal_places=2, default=0.2, max_digits=3),
|
||||
),
|
||||
]
|
18
cookbook/migrations/0172_ingredient_original_text.py
Normal file
18
cookbook/migrations/0172_ingredient_original_text.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.12 on 2022-02-25 15:19
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0171_alter_searchpreference_trigram_threshold'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ingredient',
|
||||
name='original_text',
|
||||
field=models.CharField(blank=True, default=None, max_length=512, null=True),
|
||||
),
|
||||
]
|
@ -62,9 +62,10 @@ class TreeManager(MP_NodeManager):
|
||||
# model.Manager get_or_create() is not compatible with MP_Tree
|
||||
def get_or_create(self, *args, **kwargs):
|
||||
kwargs['name'] = kwargs['name'].strip()
|
||||
try:
|
||||
return self.get(name__exact=kwargs['name'], space=kwargs['space']), False
|
||||
except self.model.DoesNotExist:
|
||||
|
||||
if obj := self.filter(name__iexact=kwargs['name'], space=kwargs['space']).first():
|
||||
return obj, False
|
||||
else:
|
||||
with scopes_disabled():
|
||||
try:
|
||||
defaults = kwargs.pop('defaults', None)
|
||||
@ -97,13 +98,6 @@ class TreeModel(MP_Node):
|
||||
else:
|
||||
return f"{self.name}"
|
||||
|
||||
# MP_Tree move uses raw SQL to execute move, override behavior to force a save triggering post_save signal
|
||||
def move(self, *args, **kwargs):
|
||||
super().move(*args, **kwargs)
|
||||
# treebeard bypasses ORM, need to retrieve the object again to avoid writing previous state back to disk
|
||||
obj = self.__class__.objects.get(id=self.id)
|
||||
obj.save()
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
parent = self.get_parent()
|
||||
@ -488,8 +482,10 @@ class Unit(ExportModelOperationsMixin('unit'), models.Model, PermissionModelMixi
|
||||
|
||||
|
||||
class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
||||
# TODO when savings a food as substitute children - assume children and descednants are also substitutes for siblings
|
||||
# exclude fields not implemented yet
|
||||
inheritable_fields = FoodInheritField.objects.exclude(field__in=['diet', 'substitute', 'substitute_children', 'substitute_siblings'])
|
||||
inheritable_fields = FoodInheritField.objects.exclude(field__in=['diet', 'substitute', ])
|
||||
# TODO add inherit children_inherit, parent_inherit, Do Not Inherit
|
||||
|
||||
# WARNING: Food inheritance relies on post_save signals, avoid using UPDATE to update Food objects unless you intend to bypass those signals
|
||||
if SORT_TREE_BY_NAME:
|
||||
@ -501,6 +497,10 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
||||
onhand_users = models.ManyToManyField(User, blank=True)
|
||||
description = models.TextField(default='', blank=True)
|
||||
inherit_fields = models.ManyToManyField(FoodInheritField, blank=True)
|
||||
substitute = models.ManyToManyField("self", blank=True)
|
||||
substitute_siblings = models.BooleanField(default=False)
|
||||
substitute_children = models.BooleanField(default=False)
|
||||
child_inherit_fields = models.ManyToManyField(FoodInheritField, blank=True, related_name='child_inherit')
|
||||
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
objects = ScopedManager(space='space', _manager_class=TreeManager)
|
||||
@ -514,34 +514,63 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
||||
else:
|
||||
return super().delete()
|
||||
|
||||
# MP_Tree move uses raw SQL to execute move, override behavior to force a save triggering post_save signal
|
||||
|
||||
def move(self, *args, **kwargs):
|
||||
super().move(*args, **kwargs)
|
||||
# treebeard bypasses ORM, need to explicity save to trigger post save signals retrieve the object again to avoid writing previous state back to disk
|
||||
obj = self.__class__.objects.get(id=self.id)
|
||||
if parent := obj.get_parent():
|
||||
# child should inherit what the parent defines it should inherit
|
||||
fields = list(parent.child_inherit_fields.all() or parent.inherit_fields.all())
|
||||
if len(fields) > 0:
|
||||
obj.inherit_fields.set(fields)
|
||||
obj.save()
|
||||
|
||||
@staticmethod
|
||||
def reset_inheritance(space=None):
|
||||
def reset_inheritance(space=None, food=None):
|
||||
# resets inherited fields to the space defaults and updates all inherited fields to root object values
|
||||
inherit = space.food_inherit.all()
|
||||
if food:
|
||||
# if child inherit fields is preset children should be set to that, otherwise inherit this foods inherited fields
|
||||
inherit = list((food.child_inherit_fields.all() or food.inherit_fields.all()).values('id', 'field'))
|
||||
tree_filter = Q(path__startswith=food.path, space=space, depth=food.depth+1)
|
||||
else:
|
||||
inherit = list(space.food_inherit.all().values('id', 'field'))
|
||||
tree_filter = Q(space=space)
|
||||
|
||||
# remove all inherited fields from food
|
||||
Through = Food.objects.filter(space=space).first().inherit_fields.through
|
||||
Through = Food.objects.filter(tree_filter).first().inherit_fields.through
|
||||
Through.objects.all().delete()
|
||||
# food is going to inherit attributes
|
||||
if space.food_inherit.all().count() > 0:
|
||||
if len(inherit) > 0:
|
||||
# ManyToMany cannot be updated through an UPDATE operation
|
||||
for i in inherit:
|
||||
Through.objects.bulk_create([
|
||||
Through(food_id=x, foodinheritfield_id=i.id)
|
||||
for x in Food.objects.filter(space=space).values_list('id', flat=True)
|
||||
Through(food_id=x, foodinheritfield_id=i['id'])
|
||||
for x in Food.objects.filter(tree_filter).values_list('id', flat=True)
|
||||
])
|
||||
|
||||
inherit = inherit.values_list('field', flat=True)
|
||||
if 'ignore_shopping' in inherit:
|
||||
# get food at root that have children that need updated
|
||||
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, ignore_shopping=True)).update(ignore_shopping=True)
|
||||
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, space=space, ignore_shopping=False)).update(ignore_shopping=False)
|
||||
inherit = [x['field'] for x in inherit]
|
||||
for field in ['ignore_shopping', 'substitute_children', 'substitute_siblings']:
|
||||
if field in inherit:
|
||||
if food and getattr(food, field, None):
|
||||
food.get_descendants().update(**{f"{field}": True})
|
||||
elif food and not getattr(food, field, True):
|
||||
food.get_descendants().update(**{f"{field}": False})
|
||||
else:
|
||||
# get food at root that have children that need updated
|
||||
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, **{f"{field}": True}, space=space)).update(**{f"{field}": True})
|
||||
Food.include_descendants(queryset=Food.objects.filter(depth=1, numchild__gt=0, **{f"{field}": False}, space=space)).update(**{f"{field}": False})
|
||||
|
||||
if 'supermarket_category' in inherit:
|
||||
# when supermarket_category is null or blank assuming it is not set and not intended to be blank for all descedants
|
||||
# find top node that has category set
|
||||
category_roots = Food.exclude_descendants(queryset=Food.objects.filter(supermarket_category__isnull=False, numchild__gt=0, space=space))
|
||||
for root in category_roots:
|
||||
root.get_descendants().update(supermarket_category=root.supermarket_category)
|
||||
if food and food.supermarket_category:
|
||||
food.get_descendants().update(supermarket_category=food.supermarket_category)
|
||||
elif food is None:
|
||||
# find top node that has category set
|
||||
category_roots = Food.exclude_descendants(queryset=Food.objects.filter(supermarket_category__isnull=False, numchild__gt=0, space=space))
|
||||
for root in category_roots:
|
||||
root.get_descendants().update(supermarket_category=root.supermarket_category)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
@ -554,14 +583,15 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
||||
|
||||
|
||||
class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, PermissionModelMixin):
|
||||
# a pre-delete signal on Food checks if the Ingredient is part of a Step, if it is raises a ProtectedError instead of cascading the delete
|
||||
# delete method on Food and Unit checks if they are part of a Recipe, if it is raises a ProtectedError instead of cascading the delete
|
||||
food = models.ForeignKey(Food, on_delete=models.CASCADE, null=True, blank=True)
|
||||
unit = models.ForeignKey(Unit, on_delete=models.PROTECT, null=True, blank=True)
|
||||
unit = models.ForeignKey(Unit, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
amount = models.DecimalField(default=0, decimal_places=16, max_digits=32)
|
||||
note = models.CharField(max_length=256, null=True, blank=True)
|
||||
is_header = models.BooleanField(default=False)
|
||||
no_amount = models.BooleanField(default=False)
|
||||
order = models.IntegerField(default=0)
|
||||
original_text = models.CharField(max_length=512, null=True, blank=True, default=None)
|
||||
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
objects = ScopedManager(space='space')
|
||||
@ -609,7 +639,7 @@ class NutritionInformation(models.Model, PermissionModelMixin):
|
||||
)
|
||||
proteins = models.DecimalField(default=0, decimal_places=16, max_digits=32)
|
||||
calories = models.DecimalField(default=0, decimal_places=16, max_digits=32)
|
||||
source = models.CharField( max_length=512, default="", null=True, blank=True)
|
||||
source = models.CharField(max_length=512, default="", null=True, blank=True)
|
||||
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
objects = ScopedManager(space='space')
|
||||
@ -725,6 +755,7 @@ class RecipeBook(ExportModelOperationsMixin('book'), models.Model, PermissionMod
|
||||
icon = models.CharField(max_length=16, blank=True, null=True)
|
||||
shared = models.ManyToManyField(User, blank=True, related_name='shared_with')
|
||||
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
filter = models.ForeignKey('cookbook.CustomFilter', null=True, blank=True, on_delete=models.SET_NULL)
|
||||
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
objects = ScopedManager(space='space')
|
||||
@ -852,11 +883,12 @@ class ShoppingListEntry(ExportModelOperationsMixin('shopping_list_entry'), model
|
||||
def __str__(self):
|
||||
return f'Shopping list entry {self.id}'
|
||||
|
||||
# TODO deprecate
|
||||
def get_shared(self):
|
||||
return self.shoppinglist_set.first().shared.all()
|
||||
try:
|
||||
return self.shoppinglist_set.first().shared.all()
|
||||
except AttributeError:
|
||||
return self.created_by.userpreference.shopping_share.all()
|
||||
|
||||
# TODO deprecate
|
||||
def get_owner(self):
|
||||
try:
|
||||
return self.created_by or self.shoppinglist_set.first().created_by
|
||||
@ -881,6 +913,12 @@ class ShoppingList(ExportModelOperationsMixin('shopping_list'), models.Model, Pe
|
||||
def __str__(self):
|
||||
return f'Shopping list {self.id}'
|
||||
|
||||
def get_shared(self):
|
||||
try:
|
||||
return self.shared.all() or self.created_by.userpreference.shopping_share.all()
|
||||
except AttributeError:
|
||||
return []
|
||||
|
||||
|
||||
class ShareLink(ExportModelOperationsMixin('share_link'), models.Model, PermissionModelMixin):
|
||||
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
|
||||
@ -996,6 +1034,26 @@ class ImportLog(models.Model, PermissionModelMixin):
|
||||
return f"{self.created_at}:{self.type}"
|
||||
|
||||
|
||||
class ExportLog(models.Model, PermissionModelMixin):
|
||||
type = models.CharField(max_length=32)
|
||||
running = models.BooleanField(default=True)
|
||||
msg = models.TextField(default="")
|
||||
|
||||
total_recipes = models.IntegerField(default=0)
|
||||
exported_recipes = models.IntegerField(default=0)
|
||||
cache_duration = models.IntegerField(default=0)
|
||||
possibly_not_expired = models.BooleanField(default=True)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
|
||||
objects = ScopedManager(space='space')
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.created_at}:{self.type}"
|
||||
|
||||
|
||||
class BookmarkletImport(ExportModelOperationsMixin('bookmarklet_import'), models.Model, PermissionModelMixin):
|
||||
html = models.TextField()
|
||||
url = models.CharField(max_length=256, null=True, blank=True)
|
||||
@ -1051,7 +1109,7 @@ class SearchPreference(models.Model, PermissionModelMixin):
|
||||
istartswith = models.ManyToManyField(SearchFields, related_name="istartswith_fields", blank=True)
|
||||
trigram = models.ManyToManyField(SearchFields, related_name="trigram_fields", blank=True, default=nameSearchField)
|
||||
fulltext = models.ManyToManyField(SearchFields, related_name="fulltext_fields", blank=True)
|
||||
trigram_threshold = models.DecimalField(default=0.1, decimal_places=2, max_digits=3)
|
||||
trigram_threshold = models.DecimalField(default=0.2, decimal_places=2, max_digits=3)
|
||||
|
||||
|
||||
class UserFile(ExportModelOperationsMixin('user_files'), models.Model, PermissionModelMixin):
|
||||
@ -1093,3 +1151,34 @@ class Automation(ExportModelOperationsMixin('automations'), models.Model, Permis
|
||||
|
||||
objects = ScopedManager(space='space')
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class CustomFilter(models.Model, PermissionModelMixin):
|
||||
RECIPE = 'RECIPE'
|
||||
FOOD = 'FOOD'
|
||||
KEYWORD = 'KEYWORD'
|
||||
|
||||
MODELS = (
|
||||
(RECIPE, _('Recipe')),
|
||||
(FOOD, _('Food')),
|
||||
(KEYWORD, _('Keyword')),
|
||||
)
|
||||
|
||||
name = models.CharField(max_length=128, null=False, blank=False)
|
||||
type = models.CharField(max_length=128, choices=(MODELS), default=MODELS[0])
|
||||
# could use JSONField, but requires installing extension on SQLite, don't need to search the objects, so seems unecessary
|
||||
search = models.TextField(blank=False, null=False)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
shared = models.ManyToManyField(User, blank=True, related_name='f_shared_with')
|
||||
|
||||
objects = ScopedManager(space='space')
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['space', 'name'], name='cf_unique_name_per_space')
|
||||
]
|
||||
|
@ -9,6 +9,8 @@ from cookbook.models import Recipe, RecipeImport, SyncLog
|
||||
from cookbook.provider.provider import Provider
|
||||
from requests.auth import HTTPBasicAuth
|
||||
|
||||
from recipes.settings import DEBUG
|
||||
|
||||
|
||||
class Nextcloud(Provider):
|
||||
|
||||
@ -28,15 +30,18 @@ class Nextcloud(Provider):
|
||||
def import_all(monitor):
|
||||
client = Nextcloud.get_client(monitor.storage)
|
||||
|
||||
if DEBUG:
|
||||
print(f'TANDOOR_PROVIDER_DEBUG checking path {monitor.path} with client {client}')
|
||||
|
||||
files = client.list(monitor.path)
|
||||
|
||||
try:
|
||||
files.pop(0) # remove first element because its the folder itself
|
||||
except IndexError:
|
||||
pass # folder is empty, no recipes will be imported
|
||||
if DEBUG:
|
||||
print(f'TANDOOR_PROVIDER_DEBUG file list {files}')
|
||||
|
||||
import_count = 0
|
||||
for file in files:
|
||||
if DEBUG:
|
||||
print(f'TANDOOR_PROVIDER_DEBUG importing file {file}')
|
||||
path = monitor.path + '/' + file
|
||||
if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists():
|
||||
name = os.path.splitext(file)[0]
|
||||
|
@ -1,26 +1,24 @@
|
||||
import random
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from gettext import gettext as _
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Avg, QuerySet, Sum
|
||||
from django.db.models import Avg, Q, QuerySet, Sum
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from drf_writable_nested import UniqueFieldsMixin, WritableNestedModelSerializer
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import NotFound, ValidationError
|
||||
from rest_framework.fields import empty
|
||||
|
||||
from cookbook.helper.HelperFunctions import str2bool
|
||||
from cookbook.helper.shopping_helper import list_from_recipe
|
||||
from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Food,
|
||||
FoodInheritField, ImportLog, Ingredient, Keyword, MealPlan, MealType,
|
||||
NutritionInformation, Recipe, RecipeBook, RecipeBookEntry,
|
||||
RecipeImport, ShareLink, ShoppingList, ShoppingListEntry,
|
||||
ShoppingListRecipe, Step, Storage, Supermarket, SupermarketCategory,
|
||||
SupermarketCategoryRelation, Sync, SyncLog, Unit, UserFile,
|
||||
UserPreference, ViewLog)
|
||||
from cookbook.helper.shopping_helper import RecipeShoppingEditor
|
||||
from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, CustomFilter,
|
||||
ExportLog, Food, FoodInheritField, ImportLog, Ingredient, Keyword,
|
||||
MealPlan, MealType, NutritionInformation, Recipe, RecipeBook,
|
||||
RecipeBookEntry, RecipeImport, ShareLink, ShoppingList,
|
||||
ShoppingListEntry, ShoppingListRecipe, Step, Storage, Supermarket,
|
||||
SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, Unit,
|
||||
UserFile, UserPreference, ViewLog)
|
||||
from cookbook.templatetags.custom_tags import markdown
|
||||
from recipes.settings import MEDIA_URL
|
||||
|
||||
@ -33,7 +31,7 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
|
||||
images = None
|
||||
|
||||
image = serializers.SerializerMethodField('get_image')
|
||||
numrecipe = serializers.ReadOnlyField(source='count_recipes_test')
|
||||
numrecipe = serializers.ReadOnlyField(source='recipe_count')
|
||||
|
||||
def get_fields(self, *args, **kwargs):
|
||||
fields = super().get_fields(*args, **kwargs)
|
||||
@ -58,9 +56,6 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
|
||||
if obj.recipe_image:
|
||||
return MEDIA_URL + obj.recipe_image
|
||||
|
||||
def count_recipes(self, obj):
|
||||
return Recipe.objects.filter(**{self.recipe_filter: obj}, space=obj.space).count()
|
||||
|
||||
|
||||
class CustomDecimalField(serializers.Field):
|
||||
"""
|
||||
@ -94,7 +89,10 @@ class CustomOnHandField(serializers.Field):
|
||||
if request := self.context.get('request', None):
|
||||
shared_users = getattr(request, '_shared_users', None)
|
||||
if shared_users is None:
|
||||
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [self.context['request'].user.id]
|
||||
try:
|
||||
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [self.context['request'].user.id]
|
||||
except AttributeError: # Anonymous users (using share links) don't have shared users
|
||||
shared_users = []
|
||||
return obj.onhand_users.filter(id__in=shared_users).exists()
|
||||
|
||||
def to_internal_value(self, data):
|
||||
@ -161,7 +159,7 @@ class FoodInheritFieldSerializer(WritableNestedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = FoodInheritField
|
||||
fields = ('id', 'name', 'field', )
|
||||
fields = ('id', 'name', 'field',)
|
||||
read_only_fields = ['id']
|
||||
|
||||
|
||||
@ -169,6 +167,11 @@ class UserPreferenceSerializer(WritableNestedModelSerializer):
|
||||
food_inherit_default = FoodInheritFieldSerializer(source='space.food_inherit', many=True, allow_null=True, required=False, read_only=True)
|
||||
plan_share = UserNameSerializer(many=True, allow_null=True, required=False, read_only=True)
|
||||
shopping_share = UserNameSerializer(many=True, allow_null=True, required=False)
|
||||
food_children_exist = serializers.SerializerMethodField('get_food_children_exist')
|
||||
|
||||
def get_food_children_exist(self, obj):
|
||||
space = getattr(self.context.get('request', None), 'space', None)
|
||||
return Food.objects.filter(depth__gt=0, space=space).exists()
|
||||
|
||||
def create(self, validated_data):
|
||||
if not validated_data.get('user', None):
|
||||
@ -180,10 +183,10 @@ class UserPreferenceSerializer(WritableNestedModelSerializer):
|
||||
class Meta:
|
||||
model = UserPreference
|
||||
fields = (
|
||||
'user', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_kj', 'search_style', 'show_recent', 'plan_share',
|
||||
'user', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_fractions', 'use_kj', 'search_style', 'show_recent', 'plan_share',
|
||||
'ingredient_decimals', 'comments', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'food_inherit_default', 'default_delay',
|
||||
'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days', 'csv_delim', 'csv_prefix',
|
||||
'filter_to_supermarket', 'shopping_add_onhand', 'left_handed'
|
||||
'filter_to_supermarket', 'shopping_add_onhand', 'left_handed', 'food_children_exist'
|
||||
)
|
||||
|
||||
|
||||
@ -297,9 +300,9 @@ class KeywordSerializer(UniqueFieldsMixin, ExtendedRecipeMixin):
|
||||
def create(self, validated_data):
|
||||
# since multi select tags dont have id's
|
||||
# duplicate names might be routed to create
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
validated_data['space'] = self.context['request'].space
|
||||
obj, created = Keyword.objects.get_or_create(**validated_data)
|
||||
name = validated_data.pop('name').strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
obj, created = Keyword.objects.get_or_create(name=name, space=space, defaults=validated_data)
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
@ -314,9 +317,9 @@ class UnitSerializer(UniqueFieldsMixin, ExtendedRecipeMixin):
|
||||
recipe_filter = 'steps__ingredients__unit'
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
validated_data['space'] = self.context['request'].space
|
||||
obj, created = Unit.objects.get_or_create(**validated_data)
|
||||
name = validated_data.pop('name').strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
obj, created = Unit.objects.get_or_create(name=name, space=space, defaults=validated_data)
|
||||
return obj
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
@ -332,9 +335,9 @@ class UnitSerializer(UniqueFieldsMixin, ExtendedRecipeMixin):
|
||||
class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
validated_data['space'] = self.context['request'].space
|
||||
obj, created = SupermarketCategory.objects.get_or_create(**validated_data)
|
||||
name = validated_data.pop('name').strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
obj, created = SupermarketCategory.objects.get_or_create(name__iexact=name, space=space, defaults=validated_data)
|
||||
return obj
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
@ -373,28 +376,56 @@ class RecipeSimpleSerializer(serializers.ModelSerializer):
|
||||
read_only_fields = ['id', 'name', 'url']
|
||||
|
||||
|
||||
class FoodSimpleSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Food
|
||||
fields = ('id', 'name')
|
||||
read_only_fields = ['id', 'name']
|
||||
|
||||
|
||||
class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedRecipeMixin):
|
||||
supermarket_category = SupermarketCategorySerializer(allow_null=True, required=False)
|
||||
recipe = RecipeSimpleSerializer(allow_null=True, required=False)
|
||||
# shopping = serializers.SerializerMethodField('get_shopping_status')
|
||||
shopping = serializers.ReadOnlyField(source='shopping_status')
|
||||
inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False)
|
||||
child_inherit_fields = FoodInheritFieldSerializer(many=True, allow_null=True, required=False)
|
||||
food_onhand = CustomOnHandField(required=False, allow_null=True)
|
||||
substitute_onhand = serializers.SerializerMethodField('get_substitute_onhand')
|
||||
substitute = FoodSimpleSerializer(many=True, allow_null=True, required=False)
|
||||
|
||||
recipe_filter = 'steps__ingredients__food'
|
||||
images = ['recipe__image']
|
||||
|
||||
def get_substitute_onhand(self, obj):
|
||||
shared_users = None
|
||||
if request := self.context.get('request', None):
|
||||
shared_users = getattr(request, '_shared_users', None)
|
||||
if shared_users is None:
|
||||
try:
|
||||
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [self.context['request'].user.id]
|
||||
except AttributeError:
|
||||
shared_users = []
|
||||
filter = Q(id__in=obj.substitute.all())
|
||||
if obj.substitute_siblings:
|
||||
filter |= Q(path__startswith=obj.path[:Food.steplen * (obj.depth - 1)], depth=obj.depth)
|
||||
if obj.substitute_children:
|
||||
filter |= Q(path__startswith=obj.path, depth__gt=obj.depth)
|
||||
return Food.objects.filter(filter).filter(onhand_users__id__in=shared_users).exists()
|
||||
|
||||
# def get_shopping_status(self, obj):
|
||||
# return ShoppingListEntry.objects.filter(space=obj.space, food=obj, checked=False).count() > 0
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['name'] = validated_data['name'].strip()
|
||||
validated_data['space'] = self.context['request'].space
|
||||
name = validated_data.pop('name').strip()
|
||||
space = validated_data.pop('space', self.context['request'].space)
|
||||
# supermarket category needs to be handled manually as food.get or create does not create nested serializers unlike a super.create of serializer
|
||||
if 'supermarket_category' in validated_data and validated_data['supermarket_category']:
|
||||
sm_category = validated_data['supermarket_category']
|
||||
sc_name = sm_category.pop('name', None)
|
||||
validated_data['supermarket_category'], sc_created = SupermarketCategory.objects.get_or_create(
|
||||
name=validated_data.pop('supermarket_category')['name'],
|
||||
space=self.context['request'].space)
|
||||
name=sc_name,
|
||||
space=space, defaults=sm_category)
|
||||
onhand = validated_data.pop('food_onhand', None)
|
||||
|
||||
# assuming if on hand for user also onhand for shopping_share users
|
||||
@ -409,7 +440,7 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
||||
else:
|
||||
validated_data['onhand_users'] = list(set(onhand_users) - set(shared_users))
|
||||
|
||||
obj, created = Food.objects.get_or_create(**validated_data)
|
||||
obj, created = Food.objects.get_or_create(name=name, space=space, defaults=validated_data)
|
||||
return obj
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
@ -417,19 +448,26 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
|
||||
validated_data['name'] = name.strip()
|
||||
# assuming if on hand for user also onhand for shopping_share users
|
||||
onhand = validated_data.get('food_onhand', None)
|
||||
reset_inherit = self.initial_data.get('reset_inherit', False)
|
||||
if not onhand is None:
|
||||
shared_users = [user := self.context['request'].user] + list(user.userpreference.shopping_share.all())
|
||||
if onhand:
|
||||
validated_data['onhand_users'] = list(self.instance.onhand_users.all()) + shared_users
|
||||
else:
|
||||
validated_data['onhand_users'] = list(set(self.instance.onhand_users.all()) - set(shared_users))
|
||||
return super(FoodSerializer, self).update(instance, validated_data)
|
||||
|
||||
# update before resetting inheritance
|
||||
saved_instance = super(FoodSerializer, self).update(instance, validated_data)
|
||||
if reset_inherit and (r := self.context.get('request', None)):
|
||||
Food.reset_inheritance(food=saved_instance, space=r.space)
|
||||
return saved_instance
|
||||
|
||||
class Meta:
|
||||
model = Food
|
||||
fields = (
|
||||
'id', 'name', 'description', 'shopping', 'recipe', 'food_onhand', 'supermarket_category',
|
||||
'image', 'parent', 'numchild', 'numrecipe', 'inherit_fields', 'full_name'
|
||||
'image', 'parent', 'numchild', 'numrecipe', 'inherit_fields', 'full_name', 'ignore_shopping',
|
||||
'substitute', 'substitute_siblings', 'substitute_children', 'substitute_onhand', 'child_inherit_fields'
|
||||
)
|
||||
read_only_fields = ('id', 'numchild', 'parent', 'image', 'numrecipe')
|
||||
|
||||
@ -443,11 +481,15 @@ class IngredientSerializer(WritableNestedModelSerializer):
|
||||
validated_data['space'] = self.context['request'].space
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
validated_data.pop('original_text', None)
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
class Meta:
|
||||
model = Ingredient
|
||||
fields = (
|
||||
'id', 'food', 'unit', 'amount', 'note', 'order',
|
||||
'is_header', 'no_amount'
|
||||
'is_header', 'no_amount', 'original_text'
|
||||
)
|
||||
|
||||
|
||||
@ -602,8 +644,22 @@ class CommentSerializer(serializers.ModelSerializer):
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class CustomFilterSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
shared = UserNameSerializer(many=True, required=False)
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['created_by'] = self.context['request'].user
|
||||
return super().create(validated_data)
|
||||
|
||||
class Meta:
|
||||
model = CustomFilter
|
||||
fields = ('id', 'name', 'search', 'shared', 'created_by')
|
||||
read_only_fields = ('created_by',)
|
||||
|
||||
|
||||
class RecipeBookSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
shared = UserNameSerializer(many=True)
|
||||
filter = CustomFilterSerializer(allow_null=True, required=False)
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['created_by'] = self.context['request'].user
|
||||
@ -611,7 +667,7 @@ class RecipeBookSerializer(SpacedModelSerializer, WritableNestedModelSerializer)
|
||||
|
||||
class Meta:
|
||||
model = RecipeBook
|
||||
fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by')
|
||||
fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by', 'filter')
|
||||
read_only_fields = ('created_by',)
|
||||
|
||||
|
||||
@ -628,7 +684,7 @@ class RecipeBookEntrySerializer(serializers.ModelSerializer):
|
||||
def create(self, validated_data):
|
||||
book = validated_data['book']
|
||||
recipe = validated_data['recipe']
|
||||
if not book.get_owner() == self.context['request'].user:
|
||||
if not book.get_owner() == self.context['request'].user and not self.context['request'].user in book.get_shared():
|
||||
raise NotFound(detail=None, code=None)
|
||||
obj, created = RecipeBookEntry.objects.get_or_create(book=book, recipe=recipe)
|
||||
return obj
|
||||
@ -658,7 +714,8 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
validated_data['created_by'] = self.context['request'].user
|
||||
mealplan = super().create(validated_data)
|
||||
if self.context['request'].data.get('addshopping', False):
|
||||
list_from_recipe(mealplan=mealplan, servings=validated_data['servings'], created_by=validated_data['created_by'], space=validated_data['space'])
|
||||
SLR = RecipeShoppingEditor(user=validated_data['created_by'], space=validated_data['space'])
|
||||
SLR.create(mealplan=mealplan, servings=validated_data['servings'])
|
||||
return mealplan
|
||||
|
||||
class Meta:
|
||||
@ -671,7 +728,6 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
read_only_fields = ('created_by',)
|
||||
|
||||
|
||||
# TODO deprecate
|
||||
class ShoppingListRecipeSerializer(serializers.ModelSerializer):
|
||||
name = serializers.SerializerMethodField('get_name') # should this be done at the front end?
|
||||
recipe_name = serializers.ReadOnlyField(source='recipe.name')
|
||||
@ -690,13 +746,10 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
|
||||
) + f' ({value:.2g})'
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
if 'servings' in validated_data:
|
||||
list_from_recipe(
|
||||
list_recipe=instance,
|
||||
servings=validated_data['servings'],
|
||||
created_by=self.context['request'].user,
|
||||
space=self.context['request'].space
|
||||
)
|
||||
# TODO remove once old shopping list
|
||||
if 'servings' in validated_data and self.context.get('view', None).__class__.__name__ != 'ShoppingListViewSet':
|
||||
SLR = RecipeShoppingEditor(user=self.context['request'].user, space=self.context['request'].space)
|
||||
SLR.edit_servings(servings=validated_data['servings'], id=instance.id)
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
class Meta:
|
||||
@ -726,9 +779,9 @@ class ShoppingListEntrySerializer(WritableNestedModelSerializer):
|
||||
def run_validation(self, data):
|
||||
if self.root.instance.__class__.__name__ == 'ShoppingListEntry':
|
||||
if (
|
||||
data.get('checked', False)
|
||||
and self.root.instance
|
||||
and not self.root.instance.checked
|
||||
data.get('checked', False)
|
||||
and self.root.instance
|
||||
and not self.root.instance.checked
|
||||
):
|
||||
# if checked flips from false to true set completed datetime
|
||||
data['completed_at'] = timezone.now()
|
||||
@ -764,7 +817,7 @@ class ShoppingListEntrySerializer(WritableNestedModelSerializer):
|
||||
'id', 'list_recipe', 'food', 'unit', 'ingredient', 'ingredient_note', 'amount', 'order', 'checked', 'recipe_mealplan',
|
||||
'created_by', 'created_at', 'completed_at', 'delay_until'
|
||||
)
|
||||
read_only_fields = ('id', 'created_by', 'created_at',)
|
||||
read_only_fields = ('id', 'created_by', 'created_at',)
|
||||
|
||||
|
||||
# TODO deprecate
|
||||
@ -850,6 +903,19 @@ class ImportLogSerializer(serializers.ModelSerializer):
|
||||
read_only_fields = ('created_by',)
|
||||
|
||||
|
||||
class ExportLogSerializer(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['created_by'] = self.context['request'].user
|
||||
validated_data['space'] = self.context['request'].space
|
||||
return super().create(validated_data)
|
||||
|
||||
class Meta:
|
||||
model = ExportLog
|
||||
fields = ('id', 'type', 'msg', 'running', 'total_recipes', 'exported_recipes', 'cache_duration', 'possibly_not_expired', 'created_by', 'created_at')
|
||||
read_only_fields = ('created_by',)
|
||||
|
||||
|
||||
class AutomationSerializer(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
|
@ -6,8 +6,9 @@ from django.contrib.postgres.search import SearchVector
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from django.utils import translation
|
||||
from django_scopes import scope
|
||||
|
||||
from cookbook.helper.shopping_helper import list_from_recipe
|
||||
from cookbook.helper.shopping_helper import RecipeShoppingEditor
|
||||
from cookbook.managers import DICTIONARY
|
||||
from cookbook.models import (Food, FoodInheritField, Ingredient, MealPlan, Recipe,
|
||||
ShoppingListEntry, Step)
|
||||
@ -17,9 +18,8 @@ if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_ps
|
||||
'django.db.backends.postgresql']:
|
||||
SQLITE = False
|
||||
|
||||
|
||||
# wraps a signal with the ability to set 'skip_signal' to avoid creating recursive signals
|
||||
|
||||
|
||||
def skip_signal(signal_func):
|
||||
@wraps(signal_func)
|
||||
def _decorator(sender, instance, **kwargs):
|
||||
@ -37,6 +37,7 @@ def update_recipe_search_vector(sender, instance=None, created=False, **kwargs):
|
||||
if SQLITE:
|
||||
return
|
||||
language = DICTIONARY.get(translation.get_language(), 'simple')
|
||||
# these indexed fields are space wide, reading user preferences would lead to inconsistent behavior
|
||||
instance.name_search_vector = SearchVector('name__unaccent', weight='A', config=language)
|
||||
instance.desc_search_vector = SearchVector('description__unaccent', weight='C', config=language)
|
||||
try:
|
||||
@ -75,8 +76,9 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
|
||||
# apply changes from parent to instance for each inherited field
|
||||
if instance.parent and inherit.count() > 0:
|
||||
parent = instance.get_parent()
|
||||
if 'ignore_shopping' in inherit:
|
||||
instance.ignore_shopping = parent.ignore_shopping
|
||||
for field in ['ignore_shopping', 'substitute_children', 'substitute_siblings']:
|
||||
if field in inherit:
|
||||
setattr(instance, field, getattr(parent, field, None))
|
||||
# if supermarket_category is not set, do not cascade - if this becomes non-intuitive can change
|
||||
if 'supermarket_category' in inherit and parent.supermarket_category:
|
||||
instance.supermarket_category = parent.supermarket_category
|
||||
@ -86,46 +88,37 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
|
||||
finally:
|
||||
del instance.skip_signal
|
||||
|
||||
# TODO figure out how to generalize this
|
||||
# apply changes to direct children - depend on save signals for those objects to cascade inheritance down
|
||||
_save = []
|
||||
for child in instance.get_children().filter(inherit_fields__field='ignore_shopping'):
|
||||
child.ignore_shopping = instance.ignore_shopping
|
||||
_save.append(child)
|
||||
# don't cascade empty supermarket category
|
||||
if instance.supermarket_category:
|
||||
# apply changes to direct children - depend on save signals for those objects to cascade inheritance down
|
||||
for child in instance.get_children().filter(inherit_fields__field='supermarket_category'):
|
||||
child.supermarket_category = instance.supermarket_category
|
||||
_save.append(child)
|
||||
for child in set(_save):
|
||||
for child in instance.get_children().filter(inherit_fields__in=Food.inheritable_fields):
|
||||
# set inherited field values
|
||||
for field in (inherit_fields := ['ignore_shopping', 'substitute_children', 'substitute_siblings']):
|
||||
if field in instance.inherit_fields.values_list('field', flat=True):
|
||||
setattr(child, field, getattr(instance, field, None))
|
||||
|
||||
# don't cascade empty supermarket category
|
||||
if instance.supermarket_category and 'supermarket_category' in inherit_fields:
|
||||
setattr(child, 'supermarket_category', getattr(instance, 'supermarket_category', None))
|
||||
|
||||
child.save()
|
||||
|
||||
|
||||
@receiver(post_save, sender=MealPlan)
|
||||
def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs):
|
||||
if not instance:
|
||||
return
|
||||
user = instance.get_owner()
|
||||
if not user.userpreference.mealplan_autoadd_shopping:
|
||||
with scope(space=instance.space):
|
||||
slr_exists = instance.shoppinglistrecipe_set.exists()
|
||||
|
||||
if not created and slr_exists:
|
||||
for x in instance.shoppinglistrecipe_set.all():
|
||||
# assuming that permissions checks for the MealPlan have happened upstream
|
||||
if instance.servings != x.servings:
|
||||
SLR = RecipeShoppingEditor(id=x.id, user=user, space=instance.space)
|
||||
SLR.edit_servings(servings=instance.servings)
|
||||
elif not user.userpreference.mealplan_autoadd_shopping or not instance.recipe:
|
||||
return
|
||||
|
||||
if not created and instance.shoppinglistrecipe_set.exists():
|
||||
for x in instance.shoppinglistrecipe_set.all():
|
||||
if instance.servings != x.servings:
|
||||
list_recipe = list_from_recipe(list_recipe=x, servings=instance.servings, space=instance.space)
|
||||
elif created:
|
||||
# if creating a mealplan - perform shopping list activities
|
||||
kwargs = {
|
||||
'mealplan': instance,
|
||||
'space': instance.space,
|
||||
'created_by': user,
|
||||
'servings': instance.servings
|
||||
}
|
||||
list_recipe = list_from_recipe(**kwargs)
|
||||
|
||||
|
||||
# user = self.context['request'].user
|
||||
# if user.userpreference.shopping_add_onhand:
|
||||
# if checked := validated_data.get('checked', None):
|
||||
# instance.food.onhand_users.add(*user.userpreference.shopping_share.all(), user)
|
||||
# elif checked == False:
|
||||
# instance.food.onhand_users.remove(*user.userpreference.shopping_share.all(), user)
|
||||
if created:
|
||||
SLR = RecipeShoppingEditor(user=user, space=instance.space)
|
||||
SLR.create(mealplan=instance, servings=instance.servings)
|
||||
|
7
cookbook/static/css/app.min.css
vendored
7
cookbook/static/css/app.min.css
vendored
@ -1140,3 +1140,10 @@
|
||||
min-width: 28rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media print{
|
||||
#switcher{
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -75,7 +75,7 @@
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item {% if request.resolver_match.url_name in 'view_search' %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url 'view_search' %}"><i
|
||||
class="fas fa-book"></i> {% trans 'Cookbook' %}</a>
|
||||
class="fas fa-book"></i> {% trans 'Recipes' %}</a>
|
||||
</li>
|
||||
<li class="nav-item {% if request.resolver_match.url_name in 'view_plan' %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url 'view_plan' %}"><i
|
||||
|
@ -1,25 +1,33 @@
|
||||
{% extends "base.html" %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% load i18n %}
|
||||
{% load render_bundle from webpack_loader %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
|
||||
|
||||
{% block title %}{% trans 'Export Recipes' %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
{{ form.media }}
|
||||
|
||||
{% block content %}
|
||||
<div id="app">
|
||||
<export-view></export-view>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block script %}
|
||||
{% if debug %}
|
||||
<script src="{% url 'js_reverse' %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static 'django_js_reverse/reverse.js' %}"></script>
|
||||
{% endif %}
|
||||
|
||||
<script type="application/javascript">
|
||||
window.EXPORT_ID = {{pk}};
|
||||
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}';
|
||||
</script>
|
||||
|
||||
{% render_bundle 'export_view' %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<h2>{% trans 'Export' %}</h2>
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
<form action="." method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-success" type="submit"><i class="fas fa-file-export"></i> {% trans 'Export' %}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
32
cookbook/templates/export_response.html
Normal file
32
cookbook/templates/export_response.html
Normal file
@ -0,0 +1,32 @@
|
||||
{% extends "base.html" %}
|
||||
{% load render_bundle from webpack_loader %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
|
||||
{% block title %}{% trans 'Export' %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="app">
|
||||
<export-response-view></export-response-view>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block script %}
|
||||
{% if debug %}
|
||||
<script src="{% url 'js_reverse' %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static 'django_js_reverse/reverse.js' %}"></script>
|
||||
{% endif %}
|
||||
|
||||
<script type="application/javascript">
|
||||
window.EXPORT_ID = {{pk}};
|
||||
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}'
|
||||
</script>
|
||||
|
||||
{% render_bundle 'export_response_view' %}
|
||||
{% endblock %}
|
@ -1,81 +0,0 @@
|
||||
{% load i18n %}
|
||||
{% comment %} TODO: Deprecate {% endcomment %}
|
||||
|
||||
<div class="modal" tabindex="-1" role="dialog" id="id_modal_cook_log">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{% trans 'Log Recipe Cooking' %}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{% trans 'All fields are optional and can be left empty.' %}</p>
|
||||
<form>
|
||||
|
||||
<label for="id_log_servings">{% trans 'Servings' %} </label>
|
||||
<input class="form-control" type="number" id="id_log_servings">
|
||||
<br/>
|
||||
<label for="id_log_rating">{% trans 'Rating' %} - <span id="id_rating_show">0/5</span></label>
|
||||
<input type="range" class="custom-range" min="0" max="5" id="id_log_rating" name="log_rating"
|
||||
value="0">
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">{% trans 'Close' %}</button>
|
||||
<button type="button" class="btn btn-primary" onclick="logCook()">{% trans 'Save' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
function openCookLogModal(id) {
|
||||
let modal = $('#id_modal_cook_log')
|
||||
modal.data('recipe_id', id)
|
||||
modal.modal('show')
|
||||
}
|
||||
|
||||
//TODO there is definitely a nicer way to do this than this ugly shit
|
||||
function logCook() {
|
||||
let modal = $('#id_modal_cook_log')
|
||||
let rating = $('#id_log_rating')
|
||||
let id = modal.data('recipe_id');
|
||||
|
||||
let url = "{% url 'api_log_cooking' recipe_id=12345 %}".replace(/12345/, id);
|
||||
|
||||
let val_servings = $('#id_log_servings').val()
|
||||
if (val_servings !== '' && val_servings !== 0) {
|
||||
url += '?s=' + val_servings
|
||||
}
|
||||
|
||||
let val_rating = rating.val()
|
||||
if (val_rating !== '' && val_rating !== 0) {
|
||||
if (val_servings !== '' && val_servings !== 0) {
|
||||
url += '&'
|
||||
} else {
|
||||
url += '?'
|
||||
}
|
||||
url += 'r=' + val_rating
|
||||
}
|
||||
|
||||
let request = new XMLHttpRequest();
|
||||
request.onreadystatechange = function () {
|
||||
|
||||
};
|
||||
request.open("GET", url, true);
|
||||
request.send();
|
||||
|
||||
modal.modal('hide')
|
||||
}
|
||||
|
||||
$('#id_log_rating').on("input", () => {
|
||||
let rating = $('#id_log_rating')
|
||||
$('#id_rating_show').html(rating.val() + '/5')
|
||||
});
|
||||
|
||||
</script>
|
@ -94,6 +94,5 @@
|
||||
{% trans "Log in to view recipes" %} <br/>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% include 'include/log_cooking.html' %}
|
||||
|
||||
{% endblock %}
|
@ -26,7 +26,7 @@
|
||||
<small class="card-title">{{ c.updated_at }} {% trans 'by' %} {{ c.created_by.username }}</small> <a
|
||||
href="{% url 'edit_comment' c.pk %}" class="d-print-none"><i
|
||||
class="fas fa-pencil-alt"></i></a><br/>
|
||||
{{ c.text }}
|
||||
{{ c.text | urlize |linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
|
@ -217,13 +217,13 @@
|
||||
</div>
|
||||
|
||||
<script type="application/javascript">
|
||||
$(function () {
|
||||
$(function() {
|
||||
$('#id_search-trigram_threshold').get(0).type = 'range';
|
||||
})
|
||||
});
|
||||
|
||||
function applyPreset (preset){
|
||||
$('#id_search-preset').val(preset)
|
||||
$('#search_form_button').click()
|
||||
function applyPreset(preset) {
|
||||
$('#id_search-preset').val(preset);
|
||||
$('#search_form_button').click();
|
||||
}
|
||||
|
||||
function copyToken() {
|
||||
@ -239,29 +239,30 @@
|
||||
}
|
||||
|
||||
// Change hash for page-reload
|
||||
$('.nav-tabs a').on('shown.bs.tab', function (e) {
|
||||
$('.nav-tabs a').on('shown.bs.tab', function(e) {
|
||||
window.location.hash = e.target.hash;
|
||||
})
|
||||
|
||||
{% comment %}
|
||||
// listen for events
|
||||
{% comment %} $(document).ready(function(){
|
||||
$(document).ready(function() {
|
||||
hideShow()
|
||||
// call hideShow when the user clicks on the mealplan_autoadd checkbox
|
||||
$("#id_shopping-mealplan_autoadd_shopping").click(function(event){
|
||||
hideShow()
|
||||
$("#id_shopping-mealplan_autoadd_shopping").click(function(event) {
|
||||
hideShow();
|
||||
});
|
||||
})
|
||||
|
||||
function hideShow(){
|
||||
if(document.getElementById('id_shopping-mealplan_autoadd_shopping').checked == true)
|
||||
{
|
||||
$('#div_id_shopping-mealplan_autoexclude_onhand').show();
|
||||
$('#div_id_shopping-mealplan_autoinclude_related').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
function hideShow() {
|
||||
if(document.getElementById('id_shopping-mealplan_autoadd_shopping').checked == true) {
|
||||
$('#div_id_shopping-mealplan_autoexclude_onhand').show();
|
||||
$('#div_id_shopping-mealplan_autoinclude_related').show();
|
||||
}
|
||||
else {
|
||||
$('#div_id_shopping-mealplan_autoexclude_onhand').hide();
|
||||
$('#div_id_shopping-mealplan_autoinclude_related').hide();
|
||||
} {% endcomment %}
|
||||
}
|
||||
}
|
||||
{% endcomment %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -834,7 +834,7 @@
|
||||
this.$http.get('{% url 'api:recipe-detail' 123456 %}'.replace('123456', recipe.id)).then((response) => {
|
||||
for (let s of response.data.steps) {
|
||||
for (let i of s.ingredients) {
|
||||
if (!i.is_header && i.food !== null && i.food.food_onhand === false) {
|
||||
if (!i.is_header && i.food !== null && !i.food.ignore_food) {
|
||||
this.shopping_list.entries.push({
|
||||
'list_recipe': slr.id,
|
||||
'food': i.food,
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
<script type="application/javascript">
|
||||
window.IMAGE_PLACEHOLDER = "{% static 'assets/recipe_no_image.svg' %}"
|
||||
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}'
|
||||
</script>
|
||||
|
||||
{% render_bundle 'shopping_list_view' %} {% endblock %}
|
||||
|
@ -88,9 +88,8 @@
|
||||
<h4>
|
||||
{% trans 'Members' %}
|
||||
<small class="text-muted"
|
||||
>{{ space_users|length }}/ {% if request.space.max_users > 0 %} {{ request.space.max_users }}{% else
|
||||
%}∞{% endif %}</small
|
||||
>
|
||||
>{{ space_users|length }}/{% if request.space.max_users > 0 %} {{ request.space.max_users }}{% else %}∞{% endif %}
|
||||
</small>
|
||||
<a class="btn btn-success float-right" href="{% url 'new_invite_link' %}"
|
||||
><i class="fas fa-plus-circle"></i> {% trans 'Invite User' %}</a
|
||||
>
|
||||
|
@ -473,9 +473,9 @@
|
||||
|
||||
<div class="card" style="margin-top: 4px">
|
||||
<div class="card-body">
|
||||
<div class="row" v-if="i.original">
|
||||
<div class="row" v-if="i.original_text">
|
||||
<div class="col-md-12" style="margin-bottom: 4px">
|
||||
<span class="text-muted"><i class="fas fa-globe"></i> [[i.original]]</span>
|
||||
<span class="text-muted"><i class="fas fa-globe"></i> [[i.original_text]]</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@ -1024,7 +1024,7 @@
|
||||
amount: String(response.body.amount),
|
||||
ingredient: {id: Math.random() * 1000, text: response.body.food},
|
||||
note: response.body.note,
|
||||
original: v
|
||||
original_text: v
|
||||
}
|
||||
this.recipe_json.recipeIngredient.push(new_ingredient)
|
||||
}).catch((err) => {
|
||||
|
@ -485,6 +485,10 @@ def test_tree_filter(obj_tree_1, obj_2, obj_3, u1_s1):
|
||||
({'has_category': True, 'inherit': False}, 'supermarket_category', False, 'cat_1'),
|
||||
({'ignore_shopping': True, 'inherit': True}, 'ignore_shopping', True, 'false'),
|
||||
({'ignore_shopping': True, 'inherit': False}, 'ignore_shopping', False, 'false'),
|
||||
({'substitute_children': True, 'inherit': True}, 'substitute_children', True, 'false'),
|
||||
({'substitute_children': True, 'inherit': False}, 'substitute_children', False, 'false'),
|
||||
({'substitute_siblings': True, 'inherit': True}, 'substitute_siblings', True, 'false'),
|
||||
({'substitute_siblings': True, 'inherit': False}, 'substitute_siblings', False, 'false'),
|
||||
], indirect=['obj_tree_1']) # indirect=True populates magic variable request.param of obj_tree_1 with the parameter
|
||||
def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
||||
with scope(space=obj_tree_1.space):
|
||||
@ -507,28 +511,42 @@ def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
||||
assert (getattr(obj_tree_1, field) == new_val) == inherit
|
||||
assert (getattr(child, field) == new_val) == inherit
|
||||
|
||||
# TODO add test_inherit with child_inherit
|
||||
|
||||
|
||||
@pytest.mark.parametrize("obj_tree_1", [
|
||||
({'has_category': True, 'inherit': False, 'ignore_shopping': True}),
|
||||
({'has_category': True, 'inherit': False, 'ignore_shopping': True, 'substitute_children': True, 'substitute_siblings': True}),
|
||||
], indirect=['obj_tree_1'])
|
||||
def test_reset_inherit(obj_tree_1, space_1):
|
||||
@pytest.mark.parametrize("global_reset", [True, False])
|
||||
@pytest.mark.parametrize("field", ['ignore_shopping', 'substitute_children', 'substitute_siblings', 'supermarket_category'])
|
||||
def test_reset_inherit_space_fields(obj_tree_1, space_1, global_reset, field):
|
||||
with scope(space=space_1):
|
||||
space_1.food_inherit.add(*Food.inheritable_fields.values_list('id', flat=True)) # set default inherit fields
|
||||
parent = obj_tree_1.get_parent()
|
||||
child = obj_tree_1.get_descendants()[0]
|
||||
obj_tree_1.ignore_shopping = False
|
||||
assert parent.ignore_shopping == child.ignore_shopping
|
||||
assert parent.ignore_shopping != obj_tree_1.ignore_shopping
|
||||
assert parent.supermarket_category != child.supermarket_category
|
||||
assert parent.supermarket_category != obj_tree_1.supermarket_category
|
||||
|
||||
parent.reset_inheritance(space=space_1)
|
||||
if field == 'supermarket_category':
|
||||
assert parent.supermarket_category != child.supermarket_category
|
||||
assert parent.supermarket_category != obj_tree_1.supermarket_category
|
||||
else:
|
||||
setattr(obj_tree_1, field, False)
|
||||
obj_tree_1.save()
|
||||
assert getattr(parent, field) == getattr(child, field)
|
||||
assert getattr(parent, field) != getattr(obj_tree_1, field)
|
||||
|
||||
if global_reset:
|
||||
space_1.food_inherit.add(*Food.inheritable_fields.values_list('id', flat=True)) # set default inherit fields
|
||||
parent.reset_inheritance(space=space_1)
|
||||
else:
|
||||
obj_tree_1.child_inherit_fields.set(Food.inheritable_fields.values_list('id', flat=True))
|
||||
obj_tree_1.save()
|
||||
parent.reset_inheritance(space=space_1, food=obj_tree_1)
|
||||
# djangotree bypasses ORM and need to be retrieved again
|
||||
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||
parent = obj_tree_1.get_parent()
|
||||
child = obj_tree_1.get_descendants()[0]
|
||||
assert parent.ignore_shopping == obj_tree_1.ignore_shopping == child.ignore_shopping
|
||||
assert parent.supermarket_category == obj_tree_1.supermarket_category == child.supermarket_category
|
||||
parent = Food.objects.get(id=parent.id)
|
||||
child = Food.objects.get(id=child.id)
|
||||
|
||||
assert (getattr(parent, field) == getattr(obj_tree_1, field)) == global_reset
|
||||
assert getattr(obj_tree_1, field) == getattr(child, field)
|
||||
|
||||
|
||||
def test_onhand(obj_1, u1_s1, u2_s1):
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from django.urls import reverse
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from cookbook.models import Recipe
|
||||
from cookbook.models import Recipe, ShareLink
|
||||
from cookbook.tests.conftest import get_random_json_recipe, validate_recipe
|
||||
|
||||
LIST_URL = 'api:recipe-list'
|
||||
@ -38,6 +38,21 @@ def test_list_space(recipe_1_s1, u1_s1, u1_s2, space_2):
|
||||
assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)['results']) == 1
|
||||
|
||||
|
||||
def test_share_permission(recipe_1_s1, u1_s1, u1_s2, a_u):
|
||||
assert u1_s1.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk])).status_code == 200
|
||||
assert u1_s2.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk])).status_code == 404
|
||||
|
||||
with scopes_disabled():
|
||||
r = u1_s1.get(reverse('new_share_link', kwargs={'pk': recipe_1_s1.pk}))
|
||||
assert r.status_code == 302
|
||||
r = u1_s2.get(reverse('new_share_link', kwargs={'pk': recipe_1_s1.pk}))
|
||||
assert r.status_code == 404
|
||||
share = ShareLink.objects.filter(recipe=recipe_1_s1).first()
|
||||
assert a_u.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 200
|
||||
assert u1_s1.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 200
|
||||
assert u1_s2.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 404 # TODO fix in https://github.com/TandoorRecipes/recipes/issues/1238
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arg", [
|
||||
['a_u', 403],
|
||||
['g1_s1', 200],
|
||||
|
@ -90,7 +90,10 @@ def test_add(arg, request, obj_1):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
r = c.post(
|
||||
reverse(LIST_URL),
|
||||
{'food': model_to_dict(obj_1.food), 'amount': 1},
|
||||
{'food': {
|
||||
'id': obj_1.food.__dict__['id'],
|
||||
'name': obj_1.food.__dict__['name'],
|
||||
}, 'amount': 1},
|
||||
content_type='application/json'
|
||||
)
|
||||
response = json.loads(r.content)
|
||||
|
@ -103,7 +103,10 @@ def test_add(arg, request, sle):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
r = c.post(
|
||||
reverse(LIST_URL),
|
||||
{'food': model_to_dict(sle[0].food), 'amount': 1},
|
||||
{'food': {
|
||||
'id': sle[0].food.__dict__['id'],
|
||||
'name': sle[0].food.__dict__['name'],
|
||||
}, 'amount': 1},
|
||||
content_type='application/json'
|
||||
)
|
||||
response = json.loads(r.content)
|
||||
@ -156,6 +159,32 @@ def test_sharing(request, shared, count, sle_2, sle, u1_s1):
|
||||
# confirm shared user sees their list and the list that's shared with them
|
||||
assert len(json.loads(r.content)) == count
|
||||
|
||||
# test shared user can mark complete
|
||||
x = shared_client.patch(
|
||||
reverse(DETAIL_URL, args={sle[0].id}),
|
||||
{'checked': True},
|
||||
content_type='application/json'
|
||||
)
|
||||
r = json.loads(shared_client.get(reverse(LIST_URL)).content)
|
||||
assert len(r) == count
|
||||
# count unchecked entries
|
||||
if not x.status_code == 404:
|
||||
count = count-1
|
||||
assert [x['checked'] for x in r].count(False) == count
|
||||
# test shared user can delete
|
||||
x = shared_client.delete(
|
||||
reverse(
|
||||
DETAIL_URL,
|
||||
args={sle[1].id}
|
||||
)
|
||||
)
|
||||
r = json.loads(shared_client.get(reverse(LIST_URL)).content)
|
||||
assert len(r) == count
|
||||
# count unchecked entries
|
||||
if not x.status_code == 404:
|
||||
count = count-1
|
||||
assert [x['checked'] for x in r].count(False) == count
|
||||
|
||||
|
||||
def test_completed(sle, u1_s1):
|
||||
# check 1 entry
|
||||
|
@ -45,19 +45,10 @@ def recipe(request, space_1, u1_s1):
|
||||
params = request.param # request.param is a magic variable
|
||||
except AttributeError:
|
||||
params = {}
|
||||
# step_recipe = params.get('steps__count', 1)
|
||||
# steps__recipe_count = params.get('steps__recipe_count', 0)
|
||||
# steps__food_recipe_count = params.get('steps__food_recipe_count', {})
|
||||
params['created_by'] = params.get('created_by', auth.get_user(u1_s1))
|
||||
params['space'] = space_1
|
||||
return RecipeFactory(**params)
|
||||
|
||||
# return RecipeFactory.create(
|
||||
# steps__recipe_count=steps__recipe_count,
|
||||
# steps__food_recipe_count=steps__food_recipe_count,
|
||||
# created_by=created_by,
|
||||
# space=space_1,
|
||||
# )
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arg", [
|
||||
@ -164,7 +155,7 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
|
||||
assert len(r) == sle_count
|
||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||
|
||||
# test removing 2 items from shopping list
|
||||
# test removing 3 items from shopping list
|
||||
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||
{'list_recipe': list_recipe, 'ingredients': keep_ing},
|
||||
content_type='application/json'
|
||||
|
@ -158,6 +158,31 @@ def dict_compare(d1, d2, details=False):
|
||||
return any([not added, not removed, not modified, not modified_dicts])
|
||||
|
||||
|
||||
def transpose(text, number=2):
|
||||
|
||||
# select random token
|
||||
tokens = text.split()
|
||||
positions = list(i for i, e in enumerate(tokens) if len(e) > 1)
|
||||
|
||||
if positions:
|
||||
|
||||
token_pos = random.choice(positions)
|
||||
|
||||
# select random positions in token
|
||||
positions = random.sample(range(len(tokens[token_pos])), number)
|
||||
|
||||
# swap the positions
|
||||
l = list(tokens[token_pos])
|
||||
for first, second in zip(positions[::2], positions[1::2]):
|
||||
l[first], l[second] = l[second], l[first]
|
||||
|
||||
# replace original tokens with swapped
|
||||
tokens[token_pos] = ''.join(l)
|
||||
|
||||
# return text with the swapped token
|
||||
return ' '.join(tokens)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def recipe_1_s1(space_1, u1_s1):
|
||||
return get_random_recipe(space_1, u1_s1)
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
|
||||
import factory
|
||||
@ -9,7 +10,7 @@ from django_scopes import scopes_disabled
|
||||
from faker import Factory as FakerFactory
|
||||
from pytest_factoryboy import register
|
||||
|
||||
from cookbook.models import Step
|
||||
from cookbook.models import Recipe, Step
|
||||
|
||||
# this code will run immediately prior to creating the model object useful when you want a reverse relationship
|
||||
# log = factory.RelatedFactory(
|
||||
@ -111,6 +112,15 @@ class FoodFactory(factory.django.DjangoModelFactory):
|
||||
)
|
||||
space = factory.SubFactory(SpaceFactory)
|
||||
|
||||
@factory.post_generation
|
||||
def users_onhand(self, create, extracted, **kwargs):
|
||||
if not create:
|
||||
return
|
||||
|
||||
if extracted:
|
||||
for user in extracted:
|
||||
self.onhand_users.add(user)
|
||||
|
||||
class Params:
|
||||
has_category = False
|
||||
has_recipe = False
|
||||
@ -120,6 +130,33 @@ class FoodFactory(factory.django.DjangoModelFactory):
|
||||
django_get_or_create = ('name', 'space',)
|
||||
|
||||
|
||||
@register
|
||||
class RecipeBookFactory(factory.django.DjangoModelFactory):
|
||||
"""RecipeBook factory."""
|
||||
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3, variable_nb_words=False))
|
||||
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
||||
icon = None
|
||||
# shared = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
||||
filter = None
|
||||
space = factory.SubFactory(SpaceFactory)
|
||||
|
||||
class Meta:
|
||||
model = 'cookbook.RecipeBook'
|
||||
django_get_or_create = ('name', 'space',)
|
||||
|
||||
|
||||
@register
|
||||
class RecipeBookEntryFactory(factory.django.DjangoModelFactory):
|
||||
"""RecipeBookEntry factory."""
|
||||
book = factory.SubFactory(RecipeBookFactory, space=factory.SelfAttribute('..recipe.space'))
|
||||
recipe = None
|
||||
|
||||
class Meta:
|
||||
model = 'cookbook.RecipeBookEntry'
|
||||
django_get_or_create = ('book', 'recipe',)
|
||||
|
||||
|
||||
@register
|
||||
class UnitFactory(factory.django.DjangoModelFactory):
|
||||
"""Unit factory."""
|
||||
@ -241,6 +278,15 @@ class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
|
||||
delay_until = None
|
||||
space = factory.SubFactory(SpaceFactory)
|
||||
|
||||
@classmethod
|
||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
||||
created_at = kwargs.pop('created_at', None)
|
||||
obj = super(ShoppingListEntryFactory, cls)._create(target_class, *args, **kwargs)
|
||||
if created_at is not None:
|
||||
obj.created_at = created_at
|
||||
obj.save()
|
||||
return obj
|
||||
|
||||
class Params:
|
||||
has_mealplan = False
|
||||
|
||||
@ -288,8 +334,6 @@ class StepFactory(factory.django.DjangoModelFactory):
|
||||
has_recipe = False
|
||||
self.ingredients.add(IngredientFactory(space=self.space, food__has_recipe=has_recipe))
|
||||
num_header = kwargs.get('header', 0)
|
||||
#######################################################
|
||||
#######################################################
|
||||
if num_header > 0:
|
||||
for i in range(num_header):
|
||||
self.ingredients.add(IngredientFactory(food=None, unit=None, amount=0, is_header=True, space=self.space))
|
||||
@ -315,9 +359,19 @@ class RecipeFactory(factory.django.DjangoModelFactory):
|
||||
waiting_time = factory.LazyAttribute(lambda x: faker.random_int(min=0, max=360))
|
||||
internal = False
|
||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
||||
created_at = factory.LazyAttribute(lambda x: faker.date_this_decade())
|
||||
created_at = factory.LazyAttribute(lambda x: faker.date_between_dates(date_start=date(2000, 1, 1), date_end=date(2020, 12, 31)))
|
||||
space = factory.SubFactory(SpaceFactory)
|
||||
|
||||
@classmethod
|
||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
||||
created_at = kwargs.pop('created_at', None)
|
||||
# updated_at = kwargs.pop('updated_at', None)
|
||||
obj = super(RecipeFactory, cls)._create(target_class, *args, **kwargs)
|
||||
if created_at is not None:
|
||||
obj.created_at = created_at
|
||||
obj.save()
|
||||
return obj
|
||||
|
||||
@factory.post_generation
|
||||
def keywords(self, create, extracted, **kwargs):
|
||||
if not create:
|
||||
@ -368,3 +422,47 @@ class RecipeFactory(factory.django.DjangoModelFactory):
|
||||
|
||||
class Meta:
|
||||
model = 'cookbook.Recipe'
|
||||
|
||||
|
||||
@register
|
||||
class CookLogFactory(factory.django.DjangoModelFactory):
|
||||
"""CookLog factory."""
|
||||
recipe = factory.SubFactory(RecipeFactory, space=factory.SelfAttribute('..space'))
|
||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
||||
created_at = factory.LazyAttribute(lambda x: faker.date_this_decade())
|
||||
rating = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=5))
|
||||
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=32))
|
||||
space = factory.SubFactory(SpaceFactory)
|
||||
|
||||
@classmethod
|
||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
||||
created_at = kwargs.pop('created_at', None)
|
||||
obj = super(CookLogFactory, cls)._create(target_class, *args, **kwargs)
|
||||
if created_at is not None:
|
||||
obj.created_at = created_at
|
||||
obj.save()
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
model = 'cookbook.CookLog'
|
||||
|
||||
|
||||
@register
|
||||
class ViewLogFactory(factory.django.DjangoModelFactory):
|
||||
"""ViewLog factory."""
|
||||
recipe = factory.SubFactory(RecipeFactory, space=factory.SelfAttribute('..space'))
|
||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
||||
created_at = factory.LazyAttribute(lambda x: faker.past_datetime(start_date='-365d'))
|
||||
space = factory.SubFactory(SpaceFactory)
|
||||
|
||||
@classmethod
|
||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
||||
created_at = kwargs.pop('created_at', None)
|
||||
obj = super(ViewLogFactory, cls)._create(target_class, *args, **kwargs)
|
||||
if created_at is not None:
|
||||
obj.created_at = created_at
|
||||
obj.save()
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
model = 'cookbook.ViewLog'
|
||||
|
File diff suppressed because it is too large
Load Diff
25
cookbook/tests/other/test_export.py
Normal file
25
cookbook/tests/other/test_export.py
Normal file
@ -0,0 +1,25 @@
|
||||
import pytest
|
||||
from django.contrib import auth
|
||||
from django.urls import reverse
|
||||
|
||||
from cookbook.forms import ImportExportBase
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.models import ExportLog
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def obj_1(space_1, u1_s1):
|
||||
return ExportLog.objects.create(type=ImportExportBase.DEFAULT, running=False, created_by=auth.get_user(u1_s1), space=space_1, exported_recipes=10, total_recipes=10)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arg", [
|
||||
['a_u', 302],
|
||||
['g1_s1', 302],
|
||||
['u1_s1', 200],
|
||||
['a1_s1', 200],
|
||||
['u1_s2', 404],
|
||||
['a1_s2', 404],
|
||||
])
|
||||
def test_export_file_cache(arg, request, obj_1):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
assert c.get(reverse('view_export_file', args=[obj_1.pk])).status_code == arg[1]
|
133
cookbook/tests/other/test_makenow_filter.py
Normal file
133
cookbook/tests/other/test_makenow_filter.py
Normal file
@ -0,0 +1,133 @@
|
||||
|
||||
import pytest
|
||||
from django.contrib import auth
|
||||
from django.urls import reverse
|
||||
from django_scopes import scope
|
||||
|
||||
from cookbook.helper.recipe_search import RecipeSearch
|
||||
from cookbook.models import Food, Recipe
|
||||
from cookbook.tests.factories import FoodFactory, RecipeFactory
|
||||
|
||||
# TODO returns recipes with all ingredients via child substitute
|
||||
# TODO returns recipes with all ingredients via sibling substitute
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def recipes(space_1):
|
||||
return RecipeFactory.create_batch(10, space=space_1)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def makenow_recipe(request, space_1):
|
||||
onhand_user = auth.get_user(request.getfixturevalue(request.param.get('onhand_users', 'u1_s1')))
|
||||
|
||||
recipe = RecipeFactory.create(space=space_1)
|
||||
for food in Food.objects.filter(ingredient__step__recipe=recipe.id):
|
||||
food.onhand_users.add(onhand_user)
|
||||
return recipe
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user1(u1_s1, u2_s1, space_1):
|
||||
user1 = auth.get_user(u1_s1)
|
||||
user2 = auth.get_user(u2_s1)
|
||||
user1.userpreference.shopping_share.add(user2)
|
||||
user2.userpreference.shopping_share.add(user1)
|
||||
return user1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("makenow_recipe", [
|
||||
({'onhand_users': 'u1_s1'}), ({'onhand_users': 'u2_s1'}),
|
||||
], indirect=['makenow_recipe'])
|
||||
def test_makenow_onhand(recipes, makenow_recipe, user1, space_1):
|
||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||
search = RecipeSearch(request, makenow='true')
|
||||
with scope(space=space_1):
|
||||
search = search.get_queryset(Recipe.objects.all())
|
||||
assert search.count() == 1
|
||||
assert search.first().id == makenow_recipe.id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("makenow_recipe", [
|
||||
({'onhand_users': 'u1_s1'}), ({'onhand_users': 'u2_s1'}),
|
||||
], indirect=['makenow_recipe'])
|
||||
def test_makenow_ignoreshopping(recipes, makenow_recipe, user1, space_1):
|
||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||
search = RecipeSearch(request, makenow='true')
|
||||
with scope(space=space_1):
|
||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
||||
food.onhand_users.clear()
|
||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||
food.ignore_shopping = True
|
||||
food.save()
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, ignore_shopping=True).count() == 1
|
||||
search = search.get_queryset(Recipe.objects.all())
|
||||
assert search.count() == 1
|
||||
assert search.first().id == makenow_recipe.id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("makenow_recipe", [
|
||||
({'onhand_users': 'u1_s1'}), ({'onhand_users': 'u2_s1'}),
|
||||
], indirect=['makenow_recipe'])
|
||||
def test_makenow_substitute(recipes, makenow_recipe, user1, space_1):
|
||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||
search = RecipeSearch(request, makenow='true')
|
||||
with scope(space=space_1):
|
||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
||||
onhand_user = food.onhand_users.first()
|
||||
food.onhand_users.clear()
|
||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||
food.substitute.add(FoodFactory.create(space=space_1, onhand_users=[onhand_user]))
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, substitute__isnull=False).count() == 1
|
||||
|
||||
search = search.get_queryset(Recipe.objects.all())
|
||||
assert search.count() == 1
|
||||
assert search.first().id == makenow_recipe.id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("makenow_recipe", [
|
||||
({'onhand_users': 'u1_s1'}), ({'onhand_users': 'u2_s1'}),
|
||||
], indirect=['makenow_recipe'])
|
||||
def test_makenow_child_substitute(recipes, makenow_recipe, user1, space_1):
|
||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||
search = RecipeSearch(request, makenow='true')
|
||||
with scope(space=space_1):
|
||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
||||
onhand_user = food.onhand_users.first()
|
||||
food.onhand_users.clear()
|
||||
food.substitute_children = True
|
||||
food.save()
|
||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||
new_food = FoodFactory.create(space=space_1, onhand_users=[onhand_user])
|
||||
new_food.move(food, 'first-child')
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, numchild__gt=0).count() == 1
|
||||
search = search.get_queryset(Recipe.objects.all())
|
||||
assert search.count() == 1
|
||||
assert search.first().id == makenow_recipe.id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("makenow_recipe", [
|
||||
({'onhand_users': 'u1_s1'}), ({'onhand_users': 'u2_s1'}),
|
||||
], indirect=['makenow_recipe'])
|
||||
def test_makenow_sibling_substitute(recipes, makenow_recipe, user1, space_1):
|
||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||
search = RecipeSearch(request, makenow='true')
|
||||
with scope(space=space_1):
|
||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
||||
onhand_user = food.onhand_users.first()
|
||||
food.onhand_users.clear()
|
||||
food.substitute_siblings = True
|
||||
food.save()
|
||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||
new_parent = FoodFactory.create(space=space_1)
|
||||
new_sibling = FoodFactory.create(space=space_1, onhand_users=[onhand_user])
|
||||
new_sibling.move(new_parent, 'first-child')
|
||||
food.move(new_parent, 'first-child')
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, depth=2).count() == 1
|
||||
search = search.get_queryset(Recipe.objects.all())
|
||||
assert search.count() == 1
|
||||
assert search.first().id == makenow_recipe.id
|
353
cookbook/tests/other/test_recipe_full_text_search.py
Normal file
353
cookbook/tests/other/test_recipe_full_text_search.py
Normal file
@ -0,0 +1,353 @@
|
||||
import itertools
|
||||
import json
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
from django.conf import settings
|
||||
from django.contrib import auth
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django_scopes import scope, scopes_disabled
|
||||
|
||||
from cookbook.models import Food, Recipe, SearchFields
|
||||
from cookbook.tests.conftest import transpose
|
||||
from cookbook.tests.factories import (CookLogFactory, FoodFactory, IngredientFactory,
|
||||
KeywordFactory, RecipeBookEntryFactory, RecipeFactory,
|
||||
UnitFactory, ViewLogFactory)
|
||||
|
||||
# TODO test combining any/all of the above
|
||||
# TODO test sort_by
|
||||
# TODO test sort_by new X number of recipes are new within last Y days
|
||||
# TODO test loading custom filter
|
||||
# TODO test loading custom filter with overrided params
|
||||
# TODO makenow with above filters
|
||||
# TODO test search food/keywords including/excluding children
|
||||
LIST_URL = 'api:recipe-list'
|
||||
sqlite = settings.DATABASES['default']['ENGINE'] not in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def accent():
|
||||
return "àbçđêf ğĦìĵķĽmñ öPqŕşŧ úvŵxyž"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def unaccent():
|
||||
return "abcdef ghijklmn opqrst uvwxyz"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user1(request, space_1, u1_s1, unaccent):
|
||||
user = auth.get_user(u1_s1)
|
||||
try:
|
||||
params = {x[0]: x[1] for x in request.param}
|
||||
except AttributeError:
|
||||
params = {}
|
||||
result = 1
|
||||
misspelled_result = 0
|
||||
search_term = unaccent
|
||||
|
||||
if params.get('fuzzy_lookups', False):
|
||||
user.searchpreference.lookup = True
|
||||
misspelled_result = 1
|
||||
if params.get('fuzzy_search', False):
|
||||
user.searchpreference.trigram.set(SearchFields.objects.all())
|
||||
misspelled_result = 1
|
||||
|
||||
if params.get('icontains', False):
|
||||
user.searchpreference.icontains.set(SearchFields.objects.all())
|
||||
search_term = 'ghijklmn'
|
||||
if params.get('istartswith', False):
|
||||
user.searchpreference.istartswith.set(SearchFields.objects.all())
|
||||
search_term = 'abcdef'
|
||||
if params.get('unaccent', False):
|
||||
user.searchpreference.unaccent.set(SearchFields.objects.all())
|
||||
misspelled_result *= 2
|
||||
result *= 2
|
||||
# full text vectors are hard coded to use unaccent - put this after unaccent to override result
|
||||
if params.get('fulltext', False):
|
||||
user.searchpreference.fulltext.set(SearchFields.objects.all())
|
||||
# user.searchpreference.search = 'websearch'
|
||||
search_term = 'ghijklmn uvwxyz'
|
||||
result = 2
|
||||
user.searchpreference.save()
|
||||
misspelled_term = transpose(search_term, number=3)
|
||||
return (u1_s1, result, misspelled_result, search_term, misspelled_term, params)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def recipes(space_1):
|
||||
return RecipeFactory.create_batch(10, space=space_1)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def found_recipe(request, space_1, accent, unaccent, u1_s1, u2_s1):
|
||||
user1 = auth.get_user(u1_s1)
|
||||
user2 = auth.get_user(u2_s1)
|
||||
days_3 = timezone.now() - timedelta(days=3)
|
||||
days_15 = timezone.now() - timedelta(days=15)
|
||||
days_30 = timezone.now() - timedelta(days=30)
|
||||
if request.param.get('createdon', None):
|
||||
recipe1 = RecipeFactory.create(space=space_1, created_at=days_3)
|
||||
recipe2 = RecipeFactory.create(space=space_1, created_at=days_30)
|
||||
recipe3 = RecipeFactory.create(space=space_1, created_at=days_15)
|
||||
|
||||
else:
|
||||
recipe1 = RecipeFactory.create(space=space_1)
|
||||
recipe2 = RecipeFactory.create(space=space_1)
|
||||
recipe3 = RecipeFactory.create(space=space_1)
|
||||
obj1 = None
|
||||
obj2 = None
|
||||
|
||||
if request.param.get('food', None):
|
||||
obj1 = FoodFactory.create(name=unaccent, space=space_1)
|
||||
obj2 = FoodFactory.create(name=accent, space=space_1)
|
||||
recipe1.steps.first().ingredients.add(IngredientFactory.create(food=obj1))
|
||||
recipe2.steps.first().ingredients.add(IngredientFactory.create(food=obj2))
|
||||
recipe3.steps.first().ingredients.add(IngredientFactory.create(food=obj1), IngredientFactory.create(food=obj2))
|
||||
if request.param.get('keyword', None):
|
||||
obj1 = KeywordFactory.create(name=unaccent, space=space_1)
|
||||
obj2 = KeywordFactory.create(name=accent, space=space_1)
|
||||
recipe1.keywords.add(obj1)
|
||||
recipe2.keywords.add(obj2)
|
||||
recipe3.keywords.add(obj1, obj2)
|
||||
recipe1.name = unaccent
|
||||
recipe2.name = accent
|
||||
recipe1.save()
|
||||
recipe2.save()
|
||||
if request.param.get('book', None):
|
||||
obj1 = RecipeBookEntryFactory.create(recipe=recipe1).book
|
||||
obj2 = RecipeBookEntryFactory.create(recipe=recipe2).book
|
||||
RecipeBookEntryFactory.create(recipe=recipe3, book=obj1)
|
||||
RecipeBookEntryFactory.create(recipe=recipe3, book=obj2)
|
||||
if request.param.get('unit', None):
|
||||
obj1 = UnitFactory.create(name=unaccent, space=space_1)
|
||||
obj2 = UnitFactory.create(name=accent, space=space_1)
|
||||
recipe1.steps.first().ingredients.add(IngredientFactory.create(unit=obj1))
|
||||
recipe2.steps.first().ingredients.add(IngredientFactory.create(unit=obj2))
|
||||
recipe3.steps.first().ingredients.add(IngredientFactory.create(unit=obj1), IngredientFactory.create(unit=obj2))
|
||||
if request.param.get('name', None):
|
||||
recipe1.name = unaccent
|
||||
recipe2.name = accent
|
||||
recipe1.save()
|
||||
recipe2.save()
|
||||
if request.param.get('description', None):
|
||||
recipe1.description = unaccent
|
||||
recipe2.description = accent
|
||||
recipe1.save()
|
||||
recipe2.save()
|
||||
if request.param.get('instruction', None):
|
||||
i1 = recipe1.steps.first()
|
||||
i2 = recipe2.steps.first()
|
||||
i1.instruction = unaccent
|
||||
i2.instruction = accent
|
||||
i1.save()
|
||||
i2.save()
|
||||
|
||||
if request.param.get('viewedon', None):
|
||||
ViewLogFactory.create(recipe=recipe1, created_by=user1, created_at=days_3, space=space_1)
|
||||
ViewLogFactory.create(recipe=recipe2, created_by=user1, created_at=days_30, space=space_1)
|
||||
ViewLogFactory.create(recipe=recipe3, created_by=user2, created_at=days_15, space=space_1)
|
||||
if request.param.get('cookedon', None):
|
||||
CookLogFactory.create(recipe=recipe1, created_by=user1, created_at=days_3, space=space_1)
|
||||
CookLogFactory.create(recipe=recipe2, created_by=user1, created_at=days_30, space=space_1)
|
||||
CookLogFactory.create(recipe=recipe3, created_by=user2, created_at=days_15, space=space_1)
|
||||
if request.param.get('timescooked', None):
|
||||
CookLogFactory.create_batch(5, recipe=recipe1, created_by=user1, space=space_1)
|
||||
CookLogFactory.create(recipe=recipe2, created_by=user1, space=space_1)
|
||||
CookLogFactory.create_batch(3, recipe=recipe3, created_by=user2, space=space_1)
|
||||
if request.param.get('rating', None):
|
||||
CookLogFactory.create(recipe=recipe1, created_by=user1, rating=5.0, space=space_1)
|
||||
CookLogFactory.create(recipe=recipe2, created_by=user1, rating=1.0, space=space_1)
|
||||
CookLogFactory.create(recipe=recipe3, created_by=user2, rating=3.0, space=space_1)
|
||||
|
||||
return (recipe1, recipe2, recipe3, obj1, obj2, request.param)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("found_recipe, param_type", [
|
||||
({'food': True}, 'foods'),
|
||||
({'keyword': True}, 'keywords'),
|
||||
({'book': True}, 'books'),
|
||||
], indirect=['found_recipe'])
|
||||
@pytest.mark.parametrize('operator', [('_or', 3, 0), ('_and', 1, 2), ])
|
||||
def test_search_or_and_not(found_recipe, param_type, operator, recipes, u1_s1, space_1):
|
||||
with scope(space=space_1):
|
||||
param1 = f"{param_type}{operator[0]}={found_recipe[3].id}"
|
||||
param2 = f"{param_type}{operator[0]}={found_recipe[4].id}"
|
||||
param1_not = f"{param_type}{operator[0]}_not={found_recipe[3].id}"
|
||||
param2_not = f"{param_type}{operator[0]}_not={found_recipe[4].id}"
|
||||
|
||||
# testing include searches
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param1}').content)
|
||||
assert r['count'] == 2
|
||||
assert found_recipe[0].id in [x['id'] for x in r['results']]
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param2}').content)
|
||||
assert r['count'] == 2
|
||||
assert found_recipe[1].id in [x['id'] for x in r['results']]
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param1}&{param2}').content)
|
||||
assert r['count'] == operator[1]
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
# testing _not searches
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param1_not}').content)
|
||||
assert r['count'] == 11
|
||||
assert found_recipe[0].id not in [x['id'] for x in r['results']]
|
||||
assert found_recipe[2].id not in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param2_not}').content)
|
||||
assert r['count'] == 11
|
||||
assert found_recipe[1].id not in [x['id'] for x in r['results']]
|
||||
assert found_recipe[2].id not in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param1_not}&{param2_not}').content)
|
||||
assert r['count'] == 10 + operator[2]
|
||||
assert found_recipe[2].id not in [x['id'] for x in r['results']]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("found_recipe", [
|
||||
({'unit': True}),
|
||||
], indirect=['found_recipe'])
|
||||
def test_search_units(found_recipe, recipes, u1_s1, space_1):
|
||||
with scope(space=space_1):
|
||||
param1 = f"units={found_recipe[3].id}"
|
||||
param2 = f"units={found_recipe[4].id}"
|
||||
|
||||
# testing include searches
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param1}').content)
|
||||
assert r['count'] == 2
|
||||
assert found_recipe[0].id in [x['id'] for x in r['results']]
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param2}').content)
|
||||
assert r['count'] == 2
|
||||
assert found_recipe[1].id in [x['id'] for x in r['results']]
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'?{param1}&{param2}').content)
|
||||
assert r['count'] == 3
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sqlite, reason="requires PostgreSQL")
|
||||
@pytest.mark.parametrize("user1", itertools.product(
|
||||
[
|
||||
('fuzzy_search', True), ('fuzzy_search', False),
|
||||
('fuzzy_lookups', True), ('fuzzy_lookups', False)
|
||||
],
|
||||
[('unaccent', True), ('unaccent', False)]
|
||||
), indirect=['user1'])
|
||||
@pytest.mark.parametrize("found_recipe, param_type", [
|
||||
({'unit': True}, 'unit'),
|
||||
({'keyword': True}, 'keyword'),
|
||||
({'food': True}, 'food'),
|
||||
], indirect=['found_recipe'])
|
||||
def test_fuzzy_lookup(found_recipe, recipes, param_type, user1, space_1):
|
||||
with scope(space=space_1):
|
||||
list_url = f'api:{param_type}-list'
|
||||
param1 = f"query={user1[3]}"
|
||||
param2 = f"query={user1[4]}"
|
||||
|
||||
r = json.loads(user1[0].get(reverse(list_url) + f'?{param1}&limit=2').content)
|
||||
assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[3].id, found_recipe[4].id]]) == user1[1]
|
||||
|
||||
r = json.loads(user1[0].get(reverse(list_url) + f'?{param2}&limit=10').content)
|
||||
assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[3].id, found_recipe[4].id]]) == user1[2]
|
||||
|
||||
# commenting this out for general use - it is really slow
|
||||
# it should be run on occasion to ensure everything still works
|
||||
# @pytest.mark.skipif(sqlite and True, reason="requires PostgreSQL")
|
||||
# @pytest.mark.parametrize("user1", itertools.product(
|
||||
# [
|
||||
# ('fuzzy_search', True), ('fuzzy_search', False),
|
||||
# ('fulltext', True), ('fulltext', False),
|
||||
# ('icontains', True), ('icontains', False),
|
||||
# ('istartswith', True), ('istartswith', False),
|
||||
# ],
|
||||
# [('unaccent', True), ('unaccent', False)]
|
||||
# ), indirect=['user1'])
|
||||
# @pytest.mark.parametrize("found_recipe", [
|
||||
# ({'name': True}),
|
||||
# ({'description': True}),
|
||||
# ({'instruction': True}),
|
||||
# ({'keyword': True}),
|
||||
# ({'food': True}),
|
||||
# ], indirect=['found_recipe'])
|
||||
# def test_search_string(found_recipe, recipes, user1, space_1):
|
||||
# with scope(space=space_1):
|
||||
# param1 = f"query={user1[3]}"
|
||||
# param2 = f"query={user1[4]}"
|
||||
|
||||
# r = json.loads(user1[0].get(reverse(LIST_URL) + f'?{param1}').content)
|
||||
# assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[0].id, found_recipe[1].id]]) == user1[1]
|
||||
|
||||
# r = json.loads(user1[0].get(reverse(LIST_URL) + f'?{param2}').content)
|
||||
# assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[0].id, found_recipe[1].id]]) == user1[2]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("found_recipe, param_type, result", [
|
||||
({'viewedon': True}, 'viewedon', (1, 1)),
|
||||
({'cookedon': True}, 'cookedon', (1, 1)),
|
||||
({'createdon': True}, 'createdon', (2, 12)), # created dates are not filtered by user
|
||||
({'createdon': True}, 'updatedon', (2, 12)), # updated dates are not filtered by user
|
||||
], indirect=['found_recipe'])
|
||||
def test_search_date(found_recipe, recipes, param_type, result, u1_s1, u2_s1, space_1):
|
||||
# force updated_at to equal created_at datetime
|
||||
with scope(space=space_1):
|
||||
for recipe in Recipe.objects.all():
|
||||
Recipe.objects.filter(id=recipe.id).update(updated_at=recipe.created_at)
|
||||
|
||||
date = (timezone.now() - timedelta(days=15)).strftime("%Y-%m-%d")
|
||||
param1 = f"?{param_type}={date}"
|
||||
param2 = f"?{param_type}=-{date}"
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'{param1}').content)
|
||||
assert r['count'] == result[0]
|
||||
assert found_recipe[0].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + f'{param2}').content)
|
||||
assert r['count'] == result[1]
|
||||
assert found_recipe[1].id in [x['id'] for x in r['results']]
|
||||
|
||||
# test today's date returns for lte and gte searches
|
||||
r = json.loads(u2_s1.get(reverse(LIST_URL) + f'{param1}').content)
|
||||
assert r['count'] == result[0]
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u2_s1.get(reverse(LIST_URL) + f'{param2}').content)
|
||||
assert r['count'] == result[1]
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("found_recipe, param_type", [
|
||||
({'rating': True}, 'rating'),
|
||||
({'timescooked': True}, 'timescooked'),
|
||||
], indirect=['found_recipe'])
|
||||
def test_search_count(found_recipe, recipes, param_type, u1_s1, u2_s1, space_1):
|
||||
param1 = f'?{param_type}=3'
|
||||
param2 = f'?{param_type}=-3'
|
||||
param3 = f'?{param_type}=0'
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + param1).content)
|
||||
assert r['count'] == 1
|
||||
assert found_recipe[0].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + param2).content)
|
||||
assert r['count'] == 1
|
||||
assert found_recipe[1].id in [x['id'] for x in r['results']]
|
||||
|
||||
# test search for not rated/cooked
|
||||
r = json.loads(u1_s1.get(reverse(LIST_URL) + param3).content)
|
||||
assert r['count'] == 11
|
||||
assert (found_recipe[0].id or found_recipe[1].id) not in [x['id'] for x in r['results']]
|
||||
|
||||
# test matched returns for lte and gte searches
|
||||
r = json.loads(u2_s1.get(reverse(LIST_URL) + param1).content)
|
||||
assert r['count'] == 1
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||
|
||||
r = json.loads(u2_s1.get(reverse(LIST_URL) + param2).content)
|
||||
assert r['count'] == 1
|
||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
@ -81,7 +81,7 @@ def test_history(arg, request, ext_recipe_1_s1):
|
||||
['a_u', 302],
|
||||
['g1_s1', 302],
|
||||
['u1_s1', 302],
|
||||
['a1_s1', 200],
|
||||
['a1_s1', 302],
|
||||
])
|
||||
def test_system(arg, request, ext_recipe_1_s1):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
|
@ -9,18 +9,21 @@ from cookbook.helper import dal
|
||||
from recipes.settings import DEBUG
|
||||
from recipes.version import VERSION_NUMBER
|
||||
|
||||
from .models import (Automation, Comment, Food, InviteLink, Keyword, MealPlan, Recipe, RecipeBook,
|
||||
RecipeBookEntry, RecipeImport, ShoppingList, Step, Storage, Supermarket,
|
||||
SupermarketCategory, Sync, SyncLog, Unit, UserFile, get_model_name)
|
||||
from .models import (Automation, Comment, CustomFilter, Food, InviteLink, Keyword, MealPlan, Recipe,
|
||||
RecipeBook, RecipeBookEntry, RecipeImport, ShoppingList, Step, Storage,
|
||||
Supermarket, SupermarketCategory, Sync, SyncLog, Unit, UserFile,
|
||||
get_model_name)
|
||||
from .views import api, data, delete, edit, import_export, lists, new, telegram, views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'automation', api.AutomationViewSet)
|
||||
router.register(r'bookmarklet-import', api.BookmarkletImportViewSet)
|
||||
router.register(r'cook-log', api.CookLogViewSet)
|
||||
router.register(r'custom-filter', api.CustomFilterViewSet)
|
||||
router.register(r'food', api.FoodViewSet)
|
||||
router.register(r'food-inherit-field', api.FoodInheritFieldViewSet)
|
||||
router.register(r'import-log', api.ImportLogViewSet)
|
||||
router.register(r'export-log', api.ExportLogViewSet)
|
||||
router.register(r'ingredient', api.IngredientViewSet)
|
||||
router.register(r'keyword', api.KeywordViewSet)
|
||||
router.register(r'meal-plan', api.MealPlanViewSet)
|
||||
@ -74,6 +77,8 @@ urlpatterns = [
|
||||
path('import/', import_export.import_recipe, name='view_import'),
|
||||
path('import-response/<int:pk>/', import_export.import_response, name='view_import_response'),
|
||||
path('export/', import_export.export_recipe, name='view_export'),
|
||||
path('export-response/<int:pk>/', import_export.export_response, name='view_export_response'),
|
||||
path('export-file/<int:pk>/', import_export.export_file, name='view_export_file'),
|
||||
|
||||
path('view/recipe/<int:pk>', views.recipe_view, name='view_recipe'),
|
||||
path('view/recipe/<int:pk>/<slug:share>', views.recipe_view, name='view_recipe'),
|
||||
@ -178,7 +183,7 @@ for m in generic_models:
|
||||
)
|
||||
)
|
||||
|
||||
vue_models = [Food, Keyword, Unit, Supermarket, SupermarketCategory, Automation, UserFile, Step]
|
||||
vue_models = [Food, Keyword, Unit, Supermarket, SupermarketCategory, Automation, UserFile, Step, CustomFilter]
|
||||
for m in vue_models:
|
||||
py_name = get_model_name(m)
|
||||
url_name = py_name.replace('_', '-')
|
||||
|
@ -15,7 +15,7 @@ from django.core.files import File
|
||||
from django.db.models import (Case, Count, Exists, F, IntegerField, OuterRef, ProtectedError, Q,
|
||||
Subquery, Value, When)
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.db.models.functions import Coalesce, Lower
|
||||
from django.http import FileResponse, HttpResponse, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
@ -41,19 +41,20 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, Cus
|
||||
from cookbook.helper.recipe_html_import import get_recipe_from_source
|
||||
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch, old_search
|
||||
from cookbook.helper.recipe_url_import import get_from_scraper
|
||||
from cookbook.helper.shopping_helper import list_from_recipe, shopping_helper
|
||||
from cookbook.models import (Automation, BookmarkletImport, CookLog, Food, FoodInheritField,
|
||||
ImportLog, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook,
|
||||
RecipeBookEntry, ShareLink, ShoppingList, ShoppingListEntry,
|
||||
ShoppingListRecipe, Step, Storage, Supermarket, SupermarketCategory,
|
||||
SupermarketCategoryRelation, Sync, SyncLog, Unit, UserFile,
|
||||
UserPreference, ViewLog)
|
||||
from cookbook.helper.shopping_helper import RecipeShoppingEditor, shopping_helper
|
||||
from cookbook.models import (Automation, BookmarkletImport, CookLog, CustomFilter, ExportLog, Food,
|
||||
FoodInheritField, ImportLog, Ingredient, Keyword, MealPlan, MealType,
|
||||
Recipe, RecipeBook, RecipeBookEntry, ShareLink, ShoppingList,
|
||||
ShoppingListEntry, ShoppingListRecipe, Step, Storage, Supermarket,
|
||||
SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, Unit,
|
||||
UserFile, UserPreference, ViewLog)
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
from cookbook.schemas import FilterSchema, QueryParam, QueryParamAutoSchema, TreeSchema
|
||||
from cookbook.serializer import (AutomationSerializer, BookmarkletImportSerializer,
|
||||
CookLogSerializer, FoodInheritFieldSerializer, FoodSerializer,
|
||||
CookLogSerializer, CustomFilterSerializer, ExportLogSerializer,
|
||||
FoodInheritFieldSerializer, FoodSerializer,
|
||||
FoodShoppingUpdateSerializer, ImportLogSerializer,
|
||||
IngredientSerializer, KeywordSerializer, MealPlanSerializer,
|
||||
MealTypeSerializer, RecipeBookEntrySerializer,
|
||||
@ -107,6 +108,7 @@ class ExtendedRecipeMixin():
|
||||
'''
|
||||
ExtendedRecipe annotates a queryset with recipe_image and recipe_count values
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def annotate_recipe(self, queryset=None, request=None, serializer=None, tree=False):
|
||||
extended = str2bool(request.query_params.get('extended', None))
|
||||
@ -118,7 +120,7 @@ class ExtendedRecipeMixin():
|
||||
# add a recipe count annotation to the query
|
||||
# explanation on construction https://stackoverflow.com/a/43771738/15762829
|
||||
recipe_count = Recipe.objects.filter(**{recipe_filter: OuterRef('id')}, space=space).values(recipe_filter).annotate(count=Count('pk')).values('count')
|
||||
queryset = queryset.annotate(recipe_count_test=Coalesce(Subquery(recipe_count), 0))
|
||||
queryset = queryset.annotate(recipe_count=Coalesce(Subquery(recipe_count), 0))
|
||||
|
||||
# add a recipe image annotation to the query
|
||||
image_subquery = Recipe.objects.filter(**{recipe_filter: OuterRef('id')}, space=space).exclude(image__isnull=True).exclude(image__exact='').order_by("?").values('image')[:1]
|
||||
@ -138,26 +140,28 @@ class FuzzyFilterMixin(ViewSetMixin, ExtendedRecipeMixin):
|
||||
schema = FilterSchema()
|
||||
|
||||
def get_queryset(self):
|
||||
self.queryset = self.queryset.filter(space=self.request.space).order_by('name')
|
||||
self.queryset = self.queryset.filter(space=self.request.space).order_by(Lower('name').asc())
|
||||
query = self.request.query_params.get('query', None)
|
||||
fuzzy = self.request.user.searchpreference.lookup
|
||||
fuzzy = self.request.user.searchpreference.lookup or any([self.model.__name__.lower() in x for x in self.request.user.searchpreference.trigram.values_list('field', flat=True)])
|
||||
|
||||
if query is not None and query not in ["''", '']:
|
||||
if fuzzy:
|
||||
self.queryset = (
|
||||
self.queryset
|
||||
.annotate(starts=Case(When(name__istartswith=query, then=(Value(.3, output_field=IntegerField()))), default=Value(0)))
|
||||
.annotate(trigram=TrigramSimilarity('name', query))
|
||||
.annotate(sort=F('starts')+F('trigram'))
|
||||
.order_by('-sort')
|
||||
)
|
||||
if any([self.model.__name__.lower() in x for x in self.request.user.searchpreference.unaccent.values_list('field', flat=True)]):
|
||||
self.queryset = self.queryset.annotate(trigram=TrigramSimilarity('name__unaccent', query))
|
||||
else:
|
||||
self.queryset = self.queryset.annotate(trigram=TrigramSimilarity('name', query))
|
||||
self.queryset = self.queryset.order_by('-trigram')
|
||||
else:
|
||||
# TODO have this check unaccent search settings or other search preferences?
|
||||
filter = Q(name__icontains=query)
|
||||
if any([self.model.__name__.lower() in x for x in self.request.user.searchpreference.unaccent.values_list('field', flat=True)]):
|
||||
filter |= Q(name__unaccent__icontains=query)
|
||||
|
||||
self.queryset = (
|
||||
self.queryset
|
||||
.annotate(starts=Case(When(name__istartswith=query, then=(Value(100))),
|
||||
default=Value(0))) # put exact matches at the top of the result set
|
||||
.filter(name__icontains=query).order_by('-starts', 'name')
|
||||
.filter(filter).order_by('-starts', Lower('name').asc())
|
||||
)
|
||||
|
||||
updated_at = self.request.query_params.get('updated_at', None)
|
||||
@ -171,16 +175,16 @@ class FuzzyFilterMixin(ViewSetMixin, ExtendedRecipeMixin):
|
||||
|
||||
limit = self.request.query_params.get('limit', None)
|
||||
random = self.request.query_params.get('random', False)
|
||||
if random:
|
||||
self.queryset = self.queryset.order_by("?")
|
||||
if limit is not None:
|
||||
if random:
|
||||
self.queryset = self.queryset.order_by("?")
|
||||
self.queryset = self.queryset[:int(limit)]
|
||||
return self.annotate_recipe(queryset=self.queryset, request=self.request, serializer=self.serializer_class)
|
||||
|
||||
|
||||
class MergeMixin(ViewSetMixin):
|
||||
@ decorators.action(detail=True, url_path='merge/(?P<target>[^/.]+)', methods=['PUT'], )
|
||||
@ decorators.renderer_classes((TemplateHTMLRenderer, JSONRenderer))
|
||||
@decorators.action(detail=True, url_path='merge/(?P<target>[^/.]+)', methods=['PUT'], )
|
||||
@decorators.renderer_classes((TemplateHTMLRenderer, JSONRenderer))
|
||||
def merge(self, request, pk, target):
|
||||
self.description = f"Merge {self.basename} onto target {self.basename} with ID of [int]."
|
||||
|
||||
@ -272,12 +276,12 @@ class TreeMixin(MergeMixin, FuzzyFilterMixin, ExtendedRecipeMixin):
|
||||
self.queryset = self.model.objects.none()
|
||||
else:
|
||||
return self.annotate_recipe(queryset=super().get_queryset(), request=self.request, serializer=self.serializer_class, tree=True)
|
||||
self.queryset = self.queryset.filter(space=self.request.space).order_by('name')
|
||||
self.queryset = self.queryset.filter(space=self.request.space).order_by(Lower('name').asc())
|
||||
|
||||
return self.annotate_recipe(queryset=self.queryset, request=self.request, serializer=self.serializer_class, tree=True)
|
||||
|
||||
@ decorators.action(detail=True, url_path='move/(?P<parent>[^/.]+)', methods=['PUT'], )
|
||||
@ decorators.renderer_classes((TemplateHTMLRenderer, JSONRenderer))
|
||||
@decorators.action(detail=True, url_path='move/(?P<parent>[^/.]+)', methods=['PUT'], )
|
||||
@decorators.renderer_classes((TemplateHTMLRenderer, JSONRenderer))
|
||||
def move(self, request, pk, parent):
|
||||
self.description = f"Move {self.basename} to be a child of {self.basename} with ID of [int]. Use ID: 0 to move {self.basename} to the root."
|
||||
if self.model.node_order_by:
|
||||
@ -400,7 +404,7 @@ class SupermarketCategoryViewSet(viewsets.ModelViewSet, StandardFilterMixin):
|
||||
permission_classes = [CustomIsUser]
|
||||
|
||||
def get_queryset(self):
|
||||
self.queryset = self.queryset.filter(space=self.request.space)
|
||||
self.queryset = self.queryset.filter(space=self.request.space).order_by(Lower('name').asc())
|
||||
return super().get_queryset()
|
||||
|
||||
|
||||
@ -457,7 +461,7 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
|
||||
# onhand_status = self.queryset.annotate(onhand_status=Exists(onhand_users_set__in=[shared_users]))
|
||||
return self.queryset.annotate(shopping_status=Exists(shopping_status)).prefetch_related('onhand_users', 'inherit_fields').select_related('recipe', 'supermarket_category')
|
||||
|
||||
@ decorators.action(detail=True, methods=['PUT'], serializer_class=FoodShoppingUpdateSerializer,)
|
||||
@decorators.action(detail=True, methods=['PUT'], serializer_class=FoodShoppingUpdateSerializer, )
|
||||
# TODO DRF only allows one action in a decorator action without overriding get_operation_id_base() this should be PUT and DELETE probably
|
||||
def shopping(self, request, pk):
|
||||
if self.request.space.demo:
|
||||
@ -488,7 +492,7 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
|
||||
class RecipeBookViewSet(viewsets.ModelViewSet, StandardFilterMixin):
|
||||
queryset = RecipeBook.objects
|
||||
serializer_class = RecipeBookSerializer
|
||||
permission_classes = [CustomIsOwner]
|
||||
permission_classes = [CustomIsOwner | CustomIsShared]
|
||||
|
||||
def get_queryset(self):
|
||||
self.queryset = self.queryset.filter(Q(created_by=self.request.user) | Q(shared=self.request.user)).filter(
|
||||
@ -507,7 +511,7 @@ class RecipeBookEntryViewSet(viewsets.ModelViewSet, viewsets.GenericViewSet):
|
||||
"""
|
||||
queryset = RecipeBookEntry.objects
|
||||
serializer_class = RecipeBookEntrySerializer
|
||||
permission_classes = [CustomIsOwner]
|
||||
permission_classes = [CustomIsOwner | CustomIsShared]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.queryset.filter(
|
||||
@ -521,7 +525,6 @@ class RecipeBookEntryViewSet(viewsets.ModelViewSet, viewsets.GenericViewSet):
|
||||
book_id = self.request.query_params.get('book', None)
|
||||
if book_id is not None:
|
||||
queryset = queryset.filter(book__pk=book_id)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
@ -536,7 +539,7 @@ class MealPlanViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
queryset = MealPlan.objects
|
||||
serializer_class = MealPlanSerializer
|
||||
permission_classes = [CustomIsOwner]
|
||||
permission_classes = [CustomIsOwner | CustomIsShared]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.queryset.filter(
|
||||
@ -626,34 +629,49 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
# TODO split read and write permission for meal plan guest
|
||||
permission_classes = [CustomIsShare | CustomIsGuest]
|
||||
pagination_class = RecipePagination
|
||||
# TODO the boolean params below (keywords_or through new) should be updated to boolean types with front end refactored accordingly
|
||||
|
||||
query_params = [
|
||||
QueryParam(name='query', description=_('Query string matched (fuzzy) against recipe name. In the future also fulltext search.')),
|
||||
QueryParam(name='keywords', description=_('ID of keyword a recipe should have. For multiple repeat parameter.'), qtype='int'),
|
||||
QueryParam(name='keywords', description=_('ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or'), qtype='int'),
|
||||
QueryParam(name='keywords_or', description=_('Keyword IDs, repeat for multiple. Return recipes with any of the keywords'), qtype='int'),
|
||||
QueryParam(name='keywords_and', description=_('Keyword IDs, repeat for multiple. Return recipes with all of the keywords.'), qtype='int'),
|
||||
QueryParam(name='keywords_or_not', description=_('Keyword IDs, repeat for multiple. Exclude recipes with any of the keywords.'), qtype='int'),
|
||||
QueryParam(name='keywords_and_not', description=_('Keyword IDs, repeat for multiple. Exclude recipes with all of the keywords.'), qtype='int'),
|
||||
QueryParam(name='foods', description=_('ID of food a recipe should have. For multiple repeat parameter.'), qtype='int'),
|
||||
QueryParam(name='foods_or', description=_('Food IDs, repeat for multiple. Return recipes with any of the foods'), qtype='int'),
|
||||
QueryParam(name='foods_and', description=_('Food IDs, repeat for multiple. Return recipes with all of the foods.'), qtype='int'),
|
||||
QueryParam(name='foods_or_not', description=_('Food IDs, repeat for multiple. Exclude recipes with any of the foods.'), qtype='int'),
|
||||
QueryParam(name='foods_and_not', description=_('Food IDs, repeat for multiple. Exclude recipes with all of the foods.'), qtype='int'),
|
||||
QueryParam(name='units', description=_('ID of unit a recipe should have.'), qtype='int'),
|
||||
QueryParam(name='rating', description=_('Rating a recipe should have. [0 - 5]'), qtype='int'),
|
||||
QueryParam(name='rating', description=_('Rating a recipe should have or greater. [0 - 5] Negative value filters rating less than.'), qtype='int'),
|
||||
QueryParam(name='books', description=_('ID of book a recipe should be in. For multiple repeat parameter.')),
|
||||
QueryParam(name='keywords_or', description=_('If recipe should have all (AND=''false'') or any (OR=''<b>true</b>'') of the provided keywords.')),
|
||||
QueryParam(name='foods_or', description=_('If recipe should have all (AND=''false'') or any (OR=''<b>true</b>'') of the provided foods.')),
|
||||
QueryParam(name='books_or', description=_('If recipe should be in all (AND=''false'') or any (OR=''<b>true</b>'') of the provided books.')),
|
||||
QueryParam(name='books_or', description=_('Book IDs, repeat for multiple. Return recipes with any of the books'), qtype='int'),
|
||||
QueryParam(name='books_and', description=_('Book IDs, repeat for multiple. Return recipes with all of the books.'), qtype='int'),
|
||||
QueryParam(name='books_or_not', description=_('Book IDs, repeat for multiple. Exclude recipes with any of the books.'), qtype='int'),
|
||||
QueryParam(name='books_and_not', description=_('Book IDs, repeat for multiple. Exclude recipes with all of the books.'), qtype='int'),
|
||||
QueryParam(name='internal', description=_('If only internal recipes should be returned. [''true''/''<b>false</b>'']')),
|
||||
QueryParam(name='random', description=_('Returns the results in randomized order. [''true''/''<b>false</b>'']')),
|
||||
QueryParam(name='new', description=_('Returns new results first in search results. [''true''/''<b>false</b>'']')),
|
||||
QueryParam(name='timescooked', description=_('Filter recipes cooked X times or more. Negative values returns cooked less than X times'), qtype='int'),
|
||||
QueryParam(name='cookedon', description=_('Filter recipes last cooked on or after YYYY-MM-DD. Prepending ''-'' filters on or before date.')),
|
||||
QueryParam(name='createdon', description=_('Filter recipes created on or after YYYY-MM-DD. Prepending ''-'' filters on or before date.')),
|
||||
QueryParam(name='updatedon', description=_('Filter recipes updated on or after YYYY-MM-DD. Prepending ''-'' filters on or before date.')),
|
||||
QueryParam(name='viewedon', description=_('Filter recipes lasts viewed on or after YYYY-MM-DD. Prepending ''-'' filters on or before date.')),
|
||||
QueryParam(name='makenow', description=_('Filter recipes that can be made with OnHand food. [''true''/''<b>false</b>'']')),
|
||||
]
|
||||
schema = QueryParamAutoSchema()
|
||||
|
||||
def get_queryset(self):
|
||||
share = self.request.query_params.get('share', None)
|
||||
|
||||
if self.detail:
|
||||
self.queryset = self.queryset.filter(space=self.request.space)
|
||||
if not share:
|
||||
self.queryset = self.queryset.filter(space=self.request.space)
|
||||
return super().get_queryset()
|
||||
|
||||
share = self.request.query_params.get('share', None)
|
||||
if not (share and self.detail):
|
||||
self.queryset = self.queryset.filter(space=self.request.space)
|
||||
|
||||
# self.queryset = search_recipes(self.request, self.queryset, self.request.GET)
|
||||
params = {x: self.request.GET.get(x) if len({**self.request.GET}[x]) == 1 else self.request.GET.getlist(x) for x in list(self.request.GET)}
|
||||
search = RecipeSearch(self.request, **params)
|
||||
self.queryset = search.get_queryset(self.queryset).prefetch_related('cooklog_set')
|
||||
@ -717,16 +735,27 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
obj = self.get_object()
|
||||
ingredients = request.data.get('ingredients', None)
|
||||
servings = request.data.get('servings', None)
|
||||
list_recipe = ShoppingListRecipe.objects.filter(id=request.data.get('list_recipe', None)).first()
|
||||
if servings is None:
|
||||
servings = getattr(list_recipe, 'servings', obj.servings)
|
||||
# created_by needs to be sticky to original creator as it is 'their' shopping list
|
||||
# changing shopping list created_by can shift some items to new owner which may not share in the other direction
|
||||
created_by = getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', request.user)
|
||||
content = {'msg': _(f'{obj.name} was added to the shopping list.')}
|
||||
list_from_recipe(list_recipe=list_recipe, recipe=obj, ingredients=ingredients, servings=servings, space=request.space, created_by=created_by)
|
||||
list_recipe = request.data.get('list_recipe', None)
|
||||
mealplan = request.data.get('mealplan', None)
|
||||
SLR = RecipeShoppingEditor(request.user, request.space, id=list_recipe, recipe=obj, mealplan=mealplan)
|
||||
|
||||
return Response(content, status=status.HTTP_204_NO_CONTENT)
|
||||
content = {'msg': _(f'{obj.name} was added to the shopping list.')}
|
||||
http_status = status.HTTP_204_NO_CONTENT
|
||||
if servings and servings <= 0:
|
||||
result = SLR.delete()
|
||||
elif list_recipe:
|
||||
result = SLR.edit(servings=servings, ingredients=ingredients)
|
||||
else:
|
||||
result = SLR.create(servings=servings, ingredients=ingredients)
|
||||
|
||||
if not result:
|
||||
content = {'msg': ('An error occurred')}
|
||||
http_status = status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
else:
|
||||
content = {'msg': _(f'{obj.name} was added to the shopping list.')}
|
||||
http_status = status.HTTP_204_NO_CONTENT
|
||||
|
||||
return Response(content, status=http_status)
|
||||
|
||||
@decorators.action(
|
||||
detail=True,
|
||||
@ -847,6 +876,16 @@ class ImportLogViewSet(viewsets.ModelViewSet):
|
||||
return self.queryset.filter(space=self.request.space)
|
||||
|
||||
|
||||
class ExportLogViewSet(viewsets.ModelViewSet):
|
||||
queryset = ExportLog.objects
|
||||
serializer_class = ExportLogSerializer
|
||||
permission_classes = [CustomIsUser]
|
||||
pagination_class = DefaultPagination
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(space=self.request.space)
|
||||
|
||||
|
||||
class BookmarkletImportViewSet(viewsets.ModelViewSet):
|
||||
queryset = BookmarkletImport.objects
|
||||
serializer_class = BookmarkletImportSerializer
|
||||
@ -877,7 +916,19 @@ class AutomationViewSet(viewsets.ModelViewSet, StandardFilterMixin):
|
||||
return super().get_queryset()
|
||||
|
||||
|
||||
class CustomFilterViewSet(viewsets.ModelViewSet, StandardFilterMixin):
|
||||
queryset = CustomFilter.objects
|
||||
serializer_class = CustomFilterSerializer
|
||||
permission_classes = [CustomIsOwner]
|
||||
|
||||
def get_queryset(self):
|
||||
self.queryset = self.queryset.filter(Q(created_by=self.request.user) | Q(shared=self.request.user)).filter(
|
||||
space=self.request.space).distinct()
|
||||
return super().get_queryset()
|
||||
|
||||
# -------------- non django rest api views --------------------
|
||||
|
||||
|
||||
def get_recipe_provider(recipe):
|
||||
if recipe.storage.method == Storage.DROPBOX:
|
||||
return Dropbox
|
||||
|
@ -156,7 +156,7 @@ def import_url(request):
|
||||
recipe.steps.add(step)
|
||||
|
||||
for kw in data['keywords']:
|
||||
if data['all_keywords']: # do not remove this check :) https://github.com/vabene1111/recipes/issues/645
|
||||
if data['all_keywords']: # do not remove this check :) https://github.com/vabene1111/recipes/issues/645
|
||||
k, created = Keyword.objects.get_or_create(name=kw['text'], space=request.space)
|
||||
recipe.keywords.add(k)
|
||||
else:
|
||||
@ -168,7 +168,8 @@ def import_url(request):
|
||||
|
||||
ingredient_parser = IngredientParser(request, True)
|
||||
for ing in data['recipeIngredient']:
|
||||
ingredient = Ingredient(space=request.space, )
|
||||
original = ing.pop('original', None) or ing.pop('original_text', None)
|
||||
ingredient = Ingredient(original_text=original, space=request.space, )
|
||||
|
||||
if food_text := ing['ingredient']['text'].strip():
|
||||
ingredient.food = ingredient_parser.get_food(food_text)
|
||||
|
@ -7,12 +7,9 @@ from django.urls import reverse, reverse_lazy
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import DeleteView
|
||||
|
||||
from cookbook.helper.permission_helper import (GroupRequiredMixin,
|
||||
OwnerRequiredMixin,
|
||||
group_required)
|
||||
from cookbook.models import (Comment, InviteLink, MealPlan, Recipe,
|
||||
RecipeBook, RecipeBookEntry, RecipeImport,
|
||||
Storage, Sync)
|
||||
from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required
|
||||
from cookbook.models import (Comment, InviteLink, MealPlan, Recipe, RecipeBook, RecipeBookEntry,
|
||||
RecipeImport, Storage, Sync)
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
|
@ -2,22 +2,16 @@ import os
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import UpdateView
|
||||
from django.views.generic.edit import FormMixin
|
||||
|
||||
from cookbook.forms import (CommentForm, ExternalRecipeForm,
|
||||
MealPlanForm,
|
||||
StorageForm, SyncForm,
|
||||
)
|
||||
from cookbook.helper.permission_helper import (GroupRequiredMixin,
|
||||
OwnerRequiredMixin,
|
||||
group_required)
|
||||
from cookbook.models import (Comment, MealPlan,
|
||||
MealType, Recipe, RecipeImport,
|
||||
Storage, Sync, UserPreference)
|
||||
from cookbook.forms import CommentForm, ExternalRecipeForm, MealPlanForm, StorageForm, SyncForm
|
||||
from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required
|
||||
from cookbook.models import (Comment, MealPlan, MealType, Recipe, RecipeImport, Storage, Sync,
|
||||
UserPreference)
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
|
@ -3,18 +3,19 @@ import threading
|
||||
from io import BytesIO
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponseRedirect, JsonResponse
|
||||
from django.shortcuts import render
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from cookbook.forms import ExportForm, ImportForm, ImportExportBase
|
||||
from cookbook.forms import ExportForm, ImportExportBase, ImportForm
|
||||
from cookbook.helper.permission_helper import group_required
|
||||
from cookbook.integration.cookbookapp import CookBookApp
|
||||
from cookbook.integration.copymethat import CopyMeThat
|
||||
from cookbook.integration.pepperplate import Pepperplate
|
||||
from cookbook.helper.recipe_search import RecipeSearch
|
||||
from cookbook.integration.cheftap import ChefTap
|
||||
from cookbook.integration.chowdown import Chowdown
|
||||
from cookbook.integration.cookbookapp import CookBookApp
|
||||
from cookbook.integration.copymethat import CopyMeThat
|
||||
from cookbook.integration.default import Default
|
||||
from cookbook.integration.domestica import Domestica
|
||||
from cookbook.integration.mealie import Mealie
|
||||
@ -22,14 +23,15 @@ from cookbook.integration.mealmaster import MealMaster
|
||||
from cookbook.integration.nextcloud_cookbook import NextcloudCookbook
|
||||
from cookbook.integration.openeats import OpenEats
|
||||
from cookbook.integration.paprika import Paprika
|
||||
from cookbook.integration.pdfexport import PDFexport
|
||||
from cookbook.integration.pepperplate import Pepperplate
|
||||
from cookbook.integration.plantoeat import Plantoeat
|
||||
from cookbook.integration.recipekeeper import RecipeKeeper
|
||||
from cookbook.integration.recettetek import RecetteTek
|
||||
from cookbook.integration.recipekeeper import RecipeKeeper
|
||||
from cookbook.integration.recipesage import RecipeSage
|
||||
from cookbook.integration.rezkonv import RezKonv
|
||||
from cookbook.integration.saffron import Saffron
|
||||
from cookbook.integration.pdfexport import PDFexport
|
||||
from cookbook.models import Recipe, ImportLog, UserPreference
|
||||
from cookbook.models import ExportLog, ImportLog, Recipe, UserPreference
|
||||
from recipes import settings
|
||||
|
||||
|
||||
@ -122,26 +124,61 @@ def export_recipe(request):
|
||||
recipes = form.cleaned_data['recipes']
|
||||
if form.cleaned_data['all']:
|
||||
recipes = Recipe.objects.filter(space=request.space, internal=True).all()
|
||||
elif custom_filter := form.cleaned_data['custom_filter']:
|
||||
search = RecipeSearch(request, filter=custom_filter)
|
||||
recipes = search.get_queryset(Recipe.objects.filter(space=request.space, internal=True))
|
||||
|
||||
integration = get_integration(request, form.cleaned_data['type'])
|
||||
|
||||
if form.cleaned_data['type'] == ImportExportBase.PDF and not settings.ENABLE_PDF_EXPORT:
|
||||
messages.add_message(request, messages.ERROR, _('The PDF Exporter is not enabled on this instance as it is still in an experimental state.'))
|
||||
return render(request, 'export.html', {'form': form})
|
||||
integration = get_integration(request, form.cleaned_data['type'])
|
||||
return integration.do_export(recipes)
|
||||
except NotImplementedError:
|
||||
messages.add_message(request, messages.ERROR, _('Exporting is not implemented for this provider'))
|
||||
return JsonResponse({'error': _('The PDF Exporter is not enabled on this instance as it is still in an experimental state.')})
|
||||
|
||||
el = ExportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space)
|
||||
|
||||
t = threading.Thread(target=integration.do_export, args=[recipes, el])
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
return JsonResponse({'export_id': el.pk})
|
||||
except NotImplementedError:
|
||||
return JsonResponse(
|
||||
{
|
||||
'error': True,
|
||||
'msg': _('Importing is not implemented for this provider')
|
||||
},
|
||||
status=400
|
||||
)
|
||||
else:
|
||||
form = ExportForm(space=request.space)
|
||||
pk = ''
|
||||
recipe = request.GET.get('r')
|
||||
if recipe:
|
||||
if re.match(r'^([0-9])+$', recipe):
|
||||
if recipe := Recipe.objects.filter(pk=int(recipe), space=request.space).first():
|
||||
form = ExportForm(initial={'recipes': recipe}, space=request.space)
|
||||
pk = Recipe.objects.filter(pk=int(recipe), space=request.space).first().pk
|
||||
|
||||
return render(request, 'export.html', {'form': form})
|
||||
return render(request, 'export.html', {'pk': pk})
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def import_response(request, pk):
|
||||
return render(request, 'import_response.html', {'pk': pk})
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def export_response(request, pk):
|
||||
return render(request, 'export_response.html', {'pk': pk})
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def export_file(request, pk):
|
||||
el = get_object_or_404(ExportLog, pk=pk, space=request.space)
|
||||
|
||||
cacheData = cache.get(f'export_file_{el.pk}')
|
||||
|
||||
if cacheData is None:
|
||||
el.possibly_not_expired = False
|
||||
el.save()
|
||||
return render(request, 'export_response.html', {'pk': pk})
|
||||
|
||||
response = HttpResponse(cacheData['file'], content_type='application/force-download')
|
||||
response['Content-Disposition'] = 'attachment; filename="' + cacheData['filename'] + '"'
|
||||
return response
|
||||
|
@ -185,6 +185,22 @@ def automation(request):
|
||||
)
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def custom_filter(request):
|
||||
# recipe-param is the name of the parameters used when filtering recipes by this attribute
|
||||
# model-name is the models.js name of the model, probably ALL-CAPS
|
||||
return render(
|
||||
request,
|
||||
'generic/model_template.html',
|
||||
{
|
||||
"title": _("Custom Filters"),
|
||||
"config": {
|
||||
'model': "CUSTOM_FILTER", # *REQUIRED* name of the model in models.js
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def user_file(request):
|
||||
try:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user