Merge branch 'develop' into feature/unit-conversion
# Conflicts: # requirements.txt
This commit is contained in:
commit
89e3e85d1e
@ -158,6 +158,7 @@ REVERSE_PROXY_AUTH=0
|
|||||||
#AUTH_LDAP_BIND_PASSWORD=
|
#AUTH_LDAP_BIND_PASSWORD=
|
||||||
#AUTH_LDAP_USER_SEARCH_BASE_DN=
|
#AUTH_LDAP_USER_SEARCH_BASE_DN=
|
||||||
#AUTH_LDAP_TLS_CACERTFILE=
|
#AUTH_LDAP_TLS_CACERTFILE=
|
||||||
|
#AUTH_LDAP_START_TLS=
|
||||||
|
|
||||||
# Enables exporting PDF (see export docs)
|
# Enables exporting PDF (see export docs)
|
||||||
# Disabled by default, uncomment to enable
|
# Disabled by default, uncomment to enable
|
||||||
|
6
.github/workflows/build-docker.yml
vendored
6
.github/workflows/build-docker.yml
vendored
@ -115,13 +115,17 @@ jobs:
|
|||||||
needs: build-container
|
needs: build-container
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
steps:
|
steps:
|
||||||
|
- name: Set tag name
|
||||||
|
run: |
|
||||||
|
# Strip "refs/tags/" prefix
|
||||||
|
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
# Send stable discord notification
|
# Send stable discord notification
|
||||||
- name: Discord notification
|
- name: Discord notification
|
||||||
env:
|
env:
|
||||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
|
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
|
||||||
uses: Ilshidur/action-discord@0.3.2
|
uses: Ilshidur/action-discord@0.3.2
|
||||||
with:
|
with:
|
||||||
args: '🚀 Version {{ EVENT_PAYLOAD.release.tag_name }} of tandoor has been released 🥳 Check it out https://github.com/vabene1111/recipes/releases/tag/{{ EVENT_PAYLOAD.release.tag_name }}'
|
args: '🚀 Version {{ VERSION }} of tandoor has been released 🥳 Check it out https://github.com/vabene1111/recipes/releases/tag/{{ VERSION }}'
|
||||||
|
|
||||||
notify-beta:
|
notify-beta:
|
||||||
name: Notify Beta
|
name: Notify Beta
|
||||||
|
@ -3,9 +3,9 @@ from collections import Counter
|
|||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
|
|
||||||
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector, TrigramSimilarity
|
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector, TrigramSimilarity
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache, caches
|
||||||
from django.core.cache import caches
|
from django.db.models import (Avg, Case, Count, Exists, F, Func, Max, OuterRef, Q, Subquery, Value,
|
||||||
from django.db.models import (Avg, Case, Count, Exists, F, Func, Max, OuterRef, Q, Subquery, Value, When, FilteredRelation)
|
When)
|
||||||
from django.db.models.functions import Coalesce, Lower, Substr
|
from django.db.models.functions import Coalesce, Lower, Substr
|
||||||
from django.utils import timezone, translation
|
from django.utils import timezone, translation
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
@ -20,7 +20,8 @@ from recipes import settings
|
|||||||
# TODO create extensive tests to make sure ORs ANDs and various filters, sorting, etc work as expected
|
# TODO create extensive tests to make sure ORs ANDs and various filters, sorting, etc work as expected
|
||||||
# TODO consider creating a simpleListRecipe API that only includes minimum of recipe info and minimal filtering
|
# TODO consider creating a simpleListRecipe API that only includes minimum of recipe info and minimal filtering
|
||||||
class RecipeSearch():
|
class RecipeSearch():
|
||||||
_postgres = settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
|
_postgres = settings.DATABASES['default']['ENGINE'] in [
|
||||||
|
'django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
|
||||||
|
|
||||||
def __init__(self, request, **params):
|
def __init__(self, request, **params):
|
||||||
self._request = request
|
self._request = request
|
||||||
@ -45,7 +46,8 @@ class RecipeSearch():
|
|||||||
cache.set(CACHE_KEY, self._search_prefs, timeout=10)
|
cache.set(CACHE_KEY, self._search_prefs, timeout=10)
|
||||||
else:
|
else:
|
||||||
self._search_prefs = SearchPreference()
|
self._search_prefs = SearchPreference()
|
||||||
self._string = self._params.get('query').strip() if self._params.get('query', None) else None
|
self._string = self._params.get('query').strip(
|
||||||
|
) if self._params.get('query', None) else None
|
||||||
self._rating = self._params.get('rating', None)
|
self._rating = self._params.get('rating', None)
|
||||||
self._keywords = {
|
self._keywords = {
|
||||||
'or': self._params.get('keywords_or', None) or self._params.get('keywords', None),
|
'or': self._params.get('keywords_or', None) or self._params.get('keywords', None),
|
||||||
@ -74,7 +76,8 @@ class RecipeSearch():
|
|||||||
self._random = str2bool(self._params.get('random', False))
|
self._random = str2bool(self._params.get('random', False))
|
||||||
self._new = str2bool(self._params.get('new', False))
|
self._new = str2bool(self._params.get('new', False))
|
||||||
self._num_recent = int(self._params.get('num_recent', 0))
|
self._num_recent = int(self._params.get('num_recent', 0))
|
||||||
self._include_children = str2bool(self._params.get('include_children', None))
|
self._include_children = str2bool(
|
||||||
|
self._params.get('include_children', None))
|
||||||
self._timescooked = self._params.get('timescooked', None)
|
self._timescooked = self._params.get('timescooked', None)
|
||||||
self._cookedon = self._params.get('cookedon', None)
|
self._cookedon = self._params.get('cookedon', None)
|
||||||
self._createdon = self._params.get('createdon', None)
|
self._createdon = self._params.get('createdon', None)
|
||||||
@ -95,18 +98,24 @@ class RecipeSearch():
|
|||||||
self._search_type = self._search_prefs.search or 'plain'
|
self._search_type = self._search_prefs.search or 'plain'
|
||||||
if self._string:
|
if self._string:
|
||||||
if self._postgres:
|
if self._postgres:
|
||||||
self._unaccent_include = self._search_prefs.unaccent.values_list('field', flat=True)
|
self._unaccent_include = self._search_prefs.unaccent.values_list(
|
||||||
|
'field', flat=True)
|
||||||
else:
|
else:
|
||||||
self._unaccent_include = []
|
self._unaccent_include = []
|
||||||
self._icontains_include = [x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.icontains.values_list('field', flat=True)]
|
self._icontains_include = [
|
||||||
self._istartswith_include = [x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.istartswith.values_list('field', flat=True)]
|
x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.icontains.values_list('field', flat=True)]
|
||||||
|
self._istartswith_include = [
|
||||||
|
x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.istartswith.values_list('field', flat=True)]
|
||||||
self._trigram_include = None
|
self._trigram_include = None
|
||||||
self._fulltext_include = None
|
self._fulltext_include = None
|
||||||
self._trigram = False
|
self._trigram = False
|
||||||
if self._postgres and self._string:
|
if self._postgres and self._string:
|
||||||
self._language = DICTIONARY.get(translation.get_language(), 'simple')
|
self._language = DICTIONARY.get(
|
||||||
self._trigram_include = [x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.trigram.values_list('field', flat=True)]
|
translation.get_language(), 'simple')
|
||||||
self._fulltext_include = self._search_prefs.fulltext.values_list('field', flat=True) or None
|
self._trigram_include = [
|
||||||
|
x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.trigram.values_list('field', flat=True)]
|
||||||
|
self._fulltext_include = self._search_prefs.fulltext.values_list(
|
||||||
|
'field', flat=True) or None
|
||||||
|
|
||||||
if self._search_type not in ['websearch', 'raw'] and self._trigram_include:
|
if self._search_type not in ['websearch', 'raw'] and self._trigram_include:
|
||||||
self._trigram = True
|
self._trigram = True
|
||||||
@ -182,8 +191,10 @@ class RecipeSearch():
|
|||||||
# otherwise sort by the remaining order_by attributes or favorite by default
|
# otherwise sort by the remaining order_by attributes or favorite by default
|
||||||
else:
|
else:
|
||||||
order += default_order
|
order += default_order
|
||||||
order[:] = [Lower('name').asc() if x == 'name' else x for x in order]
|
order[:] = [Lower('name').asc() if x ==
|
||||||
order[:] = [Lower('name').desc() if x == '-name' else x for x in order]
|
'name' else x for x in order]
|
||||||
|
order[:] = [Lower('name').desc() if x ==
|
||||||
|
'-name' else x for x in order]
|
||||||
self.orderby = order
|
self.orderby = order
|
||||||
|
|
||||||
def string_filters(self, string=None):
|
def string_filters(self, string=None):
|
||||||
@ -200,21 +211,28 @@ class RecipeSearch():
|
|||||||
for f in self._filters:
|
for f in self._filters:
|
||||||
query_filter |= f
|
query_filter |= f
|
||||||
|
|
||||||
self._queryset = self._queryset.filter(query_filter).distinct() # this creates duplicate records which can screw up other aggregates, see makenow for workaround
|
# this creates duplicate records which can screw up other aggregates, see makenow for workaround
|
||||||
|
self._queryset = self._queryset.filter(query_filter).distinct()
|
||||||
if self._fulltext_include:
|
if self._fulltext_include:
|
||||||
if self._fuzzy_match is None:
|
if self._fuzzy_match is None:
|
||||||
self._queryset = self._queryset.annotate(score=Coalesce(Max(self.search_rank), 0.0))
|
self._queryset = self._queryset.annotate(
|
||||||
|
score=Coalesce(Max(self.search_rank), 0.0))
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.annotate(rank=Coalesce(Max(self.search_rank), 0.0))
|
self._queryset = self._queryset.annotate(
|
||||||
|
rank=Coalesce(Max(self.search_rank), 0.0))
|
||||||
|
|
||||||
if self._fuzzy_match is not None:
|
if self._fuzzy_match is not None:
|
||||||
simularity = self._fuzzy_match.filter(pk=OuterRef('pk')).values('simularity')
|
simularity = self._fuzzy_match.filter(
|
||||||
|
pk=OuterRef('pk')).values('simularity')
|
||||||
if not self._fulltext_include:
|
if not self._fulltext_include:
|
||||||
self._queryset = self._queryset.annotate(score=Coalesce(Subquery(simularity), 0.0))
|
self._queryset = self._queryset.annotate(
|
||||||
|
score=Coalesce(Subquery(simularity), 0.0))
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.annotate(simularity=Coalesce(Subquery(simularity), 0.0))
|
self._queryset = self._queryset.annotate(
|
||||||
|
simularity=Coalesce(Subquery(simularity), 0.0))
|
||||||
if self._sort_includes('score') and self._fulltext_include and self._fuzzy_match is not None:
|
if self._sort_includes('score') and self._fulltext_include and self._fuzzy_match is not None:
|
||||||
self._queryset = self._queryset.annotate(score=F('rank') + F('simularity'))
|
self._queryset = self._queryset.annotate(
|
||||||
|
score=F('rank') + F('simularity'))
|
||||||
else:
|
else:
|
||||||
query_filter = Q()
|
query_filter = Q()
|
||||||
for f in [x + '__unaccent__iexact' if x in self._unaccent_include else x + '__iexact' for x in SearchFields.objects.all().values_list('field', flat=True)]:
|
for f in [x + '__unaccent__iexact' if x in self._unaccent_include else x + '__iexact' for x in SearchFields.objects.all().values_list('field', flat=True)]:
|
||||||
@ -223,7 +241,8 @@ class RecipeSearch():
|
|||||||
|
|
||||||
def _cooked_on_filter(self, cooked_date=None):
|
def _cooked_on_filter(self, cooked_date=None):
|
||||||
if self._sort_includes('lastcooked') or cooked_date:
|
if self._sort_includes('lastcooked') or cooked_date:
|
||||||
lessthan = self._sort_includes('-lastcooked') or '-' in (cooked_date or [])[:1]
|
lessthan = self._sort_includes(
|
||||||
|
'-lastcooked') or '-' in (cooked_date or [])[:1]
|
||||||
if lessthan:
|
if lessthan:
|
||||||
default = timezone.now() - timedelta(days=100000)
|
default = timezone.now() - timedelta(days=100000)
|
||||||
else:
|
else:
|
||||||
@ -233,32 +252,41 @@ class RecipeSearch():
|
|||||||
if cooked_date is None:
|
if cooked_date is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
cooked_date = date(*[int(x) for x in cooked_date.split('-') if x != ''])
|
cooked_date = date(*[int(x)
|
||||||
|
for x in cooked_date.split('-') if x != ''])
|
||||||
|
|
||||||
if lessthan:
|
if lessthan:
|
||||||
self._queryset = self._queryset.filter(lastcooked__date__lte=cooked_date).exclude(lastcooked=default)
|
self._queryset = self._queryset.filter(
|
||||||
|
lastcooked__date__lte=cooked_date).exclude(lastcooked=default)
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(lastcooked__date__gte=cooked_date).exclude(lastcooked=default)
|
self._queryset = self._queryset.filter(
|
||||||
|
lastcooked__date__gte=cooked_date).exclude(lastcooked=default)
|
||||||
|
|
||||||
def _created_on_filter(self, created_date=None):
|
def _created_on_filter(self, created_date=None):
|
||||||
if created_date is None:
|
if created_date is None:
|
||||||
return
|
return
|
||||||
lessthan = '-' in created_date[:1]
|
lessthan = '-' in created_date[:1]
|
||||||
created_date = date(*[int(x) for x in created_date.split('-') if x != ''])
|
created_date = date(*[int(x)
|
||||||
|
for x in created_date.split('-') if x != ''])
|
||||||
if lessthan:
|
if lessthan:
|
||||||
self._queryset = self._queryset.filter(created_at__date__lte=created_date)
|
self._queryset = self._queryset.filter(
|
||||||
|
created_at__date__lte=created_date)
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(created_at__date__gte=created_date)
|
self._queryset = self._queryset.filter(
|
||||||
|
created_at__date__gte=created_date)
|
||||||
|
|
||||||
def _updated_on_filter(self, updated_date=None):
|
def _updated_on_filter(self, updated_date=None):
|
||||||
if updated_date is None:
|
if updated_date is None:
|
||||||
return
|
return
|
||||||
lessthan = '-' in updated_date[:1]
|
lessthan = '-' in updated_date[:1]
|
||||||
updated_date = date(*[int(x) for x in updated_date.split('-') if x != ''])
|
updated_date = date(*[int(x)
|
||||||
|
for x in updated_date.split('-') if x != ''])
|
||||||
if lessthan:
|
if lessthan:
|
||||||
self._queryset = self._queryset.filter(updated_at__date__lte=updated_date)
|
self._queryset = self._queryset.filter(
|
||||||
|
updated_at__date__lte=updated_date)
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(updated_at__date__gte=updated_date)
|
self._queryset = self._queryset.filter(
|
||||||
|
updated_at__date__gte=updated_date)
|
||||||
|
|
||||||
def _viewed_on_filter(self, viewed_date=None):
|
def _viewed_on_filter(self, viewed_date=None):
|
||||||
if self._sort_includes('lastviewed') or viewed_date:
|
if self._sort_includes('lastviewed') or viewed_date:
|
||||||
@ -268,12 +296,15 @@ class RecipeSearch():
|
|||||||
if viewed_date is None:
|
if viewed_date is None:
|
||||||
return
|
return
|
||||||
lessthan = '-' in viewed_date[:1]
|
lessthan = '-' in viewed_date[:1]
|
||||||
viewed_date = date(*[int(x) for x in viewed_date.split('-') if x != ''])
|
viewed_date = date(*[int(x)
|
||||||
|
for x in viewed_date.split('-') if x != ''])
|
||||||
|
|
||||||
if lessthan:
|
if lessthan:
|
||||||
self._queryset = self._queryset.filter(lastviewed__date__lte=viewed_date).exclude(lastviewed=longTimeAgo)
|
self._queryset = self._queryset.filter(
|
||||||
|
lastviewed__date__lte=viewed_date).exclude(lastviewed=longTimeAgo)
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(lastviewed__date__gte=viewed_date).exclude(lastviewed=longTimeAgo)
|
self._queryset = self._queryset.filter(
|
||||||
|
lastviewed__date__gte=viewed_date).exclude(lastviewed=longTimeAgo)
|
||||||
|
|
||||||
def _new_recipes(self, new_days=7):
|
def _new_recipes(self, new_days=7):
|
||||||
# TODO make new days a user-setting
|
# TODO make new days a user-setting
|
||||||
@ -293,27 +324,32 @@ class RecipeSearch():
|
|||||||
|
|
||||||
num_recent_recipes = ViewLog.objects.filter(created_by=self._request.user, space=self._request.space).values(
|
num_recent_recipes = ViewLog.objects.filter(created_by=self._request.user, space=self._request.space).values(
|
||||||
'recipe').annotate(recent=Max('created_at')).order_by('-recent')[:num_recent]
|
'recipe').annotate(recent=Max('created_at')).order_by('-recent')[:num_recent]
|
||||||
self._queryset = self._queryset.annotate(recent=Coalesce(Max(Case(When(pk__in=num_recent_recipes.values('recipe'), then='viewlog__pk'))), Value(0)))
|
self._queryset = self._queryset.annotate(recent=Coalesce(Max(Case(When(
|
||||||
|
pk__in=num_recent_recipes.values('recipe'), then='viewlog__pk'))), Value(0)))
|
||||||
|
|
||||||
def _favorite_recipes(self, times_cooked=None):
|
def _favorite_recipes(self, times_cooked=None):
|
||||||
if self._sort_includes('favorite') or times_cooked:
|
if self._sort_includes('favorite') or times_cooked:
|
||||||
less_than = '-' in (times_cooked or []) or not self._sort_includes('-favorite')
|
less_than = '-' in (times_cooked or []
|
||||||
|
) and not self._sort_includes('-favorite')
|
||||||
if less_than:
|
if less_than:
|
||||||
default = 1000
|
default = 1000
|
||||||
else:
|
else:
|
||||||
default = 0
|
default = 0
|
||||||
favorite_recipes = CookLog.objects.filter(created_by=self._request.user, space=self._request.space, recipe=OuterRef('pk')
|
favorite_recipes = CookLog.objects.filter(created_by=self._request.user, space=self._request.space, recipe=OuterRef('pk')
|
||||||
).values('recipe').annotate(count=Count('pk', distinct=True)).values('count')
|
).values('recipe').annotate(count=Count('pk', distinct=True)).values('count')
|
||||||
self._queryset = self._queryset.annotate(favorite=Coalesce(Subquery(favorite_recipes), default))
|
self._queryset = self._queryset.annotate(
|
||||||
|
favorite=Coalesce(Subquery(favorite_recipes), default))
|
||||||
if times_cooked is None:
|
if times_cooked is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if times_cooked == '0':
|
if times_cooked == '0':
|
||||||
self._queryset = self._queryset.filter(favorite=0)
|
self._queryset = self._queryset.filter(favorite=0)
|
||||||
elif less_than:
|
elif less_than:
|
||||||
self._queryset = self._queryset.filter(favorite__lte=int(times_cooked[1:])).exclude(favorite=0)
|
self._queryset = self._queryset.filter(favorite__lte=int(
|
||||||
|
times_cooked.replace('-', ''))).exclude(favorite=0)
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(favorite__gte=int(times_cooked))
|
self._queryset = self._queryset.filter(
|
||||||
|
favorite__gte=int(times_cooked))
|
||||||
|
|
||||||
def keyword_filters(self, **kwargs):
|
def keyword_filters(self, **kwargs):
|
||||||
if all([kwargs[x] is None for x in kwargs]):
|
if all([kwargs[x] is None for x in kwargs]):
|
||||||
@ -346,7 +382,8 @@ class RecipeSearch():
|
|||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(f_and)
|
self._queryset = self._queryset.filter(f_and)
|
||||||
if 'not' in kw_filter:
|
if 'not' in kw_filter:
|
||||||
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
|
self._queryset = self._queryset.exclude(
|
||||||
|
id__in=recipes.values('id'))
|
||||||
|
|
||||||
def food_filters(self, **kwargs):
|
def food_filters(self, **kwargs):
|
||||||
if all([kwargs[x] is None for x in kwargs]):
|
if all([kwargs[x] is None for x in kwargs]):
|
||||||
@ -360,7 +397,8 @@ class RecipeSearch():
|
|||||||
foods = Food.objects.filter(pk__in=kwargs[fd_filter])
|
foods = Food.objects.filter(pk__in=kwargs[fd_filter])
|
||||||
if 'or' in fd_filter:
|
if 'or' in fd_filter:
|
||||||
if self._include_children:
|
if self._include_children:
|
||||||
f_or = Q(steps__ingredients__food__in=Food.include_descendants(foods))
|
f_or = Q(
|
||||||
|
steps__ingredients__food__in=Food.include_descendants(foods))
|
||||||
else:
|
else:
|
||||||
f_or = Q(steps__ingredients__food__in=foods)
|
f_or = Q(steps__ingredients__food__in=foods)
|
||||||
|
|
||||||
@ -372,7 +410,8 @@ class RecipeSearch():
|
|||||||
recipes = Recipe.objects.all()
|
recipes = Recipe.objects.all()
|
||||||
for food in foods:
|
for food in foods:
|
||||||
if self._include_children:
|
if self._include_children:
|
||||||
f_and = Q(steps__ingredients__food__in=food.get_descendants_and_self())
|
f_and = Q(
|
||||||
|
steps__ingredients__food__in=food.get_descendants_and_self())
|
||||||
else:
|
else:
|
||||||
f_and = Q(steps__ingredients__food=food)
|
f_and = Q(steps__ingredients__food=food)
|
||||||
if 'not' in fd_filter:
|
if 'not' in fd_filter:
|
||||||
@ -380,7 +419,8 @@ class RecipeSearch():
|
|||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(f_and)
|
self._queryset = self._queryset.filter(f_and)
|
||||||
if 'not' in fd_filter:
|
if 'not' in fd_filter:
|
||||||
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
|
self._queryset = self._queryset.exclude(
|
||||||
|
id__in=recipes.values('id'))
|
||||||
|
|
||||||
def unit_filters(self, units=None, operator=True):
|
def unit_filters(self, units=None, operator=True):
|
||||||
if operator != True:
|
if operator != True:
|
||||||
@ -389,7 +429,8 @@ class RecipeSearch():
|
|||||||
return
|
return
|
||||||
if not isinstance(units, list):
|
if not isinstance(units, list):
|
||||||
units = [units]
|
units = [units]
|
||||||
self._queryset = self._queryset.filter(steps__ingredients__unit__in=units)
|
self._queryset = self._queryset.filter(
|
||||||
|
steps__ingredients__unit__in=units)
|
||||||
|
|
||||||
def rating_filter(self, rating=None):
|
def rating_filter(self, rating=None):
|
||||||
if rating or self._sort_includes('rating'):
|
if rating or self._sort_includes('rating'):
|
||||||
@ -399,14 +440,16 @@ class RecipeSearch():
|
|||||||
else:
|
else:
|
||||||
default = 0
|
default = 0
|
||||||
# TODO make ratings a settings user-only vs all-users
|
# TODO make ratings a settings user-only vs all-users
|
||||||
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
|
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(
|
||||||
|
cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
|
||||||
if rating is None:
|
if rating is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if rating == '0':
|
if rating == '0':
|
||||||
self._queryset = self._queryset.filter(rating=0)
|
self._queryset = self._queryset.filter(rating=0)
|
||||||
elif lessthan:
|
elif lessthan:
|
||||||
self._queryset = self._queryset.filter(rating__lte=int(rating[1:])).exclude(rating=0)
|
self._queryset = self._queryset.filter(
|
||||||
|
rating__lte=int(rating[1:])).exclude(rating=0)
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(rating__gte=int(rating))
|
self._queryset = self._queryset.filter(rating__gte=int(rating))
|
||||||
|
|
||||||
@ -434,11 +477,14 @@ class RecipeSearch():
|
|||||||
recipes = Recipe.objects.all()
|
recipes = Recipe.objects.all()
|
||||||
for book in kwargs[bk_filter]:
|
for book in kwargs[bk_filter]:
|
||||||
if 'not' in bk_filter:
|
if 'not' in bk_filter:
|
||||||
recipes = recipes.filter(recipebookentry__book__id=book)
|
recipes = recipes.filter(
|
||||||
|
recipebookentry__book__id=book)
|
||||||
else:
|
else:
|
||||||
self._queryset = self._queryset.filter(recipebookentry__book__id=book)
|
self._queryset = self._queryset.filter(
|
||||||
|
recipebookentry__book__id=book)
|
||||||
if 'not' in bk_filter:
|
if 'not' in bk_filter:
|
||||||
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
|
self._queryset = self._queryset.exclude(
|
||||||
|
id__in=recipes.values('id'))
|
||||||
|
|
||||||
def step_filters(self, steps=None, operator=True):
|
def step_filters(self, steps=None, operator=True):
|
||||||
if operator != True:
|
if operator != True:
|
||||||
@ -446,7 +492,7 @@ class RecipeSearch():
|
|||||||
if not steps:
|
if not steps:
|
||||||
return
|
return
|
||||||
if not isinstance(steps, list):
|
if not isinstance(steps, list):
|
||||||
steps = [unistepsts]
|
steps = [steps]
|
||||||
self._queryset = self._queryset.filter(steps__id__in=steps)
|
self._queryset = self._queryset.filter(steps__id__in=steps)
|
||||||
|
|
||||||
def build_fulltext_filters(self, string=None):
|
def build_fulltext_filters(self, string=None):
|
||||||
@ -457,20 +503,25 @@ class RecipeSearch():
|
|||||||
rank = []
|
rank = []
|
||||||
if 'name' in self._fulltext_include:
|
if 'name' in self._fulltext_include:
|
||||||
vectors.append('name_search_vector')
|
vectors.append('name_search_vector')
|
||||||
rank.append(SearchRank('name_search_vector', self.search_query, cover_density=True))
|
rank.append(SearchRank('name_search_vector',
|
||||||
|
self.search_query, cover_density=True))
|
||||||
if 'description' in self._fulltext_include:
|
if 'description' in self._fulltext_include:
|
||||||
vectors.append('desc_search_vector')
|
vectors.append('desc_search_vector')
|
||||||
rank.append(SearchRank('desc_search_vector', self.search_query, cover_density=True))
|
rank.append(SearchRank('desc_search_vector',
|
||||||
|
self.search_query, cover_density=True))
|
||||||
if 'steps__instruction' in self._fulltext_include:
|
if 'steps__instruction' in self._fulltext_include:
|
||||||
vectors.append('steps__search_vector')
|
vectors.append('steps__search_vector')
|
||||||
rank.append(SearchRank('steps__search_vector', self.search_query, cover_density=True))
|
rank.append(SearchRank('steps__search_vector',
|
||||||
|
self.search_query, cover_density=True))
|
||||||
if 'keywords__name' in self._fulltext_include:
|
if 'keywords__name' in self._fulltext_include:
|
||||||
# explicitly settings unaccent on keywords and foods so that they behave the same as search_vector fields
|
# explicitly settings unaccent on keywords and foods so that they behave the same as search_vector fields
|
||||||
vectors.append('keywords__name__unaccent')
|
vectors.append('keywords__name__unaccent')
|
||||||
rank.append(SearchRank('keywords__name__unaccent', self.search_query, cover_density=True))
|
rank.append(SearchRank('keywords__name__unaccent',
|
||||||
|
self.search_query, cover_density=True))
|
||||||
if 'steps__ingredients__food__name' in self._fulltext_include:
|
if 'steps__ingredients__food__name' in self._fulltext_include:
|
||||||
vectors.append('steps__ingredients__food__name__unaccent')
|
vectors.append('steps__ingredients__food__name__unaccent')
|
||||||
rank.append(SearchRank('steps__ingredients__food__name', self.search_query, cover_density=True))
|
rank.append(SearchRank('steps__ingredients__food__name',
|
||||||
|
self.search_query, cover_density=True))
|
||||||
|
|
||||||
for r in rank:
|
for r in rank:
|
||||||
if self.search_rank is None:
|
if self.search_rank is None:
|
||||||
@ -478,7 +529,8 @@ class RecipeSearch():
|
|||||||
else:
|
else:
|
||||||
self.search_rank += r
|
self.search_rank += r
|
||||||
# modifying queryset will annotation creates duplicate results
|
# modifying queryset will annotation creates duplicate results
|
||||||
self._filters.append(Q(id__in=Recipe.objects.annotate(vector=SearchVector(*vectors)).filter(Q(vector=self.search_query))))
|
self._filters.append(Q(id__in=Recipe.objects.annotate(
|
||||||
|
vector=SearchVector(*vectors)).filter(Q(vector=self.search_query))))
|
||||||
|
|
||||||
def build_text_filters(self, string=None):
|
def build_text_filters(self, string=None):
|
||||||
if not string:
|
if not string:
|
||||||
@ -510,23 +562,30 @@ class RecipeSearch():
|
|||||||
def _makenow_filter(self, missing=None):
|
def _makenow_filter(self, missing=None):
|
||||||
if missing is None or (type(missing) == bool and missing == False):
|
if missing is None or (type(missing) == bool and missing == False):
|
||||||
return
|
return
|
||||||
shopping_users = [*self._request.user.get_shopping_share(), self._request.user]
|
shopping_users = [
|
||||||
|
*self._request.user.get_shopping_share(), self._request.user]
|
||||||
|
|
||||||
onhand_filter = (
|
onhand_filter = (
|
||||||
Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand
|
Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand
|
||||||
| Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users) # or substitute food onhand
|
# or substitute food onhand
|
||||||
|
| Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users)
|
||||||
| Q(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users))
|
| Q(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users))
|
||||||
| Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users))
|
| Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users))
|
||||||
)
|
)
|
||||||
makenow_recipes = Recipe.objects.annotate(
|
makenow_recipes = Recipe.objects.annotate(
|
||||||
count_food=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__isnull=False), distinct=True),
|
count_food=Count('steps__ingredients__food__pk', filter=Q(
|
||||||
count_onhand=Count('steps__ingredients__food__pk', filter=onhand_filter, distinct=True),
|
steps__ingredients__food__isnull=False), distinct=True),
|
||||||
|
count_onhand=Count('steps__ingredients__food__pk',
|
||||||
|
filter=onhand_filter, distinct=True),
|
||||||
count_ignore_shopping=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__ignore_shopping=True,
|
count_ignore_shopping=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__ignore_shopping=True,
|
||||||
steps__ingredients__food__recipe__isnull=True), distinct=True),
|
steps__ingredients__food__recipe__isnull=True), distinct=True),
|
||||||
has_child_sub=Case(When(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users), then=Value(1)), default=Value(0)),
|
has_child_sub=Case(When(steps__ingredients__food__in=self.__children_substitute_filter(
|
||||||
has_sibling_sub=Case(When(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users), then=Value(1)), default=Value(0))
|
shopping_users), then=Value(1)), default=Value(0)),
|
||||||
|
has_sibling_sub=Case(When(steps__ingredients__food__in=self.__sibling_substitute_filter(
|
||||||
|
shopping_users), then=Value(1)), default=Value(0))
|
||||||
).annotate(missingfood=F('count_food') - F('count_onhand') - F('count_ignore_shopping')).filter(missingfood=missing)
|
).annotate(missingfood=F('count_food') - F('count_onhand') - F('count_ignore_shopping')).filter(missingfood=missing)
|
||||||
self._queryset = self._queryset.distinct().filter(id__in=makenow_recipes.values('id'))
|
self._queryset = self._queryset.distinct().filter(
|
||||||
|
id__in=makenow_recipes.values('id'))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __children_substitute_filter(shopping_users=None):
|
def __children_substitute_filter(shopping_users=None):
|
||||||
@ -547,7 +606,8 @@ class RecipeSearch():
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def __sibling_substitute_filter(shopping_users=None):
|
def __sibling_substitute_filter(shopping_users=None):
|
||||||
sibling_onhand_subquery = Food.objects.filter(
|
sibling_onhand_subquery = Food.objects.filter(
|
||||||
path__startswith=Substr(OuterRef('path'), 1, Food.steplen * (OuterRef('depth') - 1)),
|
path__startswith=Substr(
|
||||||
|
OuterRef('path'), 1, Food.steplen * (OuterRef('depth') - 1)),
|
||||||
depth=OuterRef('depth'),
|
depth=OuterRef('depth'),
|
||||||
onhand_users__in=shopping_users
|
onhand_users__in=shopping_users
|
||||||
)
|
)
|
||||||
@ -586,7 +646,8 @@ class RecipeFacet():
|
|||||||
self.Recent = self._cache.get('Recent', None)
|
self.Recent = self._cache.get('Recent', None)
|
||||||
|
|
||||||
if self._queryset is not None:
|
if self._queryset is not None:
|
||||||
self._recipe_list = list(self._queryset.values_list('id', flat=True))
|
self._recipe_list = list(
|
||||||
|
self._queryset.values_list('id', flat=True))
|
||||||
self._search_params = {
|
self._search_params = {
|
||||||
'keyword_list': self._request.query_params.getlist('keywords', []),
|
'keyword_list': self._request.query_params.getlist('keywords', []),
|
||||||
'food_list': self._request.query_params.getlist('foods', []),
|
'food_list': self._request.query_params.getlist('foods', []),
|
||||||
@ -618,7 +679,8 @@ class RecipeFacet():
|
|||||||
'Books': self.Books
|
'Books': self.Books
|
||||||
|
|
||||||
}
|
}
|
||||||
caches['default'].set(self._SEARCH_CACHE_KEY, self._cache, self._cache_timeout)
|
caches['default'].set(self._SEARCH_CACHE_KEY,
|
||||||
|
self._cache, self._cache_timeout)
|
||||||
|
|
||||||
def get_facets(self, from_cache=False):
|
def get_facets(self, from_cache=False):
|
||||||
if from_cache:
|
if from_cache:
|
||||||
@ -655,13 +717,16 @@ class RecipeFacet():
|
|||||||
def get_keywords(self):
|
def get_keywords(self):
|
||||||
if self.Keywords is None:
|
if self.Keywords is None:
|
||||||
if self._search_params['search_keywords_or']:
|
if self._search_params['search_keywords_or']:
|
||||||
keywords = Keyword.objects.filter(space=self._request.space).distinct()
|
keywords = Keyword.objects.filter(
|
||||||
|
space=self._request.space).distinct()
|
||||||
else:
|
else:
|
||||||
keywords = Keyword.objects.filter(Q(recipe__in=self._recipe_list) | Q(depth=1)).filter(space=self._request.space).distinct()
|
keywords = Keyword.objects.filter(Q(recipe__in=self._recipe_list) | Q(
|
||||||
|
depth=1)).filter(space=self._request.space).distinct()
|
||||||
|
|
||||||
# set keywords to root objects only
|
# set keywords to root objects only
|
||||||
keywords = self._keyword_queryset(keywords)
|
keywords = self._keyword_queryset(keywords)
|
||||||
self.Keywords = [{**x, 'children': None} if x['numchild'] > 0 else x for x in list(keywords)]
|
self.Keywords = [{**x, 'children': None}
|
||||||
|
if x['numchild'] > 0 else x for x in list(keywords)]
|
||||||
self.set_cache('Keywords', self.Keywords)
|
self.set_cache('Keywords', self.Keywords)
|
||||||
return self.Keywords
|
return self.Keywords
|
||||||
|
|
||||||
@ -669,28 +734,28 @@ class RecipeFacet():
|
|||||||
if self.Foods is None:
|
if self.Foods is None:
|
||||||
# # if using an OR search, will annotate all keywords, otherwise, just those that appear in results
|
# # if using an OR search, will annotate all keywords, otherwise, just those that appear in results
|
||||||
if self._search_params['search_foods_or']:
|
if self._search_params['search_foods_or']:
|
||||||
foods = Food.objects.filter(space=self._request.space).distinct()
|
foods = Food.objects.filter(
|
||||||
|
space=self._request.space).distinct()
|
||||||
else:
|
else:
|
||||||
foods = Food.objects.filter(Q(ingredient__step__recipe__in=self._recipe_list) | Q(depth=1)).filter(space=self._request.space).distinct()
|
foods = Food.objects.filter(Q(ingredient__step__recipe__in=self._recipe_list) | Q(
|
||||||
|
depth=1)).filter(space=self._request.space).distinct()
|
||||||
|
|
||||||
# set keywords to root objects only
|
# set keywords to root objects only
|
||||||
foods = self._food_queryset(foods)
|
foods = self._food_queryset(foods)
|
||||||
|
|
||||||
self.Foods = [{**x, 'children': None} if x['numchild'] > 0 else x for x in list(foods)]
|
self.Foods = [{**x, 'children': None}
|
||||||
|
if x['numchild'] > 0 else x for x in list(foods)]
|
||||||
self.set_cache('Foods', self.Foods)
|
self.set_cache('Foods', self.Foods)
|
||||||
return self.Foods
|
return self.Foods
|
||||||
|
|
||||||
def get_books(self):
|
|
||||||
if self.Books is None:
|
|
||||||
self.Books = []
|
|
||||||
return self.Books
|
|
||||||
|
|
||||||
def get_ratings(self):
|
def get_ratings(self):
|
||||||
if self.Ratings is None:
|
if self.Ratings is None:
|
||||||
if not self._request.space.demo and self._request.space.show_facet_count:
|
if not self._request.space.demo and self._request.space.show_facet_count:
|
||||||
if self._queryset is None:
|
if self._queryset is None:
|
||||||
self._queryset = Recipe.objects.filter(id__in=self._recipe_list)
|
self._queryset = Recipe.objects.filter(
|
||||||
rating_qs = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then='cooklog__rating'), default=Value(0)))))
|
id__in=self._recipe_list)
|
||||||
|
rating_qs = self._queryset.annotate(rating=Round(Avg(Case(When(
|
||||||
|
cooklog__created_by=self._request.user, then='cooklog__rating'), default=Value(0)))))
|
||||||
self.Ratings = dict(Counter(r.rating for r in rating_qs))
|
self.Ratings = dict(Counter(r.rating for r in rating_qs))
|
||||||
else:
|
else:
|
||||||
self.Rating = {}
|
self.Rating = {}
|
||||||
@ -715,10 +780,13 @@ class RecipeFacet():
|
|||||||
foods = self._food_queryset(food.get_children(), food)
|
foods = self._food_queryset(food.get_children(), food)
|
||||||
deep_search = self.Foods
|
deep_search = self.Foods
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
index = next((i for i, x in enumerate(deep_search) if x["id"] == node.id), None)
|
index = next((i for i, x in enumerate(
|
||||||
|
deep_search) if x["id"] == node.id), None)
|
||||||
deep_search = deep_search[index]['children']
|
deep_search = deep_search[index]['children']
|
||||||
index = next((i for i, x in enumerate(deep_search) if x["id"] == food.id), None)
|
index = next((i for i, x in enumerate(
|
||||||
deep_search[index]['children'] = [{**x, 'children': None} if x['numchild'] > 0 else x for x in list(foods)]
|
deep_search) if x["id"] == food.id), None)
|
||||||
|
deep_search[index]['children'] = [
|
||||||
|
{**x, 'children': None} if x['numchild'] > 0 else x for x in list(foods)]
|
||||||
self.set_cache('Foods', self.Foods)
|
self.set_cache('Foods', self.Foods)
|
||||||
return self.get_facets()
|
return self.get_facets()
|
||||||
|
|
||||||
@ -731,10 +799,13 @@ class RecipeFacet():
|
|||||||
keywords = self._keyword_queryset(keyword.get_children(), keyword)
|
keywords = self._keyword_queryset(keyword.get_children(), keyword)
|
||||||
deep_search = self.Keywords
|
deep_search = self.Keywords
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
index = next((i for i, x in enumerate(deep_search) if x["id"] == node.id), None)
|
index = next((i for i, x in enumerate(
|
||||||
|
deep_search) if x["id"] == node.id), None)
|
||||||
deep_search = deep_search[index]['children']
|
deep_search = deep_search[index]['children']
|
||||||
index = next((i for i, x in enumerate(deep_search) if x["id"] == keyword.id), None)
|
index = next((i for i, x in enumerate(deep_search)
|
||||||
deep_search[index]['children'] = [{**x, 'children': None} if x['numchild'] > 0 else x for x in list(keywords)]
|
if x["id"] == keyword.id), None)
|
||||||
|
deep_search[index]['children'] = [
|
||||||
|
{**x, 'children': None} if x['numchild'] > 0 else x for x in list(keywords)]
|
||||||
self.set_cache('Keywords', self.Keywords)
|
self.set_cache('Keywords', self.Keywords)
|
||||||
return self.get_facets()
|
return self.get_facets()
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import random
|
# import random
|
||||||
import re
|
import re
|
||||||
from html import unescape
|
from html import unescape
|
||||||
from unicodedata import decomposition
|
|
||||||
|
|
||||||
|
from django.core.cache import caches
|
||||||
from django.utils.dateparse import parse_duration
|
from django.utils.dateparse import parse_duration
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from isodate import parse_duration as iso_parse_duration
|
from isodate import parse_duration as iso_parse_duration
|
||||||
@ -10,9 +10,11 @@ from isodate.isoerror import ISO8601Error
|
|||||||
from pytube import YouTube
|
from pytube import YouTube
|
||||||
from recipe_scrapers._utils import get_host_name, get_minutes
|
from recipe_scrapers._utils import get_host_name, get_minutes
|
||||||
|
|
||||||
from cookbook.helper import recipe_url_import as helper
|
# from cookbook.helper import recipe_url_import as helper
|
||||||
from cookbook.helper.ingredient_parser import IngredientParser
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.models import Keyword, Automation
|
from cookbook.models import Automation, Keyword
|
||||||
|
|
||||||
|
# from unicodedata import decomposition
|
||||||
|
|
||||||
|
|
||||||
# from recipe_scrapers._utils import get_minutes ## temporary until/unless upstream incorporates get_minutes() PR
|
# from recipe_scrapers._utils import get_minutes ## temporary until/unless upstream incorporates get_minutes() PR
|
||||||
@ -127,7 +129,7 @@ def get_from_scraper(scrape, request):
|
|||||||
try:
|
try:
|
||||||
if scrape.author():
|
if scrape.author():
|
||||||
keywords.append(scrape.author())
|
keywords.append(scrape.author())
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -367,10 +369,28 @@ def parse_time(recipe_time):
|
|||||||
|
|
||||||
def parse_keywords(keyword_json, space):
|
def parse_keywords(keyword_json, space):
|
||||||
keywords = []
|
keywords = []
|
||||||
|
keyword_aliases = {}
|
||||||
|
# retrieve keyword automation cache if it exists, otherwise build from database
|
||||||
|
KEYWORD_CACHE_KEY = f'automation_keyword_alias_{space.pk}'
|
||||||
|
if c := caches['default'].get(KEYWORD_CACHE_KEY, None):
|
||||||
|
self.food_aliases = c
|
||||||
|
caches['default'].touch(KEYWORD_CACHE_KEY, 30)
|
||||||
|
else:
|
||||||
|
for a in Automation.objects.filter(space=space, disabled=False, type=Automation.KEYWORD_ALIAS).only('param_1', 'param_2').order_by('order').all():
|
||||||
|
keyword_aliases[a.param_1] = a.param_2
|
||||||
|
caches['default'].set(KEYWORD_CACHE_KEY, keyword_aliases, 30)
|
||||||
|
|
||||||
# keywords as list
|
# keywords as list
|
||||||
for kw in keyword_json:
|
for kw in keyword_json:
|
||||||
kw = normalize_string(kw)
|
kw = normalize_string(kw)
|
||||||
|
# if alias exists use that instead
|
||||||
|
|
||||||
if len(kw) != 0:
|
if len(kw) != 0:
|
||||||
|
if keyword_aliases:
|
||||||
|
try:
|
||||||
|
kw = keyword_aliases[kw]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
if k := Keyword.objects.filter(name=kw, space=space).first():
|
if k := Keyword.objects.filter(name=kw, space=space).first():
|
||||||
keywords.append({'label': str(k), 'name': k.name, 'id': k.id})
|
keywords.append({'label': str(k), 'name': k.name, 'id': k.id})
|
||||||
else:
|
else:
|
||||||
|
Binary file not shown.
@ -8,8 +8,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
||||||
"PO-Revision-Date: 2022-05-10 15:32+0000\n"
|
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
|
||||||
"Last-Translator: zeon <zeonbg@gmail.com>\n"
|
"Last-Translator: noxonad <noxonad@proton.me>\n"
|
||||||
"Language-Team: Bulgarian <http://translate.tandoor.dev/projects/tandoor/"
|
"Language-Team: Bulgarian <http://translate.tandoor.dev/projects/tandoor/"
|
||||||
"recipes-backend/bg/>\n"
|
"recipes-backend/bg/>\n"
|
||||||
"Language: bg\n"
|
"Language: bg\n"
|
||||||
@ -17,7 +17,7 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
"X-Generator: Weblate 4.10.1\n"
|
"X-Generator: Weblate 4.15\n"
|
||||||
|
|
||||||
#: .\cookbook\filters.py:23 .\cookbook\templates\forms\ingredients.html:34
|
#: .\cookbook\filters.py:23 .\cookbook\templates\forms\ingredients.html:34
|
||||||
#: .\cookbook\templates\space.html:49 .\cookbook\templates\stats.html:28
|
#: .\cookbook\templates\space.html:49 .\cookbook\templates\stats.html:28
|
||||||
@ -1433,7 +1433,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\index.html:29
|
#: .\cookbook\templates\index.html:29
|
||||||
msgid "Search recipe ..."
|
msgid "Search recipe ..."
|
||||||
msgstr "Търсете рецепта..."
|
msgstr "Търсете рецепта ..."
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:44
|
#: .\cookbook\templates\index.html:44
|
||||||
msgid "New Recipe"
|
msgid "New Recipe"
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -8,8 +8,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
||||||
"PO-Revision-Date: 2023-03-06 10:55+0000\n"
|
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
|
||||||
"Last-Translator: Anders Obro <oebro@duck.com>\n"
|
"Last-Translator: noxonad <noxonad@proton.me>\n"
|
||||||
"Language-Team: Danish <http://translate.tandoor.dev/projects/tandoor/"
|
"Language-Team: Danish <http://translate.tandoor.dev/projects/tandoor/"
|
||||||
"recipes-backend/da/>\n"
|
"recipes-backend/da/>\n"
|
||||||
"Language: da\n"
|
"Language: da\n"
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -8,8 +8,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-04-11 15:09+0200\n"
|
"POT-Creation-Date: 2021-04-11 15:09+0200\n"
|
||||||
"PO-Revision-Date: 2021-04-11 15:23+0000\n"
|
"PO-Revision-Date: 2023-04-17 20:55+0000\n"
|
||||||
"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
|
"Last-Translator: Espen Sellevåg <buskmenn.drammer03@icloud.com>\n"
|
||||||
"Language-Team: Norwegian Bokmål <http://translate.tandoor.dev/projects/"
|
"Language-Team: Norwegian Bokmål <http://translate.tandoor.dev/projects/"
|
||||||
"tandoor/recipes-backend/nb_NO/>\n"
|
"tandoor/recipes-backend/nb_NO/>\n"
|
||||||
"Language: nb_NO\n"
|
"Language: nb_NO\n"
|
||||||
@ -17,7 +17,7 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
"X-Generator: Weblate 4.5.3\n"
|
"X-Generator: Weblate 4.15\n"
|
||||||
|
|
||||||
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:91
|
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:91
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:219
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:219
|
||||||
@ -34,19 +34,23 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\forms.py:46
|
#: .\cookbook\forms.py:46
|
||||||
msgid "Default Unit to be used when inserting a new ingredient into a recipe."
|
msgid "Default Unit to be used when inserting a new ingredient into a recipe."
|
||||||
msgstr ""
|
msgstr "Standard enhet når ny ingrediens legges til en oppskrift."
|
||||||
|
|
||||||
#: .\cookbook\forms.py:47
|
#: .\cookbook\forms.py:47
|
||||||
msgid ""
|
msgid ""
|
||||||
"Enables support for fractions in ingredient amounts (e.g. convert decimals "
|
"Enables support for fractions in ingredient amounts (e.g. convert decimals "
|
||||||
"to fractions automatically)"
|
"to fractions automatically)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Aktiverer støtte for deler av ingrediensmengde (konverterer feks. desimaler "
|
||||||
|
"til deler automatisk)"
|
||||||
|
|
||||||
#: .\cookbook\forms.py:48
|
#: .\cookbook\forms.py:48
|
||||||
msgid ""
|
msgid ""
|
||||||
"Users with whom newly created meal plan/shopping list entries should be "
|
"Users with whom newly created meal plan/shopping list entries should be "
|
||||||
"shared by default."
|
"shared by default."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Brukere som oppretter nye måltidsplaner/handlelister, deler disse "
|
||||||
|
"oppføringene som standard."
|
||||||
|
|
||||||
#: .\cookbook\forms.py:49
|
#: .\cookbook\forms.py:49
|
||||||
msgid "Show recently viewed recipes on search page."
|
msgid "Show recently viewed recipes on search page."
|
||||||
@ -58,7 +62,7 @@ msgstr "Antall desimaler ingredienser skal avrundes til."
|
|||||||
|
|
||||||
#: .\cookbook\forms.py:51
|
#: .\cookbook\forms.py:51
|
||||||
msgid "If you want to be able to create and see comments underneath recipes."
|
msgid "If you want to be able to create and see comments underneath recipes."
|
||||||
msgstr ""
|
msgstr "Hvis du ønsker å opprette og se kommentarer under oppskrifter."
|
||||||
|
|
||||||
#: .\cookbook\forms.py:53
|
#: .\cookbook\forms.py:53
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -67,6 +71,11 @@ msgid ""
|
|||||||
"Useful when shopping with multiple people but might use a little bit of "
|
"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."
|
"mobile data. If lower than instance limit it is reset when saving."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"0 vil deaktivere automatisk synkronisering. Når en handleliste vises, "
|
||||||
|
"oppdateres listen med oppgitt antall sekunders mellomrom for å synkronisere "
|
||||||
|
"endringer fra andre brukere. Nyttig dersom flere brukere handler samtidig. "
|
||||||
|
"Datatrafikk oppstår når aktiv. Hvis verdien er lavere enn grensen, "
|
||||||
|
"tilbakestilles den ved lagring."
|
||||||
|
|
||||||
#: .\cookbook\forms.py:56
|
#: .\cookbook\forms.py:56
|
||||||
msgid "Makes the navbar stick to the top of the page."
|
msgid "Makes the navbar stick to the top of the page."
|
||||||
@ -100,11 +109,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\forms.py:97 .\cookbook\forms.py:317
|
#: .\cookbook\forms.py:97 .\cookbook\forms.py:317
|
||||||
msgid "Path"
|
msgid "Path"
|
||||||
msgstr ""
|
msgstr "Sti"
|
||||||
|
|
||||||
#: .\cookbook\forms.py:98
|
#: .\cookbook\forms.py:98
|
||||||
msgid "Storage UID"
|
msgid "Storage UID"
|
||||||
msgstr ""
|
msgstr "Lagring UID"
|
||||||
|
|
||||||
#: .\cookbook\forms.py:121
|
#: .\cookbook\forms.py:121
|
||||||
msgid "Default"
|
msgid "Default"
|
||||||
@ -129,7 +138,6 @@ msgid "Old Unit"
|
|||||||
msgstr "Gammel enhet"
|
msgstr "Gammel enhet"
|
||||||
|
|
||||||
#: .\cookbook\forms.py:156
|
#: .\cookbook\forms.py:156
|
||||||
#, fuzzy
|
|
||||||
msgid "Unit that should be replaced."
|
msgid "Unit that should be replaced."
|
||||||
msgstr "Enhet som skal erstattes."
|
msgstr "Enhet som skal erstattes."
|
||||||
|
|
||||||
@ -204,12 +212,11 @@ msgstr ""
|
|||||||
#: .\cookbook\views\views.py:112 .\cookbook\views\views.py:116
|
#: .\cookbook\views\views.py:112 .\cookbook\views\views.py:116
|
||||||
#: .\cookbook\views\views.py:184
|
#: .\cookbook\views\views.py:184
|
||||||
msgid "You do not have the required permissions to view this page!"
|
msgid "You do not have the required permissions to view this page!"
|
||||||
msgstr "Du har ikke påkrevd tilgang for å vise denne siden."
|
msgstr "Du har ikke påkrevd tilgang for å vise denne siden!"
|
||||||
|
|
||||||
#: .\cookbook\helper\permission_helper.py:141
|
#: .\cookbook\helper\permission_helper.py:141
|
||||||
#, fuzzy
|
|
||||||
msgid "You are not logged in and therefore cannot view this page!"
|
msgid "You are not logged in and therefore cannot view this page!"
|
||||||
msgstr "Du er ikke innlogget og kan derfor ikke vise siden."
|
msgstr "Du er ikke innlogget og kan derfor ikke vise siden!"
|
||||||
|
|
||||||
#: .\cookbook\helper\permission_helper.py:145
|
#: .\cookbook\helper\permission_helper.py:145
|
||||||
#: .\cookbook\helper\permission_helper.py:167
|
#: .\cookbook\helper\permission_helper.py:167
|
||||||
@ -379,7 +386,7 @@ msgstr "Finner ikke siden du leter etter."
|
|||||||
|
|
||||||
#: .\cookbook\templates\404.html:33
|
#: .\cookbook\templates\404.html:33
|
||||||
msgid "Take me Home"
|
msgid "Take me Home"
|
||||||
msgstr ""
|
msgstr "Tilbake til Startsiden"
|
||||||
|
|
||||||
#: .\cookbook\templates\404.html:35
|
#: .\cookbook\templates\404.html:35
|
||||||
msgid "Report a Bug"
|
msgid "Report a Bug"
|
||||||
@ -388,12 +395,12 @@ msgstr "Rapporter en feil"
|
|||||||
#: .\cookbook\templates\account\login.html:7
|
#: .\cookbook\templates\account\login.html:7
|
||||||
#: .\cookbook\templates\base.html:170
|
#: .\cookbook\templates\base.html:170
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr ""
|
msgstr "Logg inn"
|
||||||
|
|
||||||
#: .\cookbook\templates\account\login.html:13
|
#: .\cookbook\templates\account\login.html:13
|
||||||
#: .\cookbook\templates\account\login.html:28
|
#: .\cookbook\templates\account\login.html:28
|
||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
msgstr ""
|
msgstr "Opprett bruker"
|
||||||
|
|
||||||
#: .\cookbook\templates\account\login.html:38
|
#: .\cookbook\templates\account\login.html:38
|
||||||
msgid "Social Login"
|
msgid "Social Login"
|
||||||
@ -401,7 +408,7 @@ msgstr "Sosial innlogging"
|
|||||||
|
|
||||||
#: .\cookbook\templates\account\login.html:39
|
#: .\cookbook\templates\account\login.html:39
|
||||||
msgid "You can use any of the following providers to sign in."
|
msgid "You can use any of the following providers to sign in."
|
||||||
msgstr ""
|
msgstr "Velg en av følgende leverandører for å logge på."
|
||||||
|
|
||||||
#: .\cookbook\templates\account\logout.html:5
|
#: .\cookbook\templates\account\logout.html:5
|
||||||
#: .\cookbook\templates\account\logout.html:9
|
#: .\cookbook\templates\account\logout.html:9
|
||||||
@ -416,20 +423,20 @@ msgstr "Er du sikker på at du vil logge ut?"
|
|||||||
#: .\cookbook\templates\account\password_reset.html:5
|
#: .\cookbook\templates\account\password_reset.html:5
|
||||||
#: .\cookbook\templates\account\password_reset_done.html:5
|
#: .\cookbook\templates\account\password_reset_done.html:5
|
||||||
msgid "Password Reset"
|
msgid "Password Reset"
|
||||||
msgstr ""
|
msgstr "Nullstill passord"
|
||||||
|
|
||||||
#: .\cookbook\templates\account\password_reset.html:9
|
#: .\cookbook\templates\account\password_reset.html:9
|
||||||
#: .\cookbook\templates\account\password_reset_done.html:9
|
#: .\cookbook\templates\account\password_reset_done.html:9
|
||||||
msgid "Password reset is not implemented for the time being!"
|
msgid "Password reset is not implemented for the time being!"
|
||||||
msgstr ""
|
msgstr "Det er foreløpig ikke implementert funksjon for å nullstille passord!"
|
||||||
|
|
||||||
#: .\cookbook\templates\account\signup.html:5
|
#: .\cookbook\templates\account\signup.html:5
|
||||||
msgid "Register"
|
msgid "Register"
|
||||||
msgstr ""
|
msgstr "Registrer"
|
||||||
|
|
||||||
#: .\cookbook\templates\account\signup.html:9
|
#: .\cookbook\templates\account\signup.html:9
|
||||||
msgid "Create your Account"
|
msgid "Create your Account"
|
||||||
msgstr "Opprett din konto"
|
msgstr "Opprett konto"
|
||||||
|
|
||||||
#: .\cookbook\templates\account\signup.html:14
|
#: .\cookbook\templates\account\signup.html:14
|
||||||
msgid "Create User"
|
msgid "Create User"
|
||||||
@ -442,11 +449,11 @@ msgstr "API-dokumentasjon"
|
|||||||
|
|
||||||
#: .\cookbook\templates\base.html:78
|
#: .\cookbook\templates\base.html:78
|
||||||
msgid "Utensils"
|
msgid "Utensils"
|
||||||
msgstr ""
|
msgstr "Redskaper"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:88
|
#: .\cookbook\templates\base.html:88
|
||||||
msgid "Shopping"
|
msgid "Shopping"
|
||||||
msgstr ""
|
msgstr "Handle"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:102 .\cookbook\views\delete.py:84
|
#: .\cookbook\templates\base.html:102 .\cookbook\views\delete.py:84
|
||||||
#: .\cookbook\views\edit.py:93 .\cookbook\views\lists.py:26
|
#: .\cookbook\views\edit.py:93 .\cookbook\views\lists.py:26
|
||||||
@ -456,27 +463,27 @@ msgstr "Nøkkelord"
|
|||||||
|
|
||||||
#: .\cookbook\templates\base.html:104
|
#: .\cookbook\templates\base.html:104
|
||||||
msgid "Batch Edit"
|
msgid "Batch Edit"
|
||||||
msgstr ""
|
msgstr "Oppdatere flere"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:109
|
#: .\cookbook\templates\base.html:109
|
||||||
msgid "Storage Data"
|
msgid "Storage Data"
|
||||||
msgstr ""
|
msgstr "Datalagring"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:113
|
#: .\cookbook\templates\base.html:113
|
||||||
msgid "Storage Backends"
|
msgid "Storage Backends"
|
||||||
msgstr ""
|
msgstr "Lagringsplasser"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:115
|
#: .\cookbook\templates\base.html:115
|
||||||
msgid "Configure Sync"
|
msgid "Configure Sync"
|
||||||
msgstr ""
|
msgstr "Konfigurer synkronisering"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:117
|
#: .\cookbook\templates\base.html:117
|
||||||
msgid "Discovered Recipes"
|
msgid "Discovered Recipes"
|
||||||
msgstr ""
|
msgstr "Oppdagede oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:119
|
#: .\cookbook\templates\base.html:119
|
||||||
msgid "Discovery Log"
|
msgid "Discovery Log"
|
||||||
msgstr ""
|
msgstr "Logg Oppdagelser"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:121 .\cookbook\templates\stats.html:10
|
#: .\cookbook\templates\base.html:121 .\cookbook\templates\stats.html:10
|
||||||
msgid "Statistics"
|
msgid "Statistics"
|
||||||
@ -484,7 +491,7 @@ msgstr "Statistikk"
|
|||||||
|
|
||||||
#: .\cookbook\templates\base.html:123
|
#: .\cookbook\templates\base.html:123
|
||||||
msgid "Units & Ingredients"
|
msgid "Units & Ingredients"
|
||||||
msgstr ""
|
msgstr "Enheter & Ingredienser"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:125
|
#: .\cookbook\templates\base.html:125
|
||||||
msgid "Import Recipe"
|
msgid "Import Recipe"
|
||||||
@ -521,58 +528,61 @@ msgid "API Browser"
|
|||||||
msgstr "API-utforsker"
|
msgstr "API-utforsker"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:165
|
#: .\cookbook\templates\base.html:165
|
||||||
#, fuzzy
|
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Logg ut"
|
msgstr "Logg ut"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\edit.html:6
|
#: .\cookbook\templates\batch\edit.html:6
|
||||||
msgid "Batch edit Category"
|
msgid "Batch edit Category"
|
||||||
msgstr ""
|
msgstr "Oppdater flere kategorier"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\edit.html:15
|
#: .\cookbook\templates\batch\edit.html:15
|
||||||
msgid "Batch edit Recipes"
|
msgid "Batch edit Recipes"
|
||||||
msgstr ""
|
msgstr "Oppdater flere oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\edit.html:20
|
#: .\cookbook\templates\batch\edit.html:20
|
||||||
msgid "Add the specified keywords to all recipes containing a word"
|
msgid "Add the specified keywords to all recipes containing a word"
|
||||||
msgstr ""
|
msgstr "Legg til spesifikt nøkkelord til alle oppskrifter som inneholder et ord"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:76
|
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:76
|
||||||
msgid "Sync"
|
msgid "Sync"
|
||||||
msgstr ""
|
msgstr "Synkronisering"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\monitor.html:10
|
#: .\cookbook\templates\batch\monitor.html:10
|
||||||
msgid "Manage watched Folders"
|
msgid "Manage watched Folders"
|
||||||
msgstr ""
|
msgstr "Behandle overvåkede mapper"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\monitor.html:14
|
#: .\cookbook\templates\batch\monitor.html:14
|
||||||
msgid ""
|
msgid ""
|
||||||
"On this Page you can manage all storage folder locations that should be "
|
"On this Page you can manage all storage folder locations that should be "
|
||||||
"monitored and synced."
|
"monitored and synced."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Her kan du behandle alle lagringsmapper og plasseringer for monitorering og "
|
||||||
|
"synkronisering."
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\monitor.html:16
|
#: .\cookbook\templates\batch\monitor.html:16
|
||||||
msgid "The path must be in the following format"
|
msgid "The path must be in the following format"
|
||||||
msgstr ""
|
msgstr "Stien må være i følgende format"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\monitor.html:27
|
#: .\cookbook\templates\batch\monitor.html:27
|
||||||
msgid "Sync Now!"
|
msgid "Sync Now!"
|
||||||
msgstr ""
|
msgstr "Synkroniser nå!"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\waiting.html:4
|
#: .\cookbook\templates\batch\waiting.html:4
|
||||||
#: .\cookbook\templates\batch\waiting.html:10
|
#: .\cookbook\templates\batch\waiting.html:10
|
||||||
msgid "Importing Recipes"
|
msgid "Importing Recipes"
|
||||||
msgstr ""
|
msgstr "Importerer oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\batch\waiting.html:23
|
#: .\cookbook\templates\batch\waiting.html:23
|
||||||
msgid ""
|
msgid ""
|
||||||
"This can take a few minutes, depending on the number of recipes in sync, "
|
"This can take a few minutes, depending on the number of recipes in sync, "
|
||||||
"please wait."
|
"please wait."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Dette kan ta noen minutter, avhenging av antall oppskrifter som skal "
|
||||||
|
"synkroniseres. Vennligst vent."
|
||||||
|
|
||||||
#: .\cookbook\templates\books.html:5 .\cookbook\templates\books.html:11
|
#: .\cookbook\templates\books.html:5 .\cookbook\templates\books.html:11
|
||||||
msgid "Recipe Books"
|
msgid "Recipe Books"
|
||||||
msgstr ""
|
msgstr "Oppskriftsbøker"
|
||||||
|
|
||||||
#: .\cookbook\templates\books.html:15
|
#: .\cookbook\templates\books.html:15
|
||||||
msgid "New Book"
|
msgid "New Book"
|
||||||
@ -584,32 +594,32 @@ msgstr "av"
|
|||||||
|
|
||||||
#: .\cookbook\templates\books.html:34
|
#: .\cookbook\templates\books.html:34
|
||||||
msgid "Toggle Recipes"
|
msgid "Toggle Recipes"
|
||||||
msgstr ""
|
msgstr "Veksle oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\books.html:54
|
#: .\cookbook\templates\books.html:54
|
||||||
#: .\cookbook\templates\meal_plan_entry.html:48
|
#: .\cookbook\templates\meal_plan_entry.html:48
|
||||||
#: .\cookbook\templates\recipes_table.html:64
|
#: .\cookbook\templates\recipes_table.html:64
|
||||||
msgid "Last cooked"
|
msgid "Last cooked"
|
||||||
msgstr ""
|
msgstr "Forrige tilbereding"
|
||||||
|
|
||||||
#: .\cookbook\templates\books.html:71
|
#: .\cookbook\templates\books.html:71
|
||||||
msgid "There are no recipes in this book yet."
|
msgid "There are no recipes in this book yet."
|
||||||
msgstr ""
|
msgstr "Det er foreløpig ingen oppskrifter i denne boken."
|
||||||
|
|
||||||
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6
|
||||||
msgid "Export Recipes"
|
msgid "Export Recipes"
|
||||||
msgstr ""
|
msgstr "Eksporter oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\export.html:14 .\cookbook\templates\export.html:20
|
#: .\cookbook\templates\export.html:14 .\cookbook\templates\export.html:20
|
||||||
#: .\cookbook\templates\shopping_list.html:347
|
#: .\cookbook\templates\shopping_list.html:347
|
||||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||||
msgid "Export"
|
msgid "Export"
|
||||||
msgstr ""
|
msgstr "Eksporter"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_import_recipe.html:5
|
#: .\cookbook\templates\forms\edit_import_recipe.html:5
|
||||||
#: .\cookbook\templates\forms\edit_import_recipe.html:9
|
#: .\cookbook\templates\forms\edit_import_recipe.html:9
|
||||||
msgid "Import new Recipe"
|
msgid "Import new Recipe"
|
||||||
msgstr ""
|
msgstr "Importer ny oppskrift"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:389
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:389
|
||||||
@ -635,29 +645,29 @@ msgstr "Beskrivelse"
|
|||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:72
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:72
|
||||||
msgid "Waiting Time"
|
msgid "Waiting Time"
|
||||||
msgstr ""
|
msgstr "Ventetid"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:78
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:78
|
||||||
msgid "Servings Text"
|
msgid "Servings Text"
|
||||||
msgstr ""
|
msgstr "Porsjon beskrivelse"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:89
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:89
|
||||||
msgid "Select Keywords"
|
msgid "Select Keywords"
|
||||||
msgstr ""
|
msgstr "Velg nøkkelord"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:90
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:90
|
||||||
#: .\cookbook\templates\url_import.html:212
|
#: .\cookbook\templates\url_import.html:212
|
||||||
msgid "Add Keyword"
|
msgid "Add Keyword"
|
||||||
msgstr ""
|
msgstr "Legg til nøkkelord"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:108
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:108
|
||||||
msgid "Nutrition"
|
msgid "Nutrition"
|
||||||
msgstr ""
|
msgstr "Næringsinnhold"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:112
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:112
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:162
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:162
|
||||||
msgid "Delete Step"
|
msgid "Delete Step"
|
||||||
msgstr ""
|
msgstr "Fjern trinn"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:116
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:116
|
||||||
msgid "Calories"
|
msgid "Calories"
|
||||||
@ -678,15 +688,15 @@ msgstr "Proteiner"
|
|||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:146
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:146
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:454
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:454
|
||||||
msgid "Step"
|
msgid "Step"
|
||||||
msgstr ""
|
msgstr "Trinn"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:167
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:167
|
||||||
msgid "Show as header"
|
msgid "Show as header"
|
||||||
msgstr ""
|
msgstr "Vis som overskrift"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:173
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:173
|
||||||
msgid "Hide as header"
|
msgid "Hide as header"
|
||||||
msgstr ""
|
msgstr "Skjul overskrift"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:178
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:178
|
||||||
msgid "Move Up"
|
msgid "Move Up"
|
||||||
@ -698,15 +708,15 @@ msgstr "Flytt nedover"
|
|||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:192
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:192
|
||||||
msgid "Step Name"
|
msgid "Step Name"
|
||||||
msgstr ""
|
msgstr "Trinn navn"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:196
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:196
|
||||||
msgid "Step Type"
|
msgid "Step Type"
|
||||||
msgstr ""
|
msgstr "Trinn type"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:207
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:207
|
||||||
msgid "Step time in Minutes"
|
msgid "Step time in Minutes"
|
||||||
msgstr ""
|
msgstr "Trinn tid i minutter"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:261
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:261
|
||||||
#: .\cookbook\templates\shopping_list.html:183
|
#: .\cookbook\templates\shopping_list.html:183
|
||||||
@ -740,7 +750,7 @@ msgstr "Velg mat"
|
|||||||
#: .\cookbook\templates\meal_plan.html:256
|
#: .\cookbook\templates\meal_plan.html:256
|
||||||
#: .\cookbook\templates\url_import.html:171
|
#: .\cookbook\templates\url_import.html:171
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr ""
|
msgstr "Notis"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:319
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:319
|
||||||
msgid "Delete Ingredient"
|
msgid "Delete Ingredient"
|
||||||
@ -748,7 +758,7 @@ msgstr "Slett ingrediens"
|
|||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:325
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:325
|
||||||
msgid "Make Header"
|
msgid "Make Header"
|
||||||
msgstr ""
|
msgstr "Bruk som overskrift"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:331
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:331
|
||||||
msgid "Make Ingredient"
|
msgid "Make Ingredient"
|
||||||
@ -756,15 +766,15 @@ msgstr "Opprett ingrediens"
|
|||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:337
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:337
|
||||||
msgid "Disable Amount"
|
msgid "Disable Amount"
|
||||||
msgstr ""
|
msgstr "Deaktiver mengde"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:343
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:343
|
||||||
msgid "Enable Amount"
|
msgid "Enable Amount"
|
||||||
msgstr ""
|
msgstr "Aktiver mengde"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:348
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:348
|
||||||
msgid "Copy Template Reference"
|
msgid "Copy Template Reference"
|
||||||
msgstr ""
|
msgstr "Kopier mal-referanse"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:374
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:374
|
||||||
#: .\cookbook\templates\url_import.html:196
|
#: .\cookbook\templates\url_import.html:196
|
||||||
@ -773,29 +783,28 @@ msgstr "Instruksjoner"
|
|||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:387
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:387
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:418
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:418
|
||||||
#, fuzzy
|
|
||||||
msgid "Save & View"
|
msgid "Save & View"
|
||||||
msgstr "Lagre og vis"
|
msgstr "Lagre og vis"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:391
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:391
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:424
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:424
|
||||||
msgid "Add Step"
|
msgid "Add Step"
|
||||||
msgstr ""
|
msgstr "Legg til trinn"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:394
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:394
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:428
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:428
|
||||||
msgid "Add Nutrition"
|
msgid "Add Nutrition"
|
||||||
msgstr ""
|
msgstr "Legg til næringsinnhold"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:396
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:396
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:430
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:430
|
||||||
msgid "Remove Nutrition"
|
msgid "Remove Nutrition"
|
||||||
msgstr ""
|
msgstr "Fjern næringsinnhold"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:398
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:398
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:433
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:433
|
||||||
msgid "View Recipe"
|
msgid "View Recipe"
|
||||||
msgstr ""
|
msgstr "Vis oppskrift"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:400
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:400
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:435
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:435
|
||||||
@ -804,11 +813,11 @@ msgstr "Slett oppskrift"
|
|||||||
|
|
||||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:441
|
#: .\cookbook\templates\forms\edit_internal_recipe.html:441
|
||||||
msgid "Steps"
|
msgid "Steps"
|
||||||
msgstr ""
|
msgstr "Trinn"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\ingredients.html:15
|
#: .\cookbook\templates\forms\ingredients.html:15
|
||||||
msgid "Edit Ingredients"
|
msgid "Edit Ingredients"
|
||||||
msgstr ""
|
msgstr "Rediger ingrediens"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\ingredients.html:16
|
#: .\cookbook\templates\forms\ingredients.html:16
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -820,54 +829,61 @@ msgid ""
|
|||||||
"them.\n"
|
"them.\n"
|
||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
" Følgende skjema kan brukes dersom, tilfeldigvis, to eller flere "
|
||||||
|
"enheter eller ingredienser er opprettet,\n"
|
||||||
|
" og burde være identiske.\n"
|
||||||
|
" Det slår sammen to enheter eller ingredienser og oppdaterer alle "
|
||||||
|
"oppskrifter som inneholder disse.\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\ingredients.html:24
|
#: .\cookbook\templates\forms\ingredients.html:24
|
||||||
#: .\cookbook\templates\stats.html:26
|
#: .\cookbook\templates\stats.html:26
|
||||||
msgid "Units"
|
msgid "Units"
|
||||||
msgstr ""
|
msgstr "Enheter"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\ingredients.html:26
|
#: .\cookbook\templates\forms\ingredients.html:26
|
||||||
msgid "Are you sure that you want to merge these two units?"
|
msgid "Are you sure that you want to merge these two units?"
|
||||||
msgstr ""
|
msgstr "Er du sikker på at du vil slå sammen disse enhetene?"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\ingredients.html:31
|
#: .\cookbook\templates\forms\ingredients.html:31
|
||||||
#: .\cookbook\templates\forms\ingredients.html:40
|
#: .\cookbook\templates\forms\ingredients.html:40
|
||||||
msgid "Merge"
|
msgid "Merge"
|
||||||
msgstr "Flett"
|
msgstr "Slå sammen"
|
||||||
|
|
||||||
#: .\cookbook\templates\forms\ingredients.html:36
|
#: .\cookbook\templates\forms\ingredients.html:36
|
||||||
msgid "Are you sure that you want to merge these two ingredients?"
|
msgid "Are you sure that you want to merge these two ingredients?"
|
||||||
msgstr ""
|
msgstr "Er du sikker på at du vil slå sammen disse ingrediensene?"
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\delete_template.html:18
|
#: .\cookbook\templates\generic\delete_template.html:18
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Are you sure you want to delete the %(title)s: <b>%(object)s</b> "
|
msgid "Are you sure you want to delete the %(title)s: <b>%(object)s</b> "
|
||||||
msgstr ""
|
msgstr "Er du sikker på at du vil slette %(title)s: <b>%(object)s</b> "
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\delete_template.html:21
|
#: .\cookbook\templates\generic\delete_template.html:21
|
||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr ""
|
msgstr "Bekreft"
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\edit_template.html:30
|
#: .\cookbook\templates\generic\edit_template.html:30
|
||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr ""
|
msgstr "Vis"
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\edit_template.html:34
|
#: .\cookbook\templates\generic\edit_template.html:34
|
||||||
msgid "Delete original file"
|
msgid "Delete original file"
|
||||||
msgstr ""
|
msgstr "Slett opprinnelig fil"
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\list_template.html:6
|
#: .\cookbook\templates\generic\list_template.html:6
|
||||||
#: .\cookbook\templates\generic\list_template.html:12
|
#: .\cookbook\templates\generic\list_template.html:12
|
||||||
msgid "List"
|
msgid "List"
|
||||||
msgstr ""
|
msgstr "Liste"
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\list_template.html:25
|
#: .\cookbook\templates\generic\list_template.html:25
|
||||||
msgid "Filter"
|
msgid "Filter"
|
||||||
msgstr ""
|
msgstr "Filtrer"
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\list_template.html:30
|
#: .\cookbook\templates\generic\list_template.html:30
|
||||||
msgid "Import all"
|
msgid "Import all"
|
||||||
msgstr ""
|
msgstr "Importer alle"
|
||||||
|
|
||||||
#: .\cookbook\templates\generic\new_template.html:6
|
#: .\cookbook\templates\generic\new_template.html:6
|
||||||
#: .\cookbook\templates\generic\new_template.html:14
|
#: .\cookbook\templates\generic\new_template.html:14
|
||||||
@ -891,19 +907,19 @@ msgstr "Vis logg"
|
|||||||
|
|
||||||
#: .\cookbook\templates\history.html:24
|
#: .\cookbook\templates\history.html:24
|
||||||
msgid "Cook Log"
|
msgid "Cook Log"
|
||||||
msgstr ""
|
msgstr "Tilberedingslogg"
|
||||||
|
|
||||||
#: .\cookbook\templates\import.html:6 .\cookbook\templates\test.html:6
|
#: .\cookbook\templates\import.html:6 .\cookbook\templates\test.html:6
|
||||||
msgid "Import Recipes"
|
msgid "Import Recipes"
|
||||||
msgstr ""
|
msgstr "Importer oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\include\log_cooking.html:7
|
#: .\cookbook\templates\include\log_cooking.html:7
|
||||||
msgid "Log Recipe Cooking"
|
msgid "Log Recipe Cooking"
|
||||||
msgstr ""
|
msgstr "Loggfør tilberedt oppskrift"
|
||||||
|
|
||||||
#: .\cookbook\templates\include\log_cooking.html:13
|
#: .\cookbook\templates\include\log_cooking.html:13
|
||||||
msgid "All fields are optional and can be left empty."
|
msgid "All fields are optional and can be left empty."
|
||||||
msgstr ""
|
msgstr "Alle felt er valgfri og kan stå tomme."
|
||||||
|
|
||||||
#: .\cookbook\templates\include\log_cooking.html:19
|
#: .\cookbook\templates\include\log_cooking.html:19
|
||||||
msgid "Rating"
|
msgid "Rating"
|
||||||
@ -943,44 +959,53 @@ msgid ""
|
|||||||
"can be used.\n"
|
"can be used.\n"
|
||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
" <b>Passord og nøkkelfeltene</b> er lagret som <b>ren tekst</b> i "
|
||||||
|
"databasen.\n"
|
||||||
|
" Dette er nødvendig for å kunne utføre API-forespørsler, men det øker "
|
||||||
|
"samtidig risiko for\n"
|
||||||
|
" uønsket tilgang til dem.<br/>\n"
|
||||||
|
" For å begrense kosekvensene av uønsket tilgang, kan nøkler eller "
|
||||||
|
"kontoer med begrenset tilgang benyttes.\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:29
|
#: .\cookbook\templates\index.html:29
|
||||||
msgid "Search recipe ..."
|
msgid "Search recipe ..."
|
||||||
msgstr ""
|
msgstr "Søk etter oppskrift..."
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:44
|
#: .\cookbook\templates\index.html:44
|
||||||
msgid "New Recipe"
|
msgid "New Recipe"
|
||||||
msgstr ""
|
msgstr "Ny oppskrift"
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:47
|
#: .\cookbook\templates\index.html:47
|
||||||
msgid "Website Import"
|
msgid "Website Import"
|
||||||
msgstr ""
|
msgstr "Importer fra nettside"
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:53
|
#: .\cookbook\templates\index.html:53
|
||||||
msgid "Advanced Search"
|
msgid "Advanced Search"
|
||||||
msgstr ""
|
msgstr "Avansert søk"
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:57
|
#: .\cookbook\templates\index.html:57
|
||||||
msgid "Reset Search"
|
msgid "Reset Search"
|
||||||
msgstr ""
|
msgstr "Nullstill søk"
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:85
|
#: .\cookbook\templates\index.html:85
|
||||||
msgid "Last viewed"
|
msgid "Last viewed"
|
||||||
msgstr ""
|
msgstr "Sist sett"
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:87 .\cookbook\templates\meal_plan.html:178
|
#: .\cookbook\templates\index.html:87 .\cookbook\templates\meal_plan.html:178
|
||||||
#: .\cookbook\templates\stats.html:22
|
#: .\cookbook\templates\stats.html:22
|
||||||
msgid "Recipes"
|
msgid "Recipes"
|
||||||
msgstr ""
|
msgstr "Oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\index.html:94
|
#: .\cookbook\templates\index.html:94
|
||||||
msgid "Log in to view recipes"
|
msgid "Log in to view recipes"
|
||||||
msgstr ""
|
msgstr "Logg inn for å se oppskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:5
|
#: .\cookbook\templates\markdown_info.html:5
|
||||||
#: .\cookbook\templates\markdown_info.html:13
|
#: .\cookbook\templates\markdown_info.html:13
|
||||||
msgid "Markdown Info"
|
msgid "Markdown Info"
|
||||||
msgstr ""
|
msgstr "Markdown informasjon"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:14
|
#: .\cookbook\templates\markdown_info.html:14
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -997,43 +1022,56 @@ msgid ""
|
|||||||
"below.\n"
|
"below.\n"
|
||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
" Markdown er et lettvekts markup språk som benyttes for å formatere "
|
||||||
|
"ren tekst.\n"
|
||||||
|
" Denne siden bruker biblioteket <a href=\"https://python-markdown."
|
||||||
|
"github.io/\" target=\"_blank\">Python Markdown</a> for\n"
|
||||||
|
" å konvertere teksten din til velformatert HTML. Fullstendig "
|
||||||
|
"dokumentasjon for markdown finner du\n"
|
||||||
|
" <a href=\"https://daringfireball.net/projects/markdown/syntax\" "
|
||||||
|
"target=\"_blank\">her</a>.\n"
|
||||||
|
" En ufullstendig, men sannsynligvis tilstrekkelig dokumentasjon "
|
||||||
|
"finner du under her.\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:25
|
#: .\cookbook\templates\markdown_info.html:25
|
||||||
msgid "Headers"
|
msgid "Headers"
|
||||||
msgstr ""
|
msgstr "Overskrifter"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:54
|
#: .\cookbook\templates\markdown_info.html:54
|
||||||
msgid "Formatting"
|
msgid "Formatting"
|
||||||
msgstr ""
|
msgstr "Formatering"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:56
|
#: .\cookbook\templates\markdown_info.html:56
|
||||||
#: .\cookbook\templates\markdown_info.html:72
|
#: .\cookbook\templates\markdown_info.html:72
|
||||||
msgid "Line breaks are inserted by adding two spaces after the end of a line"
|
msgid "Line breaks are inserted by adding two spaces after the end of a line"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Linjeskift er satt inn ved å sette inn to mellomrom på slutten av en linje"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:57
|
#: .\cookbook\templates\markdown_info.html:57
|
||||||
#: .\cookbook\templates\markdown_info.html:73
|
#: .\cookbook\templates\markdown_info.html:73
|
||||||
msgid "or by leaving a blank line inbetween."
|
msgid "or by leaving a blank line inbetween."
|
||||||
msgstr ""
|
msgstr "eller ved å sette inn en tom linje mellom."
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:59
|
#: .\cookbook\templates\markdown_info.html:59
|
||||||
#: .\cookbook\templates\markdown_info.html:74
|
#: .\cookbook\templates\markdown_info.html:74
|
||||||
msgid "This text is bold"
|
msgid "This text is bold"
|
||||||
msgstr ""
|
msgstr "Denne teksten er Fet"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:60
|
#: .\cookbook\templates\markdown_info.html:60
|
||||||
#: .\cookbook\templates\markdown_info.html:75
|
#: .\cookbook\templates\markdown_info.html:75
|
||||||
msgid "This text is italic"
|
msgid "This text is italic"
|
||||||
msgstr ""
|
msgstr "Denne teksten er Kursiv"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:61
|
#: .\cookbook\templates\markdown_info.html:61
|
||||||
#: .\cookbook\templates\markdown_info.html:77
|
#: .\cookbook\templates\markdown_info.html:77
|
||||||
msgid "Blockquotes are also possible"
|
msgid "Blockquotes are also possible"
|
||||||
msgstr ""
|
msgstr "Det er også mulig å sitere avsnitt"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:84
|
#: .\cookbook\templates\markdown_info.html:84
|
||||||
msgid "Lists"
|
msgid "Lists"
|
||||||
msgstr ""
|
msgstr "Lister"
|
||||||
|
|
||||||
#: .\cookbook\templates\markdown_info.html:85
|
#: .\cookbook\templates\markdown_info.html:85
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1264,7 +1302,7 @@ msgstr ""
|
|||||||
#: .\cookbook\templates\no_groups_info.html:5
|
#: .\cookbook\templates\no_groups_info.html:5
|
||||||
#: .\cookbook\templates\no_groups_info.html:12
|
#: .\cookbook\templates\no_groups_info.html:12
|
||||||
msgid "No Permissions"
|
msgid "No Permissions"
|
||||||
msgstr "Ingen tilganger."
|
msgstr "Ingen tilgang"
|
||||||
|
|
||||||
#: .\cookbook\templates\no_groups_info.html:17
|
#: .\cookbook\templates\no_groups_info.html:17
|
||||||
msgid "You do not have any groups and therefor cannot use this application."
|
msgid "You do not have any groups and therefor cannot use this application."
|
||||||
@ -1298,12 +1336,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\offline.html:6
|
#: .\cookbook\templates\offline.html:6
|
||||||
msgid "Offline"
|
msgid "Offline"
|
||||||
msgstr "Frakoblet."
|
msgstr "Frakoblet"
|
||||||
|
|
||||||
#: .\cookbook\templates\offline.html:19
|
#: .\cookbook\templates\offline.html:19
|
||||||
#, fuzzy
|
|
||||||
msgid "You are currently offline!"
|
msgid "You are currently offline!"
|
||||||
msgstr "Du er ikke tilkoblet Internett."
|
msgstr "Du er ikke tilkoblet!"
|
||||||
|
|
||||||
#: .\cookbook\templates\offline.html:20
|
#: .\cookbook\templates\offline.html:20
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1366,7 +1403,7 @@ msgstr "Stil"
|
|||||||
|
|
||||||
#: .\cookbook\templates\settings.html:79
|
#: .\cookbook\templates\settings.html:79
|
||||||
msgid "API Token"
|
msgid "API Token"
|
||||||
msgstr "API-symbol"
|
msgstr "API nøkkel"
|
||||||
|
|
||||||
#: .\cookbook\templates\settings.html:80
|
#: .\cookbook\templates\settings.html:80
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1389,9 +1426,8 @@ msgid "Cookbook Setup"
|
|||||||
msgstr "Kokeboksoppsett"
|
msgstr "Kokeboksoppsett"
|
||||||
|
|
||||||
#: .\cookbook\templates\setup.html:14
|
#: .\cookbook\templates\setup.html:14
|
||||||
#, fuzzy
|
|
||||||
msgid "Setup"
|
msgid "Setup"
|
||||||
msgstr "Sett opp"
|
msgstr "Installering"
|
||||||
|
|
||||||
#: .\cookbook\templates\setup.html:15
|
#: .\cookbook\templates\setup.html:15
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1424,11 +1460,11 @@ msgstr "Mengde"
|
|||||||
|
|
||||||
#: .\cookbook\templates\shopping_list.html:226
|
#: .\cookbook\templates\shopping_list.html:226
|
||||||
msgid "Supermarket"
|
msgid "Supermarket"
|
||||||
msgstr "Matbutikk"
|
msgstr "Butikk"
|
||||||
|
|
||||||
#: .\cookbook\templates\shopping_list.html:236
|
#: .\cookbook\templates\shopping_list.html:236
|
||||||
msgid "Select Supermarket"
|
msgid "Select Supermarket"
|
||||||
msgstr "Velg matbutikk"
|
msgstr "Velg butikk"
|
||||||
|
|
||||||
#: .\cookbook\templates\shopping_list.html:260
|
#: .\cookbook\templates\shopping_list.html:260
|
||||||
msgid "Select User"
|
msgid "Select User"
|
||||||
@ -1540,7 +1576,6 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\system.html:49 .\cookbook\templates\system.html:64
|
#: .\cookbook\templates\system.html:49 .\cookbook\templates\system.html:64
|
||||||
#: .\cookbook\templates\system.html:80 .\cookbook\templates\system.html:95
|
#: .\cookbook\templates\system.html:80 .\cookbook\templates\system.html:95
|
||||||
#, fuzzy
|
|
||||||
msgid "Ok"
|
msgid "Ok"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -8,8 +8,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
"POT-Creation-Date: 2022-02-11 08:52+0100\n"
|
||||||
"PO-Revision-Date: 2023-02-18 10:55+0000\n"
|
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
|
||||||
"Last-Translator: Joachim Weber <joachim.weber@gmx.de>\n"
|
"Last-Translator: noxonad <noxonad@proton.me>\n"
|
||||||
"Language-Team: Portuguese (Brazil) <http://translate.tandoor.dev/projects/"
|
"Language-Team: Portuguese (Brazil) <http://translate.tandoor.dev/projects/"
|
||||||
"tandoor/recipes-backend/pt_BR/>\n"
|
"tandoor/recipes-backend/pt_BR/>\n"
|
||||||
"Language: pt_BR\n"
|
"Language: pt_BR\n"
|
||||||
@ -2208,7 +2208,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\url_import.html:38
|
#: .\cookbook\templates\url_import.html:38
|
||||||
msgid "URL"
|
msgid "URL"
|
||||||
msgstr ""
|
msgstr "URL"
|
||||||
|
|
||||||
#: .\cookbook\templates\url_import.html:40
|
#: .\cookbook\templates\url_import.html:40
|
||||||
msgid "App"
|
msgid "App"
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -8,17 +8,17 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
|
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
|
||||||
"PO-Revision-Date: 2022-11-30 19:09+0000\n"
|
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
|
||||||
"Last-Translator: Alex <kovsharoff@gmail.com>\n"
|
"Last-Translator: noxonad <noxonad@proton.me>\n"
|
||||||
"Language-Team: Russian <http://translate.tandoor.dev/projects/tandoor/"
|
"Language-Team: Russian <http://translate.tandoor.dev/projects/tandoor/"
|
||||||
"recipes-backend/ru/>\n"
|
"recipes-backend/ru/>\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||||
"X-Generator: Weblate 4.14.1\n"
|
"X-Generator: Weblate 4.15\n"
|
||||||
|
|
||||||
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
|
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
|
||||||
#: .\cookbook\templates\forms\ingredients.html:34
|
#: .\cookbook\templates\forms\ingredients.html:34
|
||||||
@ -861,7 +861,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\base.html:220
|
#: .\cookbook\templates\base.html:220
|
||||||
msgid "GitHub"
|
msgid "GitHub"
|
||||||
msgstr ""
|
msgstr "GitHub"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:224
|
#: .\cookbook\templates\base.html:224
|
||||||
msgid "API Browser"
|
msgid "API Browser"
|
||||||
@ -1937,7 +1937,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\space.html:106
|
#: .\cookbook\templates\space.html:106
|
||||||
msgid "user"
|
msgid "user"
|
||||||
msgstr ""
|
msgstr "пользователь"
|
||||||
|
|
||||||
#: .\cookbook\templates\space.html:107
|
#: .\cookbook\templates\space.html:107
|
||||||
msgid "guest"
|
msgid "guest"
|
||||||
|
Binary file not shown.
@ -8,17 +8,17 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
|
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
|
||||||
"PO-Revision-Date: 2022-02-02 15:31+0000\n"
|
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
|
||||||
"Last-Translator: Mario Dvorsek <mario.dvorsek@gmail.com>\n"
|
"Last-Translator: noxonad <noxonad@proton.me>\n"
|
||||||
"Language-Team: Slovenian <http://translate.tandoor.dev/projects/tandoor/"
|
"Language-Team: Slovenian <http://translate.tandoor.dev/projects/tandoor/"
|
||||||
"recipes-backend/sl/>\n"
|
"recipes-backend/sl/>\n"
|
||||||
"Language: sl\n"
|
"Language: sl\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
|
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || "
|
||||||
"%100==4 ? 2 : 3;\n"
|
"n%100==4 ? 2 : 3;\n"
|
||||||
"X-Generator: Weblate 4.10.1\n"
|
"X-Generator: Weblate 4.15\n"
|
||||||
|
|
||||||
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
|
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
|
||||||
#: .\cookbook\templates\forms\ingredients.html:34
|
#: .\cookbook\templates\forms\ingredients.html:34
|
||||||
@ -2107,7 +2107,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\url_import.html:36
|
#: .\cookbook\templates\url_import.html:36
|
||||||
msgid "URL"
|
msgid "URL"
|
||||||
msgstr ""
|
msgstr "URL"
|
||||||
|
|
||||||
#: .\cookbook\templates\url_import.html:38
|
#: .\cookbook\templates\url_import.html:38
|
||||||
msgid "App"
|
msgid "App"
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -8,8 +8,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
||||||
"PO-Revision-Date: 2023-02-09 13:55+0000\n"
|
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
|
||||||
"Last-Translator: vertilo <vertilo.dev@gmail.com>\n"
|
"Last-Translator: noxonad <noxonad@proton.me>\n"
|
||||||
"Language-Team: Ukrainian <http://translate.tandoor.dev/projects/tandoor/"
|
"Language-Team: Ukrainian <http://translate.tandoor.dev/projects/tandoor/"
|
||||||
"recipes-backend/uk/>\n"
|
"recipes-backend/uk/>\n"
|
||||||
"Language: uk\n"
|
"Language: uk\n"
|
||||||
@ -1091,7 +1091,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: .\cookbook\templates\base.html:311
|
#: .\cookbook\templates\base.html:311
|
||||||
msgid "GitHub"
|
msgid "GitHub"
|
||||||
msgstr ""
|
msgstr "GitHub"
|
||||||
|
|
||||||
#: .\cookbook\templates\base.html:313
|
#: .\cookbook\templates\base.html:313
|
||||||
msgid "Translate Tandoor"
|
msgid "Translate Tandoor"
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -6,7 +6,7 @@ from django.urls import reverse
|
|||||||
from django_scopes import scope, scopes_disabled
|
from django_scopes import scope, scopes_disabled
|
||||||
from pytest_factoryboy import LazyFixture, register
|
from pytest_factoryboy import LazyFixture, register
|
||||||
|
|
||||||
from cookbook.models import Food, FoodInheritField, Ingredient, ShoppingList, ShoppingListEntry
|
from cookbook.models import Food, Ingredient, ShoppingListEntry
|
||||||
from cookbook.tests.factories import (FoodFactory, IngredientFactory, ShoppingListEntryFactory,
|
from cookbook.tests.factories import (FoodFactory, IngredientFactory, ShoppingListEntryFactory,
|
||||||
SupermarketCategoryFactory)
|
SupermarketCategoryFactory)
|
||||||
|
|
||||||
@ -56,23 +56,32 @@ def obj_tree_1(request, space_1):
|
|||||||
params = request.param # request.param is a magic variable
|
params = request.param # request.param is a magic variable
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
params = {}
|
params = {}
|
||||||
objs = []
|
|
||||||
inherit = params.pop('inherit', False)
|
inherit = params.pop('inherit', False)
|
||||||
objs.extend(FoodFactory.create_batch(3, space=space_1, **params))
|
FoodFactory.create_batch(3, space=space_1, **params)
|
||||||
|
objs = Food.objects.values_list('id', flat=True)
|
||||||
|
obj_id = objs[1]
|
||||||
|
child_id = objs[0]
|
||||||
|
parent_id = objs[2]
|
||||||
|
|
||||||
# set all foods to inherit everything
|
# set all foods to inherit everything
|
||||||
if inherit:
|
if inherit:
|
||||||
inherit = Food.inheritable_fields
|
inherit = Food.inheritable_fields
|
||||||
Through = Food.objects.filter(space=space_1).first().inherit_fields.through
|
Through = Food.objects.filter(
|
||||||
|
space=space_1).first().inherit_fields.through
|
||||||
for i in inherit:
|
for i in inherit:
|
||||||
Through.objects.bulk_create([
|
Through.objects.bulk_create([
|
||||||
Through(food_id=x, foodinheritfield_id=i.id)
|
Through(food_id=x, foodinheritfield_id=i.id)
|
||||||
for x in Food.objects.filter(space=space_1).values_list('id', flat=True)
|
for x in Food.objects.filter(space=space_1).values_list('id', flat=True)
|
||||||
])
|
])
|
||||||
|
|
||||||
objs[0].move(objs[1], node_location)
|
Food.objects.get(id=child_id).move(
|
||||||
objs[1].move(objs[2], node_location)
|
Food.objects.get(id=obj_id), node_location)
|
||||||
return Food.objects.get(id=objs[1].id) # whenever you move/merge a tree it's safest to re-get the object
|
|
||||||
|
Food.objects.get(id=obj_id).move(
|
||||||
|
Food.objects.get(id=parent_id), node_location)
|
||||||
|
|
||||||
|
# whenever you move/merge a tree it's safest to re-get the object
|
||||||
|
return Food.objects.get(id=obj_id)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("arg", [
|
@pytest.mark.parametrize("arg", [
|
||||||
@ -107,19 +116,23 @@ def test_list_filter(obj_1, obj_2, u1_s1):
|
|||||||
assert obj_2.name in [x['name'] for x in response['results']]
|
assert obj_2.name in [x['name'] for x in response['results']]
|
||||||
assert response['results'][0]['name'] < response['results'][1]['name']
|
assert response['results'][0]['name'] < response['results'][1]['name']
|
||||||
|
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?page_size=1').content)
|
response = json.loads(
|
||||||
|
u1_s1.get(f'{reverse(LIST_URL)}?page_size=1').content)
|
||||||
assert len(response['results']) == 1
|
assert len(response['results']) == 1
|
||||||
|
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
|
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
|
||||||
assert len(response['results']) == 1
|
assert len(response['results']) == 1
|
||||||
|
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=''&limit=1').content)
|
response = json.loads(
|
||||||
|
u1_s1.get(f'{reverse(LIST_URL)}?query=''&limit=1').content)
|
||||||
assert len(response['results']) == 1
|
assert len(response['results']) == 1
|
||||||
|
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content)
|
response = json.loads(
|
||||||
|
u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content)
|
||||||
assert response['count'] == 0
|
assert response['count'] == 0
|
||||||
|
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[:-4]}').content)
|
response = json.loads(
|
||||||
|
u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[:-4]}').content)
|
||||||
assert response['count'] == 1
|
assert response['count'] == 1
|
||||||
|
|
||||||
|
|
||||||
@ -262,8 +275,9 @@ def test_integrity(u1_s1, recipe_1_s1):
|
|||||||
|
|
||||||
def test_move(u1_s1, obj_tree_1, obj_2, obj_3, space_1):
|
def test_move(u1_s1, obj_tree_1, obj_2, obj_3, space_1):
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
|
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
|
||||||
|
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
|
||||||
assert parent.get_num_children() == 1
|
assert parent.get_num_children() == 1
|
||||||
assert parent.get_descendant_count() == 2
|
assert parent.get_descendant_count() == 2
|
||||||
assert Food.get_root_nodes().filter(space=space_1).count() == 2
|
assert Food.get_root_nodes().filter(space=space_1).count() == 2
|
||||||
@ -295,8 +309,9 @@ def test_move(u1_s1, obj_tree_1, obj_2, obj_3, space_1):
|
|||||||
|
|
||||||
def test_move_errors(u1_s1, obj_tree_1, obj_3, space_1):
|
def test_move_errors(u1_s1, obj_tree_1, obj_3, space_1):
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
|
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
|
||||||
|
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
|
||||||
# move child to root
|
# move child to root
|
||||||
r = u1_s1.put(reverse(MOVE_URL, args=[obj_tree_1.id, 0]))
|
r = u1_s1.put(reverse(MOVE_URL, args=[obj_tree_1.id, 0]))
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
@ -373,6 +388,8 @@ def test_merge_shopping_entries(obj_tree_1, u1_s1, space_1):
|
|||||||
|
|
||||||
def test_merge(u1_s1, obj_tree_1, obj_1, obj_3, space_1):
|
def test_merge(u1_s1, obj_tree_1, obj_1, obj_3, space_1):
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
|
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
|
||||||
|
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
child = obj_tree_1.get_descendants()[0]
|
||||||
assert parent.get_num_children() == 1
|
assert parent.get_num_children() == 1
|
||||||
@ -416,8 +433,9 @@ def test_merge(u1_s1, obj_tree_1, obj_1, obj_3, space_1):
|
|||||||
|
|
||||||
def test_merge_errors(u1_s1, obj_tree_1, obj_3, space_1):
|
def test_merge_errors(u1_s1, obj_tree_1, obj_3, space_1):
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
|
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
|
||||||
|
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
|
||||||
|
|
||||||
# attempt to merge with non-existent parent
|
# attempt to merge with non-existent parent
|
||||||
r = u1_s1.put(
|
r = u1_s1.put(
|
||||||
@ -451,44 +469,63 @@ def test_merge_errors(u1_s1, obj_tree_1, obj_3, space_1):
|
|||||||
|
|
||||||
def test_root_filter(obj_tree_1, obj_2, obj_3, u1_s1):
|
def test_root_filter(obj_tree_1, obj_2, obj_3, u1_s1):
|
||||||
with scope(space=obj_tree_1.space):
|
with scope(space=obj_tree_1.space):
|
||||||
|
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
|
||||||
|
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
|
||||||
|
|
||||||
# should return root objects in the space (obj_1, obj_2), ignoring query filters
|
# should return root objects in the space (obj_1, obj_2), ignoring query filters
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root=0').content)
|
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root=0').content)
|
||||||
assert len(response['results']) == 2
|
assert len(response['results']) == 2
|
||||||
|
|
||||||
|
# django_tree bypasses ORM - best to retrieve all changed objects
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
obj_2.move(parent, node_location)
|
obj_2.move(parent, node_location)
|
||||||
|
obj_2 = Food.objects.get(id=obj_2.id)
|
||||||
|
parent = Food.objects.get(id=parent.id)
|
||||||
# should return direct children of parent (obj_tree_1, obj_2), ignoring query filters
|
# should return direct children of parent (obj_tree_1, obj_2), ignoring query filters
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={parent.id}').content)
|
response = json.loads(
|
||||||
|
u1_s1.get(f'{reverse(LIST_URL)}?root={parent.id}').content)
|
||||||
assert response['count'] == 2
|
assert response['count'] == 2
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={parent.id}&query={obj_2.name[4:]}').content)
|
response = json.loads(u1_s1.get(
|
||||||
|
f'{reverse(LIST_URL)}?root={parent.id}&query={obj_2.name[4:]}').content)
|
||||||
assert response['count'] == 2
|
assert response['count'] == 2
|
||||||
|
|
||||||
|
|
||||||
def test_tree_filter(obj_tree_1, obj_2, obj_3, u1_s1):
|
def test_tree_filter(obj_tree_1, obj_2, obj_3, u1_s1):
|
||||||
with scope(space=obj_tree_1.space):
|
with scope(space=obj_tree_1.space):
|
||||||
|
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
|
||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
child = obj_tree_1.get_descendants()[0]
|
|
||||||
obj_2.move(parent, node_location)
|
obj_2.move(parent, node_location)
|
||||||
|
obj_2 = Food.objects.get(id=obj_2.id)
|
||||||
|
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
|
||||||
|
parent = Food.objects.get(id=parent.id)
|
||||||
|
|
||||||
# should return full tree starting at parent (obj_tree_1, obj_2), ignoring query filters
|
# should return full tree starting at parent (obj_tree_1, obj_2), ignoring query filters
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}').content)
|
response = json.loads(
|
||||||
|
u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}').content)
|
||||||
assert response['count'] == 4
|
assert response['count'] == 4
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}&query={obj_2.name[4:]}').content)
|
response = json.loads(u1_s1.get(
|
||||||
|
f'{reverse(LIST_URL)}?tree={parent.id}&query={obj_2.name[4:]}').content)
|
||||||
assert response['count'] == 4
|
assert response['count'] == 4
|
||||||
|
|
||||||
|
|
||||||
# This is more about the model than the API - should this be moved to a different test?
|
# This is more about the model than the API - should this be moved to a different test?
|
||||||
@pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [
|
@pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [
|
||||||
({'has_category': True, 'inherit': True}, 'supermarket_category', True, 'cat_1'),
|
({'has_category': True, 'inherit': True},
|
||||||
({'has_category': True, 'inherit': False}, 'supermarket_category', False, 'cat_1'),
|
'supermarket_category', True, 'cat_1'),
|
||||||
|
({'has_category': True, 'inherit': False},
|
||||||
|
'supermarket_category', False, 'cat_1'),
|
||||||
({'ignore_shopping': True, 'inherit': True}, 'ignore_shopping', True, 'false'),
|
({'ignore_shopping': True, 'inherit': True}, 'ignore_shopping', True, 'false'),
|
||||||
({'ignore_shopping': True, 'inherit': False}, 'ignore_shopping', False, 'false'),
|
({'ignore_shopping': True, 'inherit': False},
|
||||||
({'substitute_children': True, 'inherit': True}, 'substitute_children', True, 'false'),
|
'ignore_shopping', False, 'false'),
|
||||||
({'substitute_children': True, 'inherit': False}, 'substitute_children', False, 'false'),
|
({'substitute_children': True, 'inherit': True},
|
||||||
({'substitute_siblings': True, 'inherit': True}, 'substitute_siblings', True, 'false'),
|
'substitute_children', True, 'false'),
|
||||||
({'substitute_siblings': True, 'inherit': False}, 'substitute_siblings', False, '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
|
], 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):
|
def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
||||||
with scope(space=obj_tree_1.space):
|
with scope(space=obj_tree_1.space):
|
||||||
@ -498,8 +535,10 @@ def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
|||||||
new_val = request.getfixturevalue(new_val)
|
new_val = request.getfixturevalue(new_val)
|
||||||
# if this test passes it demonstrates that inheritance works
|
# if this test passes it demonstrates that inheritance works
|
||||||
# when moving to a parent as each food is created with a different category
|
# when moving to a parent as each food is created with a different category
|
||||||
assert (getattr(parent, field) == getattr(obj_tree_1, field)) in [inherit, True]
|
assert (getattr(parent, field) == getattr(
|
||||||
assert (getattr(obj_tree_1, field) == getattr(child, field)) in [inherit, True]
|
obj_tree_1, field)) in [inherit, True]
|
||||||
|
assert (getattr(obj_tree_1, field) == getattr(
|
||||||
|
child, field)) in [inherit, True]
|
||||||
# change parent to a new value
|
# change parent to a new value
|
||||||
setattr(parent, field, new_val)
|
setattr(parent, field, new_val)
|
||||||
with scope(space=parent.space):
|
with scope(space=parent.space):
|
||||||
@ -515,7 +554,8 @@ def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("obj_tree_1", [
|
@pytest.mark.parametrize("obj_tree_1", [
|
||||||
({'has_category': True, 'inherit': False, 'ignore_shopping': True, 'substitute_children': True, 'substitute_siblings': True}),
|
({'has_category': True, 'inherit': False, 'ignore_shopping': True,
|
||||||
|
'substitute_children': True, 'substitute_siblings': True}),
|
||||||
], indirect=['obj_tree_1'])
|
], indirect=['obj_tree_1'])
|
||||||
@pytest.mark.parametrize("global_reset", [True, False])
|
@pytest.mark.parametrize("global_reset", [True, False])
|
||||||
@pytest.mark.parametrize("field", ['ignore_shopping', 'substitute_children', 'substitute_siblings', 'supermarket_category'])
|
@pytest.mark.parametrize("field", ['ignore_shopping', 'substitute_children', 'substitute_siblings', 'supermarket_category'])
|
||||||
@ -534,10 +574,13 @@ def test_reset_inherit_space_fields(obj_tree_1, space_1, global_reset, field):
|
|||||||
assert getattr(parent, field) != getattr(obj_tree_1, field)
|
assert getattr(parent, field) != getattr(obj_tree_1, field)
|
||||||
|
|
||||||
if global_reset:
|
if global_reset:
|
||||||
space_1.food_inherit.add(*Food.inheritable_fields.values_list('id', flat=True)) # set default inherit fields
|
# set default inherit fields
|
||||||
|
space_1.food_inherit.add(
|
||||||
|
*Food.inheritable_fields.values_list('id', flat=True))
|
||||||
parent.reset_inheritance(space=space_1)
|
parent.reset_inheritance(space=space_1)
|
||||||
else:
|
else:
|
||||||
obj_tree_1.child_inherit_fields.set(Food.inheritable_fields.values_list('id', flat=True))
|
obj_tree_1.child_inherit_fields.set(
|
||||||
|
Food.inheritable_fields.values_list('id', flat=True))
|
||||||
obj_tree_1.save()
|
obj_tree_1.save()
|
||||||
parent.reset_inheritance(space=space_1, food=obj_tree_1)
|
parent.reset_inheritance(space=space_1, food=obj_tree_1)
|
||||||
# djangotree bypasses ORM and need to be retrieved again
|
# djangotree bypasses ORM and need to be retrieved again
|
||||||
@ -545,12 +588,14 @@ def test_reset_inherit_space_fields(obj_tree_1, space_1, global_reset, field):
|
|||||||
parent = Food.objects.get(id=parent.id)
|
parent = Food.objects.get(id=parent.id)
|
||||||
child = Food.objects.get(id=child.id)
|
child = Food.objects.get(id=child.id)
|
||||||
|
|
||||||
assert (getattr(parent, field) == getattr(obj_tree_1, field)) == global_reset
|
assert (getattr(parent, field) == getattr(
|
||||||
|
obj_tree_1, field)) == global_reset
|
||||||
assert getattr(obj_tree_1, field) == getattr(child, field)
|
assert getattr(obj_tree_1, field) == getattr(child, field)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("obj_tree_1", [
|
@pytest.mark.parametrize("obj_tree_1", [
|
||||||
({'has_category': True, 'inherit': False, 'ignore_shopping': True, 'substitute_children': True, 'substitute_siblings': True}),
|
({'has_category': True, 'inherit': False, 'ignore_shopping': True,
|
||||||
|
'substitute_children': True, 'substitute_siblings': True}),
|
||||||
], indirect=['obj_tree_1'])
|
], indirect=['obj_tree_1'])
|
||||||
@pytest.mark.parametrize("field", ['ignore_shopping', 'substitute_children', 'substitute_siblings', 'supermarket_category'])
|
@pytest.mark.parametrize("field", ['ignore_shopping', 'substitute_children', 'substitute_siblings', 'supermarket_category'])
|
||||||
def test_reset_inherit_no_food_instances(obj_tree_1, space_1, field):
|
def test_reset_inherit_no_food_instances(obj_tree_1, space_1, field):
|
||||||
@ -558,13 +603,17 @@ def test_reset_inherit_no_food_instances(obj_tree_1, space_1, field):
|
|||||||
parent = obj_tree_1.get_parent()
|
parent = obj_tree_1.get_parent()
|
||||||
Food.objects.all().delete()
|
Food.objects.all().delete()
|
||||||
|
|
||||||
space_1.food_inherit.add(*Food.inheritable_fields.values_list('id', flat=True)) # set default inherit fields
|
# set default inherit fields
|
||||||
|
space_1.food_inherit.add(
|
||||||
|
*Food.inheritable_fields.values_list('id', flat=True))
|
||||||
parent.reset_inheritance(space=space_1)
|
parent.reset_inheritance(space=space_1)
|
||||||
|
|
||||||
|
|
||||||
def test_onhand(obj_1, u1_s1, u2_s1):
|
def test_onhand(obj_1, u1_s1, u2_s1):
|
||||||
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == False
|
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
|
||||||
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == False
|
'food_onhand'] == False
|
||||||
|
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
|
||||||
|
'food_onhand'] == False
|
||||||
|
|
||||||
u1_s1.patch(
|
u1_s1.patch(
|
||||||
reverse(
|
reverse(
|
||||||
@ -574,10 +623,13 @@ def test_onhand(obj_1, u1_s1, u2_s1):
|
|||||||
{'food_onhand': True},
|
{'food_onhand': True},
|
||||||
content_type='application/json'
|
content_type='application/json'
|
||||||
)
|
)
|
||||||
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == True
|
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
|
||||||
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == False
|
'food_onhand'] == True
|
||||||
|
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
|
||||||
|
'food_onhand'] == False
|
||||||
|
|
||||||
user1 = auth.get_user(u1_s1)
|
user1 = auth.get_user(u1_s1)
|
||||||
user2 = auth.get_user(u2_s1)
|
user2 = auth.get_user(u2_s1)
|
||||||
user1.userpreference.shopping_share.add(user2)
|
user1.userpreference.shopping_share.add(user2)
|
||||||
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == True
|
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
|
||||||
|
'food_onhand'] == True
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
import factory
|
|
||||||
import pytest
|
import pytest
|
||||||
# work around for bug described here https://stackoverflow.com/a/70312265/15762829
|
# work around for bug described here https://stackoverflow.com/a/70312265/15762829
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.forms import model_to_dict
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django_scopes import scopes_disabled
|
||||||
from django_scopes import scope, scopes_disabled
|
|
||||||
from pytest_factoryboy import LazyFixture, register
|
|
||||||
|
|
||||||
from cookbook.models import Food, Ingredient, ShoppingListEntry, Step
|
from cookbook.models import Food, Ingredient
|
||||||
from cookbook.tests.factories import (IngredientFactory, MealPlanFactory, RecipeFactory,
|
from cookbook.tests.factories import MealPlanFactory, RecipeFactory, StepFactory, UserFactory
|
||||||
StepFactory, UserFactory)
|
|
||||||
|
|
||||||
if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2',
|
if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2',
|
||||||
'django.db.backends.postgresql']:
|
'django.db.backends.postgresql']:
|
||||||
@ -32,9 +26,12 @@ def user2(request, u1_s1):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
params = {}
|
params = {}
|
||||||
user = auth.get_user(u1_s1)
|
user = auth.get_user(u1_s1)
|
||||||
user.userpreference.mealplan_autoadd_shopping = params.get('mealplan_autoadd_shopping', True)
|
user.userpreference.mealplan_autoadd_shopping = params.get(
|
||||||
user.userpreference.mealplan_autoinclude_related = params.get('mealplan_autoinclude_related', True)
|
'mealplan_autoadd_shopping', True)
|
||||||
user.userpreference.mealplan_autoexclude_onhand = params.get('mealplan_autoexclude_onhand', True)
|
user.userpreference.mealplan_autoinclude_related = params.get(
|
||||||
|
'mealplan_autoinclude_related', True)
|
||||||
|
user.userpreference.mealplan_autoexclude_onhand = params.get(
|
||||||
|
'mealplan_autoexclude_onhand', True)
|
||||||
user.userpreference.save()
|
user.userpreference.save()
|
||||||
return u1_s1
|
return u1_s1
|
||||||
|
|
||||||
@ -50,7 +47,6 @@ def recipe(request, space_1, u1_s1):
|
|||||||
return RecipeFactory(**params)
|
return RecipeFactory(**params)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("arg", [
|
@pytest.mark.parametrize("arg", [
|
||||||
['g1_s1', 204],
|
['g1_s1', 204],
|
||||||
['u1_s1', 204],
|
['u1_s1', 204],
|
||||||
@ -59,9 +55,12 @@ def recipe(request, space_1, u1_s1):
|
|||||||
])
|
])
|
||||||
@pytest.mark.parametrize("recipe, sle_count", [
|
@pytest.mark.parametrize("recipe, sle_count", [
|
||||||
({}, 10),
|
({}, 10),
|
||||||
({'steps__recipe_count': 1}, 20), # shopping list from recipe with StepRecipe
|
# shopping list from recipe with StepRecipe
|
||||||
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19), # shopping list from recipe with food recipe
|
({'steps__recipe_count': 1}, 20),
|
||||||
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29), # shopping list from recipe with StepRecipe and food recipe
|
# shopping list from recipe with food recipe
|
||||||
|
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19),
|
||||||
|
# shopping list from recipe with StepRecipe and food recipe
|
||||||
|
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29),
|
||||||
], indirect=['recipe'])
|
], indirect=['recipe'])
|
||||||
def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
|
def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
|
||||||
c = request.getfixturevalue(arg[0])
|
c = request.getfixturevalue(arg[0])
|
||||||
@ -78,16 +77,20 @@ def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
|
|||||||
if r.status_code == 204: # skip anonymous user
|
if r.status_code == 204: # skip anonymous user
|
||||||
|
|
||||||
r = json.loads(c.get(reverse(SHOPPING_LIST_URL)).content)
|
r = json.loads(c.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
assert len(r) == sle_count # recipe factory creates 10 ingredients by default
|
# recipe factory creates 10 ingredients by default
|
||||||
|
assert len(r) == sle_count
|
||||||
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
|
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
|
||||||
# user in space can't see shopping list
|
# user in space can't see shopping list
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
|
assert len(json.loads(
|
||||||
|
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
|
||||||
user.userpreference.shopping_share.add(auth.get_user(u2_s1))
|
user.userpreference.shopping_share.add(auth.get_user(u2_s1))
|
||||||
# after share, user in space can see shopping list
|
# after share, user in space can see shopping list
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
assert len(json.loads(
|
||||||
|
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
# confirm that the author of the recipe doesn't have access to shopping list
|
# confirm that the author of the recipe doesn't have access to shopping list
|
||||||
if c != u1_s1:
|
if c != u1_s1:
|
||||||
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
|
assert len(json.loads(
|
||||||
|
u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
|
||||||
|
|
||||||
r = c.get(url)
|
r = c.get(url)
|
||||||
assert r.status_code == 405
|
assert r.status_code == 405
|
||||||
@ -99,9 +102,12 @@ def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("recipe, sle_count", [
|
@pytest.mark.parametrize("recipe, sle_count", [
|
||||||
({}, 10),
|
({}, 10),
|
||||||
({'steps__recipe_count': 1}, 20), # shopping list from recipe with StepRecipe
|
# shopping list from recipe with StepRecipe
|
||||||
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19), # shopping list from recipe with food recipe
|
({'steps__recipe_count': 1}, 20),
|
||||||
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29), # shopping list from recipe with StepRecipe and food recipe
|
# shopping list from recipe with food recipe
|
||||||
|
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19),
|
||||||
|
# shopping list from recipe with StepRecipe and food recipe
|
||||||
|
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29),
|
||||||
], indirect=['recipe'])
|
], indirect=['recipe'])
|
||||||
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
||||||
def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u2_s1):
|
def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u2_s1):
|
||||||
@ -115,31 +121,33 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
|
|||||||
user.userpreference.save()
|
user.userpreference.save()
|
||||||
|
|
||||||
if use_mealplan:
|
if use_mealplan:
|
||||||
mealplan = MealPlanFactory(space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
|
mealplan = MealPlanFactory(
|
||||||
|
space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
|
||||||
else:
|
else:
|
||||||
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
||||||
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
|
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
|
||||||
all_ing = [x['ingredient'] for x in r]
|
all_ing = [x['ingredient'] for x in r]
|
||||||
keep_ing = all_ing[1:-1] # remove first and last element
|
keep_ing = all_ing[1:-1] # remove first and last element
|
||||||
del keep_ing[int(len(keep_ing)/2)] # remove a middle element
|
del keep_ing[int(len(keep_ing) / 2)] # remove a middle element
|
||||||
list_recipe = r[0]['list_recipe']
|
list_recipe = r[0]['list_recipe']
|
||||||
amount_sum = sum([x['amount'] for x in r])
|
amount_sum = sum([x['amount'] for x in r])
|
||||||
|
|
||||||
# test modifying shopping list as different user
|
# test modifying shopping list as different user
|
||||||
# test increasing servings size of recipe shopping list
|
# test increasing servings size of recipe shopping list
|
||||||
if use_mealplan:
|
if use_mealplan:
|
||||||
mealplan.servings = 2*recipe.servings
|
mealplan.servings = 2 * recipe.servings
|
||||||
mealplan.save()
|
mealplan.save()
|
||||||
else:
|
else:
|
||||||
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
{'list_recipe': list_recipe, 'servings': 2*recipe.servings},
|
{'list_recipe': list_recipe, 'servings': 2 * recipe.servings},
|
||||||
content_type='application/json'
|
content_type='application/json'
|
||||||
)
|
)
|
||||||
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
assert sum([x['amount'] for x in r]) == amount_sum * 2
|
assert sum([x['amount'] for x in r]) == amount_sum * 2
|
||||||
assert len(r) == sle_count
|
assert len(r) == sle_count
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
assert len(json.loads(
|
||||||
|
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
# testing decreasing servings size of recipe shopping list
|
# testing decreasing servings size of recipe shopping list
|
||||||
if use_mealplan:
|
if use_mealplan:
|
||||||
@ -153,7 +161,8 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
|
|||||||
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
assert sum([x['amount'] for x in r]) == amount_sum * .5
|
assert sum([x['amount'] for x in r]) == amount_sum * .5
|
||||||
assert len(r) == sle_count
|
assert len(r) == sle_count
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
assert len(json.loads(
|
||||||
|
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
# test removing 3 items from shopping list
|
# test removing 3 items from shopping list
|
||||||
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
@ -162,7 +171,8 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
|
|||||||
)
|
)
|
||||||
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
assert len(r) == sle_count - 3
|
assert len(r) == sle_count - 3
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - 3
|
assert len(json.loads(
|
||||||
|
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - 3
|
||||||
|
|
||||||
# add all ingredients to existing shopping list - don't change serving size
|
# add all ingredients to existing shopping list - don't change serving size
|
||||||
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
@ -172,14 +182,16 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
|
|||||||
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
assert sum([x['amount'] for x in r]) == amount_sum * .5
|
assert sum([x['amount'] for x in r]) == amount_sum * .5
|
||||||
assert len(r) == sle_count
|
assert len(r) == sle_count
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
assert len(json.loads(
|
||||||
|
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("user2, sle_count", [
|
@pytest.mark.parametrize("user2, sle_count", [
|
||||||
({'mealplan_autoadd_shopping': False}, (0, 18)),
|
({'mealplan_autoadd_shopping': False}, (0, 18)),
|
||||||
({'mealplan_autoinclude_related': False}, (9, 9)),
|
({'mealplan_autoinclude_related': False}, (9, 9)),
|
||||||
({'mealplan_autoexclude_onhand': False}, (20, 20)),
|
({'mealplan_autoexclude_onhand': False}, (20, 20)),
|
||||||
({'mealplan_autoexclude_onhand': False, 'mealplan_autoinclude_related': False}, (10, 10)),
|
({'mealplan_autoexclude_onhand': False,
|
||||||
|
'mealplan_autoinclude_related': False}, (10, 10)),
|
||||||
], indirect=['user2'])
|
], indirect=['user2'])
|
||||||
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
||||||
@pytest.mark.parametrize("recipe", [({'steps__recipe_count': 1})], indirect=['recipe'])
|
@pytest.mark.parametrize("recipe", [({'steps__recipe_count': 1})], indirect=['recipe'])
|
||||||
@ -191,20 +203,24 @@ def test_shopping_recipe_userpreference(recipe, sle_count, use_mealplan, user2):
|
|||||||
food = Food.objects.get(id=ingredients[2].food.id)
|
food = Food.objects.get(id=ingredients[2].food.id)
|
||||||
food.onhand_users.add(user)
|
food.onhand_users.add(user)
|
||||||
food.save()
|
food.save()
|
||||||
food = recipe.steps.exclude(step_recipe=None).first().step_recipe.steps.first().ingredients.first().food
|
food = recipe.steps.exclude(step_recipe=None).first(
|
||||||
|
).step_recipe.steps.first().ingredients.first().food
|
||||||
food = Food.objects.get(id=food.id)
|
food = Food.objects.get(id=food.id)
|
||||||
food.onhand_users.add(user)
|
food.onhand_users.add(user)
|
||||||
food.save()
|
food.save()
|
||||||
|
|
||||||
if use_mealplan:
|
if use_mealplan:
|
||||||
mealplan = MealPlanFactory(space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
|
MealPlanFactory(
|
||||||
assert len(json.loads(user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[0]
|
space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
|
||||||
|
assert len(json.loads(
|
||||||
|
user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[0]
|
||||||
else:
|
else:
|
||||||
user2.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
user2.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
||||||
assert len(json.loads(user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[1]
|
assert len(json.loads(
|
||||||
|
user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[1]
|
||||||
|
|
||||||
|
|
||||||
def test_shopping_recipe_mixed_authors(u1_s1, u2_s1,space_1):
|
def test_shopping_recipe_mixed_authors(u1_s1, u2_s1, space_1):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
user1 = auth.get_user(u1_s1)
|
user1 = auth.get_user(u1_s1)
|
||||||
user2 = auth.get_user(u2_s1)
|
user2 = auth.get_user(u2_s1)
|
||||||
@ -213,15 +229,19 @@ def test_shopping_recipe_mixed_authors(u1_s1, u2_s1,space_1):
|
|||||||
recipe1 = RecipeFactory(created_by=user1, space=space)
|
recipe1 = RecipeFactory(created_by=user1, space=space)
|
||||||
recipe2 = RecipeFactory(created_by=user2, space=space)
|
recipe2 = RecipeFactory(created_by=user2, space=space)
|
||||||
recipe3 = RecipeFactory(created_by=user3, space=space)
|
recipe3 = RecipeFactory(created_by=user3, space=space)
|
||||||
food = Food.objects.get(id=recipe1.steps.first().ingredients.first().food.id)
|
food = Food.objects.get(
|
||||||
|
id=recipe1.steps.first().ingredients.first().food.id)
|
||||||
food.recipe = recipe2
|
food.recipe = recipe2
|
||||||
food.save()
|
food.save()
|
||||||
recipe1.steps.add(StepFactory(step_recipe=recipe3, ingredients__count=0, space=space))
|
recipe1.steps.add(StepFactory(step_recipe=recipe3,
|
||||||
|
ingredients__count=0, space=space))
|
||||||
recipe1.save()
|
recipe1.save()
|
||||||
|
|
||||||
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe1.id}))
|
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe1.id}))
|
||||||
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 29
|
assert len(json.loads(
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
|
u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 29
|
||||||
|
assert len(json.loads(
|
||||||
|
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("recipe", [{'steps__ingredients__header': 1}], indirect=['recipe'])
|
@pytest.mark.parametrize("recipe", [{'steps__ingredients__header': 1}], indirect=['recipe'])
|
||||||
@ -230,4 +250,5 @@ def test_shopping_with_header_ingredient(u1_s1, recipe):
|
|||||||
# recipe.step_set.first().ingredient_set.add(IngredientFactory(ingredients__header=1))
|
# recipe.step_set.first().ingredient_set.add(IngredientFactory(ingredients__header=1))
|
||||||
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
||||||
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 10
|
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 10
|
||||||
assert len(json.loads(u1_s1.get(reverse('api:ingredient-list')).content)['results']) == 11
|
assert len(json.loads(
|
||||||
|
u1_s1.get(reverse('api:ingredient-list')).content)['results']) == 11
|
||||||
|
@ -5,12 +5,11 @@ import uuid
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.contrib.auth.models import Group, User
|
|
||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
from pytest_factoryboy import LazyFixture, register
|
from pytest_factoryboy import register
|
||||||
|
|
||||||
from cookbook.models import Food, Ingredient, Recipe, Space, Step, Unit
|
from cookbook.models import Food, Ingredient, Recipe, Step, Unit
|
||||||
from cookbook.tests.factories import FoodFactory, SpaceFactory, UserFactory
|
from cookbook.tests.factories import SpaceFactory, UserFactory
|
||||||
|
|
||||||
register(SpaceFactory, 'space_1')
|
register(SpaceFactory, 'space_1')
|
||||||
register(SpaceFactory, 'space_2')
|
register(SpaceFactory, 'space_2')
|
||||||
@ -60,8 +59,10 @@ def get_random_recipe(space_1, u1_s1):
|
|||||||
internal=True,
|
internal=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
s1 = Step.objects.create(name=str(uuid.uuid4()), instruction=str(uuid.uuid4()), space=space_1, )
|
s1 = Step.objects.create(name=str(uuid.uuid4()),
|
||||||
s2 = Step.objects.create(name=str(uuid.uuid4()), instruction=str(uuid.uuid4()), space=space_1, )
|
instruction=str(uuid.uuid4()), space=space_1, )
|
||||||
|
s2 = Step.objects.create(name=str(uuid.uuid4()),
|
||||||
|
instruction=str(uuid.uuid4()), space=space_1, )
|
||||||
|
|
||||||
r.steps.add(s1)
|
r.steps.add(s1)
|
||||||
r.steps.add(s2)
|
r.steps.add(s2)
|
||||||
@ -70,8 +71,10 @@ def get_random_recipe(space_1, u1_s1):
|
|||||||
s1.ingredients.add(
|
s1.ingredients.add(
|
||||||
Ingredient.objects.create(
|
Ingredient.objects.create(
|
||||||
amount=1,
|
amount=1,
|
||||||
food=Food.objects.get_or_create(name=str(uuid.uuid4()), space=space_1)[0],
|
food=Food.objects.get_or_create(
|
||||||
unit=Unit.objects.create(name=str(uuid.uuid4()), space=space_1, ),
|
name=str(uuid.uuid4()), space=space_1)[0],
|
||||||
|
unit=Unit.objects.create(
|
||||||
|
name=str(uuid.uuid4()), space=space_1, ),
|
||||||
note=str(uuid.uuid4()),
|
note=str(uuid.uuid4()),
|
||||||
space=space_1,
|
space=space_1,
|
||||||
)
|
)
|
||||||
@ -80,8 +83,10 @@ def get_random_recipe(space_1, u1_s1):
|
|||||||
s2.ingredients.add(
|
s2.ingredients.add(
|
||||||
Ingredient.objects.create(
|
Ingredient.objects.create(
|
||||||
amount=1,
|
amount=1,
|
||||||
food=Food.objects.get_or_create(name=str(uuid.uuid4()), space=space_1)[0],
|
food=Food.objects.get_or_create(
|
||||||
unit=Unit.objects.create(name=str(uuid.uuid4()), space=space_1, ),
|
name=str(uuid.uuid4()), space=space_1)[0],
|
||||||
|
unit=Unit.objects.create(
|
||||||
|
name=str(uuid.uuid4()), space=space_1, ),
|
||||||
note=str(uuid.uuid4()),
|
note=str(uuid.uuid4()),
|
||||||
space=space_1,
|
space=space_1,
|
||||||
)
|
)
|
||||||
@ -99,8 +104,10 @@ def get_random_json_recipe():
|
|||||||
{
|
{
|
||||||
"instruction": str(uuid.uuid4()),
|
"instruction": str(uuid.uuid4()),
|
||||||
"ingredients": [
|
"ingredients": [
|
||||||
{"food": {"name": str(uuid.uuid4())}, "unit": {"name": str(uuid.uuid4())}, "amount": random.randint(0, 10)},
|
{"food": {"name": str(uuid.uuid4())}, "unit": {"name": str(
|
||||||
{"food": {"name": str(uuid.uuid4())}, "unit": {"name": str(uuid.uuid4())}, "amount": random.randint(0, 10)},
|
uuid.uuid4())}, "amount": random.randint(0, 10)},
|
||||||
|
{"food": {"name": str(uuid.uuid4())}, "unit": {"name": str(
|
||||||
|
uuid.uuid4())}, "amount": random.randint(0, 10)},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -133,7 +140,8 @@ def validate_recipe(expected, recipe):
|
|||||||
for key in expected_lists:
|
for key in expected_lists:
|
||||||
for k in expected_lists[key]:
|
for k in expected_lists[key]:
|
||||||
try:
|
try:
|
||||||
print('comparing ', any([dict_compare(k, i) for i in target_lists[key]]))
|
print('comparing ', any([dict_compare(k, i)
|
||||||
|
for i in target_lists[key]]))
|
||||||
assert any([dict_compare(k, i) for i in target_lists[key]])
|
assert any([dict_compare(k, i) for i in target_lists[key]])
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
for result in [dict_compare(k, i, details=True) for i in target_lists[key]]:
|
for result in [dict_compare(k, i, details=True) for i in target_lists[key]]:
|
||||||
@ -152,7 +160,8 @@ def dict_compare(d1, d2, details=False):
|
|||||||
added = d1_keys - d2_keys
|
added = d1_keys - d2_keys
|
||||||
removed = d2_keys - d1_keys
|
removed = d2_keys - d1_keys
|
||||||
modified = {o: (d1[o], d2[o]) for o in not_dicts if d1[o] != d2[o]}
|
modified = {o: (d1[o], d2[o]) for o in not_dicts if d1[o] != d2[o]}
|
||||||
modified_dicts = {o: (d1[o], d2[o]) for o in sub_dicts if not d1[o].items() <= d2[o].items()}
|
modified_dicts = {o: (d1[o], d2[o])
|
||||||
|
for o in sub_dicts if not d1[o].items() <= d2[o].items()}
|
||||||
if details:
|
if details:
|
||||||
return added, removed, modified, modified_dicts
|
return added, removed, modified, modified_dicts
|
||||||
else:
|
else:
|
||||||
@ -173,12 +182,12 @@ def transpose(text, number=2):
|
|||||||
positions = random.sample(range(len(tokens[token_pos])), number)
|
positions = random.sample(range(len(tokens[token_pos])), number)
|
||||||
|
|
||||||
# swap the positions
|
# swap the positions
|
||||||
l = list(tokens[token_pos])
|
lt = list(tokens[token_pos])
|
||||||
for first, second in zip(positions[::2], positions[1::2]):
|
for first, second in zip(positions[::2], positions[1::2]):
|
||||||
l[first], l[second] = l[second], l[first]
|
lt[first], lt[second] = lt[second], lt[first]
|
||||||
|
|
||||||
# replace original tokens with swapped
|
# replace original tokens with swapped
|
||||||
tokens[token_pos] = ''.join(l)
|
tokens[token_pos] = ''.join(lt)
|
||||||
|
|
||||||
# return text with the swapped token
|
# return text with the swapped token
|
||||||
return ' '.join(tokens)
|
return ' '.join(tokens)
|
||||||
|
@ -4,13 +4,12 @@ from decimal import Decimal
|
|||||||
|
|
||||||
import factory
|
import factory
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib import auth
|
|
||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
from faker import Factory as FakerFactory
|
from faker import Factory as FakerFactory
|
||||||
from pytest_factoryboy import register
|
from pytest_factoryboy import register
|
||||||
|
|
||||||
from cookbook.models import Recipe, Step, UserSpace
|
from cookbook.models import UserSpace
|
||||||
|
|
||||||
# this code will run immediately prior to creating the model object useful when you want a reverse relationship
|
# this code will run immediately prior to creating the model object useful when you want a reverse relationship
|
||||||
# log = factory.RelatedFactory(
|
# log = factory.RelatedFactory(
|
||||||
@ -53,7 +52,8 @@ class SpaceFactory(factory.django.DjangoModelFactory):
|
|||||||
class UserFactory(factory.django.DjangoModelFactory):
|
class UserFactory(factory.django.DjangoModelFactory):
|
||||||
|
|
||||||
"""User factory."""
|
"""User factory."""
|
||||||
username = factory.LazyAttribute(lambda x: faker.simple_profile()['username'])
|
username = factory.LazyAttribute(
|
||||||
|
lambda x: faker.simple_profile()['username'])
|
||||||
first_name = factory.LazyAttribute(lambda x: faker.first_name())
|
first_name = factory.LazyAttribute(lambda x: faker.first_name())
|
||||||
last_name = factory.LazyAttribute(lambda x: faker.last_name())
|
last_name = factory.LazyAttribute(lambda x: faker.last_name())
|
||||||
email = factory.LazyAttribute(lambda x: faker.email())
|
email = factory.LazyAttribute(lambda x: faker.email())
|
||||||
@ -65,7 +65,8 @@ class UserFactory(factory.django.DjangoModelFactory):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if extracted:
|
if extracted:
|
||||||
us = UserSpace.objects.create(space=self.space, user=self, active=True)
|
us = UserSpace.objects.create(
|
||||||
|
space=self.space, user=self, active=True)
|
||||||
us.groups.add(Group.objects.get(name=extracted))
|
us.groups.add(Group.objects.get(name=extracted))
|
||||||
|
|
||||||
@factory.post_generation
|
@factory.post_generation
|
||||||
@ -75,10 +76,12 @@ class UserFactory(factory.django.DjangoModelFactory):
|
|||||||
|
|
||||||
if extracted:
|
if extracted:
|
||||||
for prefs in extracted:
|
for prefs in extracted:
|
||||||
self.userpreference[prefs] = extracted[prefs]/0 # intentionally break so it can be debugged later
|
# intentionally break so it can be debugged later
|
||||||
|
self.userpreference[prefs] = extracted[prefs] / 0
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
|
django_get_or_create = ('username', 'space',)
|
||||||
|
|
||||||
|
|
||||||
@register
|
@register
|
||||||
@ -98,18 +101,22 @@ class SupermarketCategoryFactory(factory.django.DjangoModelFactory):
|
|||||||
class FoodFactory(factory.django.DjangoModelFactory):
|
class FoodFactory(factory.django.DjangoModelFactory):
|
||||||
"""Food factory."""
|
"""Food factory."""
|
||||||
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10)[:128])
|
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10)[:128])
|
||||||
plural_name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3, variable_nb_words=False))
|
plural_name = factory.LazyAttribute(
|
||||||
|
lambda x: faker.sentence(nb_words=3, variable_nb_words=False))
|
||||||
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
||||||
supermarket_category = factory.Maybe(
|
supermarket_category = factory.Maybe(
|
||||||
factory.LazyAttribute(lambda x: x.has_category),
|
factory.LazyAttribute(lambda x: x.has_category),
|
||||||
yes_declaration=factory.SubFactory(SupermarketCategoryFactory, space=factory.SelfAttribute('..space')),
|
yes_declaration=factory.SubFactory(
|
||||||
|
SupermarketCategoryFactory, space=factory.SelfAttribute('..space')),
|
||||||
no_declaration=None
|
no_declaration=None
|
||||||
)
|
)
|
||||||
recipe = factory.Maybe(
|
recipe = factory.Maybe(
|
||||||
factory.LazyAttribute(lambda x: x.has_recipe),
|
factory.LazyAttribute(lambda x: x.has_recipe),
|
||||||
yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
|
yes_declaration=factory.SubFactory(
|
||||||
|
'cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
|
||||||
no_declaration=None
|
no_declaration=None
|
||||||
)
|
)
|
||||||
|
path = None
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
@factory.post_generation
|
@factory.post_generation
|
||||||
@ -127,17 +134,19 @@ class FoodFactory(factory.django.DjangoModelFactory):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = 'cookbook.Food'
|
model = 'cookbook.Food'
|
||||||
django_get_or_create = ('name', 'plural_name', 'space',)
|
django_get_or_create = ('name', 'plural_name', 'path', 'space',)
|
||||||
|
|
||||||
|
|
||||||
@register
|
@register
|
||||||
class RecipeBookFactory(factory.django.DjangoModelFactory):
|
class RecipeBookFactory(factory.django.DjangoModelFactory):
|
||||||
"""RecipeBook factory."""
|
"""RecipeBook factory."""
|
||||||
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3, variable_nb_words=False))
|
name = factory.LazyAttribute(lambda x: faker.sentence(
|
||||||
|
nb_words=3, variable_nb_words=False))
|
||||||
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
||||||
icon = None
|
icon = None
|
||||||
# shared = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
# shared = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
||||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
created_by = factory.SubFactory(
|
||||||
|
UserFactory, space=factory.SelfAttribute('..space'))
|
||||||
filter = None
|
filter = None
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
@ -149,7 +158,8 @@ class RecipeBookFactory(factory.django.DjangoModelFactory):
|
|||||||
@register
|
@register
|
||||||
class RecipeBookEntryFactory(factory.django.DjangoModelFactory):
|
class RecipeBookEntryFactory(factory.django.DjangoModelFactory):
|
||||||
"""RecipeBookEntry factory."""
|
"""RecipeBookEntry factory."""
|
||||||
book = factory.SubFactory(RecipeBookFactory, space=factory.SelfAttribute('..recipe.space'))
|
book = factory.SubFactory(
|
||||||
|
RecipeBookFactory, space=factory.SelfAttribute('..recipe.space'))
|
||||||
recipe = None
|
recipe = None
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -173,7 +183,8 @@ class UnitFactory(factory.django.DjangoModelFactory):
|
|||||||
@register
|
@register
|
||||||
class KeywordFactory(factory.django.DjangoModelFactory):
|
class KeywordFactory(factory.django.DjangoModelFactory):
|
||||||
"""Keyword factory."""
|
"""Keyword factory."""
|
||||||
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=2, variable_nb_words=False))
|
name = factory.LazyAttribute(lambda x: faker.sentence(
|
||||||
|
nb_words=2, variable_nb_words=False))
|
||||||
# icon = models.CharField(max_length=16, blank=True, null=True)
|
# icon = models.CharField(max_length=16, blank=True, null=True)
|
||||||
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
@ -184,15 +195,17 @@ class KeywordFactory(factory.django.DjangoModelFactory):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = 'cookbook.Keyword'
|
model = 'cookbook.Keyword'
|
||||||
django_get_or_create = ('name', 'space',)
|
django_get_or_create = ('name', 'space')
|
||||||
exclude = ('num')
|
exclude = ('num')
|
||||||
|
|
||||||
|
|
||||||
@register
|
@register
|
||||||
class IngredientFactory(factory.django.DjangoModelFactory):
|
class IngredientFactory(factory.django.DjangoModelFactory):
|
||||||
"""Ingredient factory."""
|
"""Ingredient factory."""
|
||||||
food = factory.SubFactory(FoodFactory, space=factory.SelfAttribute('..space'))
|
food = factory.SubFactory(
|
||||||
unit = factory.SubFactory(UnitFactory, space=factory.SelfAttribute('..space'))
|
FoodFactory, space=factory.SelfAttribute('..space'))
|
||||||
|
unit = factory.SubFactory(
|
||||||
|
UnitFactory, space=factory.SelfAttribute('..space'))
|
||||||
amount = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10))
|
amount = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10))
|
||||||
note = factory.LazyAttribute(lambda x: faker.sentence(nb_words=8))
|
note = factory.LazyAttribute(lambda x: faker.sentence(nb_words=8))
|
||||||
is_header = False
|
is_header = False
|
||||||
@ -210,7 +223,8 @@ class MealTypeFactory(factory.django.DjangoModelFactory):
|
|||||||
# icon =
|
# icon =
|
||||||
color = factory.LazyAttribute(lambda x: faker.safe_hex_color())
|
color = factory.LazyAttribute(lambda x: faker.safe_hex_color())
|
||||||
default = False
|
default = False
|
||||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
created_by = factory.SubFactory(
|
||||||
|
UserFactory, space=factory.SelfAttribute('..space'))
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -221,13 +235,17 @@ class MealTypeFactory(factory.django.DjangoModelFactory):
|
|||||||
class MealPlanFactory(factory.django.DjangoModelFactory):
|
class MealPlanFactory(factory.django.DjangoModelFactory):
|
||||||
recipe = factory.Maybe(
|
recipe = factory.Maybe(
|
||||||
factory.LazyAttribute(lambda x: x.has_recipe),
|
factory.LazyAttribute(lambda x: x.has_recipe),
|
||||||
yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
|
yes_declaration=factory.SubFactory(
|
||||||
|
'cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
|
||||||
no_declaration=None
|
no_declaration=None
|
||||||
)
|
)
|
||||||
servings = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=1000)/100))
|
servings = factory.LazyAttribute(
|
||||||
|
lambda x: Decimal(faker.random_int(min=1, max=1000) / 100))
|
||||||
title = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
|
title = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
|
||||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
created_by = factory.SubFactory(
|
||||||
meal_type = factory.SubFactory(MealTypeFactory, space=factory.SelfAttribute('..space'))
|
UserFactory, space=factory.SelfAttribute('..space'))
|
||||||
|
meal_type = factory.SubFactory(
|
||||||
|
MealTypeFactory, space=factory.SelfAttribute('..space'))
|
||||||
note = factory.LazyAttribute(lambda x: faker.paragraph())
|
note = factory.LazyAttribute(lambda x: faker.paragraph())
|
||||||
date = factory.LazyAttribute(lambda x: faker.future_date())
|
date = factory.LazyAttribute(lambda x: faker.future_date())
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
@ -244,11 +262,13 @@ class ShoppingListRecipeFactory(factory.django.DjangoModelFactory):
|
|||||||
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
|
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
|
||||||
recipe = factory.Maybe(
|
recipe = factory.Maybe(
|
||||||
factory.LazyAttribute(lambda x: x.has_recipe),
|
factory.LazyAttribute(lambda x: x.has_recipe),
|
||||||
yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
|
yes_declaration=factory.SubFactory(
|
||||||
|
'cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
|
||||||
no_declaration=None
|
no_declaration=None
|
||||||
)
|
)
|
||||||
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10))
|
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10))
|
||||||
mealplan = factory.SubFactory(MealPlanFactory, space=factory.SelfAttribute('..space'))
|
mealplan = factory.SubFactory(
|
||||||
|
MealPlanFactory, space=factory.SelfAttribute('..space'))
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
class Params:
|
class Params:
|
||||||
@ -264,25 +284,32 @@ class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
|
|||||||
|
|
||||||
list_recipe = factory.Maybe(
|
list_recipe = factory.Maybe(
|
||||||
factory.LazyAttribute(lambda x: x.has_mealplan),
|
factory.LazyAttribute(lambda x: x.has_mealplan),
|
||||||
yes_declaration=factory.SubFactory(ShoppingListRecipeFactory, space=factory.SelfAttribute('..space')),
|
yes_declaration=factory.SubFactory(
|
||||||
|
ShoppingListRecipeFactory, space=factory.SelfAttribute('..space')),
|
||||||
no_declaration=None
|
no_declaration=None
|
||||||
)
|
)
|
||||||
food = factory.SubFactory(FoodFactory, space=factory.SelfAttribute('..space'))
|
food = factory.SubFactory(
|
||||||
unit = factory.SubFactory(UnitFactory, space=factory.SelfAttribute('..space'))
|
FoodFactory, space=factory.SelfAttribute('..space'))
|
||||||
|
unit = factory.SubFactory(
|
||||||
|
UnitFactory, space=factory.SelfAttribute('..space'))
|
||||||
# # ingredient = factory.SubFactory(IngredientFactory)
|
# # ingredient = factory.SubFactory(IngredientFactory)
|
||||||
amount = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=100))/10)
|
amount = factory.LazyAttribute(
|
||||||
|
lambda x: Decimal(faker.random_int(min=1, max=100)) / 10)
|
||||||
order = factory.Sequence(int)
|
order = factory.Sequence(int)
|
||||||
checked = False
|
checked = False
|
||||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
created_by = factory.SubFactory(
|
||||||
|
UserFactory, space=factory.SelfAttribute('..space'))
|
||||||
created_at = factory.LazyAttribute(lambda x: faker.past_date())
|
created_at = factory.LazyAttribute(lambda x: faker.past_date())
|
||||||
completed_at = None
|
completed_at = None
|
||||||
delay_until = None
|
delay_until = None
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
# override create to prevent auto_add_now from changing the created_at date
|
||||||
|
def _create(cls, target_class, *args, **kwargs):
|
||||||
created_at = kwargs.pop('created_at', None)
|
created_at = kwargs.pop('created_at', None)
|
||||||
obj = super(ShoppingListEntryFactory, cls)._create(target_class, *args, **kwargs)
|
obj = super(ShoppingListEntryFactory, cls)._create(
|
||||||
|
target_class, *args, **kwargs)
|
||||||
if created_at is not None:
|
if created_at is not None:
|
||||||
obj.created_at = created_at
|
obj.created_at = created_at
|
||||||
obj.save()
|
obj.save()
|
||||||
@ -298,7 +325,8 @@ class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
|
|||||||
@register
|
@register
|
||||||
class StepFactory(factory.django.DjangoModelFactory):
|
class StepFactory(factory.django.DjangoModelFactory):
|
||||||
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
|
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
|
||||||
instruction = factory.LazyAttribute(lambda x: ''.join(faker.paragraphs(nb=5)))
|
instruction = factory.LazyAttribute(
|
||||||
|
lambda x: ''.join(faker.paragraphs(nb=5)))
|
||||||
# TODO add optional recipe food, make dependent on recipe, make number of recipes a Params
|
# TODO add optional recipe food, make dependent on recipe, make number of recipes a Params
|
||||||
ingredients__count = 10 # default number of ingredients to add
|
ingredients__count = 10 # default number of ingredients to add
|
||||||
ingredients__header = 0
|
ingredients__header = 0
|
||||||
@ -330,14 +358,16 @@ class StepFactory(factory.django.DjangoModelFactory):
|
|||||||
for i in range(num_ing):
|
for i in range(num_ing):
|
||||||
if num_food_recipe > 0:
|
if num_food_recipe > 0:
|
||||||
has_recipe = True
|
has_recipe = True
|
||||||
num_food_recipe = num_food_recipe-1
|
num_food_recipe = num_food_recipe - 1
|
||||||
else:
|
else:
|
||||||
has_recipe = False
|
has_recipe = False
|
||||||
self.ingredients.add(IngredientFactory(space=self.space, food__has_recipe=has_recipe))
|
self.ingredients.add(IngredientFactory(
|
||||||
|
space=self.space, food__has_recipe=has_recipe))
|
||||||
num_header = kwargs.get('header', 0)
|
num_header = kwargs.get('header', 0)
|
||||||
if num_header > 0:
|
if num_header > 0:
|
||||||
for i in range(num_header):
|
for i in range(num_header):
|
||||||
self.ingredients.add(IngredientFactory(food=None, unit=None, amount=0, is_header=True, space=self.space))
|
self.ingredients.add(IngredientFactory(
|
||||||
|
food=None, unit=None, amount=0, is_header=True, space=self.space))
|
||||||
elif extracted:
|
elif extracted:
|
||||||
for ing in extracted:
|
for ing in extracted:
|
||||||
self.ingredients.add(ing)
|
self.ingredients.add(ing)
|
||||||
@ -351,20 +381,27 @@ class RecipeFactory(factory.django.DjangoModelFactory):
|
|||||||
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=7))
|
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=7))
|
||||||
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
|
||||||
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=20))
|
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=20))
|
||||||
servings_text = factory.LazyAttribute(lambda x: faker.sentence(nb_words=1)) # TODO generate list of expected servings text that can be iterated through
|
# TODO generate list of expected servings text that can be iterated through
|
||||||
|
servings_text = factory.LazyAttribute(lambda x: faker.sentence(nb_words=1))
|
||||||
keywords__count = 5 # default number of keywords to generate
|
keywords__count = 5 # default number of keywords to generate
|
||||||
steps__count = 1 # default number of steps to create
|
steps__count = 1 # default number of steps to create
|
||||||
steps__recipe_count = 0 # default number of step recipes to create
|
steps__recipe_count = 0 # default number of step recipes to create
|
||||||
steps__food_recipe_count = {} # by default, don't create food recipes, to override {'steps__food_recipe_count': {'step': 0, 'count': 1}}
|
# by default, don't create food recipes, to override {'steps__food_recipe_count': {'step': 0, 'count': 1}}
|
||||||
working_time = factory.LazyAttribute(lambda x: faker.random_int(min=0, max=360))
|
steps__food_recipe_count = {}
|
||||||
waiting_time = factory.LazyAttribute(lambda x: faker.random_int(min=0, max=360))
|
working_time = factory.LazyAttribute(
|
||||||
|
lambda x: faker.random_int(min=0, max=360))
|
||||||
|
waiting_time = factory.LazyAttribute(
|
||||||
|
lambda x: faker.random_int(min=0, max=360))
|
||||||
internal = False
|
internal = False
|
||||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
created_by = factory.SubFactory(
|
||||||
created_at = factory.LazyAttribute(lambda x: faker.date_between_dates(date_start=date(2000, 1, 1), date_end=date(2020, 12, 31)))
|
UserFactory, space=factory.SelfAttribute('..space'))
|
||||||
|
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)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
# override create to prevent auto_add_now from changing the created_at date
|
||||||
|
def _create(cls, target_class, *args, **kwargs):
|
||||||
created_at = kwargs.pop('created_at', None)
|
created_at = kwargs.pop('created_at', None)
|
||||||
# updated_at = kwargs.pop('updated_at', None)
|
# updated_at = kwargs.pop('updated_at', None)
|
||||||
obj = super(RecipeFactory, cls)._create(target_class, *args, **kwargs)
|
obj = super(RecipeFactory, cls)._create(target_class, *args, **kwargs)
|
||||||
@ -401,11 +438,13 @@ class RecipeFactory(factory.django.DjangoModelFactory):
|
|||||||
ing_recipe_count = 0
|
ing_recipe_count = 0
|
||||||
if food_recipe_count.get('step', None) == i:
|
if food_recipe_count.get('step', None) == i:
|
||||||
ing_recipe_count = food_recipe_count.get('count', 0)
|
ing_recipe_count = food_recipe_count.get('count', 0)
|
||||||
self.steps.add(StepFactory(space=self.space, ingredients__food_recipe_count=ing_recipe_count, ingredients__header=num_ing_headers))
|
self.steps.add(StepFactory(
|
||||||
num_ing_headers+-1
|
space=self.space, ingredients__food_recipe_count=ing_recipe_count, ingredients__header=num_ing_headers))
|
||||||
|
num_ing_headers + - 1
|
||||||
if num_recipe_steps > 0:
|
if num_recipe_steps > 0:
|
||||||
for j in range(num_recipe_steps):
|
for j in range(num_recipe_steps):
|
||||||
self.steps.add(StepFactory(space=self.space, step_recipe__has_recipe=True, ingredients__count=0))
|
self.steps.add(StepFactory(
|
||||||
|
space=self.space, step_recipe__has_recipe=True, ingredients__count=0))
|
||||||
if extracted and (num_steps + num_recipe_steps == 0):
|
if extracted and (num_steps + num_recipe_steps == 0):
|
||||||
for step in extracted:
|
for step in extracted:
|
||||||
self.steps.add(step)
|
self.steps.add(step)
|
||||||
@ -428,15 +467,18 @@ class RecipeFactory(factory.django.DjangoModelFactory):
|
|||||||
@register
|
@register
|
||||||
class CookLogFactory(factory.django.DjangoModelFactory):
|
class CookLogFactory(factory.django.DjangoModelFactory):
|
||||||
"""CookLog factory."""
|
"""CookLog factory."""
|
||||||
recipe = factory.SubFactory(RecipeFactory, space=factory.SelfAttribute('..space'))
|
recipe = factory.SubFactory(
|
||||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
RecipeFactory, space=factory.SelfAttribute('..space'))
|
||||||
|
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_this_decade())
|
||||||
rating = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=5))
|
rating = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=5))
|
||||||
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=32))
|
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=32))
|
||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
# override create to prevent auto_add_now from changing the created_at date
|
||||||
|
def _create(cls, target_class, *args, **kwargs):
|
||||||
created_at = kwargs.pop('created_at', None)
|
created_at = kwargs.pop('created_at', None)
|
||||||
obj = super(CookLogFactory, cls)._create(target_class, *args, **kwargs)
|
obj = super(CookLogFactory, cls)._create(target_class, *args, **kwargs)
|
||||||
if created_at is not None:
|
if created_at is not None:
|
||||||
@ -451,13 +493,17 @@ class CookLogFactory(factory.django.DjangoModelFactory):
|
|||||||
@register
|
@register
|
||||||
class ViewLogFactory(factory.django.DjangoModelFactory):
|
class ViewLogFactory(factory.django.DjangoModelFactory):
|
||||||
"""ViewLog factory."""
|
"""ViewLog factory."""
|
||||||
recipe = factory.SubFactory(RecipeFactory, space=factory.SelfAttribute('..space'))
|
recipe = factory.SubFactory(
|
||||||
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
|
RecipeFactory, space=factory.SelfAttribute('..space'))
|
||||||
created_at = factory.LazyAttribute(lambda x: faker.past_datetime(start_date='-365d'))
|
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)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
|
# override create to prevent auto_add_now from changing the created_at date
|
||||||
|
def _create(cls, target_class, *args, **kwargs):
|
||||||
created_at = kwargs.pop('created_at', None)
|
created_at = kwargs.pop('created_at', None)
|
||||||
obj = super(ViewLogFactory, cls)._create(target_class, *args, **kwargs)
|
obj = super(ViewLogFactory, cls)._create(target_class, *args, **kwargs)
|
||||||
if created_at is not None:
|
if created_at is not None:
|
||||||
|
@ -11,6 +11,11 @@ from cookbook.tests.factories import FoodFactory, RecipeFactory
|
|||||||
# TODO returns recipes with all ingredients via child substitute
|
# TODO returns recipes with all ingredients via child substitute
|
||||||
# TODO returns recipes with all ingredients via sibling substitute
|
# TODO returns recipes with all ingredients via sibling substitute
|
||||||
|
|
||||||
|
if (Food.node_order_by):
|
||||||
|
node_location = 'sorted-child'
|
||||||
|
else:
|
||||||
|
node_location = 'last-child'
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def recipes(space_1):
|
def recipes(space_1):
|
||||||
@ -19,7 +24,8 @@ def recipes(space_1):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def makenow_recipe(request, space_1):
|
def makenow_recipe(request, space_1):
|
||||||
onhand_user = auth.get_user(request.getfixturevalue(request.param.get('onhand_users', 'u1_s1')))
|
onhand_user = auth.get_user(request.getfixturevalue(
|
||||||
|
request.param.get('onhand_users', 'u1_s1')))
|
||||||
|
|
||||||
recipe = RecipeFactory.create(space=space_1)
|
recipe = RecipeFactory.create(space=space_1)
|
||||||
for food in Food.objects.filter(ingredient__step__recipe=recipe.id):
|
for food in Food.objects.filter(ingredient__step__recipe=recipe.id):
|
||||||
@ -55,13 +61,16 @@ def test_makenow_ignoreshopping(recipes, makenow_recipe, user1, space_1):
|
|||||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||||
search = RecipeSearch(request, makenow='true')
|
search = RecipeSearch(request, makenow='true')
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
food = Food.objects.filter(
|
||||||
|
ingredient__step__recipe=makenow_recipe.id).first()
|
||||||
food.onhand_users.clear()
|
food.onhand_users.clear()
|
||||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||||
food.ignore_shopping = True
|
food.ignore_shopping = True
|
||||||
food.save()
|
food.save()
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
assert Food.objects.filter(
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, ignore_shopping=True).count() == 1
|
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())
|
search = search.get_queryset(Recipe.objects.all())
|
||||||
assert search.count() == 1
|
assert search.count() == 1
|
||||||
assert search.first().id == makenow_recipe.id
|
assert search.first().id == makenow_recipe.id
|
||||||
@ -74,13 +83,17 @@ def test_makenow_substitute(recipes, makenow_recipe, user1, space_1):
|
|||||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||||
search = RecipeSearch(request, makenow='true')
|
search = RecipeSearch(request, makenow='true')
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
food = Food.objects.filter(
|
||||||
|
ingredient__step__recipe=makenow_recipe.id).first()
|
||||||
onhand_user = food.onhand_users.first()
|
onhand_user = food.onhand_users.first()
|
||||||
food.onhand_users.clear()
|
food.onhand_users.clear()
|
||||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||||
food.substitute.add(FoodFactory.create(space=space_1, onhand_users=[onhand_user]))
|
food.substitute.add(FoodFactory.create(
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
space=space_1, onhand_users=[onhand_user]))
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, substitute__isnull=False).count() == 1
|
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())
|
search = search.get_queryset(Recipe.objects.all())
|
||||||
assert search.count() == 1
|
assert search.count() == 1
|
||||||
@ -94,16 +107,20 @@ def test_makenow_child_substitute(recipes, makenow_recipe, user1, space_1):
|
|||||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||||
search = RecipeSearch(request, makenow='true')
|
search = RecipeSearch(request, makenow='true')
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
food = Food.objects.filter(
|
||||||
|
ingredient__step__recipe=makenow_recipe.id).first()
|
||||||
onhand_user = food.onhand_users.first()
|
onhand_user = food.onhand_users.first()
|
||||||
food.onhand_users.clear()
|
food.onhand_users.clear()
|
||||||
food.substitute_children = True
|
food.substitute_children = True
|
||||||
food.save()
|
food.save()
|
||||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||||
new_food = FoodFactory.create(space=space_1, onhand_users=[onhand_user])
|
new_food = FoodFactory.create(
|
||||||
new_food.move(food, 'first-child')
|
space=space_1, onhand_users=[onhand_user])
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
new_food.move(food, node_location)
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, numchild__gt=0).count() == 1
|
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())
|
search = search.get_queryset(Recipe.objects.all())
|
||||||
assert search.count() == 1
|
assert search.count() == 1
|
||||||
assert search.first().id == makenow_recipe.id
|
assert search.first().id == makenow_recipe.id
|
||||||
@ -116,18 +133,22 @@ def test_makenow_sibling_substitute(recipes, makenow_recipe, user1, space_1):
|
|||||||
request = type('', (object,), {'space': space_1, 'user': user1})()
|
request = type('', (object,), {'space': space_1, 'user': user1})()
|
||||||
search = RecipeSearch(request, makenow='true')
|
search = RecipeSearch(request, makenow='true')
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
food = Food.objects.filter(ingredient__step__recipe=makenow_recipe.id).first()
|
food = Food.objects.filter(
|
||||||
|
ingredient__step__recipe=makenow_recipe.id).first()
|
||||||
onhand_user = food.onhand_users.first()
|
onhand_user = food.onhand_users.first()
|
||||||
food.onhand_users.clear()
|
food.onhand_users.clear()
|
||||||
food.substitute_siblings = True
|
food.substitute_siblings = True
|
||||||
food.save()
|
food.save()
|
||||||
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
assert search.get_queryset(Recipe.objects.all()).count() == 0
|
||||||
new_parent = FoodFactory.create(space=space_1)
|
new_parent = FoodFactory.create(space=space_1)
|
||||||
new_sibling = FoodFactory.create(space=space_1, onhand_users=[onhand_user])
|
new_sibling = FoodFactory.create(
|
||||||
new_sibling.move(new_parent, 'first-child')
|
space=space_1, onhand_users=[onhand_user])
|
||||||
food.move(new_parent, 'first-child')
|
new_sibling.move(new_parent, node_location)
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, onhand_users__isnull=False).count() == 9
|
food.move(new_parent, node_location)
|
||||||
assert Food.objects.filter(ingredient__step__recipe=makenow_recipe.id, depth=2).count() == 1
|
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())
|
search = search.get_queryset(Recipe.objects.all())
|
||||||
assert search.count() == 1
|
assert search.count() == 1
|
||||||
assert search.first().id == makenow_recipe.id
|
assert search.first().id == makenow_recipe.id
|
||||||
|
@ -7,9 +7,9 @@ from django.conf import settings
|
|||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django_scopes import scope, scopes_disabled
|
from django_scopes import scope
|
||||||
|
|
||||||
from cookbook.models import Food, Recipe, SearchFields
|
from cookbook.models import Recipe, SearchFields
|
||||||
from cookbook.tests.conftest import transpose
|
from cookbook.tests.conftest import transpose
|
||||||
from cookbook.tests.factories import (CookLogFactory, FoodFactory, IngredientFactory,
|
from cookbook.tests.factories import (CookLogFactory, FoodFactory, IngredientFactory,
|
||||||
KeywordFactory, RecipeBookEntryFactory, RecipeFactory,
|
KeywordFactory, RecipeBookEntryFactory, RecipeFactory,
|
||||||
@ -23,7 +23,8 @@ from cookbook.tests.factories import (CookLogFactory, FoodFactory, IngredientFac
|
|||||||
# TODO makenow with above filters
|
# TODO makenow with above filters
|
||||||
# TODO test search food/keywords including/excluding children
|
# TODO test search food/keywords including/excluding children
|
||||||
LIST_URL = 'api:recipe-list'
|
LIST_URL = 'api:recipe-list'
|
||||||
sqlite = settings.DATABASES['default']['ENGINE'] not in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
|
sqlite = settings.DATABASES['default']['ENGINE'] not in [
|
||||||
|
'django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -50,26 +51,43 @@ def user1(request, space_1, u1_s1, unaccent):
|
|||||||
if params.get('fuzzy_lookups', False):
|
if params.get('fuzzy_lookups', False):
|
||||||
user.searchpreference.lookup = True
|
user.searchpreference.lookup = True
|
||||||
misspelled_result = 1
|
misspelled_result = 1
|
||||||
|
else:
|
||||||
|
user.searchpreference.lookup = False
|
||||||
|
|
||||||
if params.get('fuzzy_search', False):
|
if params.get('fuzzy_search', False):
|
||||||
user.searchpreference.trigram.set(SearchFields.objects.all())
|
user.searchpreference.trigram.set(SearchFields.objects.all())
|
||||||
misspelled_result = 1
|
misspelled_result = 1
|
||||||
|
else:
|
||||||
|
user.searchpreference.trigram.set([])
|
||||||
|
|
||||||
if params.get('icontains', False):
|
if params.get('icontains', False):
|
||||||
user.searchpreference.icontains.set(SearchFields.objects.all())
|
user.searchpreference.icontains.set(SearchFields.objects.all())
|
||||||
search_term = 'ghijklmn'
|
search_term = 'ghijklmn'
|
||||||
|
else:
|
||||||
|
user.searchpreference.icontains.set([])
|
||||||
|
|
||||||
if params.get('istartswith', False):
|
if params.get('istartswith', False):
|
||||||
user.searchpreference.istartswith.set(SearchFields.objects.all())
|
user.searchpreference.istartswith.set(SearchFields.objects.all())
|
||||||
search_term = 'abcdef'
|
search_term = 'abcdef'
|
||||||
|
else:
|
||||||
|
user.searchpreference.istartswith.set([])
|
||||||
|
|
||||||
if params.get('unaccent', False):
|
if params.get('unaccent', False):
|
||||||
user.searchpreference.unaccent.set(SearchFields.objects.all())
|
user.searchpreference.unaccent.set(SearchFields.objects.all())
|
||||||
misspelled_result *= 2
|
misspelled_result *= 2
|
||||||
result *= 2
|
result *= 2
|
||||||
|
else:
|
||||||
|
user.searchpreference.unaccent.set([])
|
||||||
|
|
||||||
# full text vectors are hard coded to use unaccent - put this after unaccent to override result
|
# full text vectors are hard coded to use unaccent - put this after unaccent to override result
|
||||||
if params.get('fulltext', False):
|
if params.get('fulltext', False):
|
||||||
user.searchpreference.fulltext.set(SearchFields.objects.all())
|
user.searchpreference.fulltext.set(SearchFields.objects.all())
|
||||||
# user.searchpreference.search = 'websearch'
|
# user.searchpreference.search = 'websearch'
|
||||||
search_term = 'ghijklmn uvwxyz'
|
search_term = 'ghijklmn uvwxyz'
|
||||||
result = 2
|
result = 2
|
||||||
|
else:
|
||||||
|
user.searchpreference.fulltext.set([])
|
||||||
|
|
||||||
user.searchpreference.save()
|
user.searchpreference.save()
|
||||||
misspelled_term = transpose(search_term, number=3)
|
misspelled_term = transpose(search_term, number=3)
|
||||||
return (u1_s1, result, misspelled_result, search_term, misspelled_term, params)
|
return (u1_s1, result, misspelled_result, search_term, misspelled_term, params)
|
||||||
@ -104,7 +122,8 @@ def found_recipe(request, space_1, accent, unaccent, u1_s1, u2_s1):
|
|||||||
obj2 = FoodFactory.create(name=accent, space=space_1)
|
obj2 = FoodFactory.create(name=accent, space=space_1)
|
||||||
recipe1.steps.first().ingredients.add(IngredientFactory.create(food=obj1))
|
recipe1.steps.first().ingredients.add(IngredientFactory.create(food=obj1))
|
||||||
recipe2.steps.first().ingredients.add(IngredientFactory.create(food=obj2))
|
recipe2.steps.first().ingredients.add(IngredientFactory.create(food=obj2))
|
||||||
recipe3.steps.first().ingredients.add(IngredientFactory.create(food=obj1), IngredientFactory.create(food=obj2))
|
recipe3.steps.first().ingredients.add(IngredientFactory.create(
|
||||||
|
food=obj1), IngredientFactory.create(food=obj2))
|
||||||
if request.param.get('keyword', None):
|
if request.param.get('keyword', None):
|
||||||
obj1 = KeywordFactory.create(name=unaccent, space=space_1)
|
obj1 = KeywordFactory.create(name=unaccent, space=space_1)
|
||||||
obj2 = KeywordFactory.create(name=accent, space=space_1)
|
obj2 = KeywordFactory.create(name=accent, space=space_1)
|
||||||
@ -125,7 +144,8 @@ def found_recipe(request, space_1, accent, unaccent, u1_s1, u2_s1):
|
|||||||
obj2 = UnitFactory.create(name=accent, space=space_1)
|
obj2 = UnitFactory.create(name=accent, space=space_1)
|
||||||
recipe1.steps.first().ingredients.add(IngredientFactory.create(unit=obj1))
|
recipe1.steps.first().ingredients.add(IngredientFactory.create(unit=obj1))
|
||||||
recipe2.steps.first().ingredients.add(IngredientFactory.create(unit=obj2))
|
recipe2.steps.first().ingredients.add(IngredientFactory.create(unit=obj2))
|
||||||
recipe3.steps.first().ingredients.add(IngredientFactory.create(unit=obj1), IngredientFactory.create(unit=obj2))
|
recipe3.steps.first().ingredients.add(IngredientFactory.create(
|
||||||
|
unit=obj1), IngredientFactory.create(unit=obj2))
|
||||||
if request.param.get('name', None):
|
if request.param.get('name', None):
|
||||||
recipe1.name = unaccent
|
recipe1.name = unaccent
|
||||||
recipe2.name = accent
|
recipe2.name = accent
|
||||||
@ -145,21 +165,32 @@ def found_recipe(request, space_1, accent, unaccent, u1_s1, u2_s1):
|
|||||||
i2.save()
|
i2.save()
|
||||||
|
|
||||||
if request.param.get('viewedon', None):
|
if request.param.get('viewedon', None):
|
||||||
ViewLogFactory.create(recipe=recipe1, created_by=user1, created_at=days_3, space=space_1)
|
ViewLogFactory.create(recipe=recipe1, created_by=user1,
|
||||||
ViewLogFactory.create(recipe=recipe2, created_by=user1, created_at=days_30, space=space_1)
|
created_at=days_3, space=space_1)
|
||||||
ViewLogFactory.create(recipe=recipe3, created_by=user2, created_at=days_15, 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):
|
if request.param.get('cookedon', None):
|
||||||
CookLogFactory.create(recipe=recipe1, created_by=user1, created_at=days_3, space=space_1)
|
CookLogFactory.create(recipe=recipe1, created_by=user1,
|
||||||
CookLogFactory.create(recipe=recipe2, created_by=user1, created_at=days_30, space=space_1)
|
created_at=days_3, space=space_1)
|
||||||
CookLogFactory.create(recipe=recipe3, created_by=user2, created_at=days_15, 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):
|
if request.param.get('timescooked', None):
|
||||||
CookLogFactory.create_batch(5, recipe=recipe1, created_by=user1, space=space_1)
|
CookLogFactory.create_batch(
|
||||||
|
5, recipe=recipe1, created_by=user1, space=space_1)
|
||||||
CookLogFactory.create(recipe=recipe2, 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)
|
CookLogFactory.create_batch(
|
||||||
|
3, recipe=recipe3, created_by=user2, space=space_1)
|
||||||
if request.param.get('rating', None):
|
if request.param.get('rating', None):
|
||||||
CookLogFactory.create(recipe=recipe1, created_by=user1, rating=5.0, space=space_1)
|
CookLogFactory.create(
|
||||||
CookLogFactory.create(recipe=recipe2, created_by=user1, rating=1.0, space=space_1)
|
recipe=recipe1, created_by=user1, rating=5.0, space=space_1)
|
||||||
CookLogFactory.create(recipe=recipe3, created_by=user2, rating=3.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)
|
return (recipe1, recipe2, recipe3, obj1, obj2, request.param)
|
||||||
|
|
||||||
@ -188,7 +219,8 @@ def test_search_or_and_not(found_recipe, param_type, operator, recipes, u1_s1, s
|
|||||||
assert found_recipe[1].id in [x['id'] for x in r['results']]
|
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']]
|
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)
|
r = json.loads(u1_s1.get(reverse(LIST_URL) +
|
||||||
|
f'?{param1}&{param2}').content)
|
||||||
assert r['count'] == operator[1]
|
assert r['count'] == operator[1]
|
||||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||||
|
|
||||||
@ -203,7 +235,8 @@ def test_search_or_and_not(found_recipe, param_type, operator, recipes, u1_s1, s
|
|||||||
assert found_recipe[1].id not in [x['id'] for x in r['results']]
|
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']]
|
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)
|
r = json.loads(u1_s1.get(reverse(LIST_URL) +
|
||||||
|
f'?{param1_not}&{param2_not}').content)
|
||||||
assert r['count'] == 10 + operator[2]
|
assert r['count'] == 10 + operator[2]
|
||||||
assert found_recipe[2].id not in [x['id'] for x in r['results']]
|
assert found_recipe[2].id not in [x['id'] for x in r['results']]
|
||||||
|
|
||||||
@ -227,7 +260,8 @@ def test_search_units(found_recipe, recipes, u1_s1, space_1):
|
|||||||
assert found_recipe[1].id in [x['id'] for x in r['results']]
|
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']]
|
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)
|
r = json.loads(u1_s1.get(reverse(LIST_URL) +
|
||||||
|
f'?{param1}&{param2}').content)
|
||||||
assert r['count'] == 3
|
assert r['count'] == 3
|
||||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||||
|
|
||||||
@ -251,11 +285,15 @@ def test_fuzzy_lookup(found_recipe, recipes, param_type, user1, space_1):
|
|||||||
param1 = f"query={user1[3]}"
|
param1 = f"query={user1[3]}"
|
||||||
param2 = f"query={user1[4]}"
|
param2 = f"query={user1[4]}"
|
||||||
|
|
||||||
r = json.loads(user1[0].get(reverse(list_url) + f'?{param1}&limit=2').content)
|
r = json.loads(user1[0].get(reverse(list_url) +
|
||||||
assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[3].id, found_recipe[4].id]]) == user1[1]
|
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)
|
r = json.loads(user1[0].get(reverse(list_url) +
|
||||||
assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[3].id, found_recipe[4].id]]) == user1[2]
|
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
|
# commenting this out for general use - it is really slow
|
||||||
# it should be run on occasion to ensure everything still works
|
# it should be run on occasion to ensure everything still works
|
||||||
@ -276,29 +314,35 @@ def test_fuzzy_lookup(found_recipe, recipes, param_type, user1, space_1):
|
|||||||
# ({'keyword': True}),
|
# ({'keyword': True}),
|
||||||
# ({'food': True}),
|
# ({'food': True}),
|
||||||
# ], indirect=['found_recipe'])
|
# ], indirect=['found_recipe'])
|
||||||
|
# # user array contains: user client, expected count of search, expected count of mispelled search, search string, mispelled search string, user search preferences
|
||||||
# def test_search_string(found_recipe, recipes, user1, space_1):
|
# def test_search_string(found_recipe, recipes, user1, space_1):
|
||||||
# with scope(space=space_1):
|
# with scope(space=space_1):
|
||||||
# param1 = f"query={user1[3]}"
|
# param1 = f"query={user1[3]}"
|
||||||
# param2 = f"query={user1[4]}"
|
# param2 = f"query={user1[4]}"
|
||||||
|
|
||||||
# r = json.loads(user1[0].get(reverse(LIST_URL) + f'?{param1}').content)
|
# 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]
|
# 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)
|
# 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]
|
# 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", [
|
@pytest.mark.parametrize("found_recipe, param_type, result", [
|
||||||
({'viewedon': True}, 'viewedon', (1, 1)),
|
({'viewedon': True}, 'viewedon', (1, 1)),
|
||||||
({'cookedon': True}, 'cookedon', (1, 1)),
|
({'cookedon': True}, 'cookedon', (1, 1)),
|
||||||
({'createdon': True}, 'createdon', (2, 12)), # created dates are not filtered by user
|
# created dates are not filtered by user
|
||||||
({'createdon': True}, 'updatedon', (2, 12)), # updated dates are not filtered by user
|
({'createdon': True}, 'createdon', (2, 12)),
|
||||||
|
# updated dates are not filtered by user
|
||||||
|
({'createdon': True}, 'updatedon', (2, 12)),
|
||||||
], indirect=['found_recipe'])
|
], indirect=['found_recipe'])
|
||||||
def test_search_date(found_recipe, recipes, param_type, result, u1_s1, u2_s1, space_1):
|
def test_search_date(found_recipe, recipes, param_type, result, u1_s1, u2_s1, space_1):
|
||||||
# force updated_at to equal created_at datetime
|
# force updated_at to equal created_at datetime
|
||||||
with scope(space=space_1):
|
with scope(space=space_1):
|
||||||
for recipe in Recipe.objects.all():
|
for recipe in Recipe.objects.all():
|
||||||
Recipe.objects.filter(id=recipe.id).update(updated_at=recipe.created_at)
|
Recipe.objects.filter(id=recipe.id).update(
|
||||||
|
updated_at=recipe.created_at)
|
||||||
|
|
||||||
date = (timezone.now() - timedelta(days=15)).strftime("%Y-%m-%d")
|
date = (timezone.now() - timedelta(days=15)).strftime("%Y-%m-%d")
|
||||||
param1 = f"?{param_type}={date}"
|
param1 = f"?{param_type}={date}"
|
||||||
@ -321,34 +365,34 @@ def test_search_date(found_recipe, recipes, param_type, result, u1_s1, u2_s1, sp
|
|||||||
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||||
|
|
||||||
|
|
||||||
# TODO this is somehow screwed, probably the search itself, dont want to fix it for now
|
@pytest.mark.parametrize("found_recipe, param_type", [
|
||||||
# @pytest.mark.parametrize("found_recipe, param_type", [
|
({'rating': True}, 'rating'),
|
||||||
# ({'rating': True}, 'rating'),
|
({'timescooked': True}, 'timescooked'),
|
||||||
# ({'timescooked': True}, 'timescooked'),
|
], indirect=['found_recipe'])
|
||||||
# ], indirect=['found_recipe'])
|
def test_search_count(found_recipe, recipes, param_type, u1_s1, u2_s1, space_1):
|
||||||
# def test_search_count(found_recipe, recipes, param_type, u1_s1, u2_s1, space_1):
|
param1 = f'?{param_type}=3'
|
||||||
# param1 = f'?{param_type}=3'
|
param2 = f'?{param_type}=-3'
|
||||||
# param2 = f'?{param_type}=-3'
|
param3 = f'?{param_type}=0'
|
||||||
# param3 = f'?{param_type}=0'
|
|
||||||
#
|
r = json.loads(u1_s1.get(reverse(LIST_URL) + param1).content)
|
||||||
# r = json.loads(u1_s1.get(reverse(LIST_URL) + param1).content)
|
assert r['count'] == 1
|
||||||
# assert r['count'] == 1
|
assert found_recipe[0].id in [x['id'] for x in r['results']]
|
||||||
# assert found_recipe[0].id in [x['id'] for x in r['results']]
|
|
||||||
#
|
r = json.loads(u1_s1.get(reverse(LIST_URL) + param2).content)
|
||||||
# r = json.loads(u1_s1.get(reverse(LIST_URL) + param2).content)
|
assert r['count'] == 1
|
||||||
# assert r['count'] == 1
|
assert found_recipe[1].id in [x['id'] for x in r['results']]
|
||||||
# assert found_recipe[1].id in [x['id'] for x in r['results']]
|
|
||||||
#
|
# test search for not rated/cooked
|
||||||
# # test search for not rated/cooked
|
r = json.loads(u1_s1.get(reverse(LIST_URL) + param3).content)
|
||||||
# r = json.loads(u1_s1.get(reverse(LIST_URL) + param3).content)
|
assert r['count'] == 11
|
||||||
# assert r['count'] == 11
|
assert (found_recipe[0].id or found_recipe[1].id) not in [
|
||||||
# assert (found_recipe[0].id or found_recipe[1].id) not in [x['id'] for x in r['results']]
|
x['id'] for x in r['results']]
|
||||||
#
|
|
||||||
# # test matched returns for lte and gte searches
|
# test matched returns for lte and gte searches
|
||||||
# r = json.loads(u2_s1.get(reverse(LIST_URL) + param1).content)
|
r = json.loads(u2_s1.get(reverse(LIST_URL) + param1).content)
|
||||||
# assert r['count'] == 1
|
assert r['count'] == 1
|
||||||
# assert found_recipe[2].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(u2_s1.get(reverse(LIST_URL) + param2).content)
|
r = json.loads(u2_s1.get(reverse(LIST_URL) + param2).content)
|
||||||
# assert r['count'] == 1
|
assert r['count'] == 1
|
||||||
# assert found_recipe[2].id in [x['id'] for x in r['results']]
|
assert found_recipe[2].id in [x['id'] for x in r['results']]
|
||||||
|
@ -96,6 +96,7 @@ AUTH_LDAP_USER_SEARCH_FILTER_STR=(uid=%(user)s)
|
|||||||
AUTH_LDAP_USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn', 'email': 'mail'}
|
AUTH_LDAP_USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn', 'email': 'mail'}
|
||||||
AUTH_LDAP_ALWAYS_UPDATE_USER=1
|
AUTH_LDAP_ALWAYS_UPDATE_USER=1
|
||||||
AUTH_LDAP_CACHE_TIMEOUT=3600
|
AUTH_LDAP_CACHE_TIMEOUT=3600
|
||||||
|
AUTH_LDAP_START_TLS=1
|
||||||
AUTH_LDAP_TLS_CACERTFILE=/etc/ssl/certs/own-ca.pem
|
AUTH_LDAP_TLS_CACERTFILE=/etc/ssl/certs/own-ca.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,64 +18,68 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "Englisch"
|
msgstr "Englisch"
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Deutsch"
|
msgstr "Deutsch"
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "English"
|
#| msgid "English"
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr "Englisch"
|
msgstr "Englisch"
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -17,62 +17,66 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -19,62 +19,66 @@ msgstr ""
|
|||||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
|
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
|
||||||
"2);\n"
|
"2);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -17,62 +17,66 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -18,62 +18,66 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-01-19 19:14+0100\n"
|
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -17,62 +17,66 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: .\recipes\settings.py:382
|
#: .\recipes\settings.py:436
|
||||||
msgid "Armenian "
|
msgid "Armenian "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:383
|
#: .\recipes\settings.py:437
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:384
|
#: .\recipes\settings.py:438
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:385
|
#: .\recipes\settings.py:439
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:386
|
#: .\recipes\settings.py:440
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:387
|
#: .\recipes\settings.py:441
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:388
|
#: .\recipes\settings.py:442
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:389
|
#: .\recipes\settings.py:443
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:390
|
#: .\recipes\settings.py:444
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:391
|
#: .\recipes\settings.py:445
|
||||||
|
msgid "Hungarian"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: .\recipes\settings.py:446
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:392
|
#: .\recipes\settings.py:447
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:393
|
#: .\recipes\settings.py:448
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:394
|
#: .\recipes\settings.py:449
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:395
|
#: .\recipes\settings.py:450
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: .\recipes\settings.py:396
|
#: .\recipes\settings.py:451
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -24,7 +24,8 @@ load_dotenv()
|
|||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
# Get vars from .env files
|
# Get vars from .env files
|
||||||
SECRET_KEY = os.getenv('SECRET_KEY') if os.getenv('SECRET_KEY') else 'INSECURE_STANDARD_KEY_SET_IN_ENV'
|
SECRET_KEY = os.getenv('SECRET_KEY') if os.getenv(
|
||||||
|
'SECRET_KEY') else 'INSECURE_STANDARD_KEY_SET_IN_ENV'
|
||||||
|
|
||||||
DEBUG = bool(int(os.getenv('DEBUG', True)))
|
DEBUG = bool(int(os.getenv('DEBUG', True)))
|
||||||
DEBUG_TOOLBAR = bool(int(os.getenv('DEBUG_TOOLBAR', True)))
|
DEBUG_TOOLBAR = bool(int(os.getenv('DEBUG_TOOLBAR', True)))
|
||||||
@ -35,9 +36,11 @@ SOCIAL_DEFAULT_GROUP = os.getenv('SOCIAL_DEFAULT_GROUP', 'guest')
|
|||||||
SPACE_DEFAULT_MAX_RECIPES = int(os.getenv('SPACE_DEFAULT_MAX_RECIPES', 0))
|
SPACE_DEFAULT_MAX_RECIPES = int(os.getenv('SPACE_DEFAULT_MAX_RECIPES', 0))
|
||||||
SPACE_DEFAULT_MAX_USERS = int(os.getenv('SPACE_DEFAULT_MAX_USERS', 0))
|
SPACE_DEFAULT_MAX_USERS = int(os.getenv('SPACE_DEFAULT_MAX_USERS', 0))
|
||||||
SPACE_DEFAULT_MAX_FILES = int(os.getenv('SPACE_DEFAULT_MAX_FILES', 0))
|
SPACE_DEFAULT_MAX_FILES = int(os.getenv('SPACE_DEFAULT_MAX_FILES', 0))
|
||||||
SPACE_DEFAULT_ALLOW_SHARING = bool(int(os.getenv('SPACE_DEFAULT_ALLOW_SHARING', True)))
|
SPACE_DEFAULT_ALLOW_SHARING = bool(
|
||||||
|
int(os.getenv('SPACE_DEFAULT_ALLOW_SHARING', True)))
|
||||||
|
|
||||||
INTERNAL_IPS = os.getenv('INTERNAL_IPS').split(',') if os.getenv('INTERNAL_IPS') else ['127.0.0.1']
|
INTERNAL_IPS = os.getenv('INTERNAL_IPS').split(
|
||||||
|
',') if os.getenv('INTERNAL_IPS') else ['127.0.0.1']
|
||||||
|
|
||||||
# allow djangos wsgi server to server mediafiles
|
# allow djangos wsgi server to server mediafiles
|
||||||
GUNICORN_MEDIA = bool(int(os.getenv('GUNICORN_MEDIA', True)))
|
GUNICORN_MEDIA = bool(int(os.getenv('GUNICORN_MEDIA', True)))
|
||||||
@ -51,9 +54,11 @@ KJ_PREF_DEFAULT = bool(int(os.getenv('KJ_PREF_DEFAULT', False)))
|
|||||||
STICKY_NAV_PREF_DEFAULT = bool(int(os.getenv('STICKY_NAV_PREF_DEFAULT', True)))
|
STICKY_NAV_PREF_DEFAULT = bool(int(os.getenv('STICKY_NAV_PREF_DEFAULT', True)))
|
||||||
|
|
||||||
# minimum interval that users can set for automatic sync of shopping lists
|
# minimum interval that users can set for automatic sync of shopping lists
|
||||||
SHOPPING_MIN_AUTOSYNC_INTERVAL = int(os.getenv('SHOPPING_MIN_AUTOSYNC_INTERVAL', 5))
|
SHOPPING_MIN_AUTOSYNC_INTERVAL = int(
|
||||||
|
os.getenv('SHOPPING_MIN_AUTOSYNC_INTERVAL', 5))
|
||||||
|
|
||||||
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS').split(',') if os.getenv('ALLOWED_HOSTS') else ['*']
|
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS').split(
|
||||||
|
',') if os.getenv('ALLOWED_HOSTS') else ['*']
|
||||||
|
|
||||||
if os.getenv('CSRF_TRUSTED_ORIGINS'):
|
if os.getenv('CSRF_TRUSTED_ORIGINS'):
|
||||||
CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS').split(',')
|
CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS').split(',')
|
||||||
@ -131,7 +136,8 @@ try:
|
|||||||
plugin_module = f'recipes.plugins.{d}.apps.{app_config_classname}'
|
plugin_module = f'recipes.plugins.{d}.apps.{app_config_classname}'
|
||||||
if plugin_module not in INSTALLED_APPS:
|
if plugin_module not in INSTALLED_APPS:
|
||||||
INSTALLED_APPS.append(plugin_module)
|
INSTALLED_APPS.append(plugin_module)
|
||||||
plugin_class = getattr(sys.modules[apps_path], app_config_classname)
|
plugin_class = getattr(
|
||||||
|
sys.modules[apps_path], app_config_classname)
|
||||||
plugin_config = {
|
plugin_config = {
|
||||||
'name': plugin_class.verbose_name if hasattr(plugin_class, 'verbose_name') else plugin_class.name,
|
'name': plugin_class.verbose_name if hasattr(plugin_class, 'verbose_name') else plugin_class.name,
|
||||||
'module': f'recipes.plugins.{d}',
|
'module': f'recipes.plugins.{d}',
|
||||||
@ -148,7 +154,8 @@ except Exception:
|
|||||||
if DEBUG:
|
if DEBUG:
|
||||||
print('ERROR failed to initialize plugins')
|
print('ERROR failed to initialize plugins')
|
||||||
|
|
||||||
SOCIAL_PROVIDERS = os.getenv('SOCIAL_PROVIDERS').split(',') if os.getenv('SOCIAL_PROVIDERS') else []
|
SOCIAL_PROVIDERS = os.getenv('SOCIAL_PROVIDERS').split(
|
||||||
|
',') if os.getenv('SOCIAL_PROVIDERS') else []
|
||||||
SOCIALACCOUNT_EMAIL_VERIFICATION = 'none'
|
SOCIALACCOUNT_EMAIL_VERIFICATION = 'none'
|
||||||
INSTALLED_APPS = INSTALLED_APPS + SOCIAL_PROVIDERS
|
INSTALLED_APPS = INSTALLED_APPS + SOCIAL_PROVIDERS
|
||||||
|
|
||||||
@ -194,7 +201,8 @@ if DEBUG_TOOLBAR:
|
|||||||
INSTALLED_APPS += ('debug_toolbar',)
|
INSTALLED_APPS += ('debug_toolbar',)
|
||||||
|
|
||||||
SORT_TREE_BY_NAME = bool(int(os.getenv('SORT_TREE_BY_NAME', False)))
|
SORT_TREE_BY_NAME = bool(int(os.getenv('SORT_TREE_BY_NAME', False)))
|
||||||
DISABLE_TREE_FIX_STARTUP = bool(int(os.getenv('DISABLE_TREE_FIX_STARTUP', False)))
|
DISABLE_TREE_FIX_STARTUP = bool(
|
||||||
|
int(os.getenv('DISABLE_TREE_FIX_STARTUP', False)))
|
||||||
|
|
||||||
if bool(int(os.getenv('SQL_DEBUG', False))):
|
if bool(int(os.getenv('SQL_DEBUG', False))):
|
||||||
MIDDLEWARE += ('recipes.middleware.SqlPrintingMiddleware',)
|
MIDDLEWARE += ('recipes.middleware.SqlPrintingMiddleware',)
|
||||||
@ -213,6 +221,7 @@ if LDAP_AUTH:
|
|||||||
|
|
||||||
AUTHENTICATION_BACKENDS.append('django_auth_ldap.backend.LDAPBackend')
|
AUTHENTICATION_BACKENDS.append('django_auth_ldap.backend.LDAPBackend')
|
||||||
AUTH_LDAP_SERVER_URI = os.getenv('AUTH_LDAP_SERVER_URI')
|
AUTH_LDAP_SERVER_URI = os.getenv('AUTH_LDAP_SERVER_URI')
|
||||||
|
AUTH_LDAP_START_TLS = bool(int(os.getenv('AUTH_LDAP_START_TLS', False)))
|
||||||
AUTH_LDAP_BIND_DN = os.getenv('AUTH_LDAP_BIND_DN')
|
AUTH_LDAP_BIND_DN = os.getenv('AUTH_LDAP_BIND_DN')
|
||||||
AUTH_LDAP_BIND_PASSWORD = os.getenv('AUTH_LDAP_BIND_PASSWORD')
|
AUTH_LDAP_BIND_PASSWORD = os.getenv('AUTH_LDAP_BIND_PASSWORD')
|
||||||
AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
||||||
@ -225,10 +234,12 @@ if LDAP_AUTH:
|
|||||||
'last_name': 'sn',
|
'last_name': 'sn',
|
||||||
'email': 'mail',
|
'email': 'mail',
|
||||||
}
|
}
|
||||||
AUTH_LDAP_ALWAYS_UPDATE_USER = bool(int(os.getenv('AUTH_LDAP_ALWAYS_UPDATE_USER', True)))
|
AUTH_LDAP_ALWAYS_UPDATE_USER = bool(
|
||||||
|
int(os.getenv('AUTH_LDAP_ALWAYS_UPDATE_USER', True)))
|
||||||
AUTH_LDAP_CACHE_TIMEOUT = int(os.getenv('AUTH_LDAP_CACHE_TIMEOUT', 3600))
|
AUTH_LDAP_CACHE_TIMEOUT = int(os.getenv('AUTH_LDAP_CACHE_TIMEOUT', 3600))
|
||||||
if 'AUTH_LDAP_TLS_CACERTFILE' in os.environ:
|
if 'AUTH_LDAP_TLS_CACERTFILE' in os.environ:
|
||||||
AUTH_LDAP_GLOBAL_OPTIONS = {ldap.OPT_X_TLS_CACERTFILE: os.getenv('AUTH_LDAP_TLS_CACERTFILE')}
|
AUTH_LDAP_GLOBAL_OPTIONS = {
|
||||||
|
ldap.OPT_X_TLS_CACERTFILE: os.getenv('AUTH_LDAP_TLS_CACERTFILE')}
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
@ -249,7 +260,8 @@ ACCOUNT_ADAPTER = 'cookbook.helper.AllAuthCustomAdapter'
|
|||||||
|
|
||||||
if REVERSE_PROXY_AUTH:
|
if REVERSE_PROXY_AUTH:
|
||||||
MIDDLEWARE.insert(8, 'recipes.middleware.CustomRemoteUser')
|
MIDDLEWARE.insert(8, 'recipes.middleware.CustomRemoteUser')
|
||||||
AUTHENTICATION_BACKENDS.append('django.contrib.auth.backends.RemoteUserBackend')
|
AUTHENTICATION_BACKENDS.append(
|
||||||
|
'django.contrib.auth.backends.RemoteUserBackend')
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
|
||||||
@ -444,7 +456,8 @@ LANGUAGES = [
|
|||||||
|
|
||||||
SCRIPT_NAME = os.getenv('SCRIPT_NAME', '')
|
SCRIPT_NAME = os.getenv('SCRIPT_NAME', '')
|
||||||
# path for django_js_reverse to generate the javascript file containing all urls. Only done because the default command (collectstatic_js_reverse) fails to update the manifest
|
# path for django_js_reverse to generate the javascript file containing all urls. Only done because the default command (collectstatic_js_reverse) fails to update the manifest
|
||||||
JS_REVERSE_OUTPUT_PATH = os.path.join(BASE_DIR, "cookbook/static/django_js_reverse")
|
JS_REVERSE_OUTPUT_PATH = os.path.join(
|
||||||
|
BASE_DIR, "cookbook/static/django_js_reverse")
|
||||||
JS_REVERSE_SCRIPT_PREFIX = os.getenv('JS_REVERSE_SCRIPT_PREFIX', SCRIPT_NAME)
|
JS_REVERSE_SCRIPT_PREFIX = os.getenv('JS_REVERSE_SCRIPT_PREFIX', SCRIPT_NAME)
|
||||||
|
|
||||||
STATIC_URL = os.getenv('STATIC_URL', '/static/')
|
STATIC_URL = os.getenv('STATIC_URL', '/static/')
|
||||||
@ -499,4 +512,5 @@ EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD', '')
|
|||||||
EMAIL_USE_TLS = bool(int(os.getenv('EMAIL_USE_TLS', False)))
|
EMAIL_USE_TLS = bool(int(os.getenv('EMAIL_USE_TLS', False)))
|
||||||
EMAIL_USE_SSL = bool(int(os.getenv('EMAIL_USE_SSL', False)))
|
EMAIL_USE_SSL = bool(int(os.getenv('EMAIL_USE_SSL', False)))
|
||||||
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'webmaster@localhost')
|
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'webmaster@localhost')
|
||||||
ACCOUNT_EMAIL_SUBJECT_PREFIX = os.getenv('ACCOUNT_EMAIL_SUBJECT_PREFIX', '[Tandoor Recipes] ') # allauth sender prefix
|
ACCOUNT_EMAIL_SUBJECT_PREFIX = os.getenv(
|
||||||
|
'ACCOUNT_EMAIL_SUBJECT_PREFIX', '[Tandoor Recipes] ') # allauth sender prefix
|
||||||
|
@ -29,12 +29,12 @@ microdata==0.8.0
|
|||||||
Jinja2==3.1.2
|
Jinja2==3.1.2
|
||||||
django-webpack-loader==1.8.1
|
django-webpack-loader==1.8.1
|
||||||
git+https://github.com/BITSOLVER/django-js-reverse@071e304fd600107bc64bbde6f2491f1fe049ec82
|
git+https://github.com/BITSOLVER/django-js-reverse@071e304fd600107bc64bbde6f2491f1fe049ec82
|
||||||
django-allauth==0.52.0
|
django-allauth==0.54.0
|
||||||
recipe-scrapers==14.35.0
|
recipe-scrapers==14.36.1
|
||||||
django-scopes==1.2.0.post1
|
django-scopes==1.2.0.post1
|
||||||
pytest==7.2.2
|
pytest==7.3.1
|
||||||
pytest-django==4.5.2
|
pytest-django==4.5.2
|
||||||
django-treebeard==4.5.1
|
django-treebeard==4.7
|
||||||
django-cors-headers==3.13.0
|
django-cors-headers==3.13.0
|
||||||
django-storages==1.13.2
|
django-storages==1.13.2
|
||||||
boto3==1.26.41
|
boto3==1.26.41
|
||||||
@ -42,7 +42,7 @@ django-prometheus==2.2.0
|
|||||||
django-hCaptcha==0.2.0
|
django-hCaptcha==0.2.0
|
||||||
python-ldap==3.4.3
|
python-ldap==3.4.3
|
||||||
django-auth-ldap==4.2.0
|
django-auth-ldap==4.2.0
|
||||||
pytest-factoryboy==2.5.0
|
pytest-factoryboy==2.5.1
|
||||||
pyppeteer==1.0.2
|
pyppeteer==1.0.2
|
||||||
validators==0.20.0
|
validators==0.20.0
|
||||||
pytube==12.1.0
|
pytube==12.1.0
|
||||||
|
@ -12,18 +12,17 @@
|
|||||||
<i class="far fa-check-circle text-primary" v-if="!ingredient.checked"></i>
|
<i class="far fa-check-circle text-primary" v-if="!ingredient.checked"></i>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-nowrap" @click="done">
|
<td class="text-nowrap" @click="done">
|
||||||
<span v-if="ingredient.amount !== 0 && !ingredient.no_amount"
|
<span v-if="ingredient.amount !== 0 && !ingredient.no_amount" v-html="calculateAmount(ingredient.amount)"></span>
|
||||||
v-html="calculateAmount(ingredient.amount)"></span>
|
|
||||||
</td>
|
</td>
|
||||||
<td @click="done">
|
<td @click="done">
|
||||||
<template v-if="ingredient.unit !== null && !ingredient.no_amount">
|
<template v-if="ingredient.unit !== null && !ingredient.no_amount">
|
||||||
<template >
|
<template>
|
||||||
<template v-if="ingredient.unit.plural_name === '' || ingredient.unit.plural_name === null">
|
<template v-if="ingredient.unit.plural_name === '' || ingredient.unit.plural_name === null">
|
||||||
<span>{{ ingredient.unit.name }}</span>
|
<span>{{ ingredient.unit.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span v-if="ingredient.always_use_plural_unit">{{ ingredient.unit.plural_name}}</span>
|
<span v-if="ingredient.always_use_plural_unit">{{ ingredient.unit.plural_name }}</span>
|
||||||
<span v-else-if="(ingredient.amount * this.ingredient_factor) > 1">{{ ingredient.unit.plural_name }}</span>
|
<span v-else-if="ingredient.amount * this.ingredient_factor > 1">{{ ingredient.unit.plural_name }}</span>
|
||||||
<span v-else>{{ ingredient.unit.name }}</span>
|
<span v-else>{{ ingredient.unit.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
@ -31,11 +30,10 @@
|
|||||||
</td>
|
</td>
|
||||||
<td @click="done">
|
<td @click="done">
|
||||||
<template v-if="ingredient.food !== null">
|
<template v-if="ingredient.food !== null">
|
||||||
<a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)"
|
<a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)" v-if="ingredient.food.recipe !== null" target="_blank" rel="noopener noreferrer">{{
|
||||||
v-if="ingredient.food.recipe !== null" target="_blank"
|
ingredient.food.name
|
||||||
rel="noopener noreferrer">{{ ingredient.food.name }}</a>
|
}}</a>
|
||||||
<template v-if="ingredient.food.recipe === null">
|
<template v-if="ingredient.food.recipe === null">
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="ingredient.food.plural_name === '' || ingredient.food.plural_name === null">
|
<template v-if="ingredient.food.plural_name === '' || ingredient.food.plural_name === null">
|
||||||
<span>{{ ingredient.food.name }}</span>
|
<span>{{ ingredient.food.name }}</span>
|
||||||
@ -43,7 +41,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<span v-if="ingredient.always_use_plural_food">{{ ingredient.food.plural_name }}</span>
|
<span v-if="ingredient.always_use_plural_food">{{ ingredient.food.plural_name }}</span>
|
||||||
<span v-else-if="ingredient.no_amount">{{ ingredient.food.name }}</span>
|
<span v-else-if="ingredient.no_amount">{{ ingredient.food.name }}</span>
|
||||||
<span v-else-if="(ingredient.amount * this.ingredient_factor) > 1">{{ ingredient.food.plural_name }}</span>
|
<span v-else-if="ingredient.amount * this.ingredient_factor > 1">{{ ingredient.food.plural_name }}</span>
|
||||||
<span v-else>{{ ingredient.food.name }}</span>
|
<span v-else>{{ ingredient.food.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
@ -51,35 +49,32 @@
|
|||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td v-if="detailed">
|
<td v-if="detailed">
|
||||||
<div v-if="ingredient.note">
|
<template v-if="ingredient.note">
|
||||||
<span v-b-popover.hover="ingredient.note" class="d-print-none touchable p-0 pl-md-2 pr-md-2">
|
<span v-b-popover.hover="ingredient.note" class="d-print-none touchable py-0 px-2">
|
||||||
<i class="far fa-comment"></i>
|
<i class="far fa-comment"></i>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="d-none d-print-block"><i class="far fa-comment-alt d-print-none"></i> {{
|
<div class="d-none d-print-block"><i class="far fa-comment-alt d-print-none"></i> {{ ingredient.note }}</div>
|
||||||
ingredient.note
|
</template>
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</template>
|
</template>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {calculateAmount, ResolveUrlMixin} from "@/utils/utils"
|
import { calculateAmount, ResolveUrlMixin } from "@/utils/utils"
|
||||||
|
|
||||||
import Vue from "vue"
|
import Vue from "vue"
|
||||||
import VueSanitize from "vue-sanitize";
|
import VueSanitize from "vue-sanitize"
|
||||||
|
|
||||||
Vue.use(VueSanitize);
|
Vue.use(VueSanitize)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "IngredientComponent",
|
name: "IngredientComponent",
|
||||||
props: {
|
props: {
|
||||||
ingredient: Object,
|
ingredient: Object,
|
||||||
ingredient_factor: {type: Number, default: 1},
|
ingredient_factor: { type: Number, default: 1 },
|
||||||
detailed: {type: Boolean, default: true},
|
detailed: { type: Boolean, default: true },
|
||||||
},
|
},
|
||||||
mixins: [ResolveUrlMixin],
|
mixins: [ResolveUrlMixin],
|
||||||
data() {
|
data() {
|
||||||
@ -88,9 +83,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
mounted() {
|
mounted() {},
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
calculateAmount: function (x) {
|
calculateAmount: function (x) {
|
||||||
return this.$sanitize(calculateAmount(x, this.ingredient_factor))
|
return this.$sanitize(calculateAmount(x, this.ingredient_factor))
|
||||||
@ -106,9 +99,9 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
/* increase size of hover/touchable space without changing spacing */
|
/* increase size of hover/touchable space without changing spacing */
|
||||||
.touchable {
|
.touchable {
|
||||||
padding-right: 2em;
|
/* padding-right: 2em;
|
||||||
padding-left: 2em;
|
padding-left: 2em; */
|
||||||
margin-right: -2em;
|
margin-right: -1em;
|
||||||
margin-left: -2em;
|
margin-left: -1em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
"Cancel": "Abbrechen",
|
"Cancel": "Abbrechen",
|
||||||
"success_deleting_resource": "Ressource erfolgreich gelöscht!",
|
"success_deleting_resource": "Ressource erfolgreich gelöscht!",
|
||||||
"Load_More": "Weitere laden",
|
"Load_More": "Weitere laden",
|
||||||
"Ok": "Öffnen",
|
"Ok": "Ok",
|
||||||
"Link": "Link",
|
"Link": "Link",
|
||||||
"Key_Ctrl": "Strg",
|
"Key_Ctrl": "Strg",
|
||||||
"move_title": "{type} verschieben",
|
"move_title": "{type} verschieben",
|
||||||
@ -114,7 +114,7 @@
|
|||||||
"Create_New_Shopping Category": "Neue Einkaufskategorie erstellen",
|
"Create_New_Shopping Category": "Neue Einkaufskategorie erstellen",
|
||||||
"Automate": "Automatisieren",
|
"Automate": "Automatisieren",
|
||||||
"Type": "Typ",
|
"Type": "Typ",
|
||||||
"and_up": "& Höher",
|
"and_up": "& Hoch",
|
||||||
"Unrated": "Unbewertet",
|
"Unrated": "Unbewertet",
|
||||||
"Shopping_list": "Einkaufsliste",
|
"Shopping_list": "Einkaufsliste",
|
||||||
"step_time_minutes": "Schritt Dauer in Minuten",
|
"step_time_minutes": "Schritt Dauer in Minuten",
|
||||||
@ -206,7 +206,7 @@
|
|||||||
"New_Cookbook": "Neues Kochbuch",
|
"New_Cookbook": "Neues Kochbuch",
|
||||||
"Coming_Soon": "Bald verfügbar",
|
"Coming_Soon": "Bald verfügbar",
|
||||||
"Auto_Planner": "Smart Planen",
|
"Auto_Planner": "Smart Planen",
|
||||||
"Hide_Keyword": "Keywords schließen",
|
"Hide_Keyword": "Schlüsselwörter verbergen",
|
||||||
"Clear": "Leeren",
|
"Clear": "Leeren",
|
||||||
"GroupBy": "Gruppieren nach",
|
"GroupBy": "Gruppieren nach",
|
||||||
"IgnoreThis": "Füge {food} nie automatisch zur Einkaufsliste hinzu",
|
"IgnoreThis": "Füge {food} nie automatisch zur Einkaufsliste hinzu",
|
||||||
@ -222,11 +222,11 @@
|
|||||||
"NoCategory": "Keine Kategorie ausgewählt.",
|
"NoCategory": "Keine Kategorie ausgewählt.",
|
||||||
"ShowDelayed": "Zeige verschobene Elemente",
|
"ShowDelayed": "Zeige verschobene Elemente",
|
||||||
"Completed": "Fertig",
|
"Completed": "Fertig",
|
||||||
"OfflineAlert": "Du bist offline, deine Einkaufsliste wird nicht synchronisiert.",
|
"OfflineAlert": "Du bist offline. Deine Einkaufsliste wird nicht synchronisiert.",
|
||||||
"shopping_share": "Einkaufsliste teilen",
|
"shopping_share": "Einkaufsliste teilen",
|
||||||
"mealplan_autoadd_shopping": "Automatisches Hinzufügen zum Essensplan",
|
"mealplan_autoadd_shopping": "Automatisches Hinzufügen zum Essensplan",
|
||||||
"mealplan_autoexclude_onhand": "Ignoriere vorrätige Zutaten",
|
"mealplan_autoexclude_onhand": "Ignoriere vorrätige Zutaten",
|
||||||
"mealplan_autoinclude_related": "Füge verwandte Rezepte hinzu",
|
"mealplan_autoinclude_related": "Ähnliche Rezepte hinzufügen",
|
||||||
"default_delay": "Standard-Verzögerungszeit",
|
"default_delay": "Standard-Verzögerungszeit",
|
||||||
"Added_by": "Hinzugefügt durch",
|
"Added_by": "Hinzugefügt durch",
|
||||||
"AddToShopping": "Zur Einkaufsliste hinzufügen",
|
"AddToShopping": "Zur Einkaufsliste hinzufügen",
|
||||||
@ -241,7 +241,7 @@
|
|||||||
"IngredientInShopping": "Diese Zutat befindet sich auf Ihrer Einkaufsliste.",
|
"IngredientInShopping": "Diese Zutat befindet sich auf Ihrer Einkaufsliste.",
|
||||||
"NotInShopping": "{food} befindet sich nicht auf Ihrer Einkaufsliste.",
|
"NotInShopping": "{food} befindet sich nicht auf Ihrer Einkaufsliste.",
|
||||||
"OnHand": "Aktuell vorrätig",
|
"OnHand": "Aktuell vorrätig",
|
||||||
"FoodNotOnHand": "Sie habe {food} nicht vorrätig.",
|
"FoodNotOnHand": "Sie haben {food} nicht vorrätig.",
|
||||||
"Undefined": "undefiniert",
|
"Undefined": "undefiniert",
|
||||||
"AddFoodToShopping": "Fügen Sie {food} zur Einkaufsliste hinzu",
|
"AddFoodToShopping": "Fügen Sie {food} zur Einkaufsliste hinzu",
|
||||||
"RemoveFoodFromShopping": "{food} von der Einkaufsliste löschen",
|
"RemoveFoodFromShopping": "{food} von der Einkaufsliste löschen",
|
||||||
@ -251,23 +251,23 @@
|
|||||||
"mealplan_autoadd_shopping_desc": "Zutaten aus dem Essensplan automatisch zur Einkaufsliste hinzufügen.",
|
"mealplan_autoadd_shopping_desc": "Zutaten aus dem Essensplan automatisch zur Einkaufsliste hinzufügen.",
|
||||||
"Pin": "Anheften",
|
"Pin": "Anheften",
|
||||||
"mark_complete": "Vollständig markieren",
|
"mark_complete": "Vollständig markieren",
|
||||||
"shopping_add_onhand_desc": "Markiere Lebensmittel als \"Vorrätig\", wenn von der Einkaufsliste abgehakt wurden.",
|
"shopping_add_onhand_desc": "Zutat beim Abhaken auf der Einkausfliste als \"vorrätig\" kennzeichnen.",
|
||||||
"left_handed": "Linkshänder-Modus",
|
"left_handed": "Linkshänder-Modus",
|
||||||
"left_handed_help": "Optimiert die Benutzeroberfläche für die Bedienung mit der linken Hand.",
|
"left_handed_help": "Optimiert die Benutzeroberfläche für die Bedienung mit der linken Hand.",
|
||||||
"FoodInherit": "Lebensmittel vererbbare Felder",
|
"FoodInherit": "Lebensmittel vererbbare Felder",
|
||||||
"SupermarketCategoriesOnly": "Nur Supermarktkategorien",
|
"SupermarketCategoriesOnly": "Nur Supermarktkategorien",
|
||||||
"InheritWarning": "{food} ist auf Vererbung gesetzt ist, Änderungen werden möglicherweise nicht gespeichert.",
|
"InheritWarning": "{food} ist auf Vererbung gesetzt, Änderungen werden möglicherweise nicht gespeichert.",
|
||||||
"mealplan_autoexclude_onhand_desc": "Beim (manuellen oder automatischen) Hinzufügen eines Essensplans zur Einkaufsliste vorrätige Zutagen ausnehmen.",
|
"mealplan_autoexclude_onhand_desc": "Wenn ein Speiseplan zur Einkaufsliste zugefügt wird (manuell oder automatisch), Zutaten ausschliessen, die gerade vorrätig sind.",
|
||||||
"mealplan_autoinclude_related_desc": "Wenn Sie einen Essensplan zur Einkaufsliste hinzufügen (manuell oder automatisch), fügen Sie alle zugehörigen Rezepte hinzu.",
|
"mealplan_autoinclude_related_desc": "Wenn Sie einen Essensplan zur Einkaufsliste hinzufügen (manuell oder automatisch), fügen Sie alle zugehörigen Rezepte hinzu.",
|
||||||
"default_delay_desc": "Voreingestellte Anzahl von Stunden für die Verzögerung eines Einkaufslisteneintrags.",
|
"default_delay_desc": "Voreingestellte Anzahl von Stunden für die Verzögerung eines Einkaufslisteneintrags.",
|
||||||
"filter_to_supermarket": "Nach Supermarkt filtern",
|
"filter_to_supermarket": "Nach Supermarkt filtern",
|
||||||
"err_move_self": "Element kann nicht auf sich selbst verschoben werden",
|
"err_move_self": "Element kann nicht auf sich selbst verschoben werden",
|
||||||
"nothing": "Nichts zu tun",
|
"nothing": "Nichts zu tun",
|
||||||
"err_merge_self": "Element kann nicht mit sich selbst zusammengeführt werden",
|
"err_merge_self": "Element kann nicht mit sich selbst zusammengeführt werden",
|
||||||
"show_sql": "SQL anzeigen",
|
"show_sql": "Zeige SQL",
|
||||||
"filter_to_supermarket_desc": "Standardmäßig wird die Einkaufsliste so gefiltert, dass sie nur Kategorien für den ausgewählten Supermarkt enthält.",
|
"filter_to_supermarket_desc": "Standardmäßig wird die Einkaufsliste so gefiltert, dass sie nur Kategorien für den ausgewählten Supermarkt enthält.",
|
||||||
"CategoryName": "Kategorie Name",
|
"CategoryName": "Kategorienname",
|
||||||
"SupermarketName": "Supermarkt Name",
|
"SupermarketName": "Name Supermarkt",
|
||||||
"CategoryInstruction": "Ziehen Sie Kategorien, um die Reihenfolge zu ändern, in der die Kategorien in der Einkaufsliste erscheinen.",
|
"CategoryInstruction": "Ziehen Sie Kategorien, um die Reihenfolge zu ändern, in der die Kategorien in der Einkaufsliste erscheinen.",
|
||||||
"shopping_recent_days_desc": "Tage der letzten Einträge in der Einkaufsliste, die angezeigt werden sollen.",
|
"shopping_recent_days_desc": "Tage der letzten Einträge in der Einkaufsliste, die angezeigt werden sollen.",
|
||||||
"shopping_recent_days": "Letzte Tage",
|
"shopping_recent_days": "Letzte Tage",
|
||||||
@ -277,7 +277,7 @@
|
|||||||
"csv_delim_help": "Trennzeichen für CSV-Exporte.",
|
"csv_delim_help": "Trennzeichen für CSV-Exporte.",
|
||||||
"csv_delim_label": "CSV-Trennzeichen",
|
"csv_delim_label": "CSV-Trennzeichen",
|
||||||
"SuccessClipboard": "Einkaufsliste wurde in die Zwischenablage kopiert",
|
"SuccessClipboard": "Einkaufsliste wurde in die Zwischenablage kopiert",
|
||||||
"copy_to_clipboard": "In die Zwischenablage kopieren",
|
"copy_to_clipboard": "In Zwischenablage kopieren",
|
||||||
"csv_prefix_help": "Präfix, das beim Kopieren der Liste in die Zwischenablage hinzugefügt wird.",
|
"csv_prefix_help": "Präfix, das beim Kopieren der Liste in die Zwischenablage hinzugefügt wird.",
|
||||||
"csv_prefix_label": "Listenpräfix",
|
"csv_prefix_label": "Listenpräfix",
|
||||||
"copy_markdown_table": "Als Markdown-Tabelle kopieren",
|
"copy_markdown_table": "Als Markdown-Tabelle kopieren",
|
||||||
@ -291,10 +291,10 @@
|
|||||||
"remember_search": "Suchbegriff merken",
|
"remember_search": "Suchbegriff merken",
|
||||||
"remember_hours": "Stunden zu erinnern",
|
"remember_hours": "Stunden zu erinnern",
|
||||||
"tree_select": "Baum-Auswahl verwenden",
|
"tree_select": "Baum-Auswahl verwenden",
|
||||||
"CountMore": "...+{count} weitere",
|
"CountMore": "...+{count} mehr",
|
||||||
"ignore_shopping_help": "Füge Zutat nie zur Einkaufsliste hinzu (z.B. Wasser)",
|
"ignore_shopping_help": "Zutat nie auf Einkaufsliste setzen (z.B. Wasser)",
|
||||||
"OnHand_help": "Lebensmittel ist \"Vorrätig\" und wird nicht automatisch zur Einkaufsliste hinzugefügt. Der Status \"Vorrätig\" wird mit den Benutzern der Einkaufsliste geteilt.",
|
"OnHand_help": "Lebensmittel ist \"Vorrätig\" und wird nicht automatisch zur Einkaufsliste hinzugefügt. Der Status \"Vorrätig\" wird mit den Benutzern der Einkaufsliste geteilt.",
|
||||||
"shopping_category_help": "Supermärkte können nach Einkaufskategorien geordnet und gefiltert werden, je nachdem, wie die Gänge angeordnet sind.",
|
"shopping_category_help": "Einkaufsläden können nach Produktkategorie entsprechend der Anordnung der Regalreihen sortiert werden.",
|
||||||
"Foods": "Lebensmittel",
|
"Foods": "Lebensmittel",
|
||||||
"food_recipe_help": "Wird ein Rezept hier verknüpft, wird diese Verknüpfung in allen anderen Rezepten übernommen, die dieses Lebensmittel beinhaltet",
|
"food_recipe_help": "Wird ein Rezept hier verknüpft, wird diese Verknüpfung in allen anderen Rezepten übernommen, die dieses Lebensmittel beinhaltet",
|
||||||
"review_shopping": "Überprüfe die Einkaufsliste vor dem Speichern",
|
"review_shopping": "Überprüfe die Einkaufsliste vor dem Speichern",
|
||||||
@ -356,10 +356,10 @@
|
|||||||
"search_rank": "Such-Rang",
|
"search_rank": "Such-Rang",
|
||||||
"paste_ingredients": "Zutaten einfügen",
|
"paste_ingredients": "Zutaten einfügen",
|
||||||
"Ingredient Editor": "Zutateneditor",
|
"Ingredient Editor": "Zutateneditor",
|
||||||
"Protected": "Geschützt",
|
"Protected": "Schützen",
|
||||||
"not": "nicht",
|
"not": "nicht",
|
||||||
"warning_duplicate_filter": "Warnung: Wegen technischen Limitierungen können mehrere Filter der selben Kombination (und/oder/nicht) zu unerwarteten Ergebnissen führen.",
|
"warning_duplicate_filter": "Warnung: Wegen technischen Limitierungen können mehrere Filter der selben Kombination (und/oder/nicht) zu unerwarteten Ergebnissen führen.",
|
||||||
"and_down": "& Niedriger",
|
"and_down": "& Runter",
|
||||||
"enable_expert": "Expertenmodus aktivieren",
|
"enable_expert": "Expertenmodus aktivieren",
|
||||||
"filter_name": "Name des Filters",
|
"filter_name": "Name des Filters",
|
||||||
"shared_with": "Geteilt mit",
|
"shared_with": "Geteilt mit",
|
||||||
@ -407,11 +407,11 @@
|
|||||||
"Warning_Delete_Supermarket_Category": "Die Löschung einer Supermarktkategorie werden auch alle Beziehungen zu Lebensmitteln gelöscht. Bist du dir sicher?",
|
"Warning_Delete_Supermarket_Category": "Die Löschung einer Supermarktkategorie werden auch alle Beziehungen zu Lebensmitteln gelöscht. Bist du dir sicher?",
|
||||||
"New_Supermarket": "Erstelle einen neuen Supermarkt",
|
"New_Supermarket": "Erstelle einen neuen Supermarkt",
|
||||||
"New_Supermarket_Category": "Erstelle eine neue Supermarktkategorie",
|
"New_Supermarket_Category": "Erstelle eine neue Supermarktkategorie",
|
||||||
"warning_space_delete": "Du kannst deinen Bereich inklusive all deiner Rezepte, Einkaufslisten, Essensplänen und allem anderen, die du erstellt hast löschen. Dieser Schritt kann nicht rückgängig gemacht werden! Bist du sicher, dass du das tun möchtest?",
|
"warning_space_delete": "Du kannst deinen Space inklusive all deiner Rezepte, Shoppinglisten, Essensplänen und allem anderen, das du erstellt hast löschen. Dieser Schritt kann nicht rückgängig gemacht werden! Bist du sicher, dass du das tun möchtest?",
|
||||||
"Copy Link": "Link kopieren",
|
"Copy Link": "Kopiere den Link in die Zwischenablage",
|
||||||
"Users": "Benutzer",
|
"Users": "Benutzer",
|
||||||
"facet_count_info": "Zeige die Anzahl der Rezepte auf den Suchfiltern.",
|
"facet_count_info": "Zeige die Anzahl der Rezepte auf den Suchfiltern.",
|
||||||
"Copy Token": "Token kopieren",
|
"Copy Token": "Kopiere Token",
|
||||||
"Invites": "Einladungen",
|
"Invites": "Einladungen",
|
||||||
"Message": "Nachricht",
|
"Message": "Nachricht",
|
||||||
"Bookmarklet": "Lesezeichen",
|
"Bookmarklet": "Lesezeichen",
|
||||||
@ -473,11 +473,13 @@
|
|||||||
"UnpinnedConfirmation": "{recipe} wurde gelöst.",
|
"UnpinnedConfirmation": "{recipe} wurde gelöst.",
|
||||||
"Description_Replace": "Beschreibung ersetzen",
|
"Description_Replace": "Beschreibung ersetzen",
|
||||||
"Instruction_Replace": "Anleitung ersetzen",
|
"Instruction_Replace": "Anleitung ersetzen",
|
||||||
"Split_All_Steps": "Teile alle Zeilen in seperate Schritte auf.",
|
"Split_All_Steps": "Teile alle Zeilen in separate Schritte auf.",
|
||||||
"Auto_Sort_Help": "Verschiebe alle Zutaten zu dem Schritt, der am Besten passt.",
|
"Auto_Sort_Help": "Verschiebe alle Zutaten zu dem Schritt, der am Besten passt.",
|
||||||
"Combine_All_Steps": "Fasse alle Schritte in einem einzelnem Feld zusammen.",
|
"Combine_All_Steps": "Fasse alle Schritte in einem einzelnem Feld zusammen.",
|
||||||
"reset_children_help": "Überschreibe alle Kinder mit den Werten der vererbten Felder. Die vererbten Felder der Kinder werden als vererbte Felder gesetzt, es sei denn, das Kind-Vererben-Feld ist gesetzt.",
|
"reset_children_help": "Überschreibe alle Kinder mit den Werten der vererbten Felder. Die vererbten Felder der Kinder werden als vererbte Felder gesetzt, es sei denn, das Kind-Vererben-Feld ist gesetzt.",
|
||||||
"Unpin": "Lösen",
|
"Unpin": "Lösen",
|
||||||
"Amount": "Menge",
|
"Amount": "Menge",
|
||||||
"Original_Text": "Originaltext"
|
"Original_Text": "Originaler Text",
|
||||||
|
"Import Recipe": "Rezept importieren",
|
||||||
|
"Create Recipe": "Rezept erstellen"
|
||||||
}
|
}
|
||||||
|
@ -469,7 +469,7 @@
|
|||||||
"New_Supermarket_Category": "Create new supermarket category",
|
"New_Supermarket_Category": "Create new supermarket category",
|
||||||
"Are_You_Sure": "Are you sure?",
|
"Are_You_Sure": "Are you sure?",
|
||||||
"Valid Until": "Valid Until",
|
"Valid Until": "Valid Until",
|
||||||
"Split_All_Steps": "Split all rows into seperate steps.",
|
"Split_All_Steps": "Split all rows into separate steps.",
|
||||||
"Combine_All_Steps": "Combine all steps into a single field.",
|
"Combine_All_Steps": "Combine all steps into a single field.",
|
||||||
"Plural": "Plural",
|
"Plural": "Plural",
|
||||||
"plural_short": "plural",
|
"plural_short": "plural",
|
||||||
|
482
vue/src/locales/nb_NO.json
Normal file
482
vue/src/locales/nb_NO.json
Normal file
@ -0,0 +1,482 @@
|
|||||||
|
{
|
||||||
|
"warning_feature_beta": "Denne funksjonen er foreløpig i BETA-versjon (testing). Regn med feil og at det i fremtidige oppdateringer kan komme endringer som gjør funksjonen ubrukelig.",
|
||||||
|
"err_fetching_resource": "Feil ved henting av ressurs!",
|
||||||
|
"err_creating_resource": "Feil ved oppretting av ressurs!",
|
||||||
|
"err_updating_resource": "Feil ved oppdatering av ressurs!",
|
||||||
|
"err_deleting_resource": "Feil ved sletting av ressurs!",
|
||||||
|
"err_deleting_protected_resource": "Objektet du prøver å slette er fortsatt i bruk, og kan ikke slettes.",
|
||||||
|
"err_moving_resource": "Feil ved flytting av ressurs!",
|
||||||
|
"err_merging_resource": "Feil ved sammenslåing av ressurs!",
|
||||||
|
"success_fetching_resource": "Vellykket henting av ressurs!",
|
||||||
|
"success_creating_resource": "Vellykket oppretting av ressurs!",
|
||||||
|
"success_updating_resource": "Vellykket oppdatering av ressurs!",
|
||||||
|
"success_deleting_resource": "Vellykket sletting av ressurs!",
|
||||||
|
"success_moving_resource": "Vellykket flytting av ressurs!",
|
||||||
|
"success_merging_resource": "Vellykket sammenslåing av ressurs!",
|
||||||
|
"file_upload_disabled": "Opplasting av filer er ikke aktivert i området ditt.",
|
||||||
|
"warning_space_delete": "Du kan slette området, inkludert alle oppskrifter, handlelister, måltidsplaner og alt annet du har opprettet. Dette kan ikke angres! Er du sikker på at du vil gjøre dette?",
|
||||||
|
"food_inherit_info": "Felter på matvarer som skal arves som standard.",
|
||||||
|
"facet_count_info": "Vis oppskriftsantall i søkefilter.",
|
||||||
|
"step_time_minutes": "Tid for trinn, i minutter",
|
||||||
|
"confirm_delete": "Er du sikker på at du vil slette dette {object}?",
|
||||||
|
"import_running": "Importering pågår. Vennligst vent!",
|
||||||
|
"all_fields_optional": "Alle felt er valgfri, og kan stå tomme.",
|
||||||
|
"convert_internal": "Konverter til intern oppskrift",
|
||||||
|
"show_only_internal": "Vis bare interne oppskrifter",
|
||||||
|
"show_split_screen": "Delt visning",
|
||||||
|
"Log_Recipe_Cooking": "Logg oppskriftsbruk",
|
||||||
|
"External_Recipe_Image": "Bilde av ekstern oppskrift",
|
||||||
|
"Add_to_Shopping": "Legg til i handleliste",
|
||||||
|
"Add_to_Plan": "Legg til i Plan",
|
||||||
|
"Step_start_time": "Trinn starttid",
|
||||||
|
"Sort_by_new": "Sorter etter nyest",
|
||||||
|
"Table_of_Contents": "Innholdsfortegnelse",
|
||||||
|
"Recipes_per_page": "Oppskrifter per side",
|
||||||
|
"Show_as_header": "Vis som overskrift",
|
||||||
|
"Hide_as_header": "Skjul overskrift",
|
||||||
|
"Add_nutrition_recipe": "Legg til næringsinnhold til oppskrift",
|
||||||
|
"Remove_nutrition_recipe": "Fjern næringsinnhold fra oppskrift",
|
||||||
|
"Copy_template_reference": "Kopier mal-referanse",
|
||||||
|
"Save_and_View": "Lagre og vis",
|
||||||
|
"Manage_Books": "Administrer bøker",
|
||||||
|
"Meal_Plan": "Måltidsplan",
|
||||||
|
"Select_Book": "Velg bok",
|
||||||
|
"Select_File": "Velg fil",
|
||||||
|
"Recipe_Image": "Oppskriftsbilde",
|
||||||
|
"Import_finished": "Importering fullført",
|
||||||
|
"View_Recipes": "Vis oppskrifter",
|
||||||
|
"Log_Cooking": "Loggfør tilbereding",
|
||||||
|
"New_Recipe": "Ny oppskrift",
|
||||||
|
"Url_Import": "Importer lenke",
|
||||||
|
"Reset_Search": "Nullstill søk",
|
||||||
|
"Recently_Viewed": "Nylig vist",
|
||||||
|
"Load_More": "Last inn flere",
|
||||||
|
"New_Keyword": "Nytt nøkkelord",
|
||||||
|
"Delete_Keyword": "Slett nøkkelord",
|
||||||
|
"Edit_Keyword": "Rediger nøkkelord",
|
||||||
|
"Edit_Recipe": "Rediger oppskrift",
|
||||||
|
"Move_Keyword": "Flytt nøkkelord",
|
||||||
|
"Merge_Keyword": "Slå sammen nøkkelord",
|
||||||
|
"Hide_Keywords": "Skjul nøkkelord",
|
||||||
|
"Hide_Recipes": "Skjul oppskrifter",
|
||||||
|
"Move_Up": "Flytt opp",
|
||||||
|
"Move_Down": "Flytt ned",
|
||||||
|
"Step_Name": "Trinn navn",
|
||||||
|
"Step_Type": "Trinn type",
|
||||||
|
"Make_Header": "Bruk som overskrift",
|
||||||
|
"Make_Ingredient": "Bruk som ingrediens",
|
||||||
|
"Amount": "Mengde",
|
||||||
|
"Enable_Amount": "Aktiver mengde",
|
||||||
|
"Disable_Amount": "Deaktiver mengde",
|
||||||
|
"Ingredient Editor": "",
|
||||||
|
"Description_Replace": "",
|
||||||
|
"Instruction_Replace": "",
|
||||||
|
"Auto_Sort": "",
|
||||||
|
"Auto_Sort_Help": "",
|
||||||
|
"Private_Recipe": "",
|
||||||
|
"Private_Recipe_Help": "",
|
||||||
|
"reusable_help_text": "",
|
||||||
|
"Add_Step": "",
|
||||||
|
"Keywords": "",
|
||||||
|
"Books": "Bøker",
|
||||||
|
"Proteins": "",
|
||||||
|
"Fats": "",
|
||||||
|
"Carbohydrates": "Karbohydrater",
|
||||||
|
"Calories": "",
|
||||||
|
"Energy": "",
|
||||||
|
"Nutrition": "",
|
||||||
|
"Date": "",
|
||||||
|
"Share": "",
|
||||||
|
"Automation": "",
|
||||||
|
"Parameter": "",
|
||||||
|
"Export": "",
|
||||||
|
"Copy": "",
|
||||||
|
"Rating": "Karakter",
|
||||||
|
"Close": "Lukk",
|
||||||
|
"Cancel": "",
|
||||||
|
"Link": "Lenke",
|
||||||
|
"Add": "",
|
||||||
|
"New": "",
|
||||||
|
"Note": "",
|
||||||
|
"Success": "",
|
||||||
|
"Failure": "",
|
||||||
|
"Protected": "",
|
||||||
|
"Ingredients": "Ingredienser",
|
||||||
|
"Supermarket": "Butikk",
|
||||||
|
"Categories": "",
|
||||||
|
"Category": "",
|
||||||
|
"Selected": "",
|
||||||
|
"min": "",
|
||||||
|
"Servings": "",
|
||||||
|
"Waiting": "",
|
||||||
|
"Preparation": "",
|
||||||
|
"External": "",
|
||||||
|
"Size": "",
|
||||||
|
"Files": "",
|
||||||
|
"File": "",
|
||||||
|
"Edit": "",
|
||||||
|
"Image": "",
|
||||||
|
"Delete": "",
|
||||||
|
"Open": "",
|
||||||
|
"Ok": "",
|
||||||
|
"Save": "",
|
||||||
|
"Step": "",
|
||||||
|
"Search": "",
|
||||||
|
"Import": "",
|
||||||
|
"Print": "",
|
||||||
|
"Settings": "Innstillinger",
|
||||||
|
"or": "",
|
||||||
|
"and": "",
|
||||||
|
"Information": "",
|
||||||
|
"Download": "",
|
||||||
|
"Create": "Opprett",
|
||||||
|
"Search Settings": "",
|
||||||
|
"View": "",
|
||||||
|
"Recipes": "",
|
||||||
|
"Move": "",
|
||||||
|
"Merge": "",
|
||||||
|
"Parent": "",
|
||||||
|
"Copy Link": "",
|
||||||
|
"Copy Token": "",
|
||||||
|
"delete_confirmation": "",
|
||||||
|
"move_confirmation": "",
|
||||||
|
"merge_confirmation": "",
|
||||||
|
"create_rule": "",
|
||||||
|
"move_selection": "",
|
||||||
|
"merge_selection": "",
|
||||||
|
"Root": "",
|
||||||
|
"Ignore_Shopping": "",
|
||||||
|
"Shopping_Category": "",
|
||||||
|
"Shopping_Categories": "",
|
||||||
|
"Edit_Food": "",
|
||||||
|
"Move_Food": "",
|
||||||
|
"New_Food": "",
|
||||||
|
"Hide_Food": "",
|
||||||
|
"Food_Alias": "",
|
||||||
|
"Unit_Alias": "",
|
||||||
|
"Keyword_Alias": "",
|
||||||
|
"Delete_Food": "",
|
||||||
|
"No_ID": "",
|
||||||
|
"Meal_Plan_Days": "",
|
||||||
|
"merge_title": "",
|
||||||
|
"move_title": "",
|
||||||
|
"Food": "",
|
||||||
|
"Original_Text": "",
|
||||||
|
"Recipe_Book": "",
|
||||||
|
"del_confirmation_tree": "",
|
||||||
|
"delete_title": "",
|
||||||
|
"create_title": "",
|
||||||
|
"edit_title": "",
|
||||||
|
"Name": "",
|
||||||
|
"Type": "",
|
||||||
|
"Description": "",
|
||||||
|
"Recipe": "",
|
||||||
|
"tree_root": "",
|
||||||
|
"Icon": "",
|
||||||
|
"Unit": "",
|
||||||
|
"Decimals": "",
|
||||||
|
"Default_Unit": "",
|
||||||
|
"No_Results": "",
|
||||||
|
"New_Unit": "",
|
||||||
|
"Create_New_Shopping Category": "",
|
||||||
|
"Create_New_Food": "",
|
||||||
|
"Create_New_Keyword": "",
|
||||||
|
"Create_New_Unit": "",
|
||||||
|
"Create_New_Meal_Type": "",
|
||||||
|
"Create_New_Shopping_Category": "",
|
||||||
|
"and_up": "",
|
||||||
|
"and_down": "",
|
||||||
|
"Instructions": "",
|
||||||
|
"Unrated": "",
|
||||||
|
"Automate": "",
|
||||||
|
"Empty": "",
|
||||||
|
"Key_Ctrl": "",
|
||||||
|
"Key_Shift": "",
|
||||||
|
"Time": "",
|
||||||
|
"Text": "",
|
||||||
|
"Shopping_list": "",
|
||||||
|
"Added_by": "",
|
||||||
|
"Added_on": "",
|
||||||
|
"AddToShopping": "",
|
||||||
|
"IngredientInShopping": "",
|
||||||
|
"NotInShopping": "",
|
||||||
|
"OnHand": "",
|
||||||
|
"FoodOnHand": "",
|
||||||
|
"FoodNotOnHand": "",
|
||||||
|
"Undefined": "",
|
||||||
|
"Create_Meal_Plan_Entry": "",
|
||||||
|
"Edit_Meal_Plan_Entry": "",
|
||||||
|
"Title": "",
|
||||||
|
"Week": "",
|
||||||
|
"Month": "",
|
||||||
|
"Year": "",
|
||||||
|
"Planner": "",
|
||||||
|
"Planner_Settings": "",
|
||||||
|
"Period": "",
|
||||||
|
"Plan_Period_To_Show": "",
|
||||||
|
"Periods": "",
|
||||||
|
"Plan_Show_How_Many_Periods": "",
|
||||||
|
"Starting_Day": "",
|
||||||
|
"Meal_Types": "",
|
||||||
|
"Meal_Type": "",
|
||||||
|
"New_Entry": "",
|
||||||
|
"Clone": "",
|
||||||
|
"Drag_Here_To_Delete": "",
|
||||||
|
"Meal_Type_Required": "",
|
||||||
|
"Title_or_Recipe_Required": "",
|
||||||
|
"Color": "",
|
||||||
|
"New_Meal_Type": "",
|
||||||
|
"Use_Fractions": "",
|
||||||
|
"Use_Fractions_Help": "",
|
||||||
|
"AddFoodToShopping": "",
|
||||||
|
"RemoveFoodFromShopping": "",
|
||||||
|
"DeleteShoppingConfirm": "",
|
||||||
|
"IgnoredFood": "",
|
||||||
|
"Add_Servings_to_Shopping": "",
|
||||||
|
"Week_Numbers": "",
|
||||||
|
"Show_Week_Numbers": "",
|
||||||
|
"Export_As_ICal": "",
|
||||||
|
"Export_To_ICal": "",
|
||||||
|
"Cannot_Add_Notes_To_Shopping": "",
|
||||||
|
"Added_To_Shopping_List": "",
|
||||||
|
"Shopping_List_Empty": "",
|
||||||
|
"Next_Period": "",
|
||||||
|
"Previous_Period": "",
|
||||||
|
"Current_Period": "",
|
||||||
|
"Next_Day": "",
|
||||||
|
"Previous_Day": "",
|
||||||
|
"Inherit": "",
|
||||||
|
"InheritFields": "",
|
||||||
|
"FoodInherit": "",
|
||||||
|
"ShowUncategorizedFood": "",
|
||||||
|
"GroupBy": "",
|
||||||
|
"Language": "",
|
||||||
|
"Theme": "",
|
||||||
|
"SupermarketCategoriesOnly": "",
|
||||||
|
"MoveCategory": "",
|
||||||
|
"CountMore": "",
|
||||||
|
"IgnoreThis": "",
|
||||||
|
"DelayFor": "",
|
||||||
|
"Warning": "",
|
||||||
|
"NoCategory": "",
|
||||||
|
"InheritWarning": "",
|
||||||
|
"ShowDelayed": "",
|
||||||
|
"Completed": "",
|
||||||
|
"OfflineAlert": "",
|
||||||
|
"shopping_share": "",
|
||||||
|
"shopping_auto_sync": "",
|
||||||
|
"one_url_per_line": "",
|
||||||
|
"mealplan_autoadd_shopping": "",
|
||||||
|
"mealplan_autoexclude_onhand": "",
|
||||||
|
"mealplan_autoinclude_related": "",
|
||||||
|
"default_delay": "",
|
||||||
|
"plan_share_desc": "",
|
||||||
|
"shopping_share_desc": "",
|
||||||
|
"shopping_auto_sync_desc": "",
|
||||||
|
"mealplan_autoadd_shopping_desc": "",
|
||||||
|
"mealplan_autoexclude_onhand_desc": "",
|
||||||
|
"mealplan_autoinclude_related_desc": "",
|
||||||
|
"default_delay_desc": "",
|
||||||
|
"filter_to_supermarket": "",
|
||||||
|
"Coming_Soon": "",
|
||||||
|
"Auto_Planner": "",
|
||||||
|
"New_Cookbook": "",
|
||||||
|
"Hide_Keyword": "",
|
||||||
|
"Hour": "",
|
||||||
|
"Hours": "",
|
||||||
|
"Day": "",
|
||||||
|
"Days": "",
|
||||||
|
"Second": "",
|
||||||
|
"Seconds": "",
|
||||||
|
"Clear": "",
|
||||||
|
"Users": "",
|
||||||
|
"Invites": "",
|
||||||
|
"err_move_self": "",
|
||||||
|
"nothing": "",
|
||||||
|
"err_merge_self": "",
|
||||||
|
"show_sql": "",
|
||||||
|
"filter_to_supermarket_desc": "",
|
||||||
|
"CategoryName": "",
|
||||||
|
"SupermarketName": "",
|
||||||
|
"CategoryInstruction": "",
|
||||||
|
"shopping_recent_days_desc": "",
|
||||||
|
"shopping_recent_days": "",
|
||||||
|
"download_pdf": "",
|
||||||
|
"download_csv": "",
|
||||||
|
"csv_delim_help": "",
|
||||||
|
"csv_delim_label": "",
|
||||||
|
"SuccessClipboard": "",
|
||||||
|
"copy_to_clipboard": "",
|
||||||
|
"csv_prefix_help": "",
|
||||||
|
"csv_prefix_label": "",
|
||||||
|
"copy_markdown_table": "",
|
||||||
|
"in_shopping": "",
|
||||||
|
"DelayUntil": "",
|
||||||
|
"Pin": "",
|
||||||
|
"Unpin": "",
|
||||||
|
"PinnedConfirmation": "",
|
||||||
|
"UnpinnedConfirmation": "",
|
||||||
|
"mark_complete": "",
|
||||||
|
"QuickEntry": "",
|
||||||
|
"shopping_add_onhand_desc": "",
|
||||||
|
"shopping_add_onhand": "",
|
||||||
|
"related_recipes": "",
|
||||||
|
"today_recipes": "",
|
||||||
|
"sql_debug": "",
|
||||||
|
"remember_search": "",
|
||||||
|
"remember_hours": "",
|
||||||
|
"tree_select": "",
|
||||||
|
"OnHand_help": "",
|
||||||
|
"ignore_shopping_help": "",
|
||||||
|
"shopping_category_help": "",
|
||||||
|
"food_recipe_help": "",
|
||||||
|
"Foods": "",
|
||||||
|
"Account": "",
|
||||||
|
"Cosmetic": "",
|
||||||
|
"API": "",
|
||||||
|
"enable_expert": "",
|
||||||
|
"expert_mode": "",
|
||||||
|
"simple_mode": "",
|
||||||
|
"advanced": "",
|
||||||
|
"fields": "",
|
||||||
|
"show_keywords": "",
|
||||||
|
"show_foods": "",
|
||||||
|
"show_books": "",
|
||||||
|
"show_rating": "",
|
||||||
|
"show_units": "",
|
||||||
|
"show_filters": "",
|
||||||
|
"not": "",
|
||||||
|
"save_filter": "",
|
||||||
|
"filter_name": "",
|
||||||
|
"left_handed": "",
|
||||||
|
"left_handed_help": "",
|
||||||
|
"Custom Filter": "",
|
||||||
|
"shared_with": "",
|
||||||
|
"sort_by": "",
|
||||||
|
"asc": "",
|
||||||
|
"desc": "",
|
||||||
|
"date_viewed": "",
|
||||||
|
"last_cooked": "",
|
||||||
|
"times_cooked": "",
|
||||||
|
"date_created": "",
|
||||||
|
"show_sortby": "",
|
||||||
|
"search_rank": "",
|
||||||
|
"make_now": "",
|
||||||
|
"recipe_filter": "",
|
||||||
|
"book_filter_help": "",
|
||||||
|
"review_shopping": "",
|
||||||
|
"view_recipe": "",
|
||||||
|
"copy_to_new": "",
|
||||||
|
"recipe_name": "",
|
||||||
|
"paste_ingredients_placeholder": "",
|
||||||
|
"paste_ingredients": "",
|
||||||
|
"ingredient_list": "",
|
||||||
|
"explain": "",
|
||||||
|
"filter": "",
|
||||||
|
"Website": "",
|
||||||
|
"App": "",
|
||||||
|
"Message": "",
|
||||||
|
"Bookmarklet": "",
|
||||||
|
"Sticky_Nav": "",
|
||||||
|
"Sticky_Nav_Help": "",
|
||||||
|
"Nav_Color": "",
|
||||||
|
"Nav_Color_Help": "",
|
||||||
|
"Use_Kj": "",
|
||||||
|
"Comments_setting": "",
|
||||||
|
"click_image_import": "",
|
||||||
|
"no_more_images_found": "",
|
||||||
|
"import_duplicates": "",
|
||||||
|
"paste_json": "",
|
||||||
|
"Click_To_Edit": "",
|
||||||
|
"search_no_recipes": "",
|
||||||
|
"search_import_help_text": "",
|
||||||
|
"search_create_help_text": "",
|
||||||
|
"warning_duplicate_filter": "",
|
||||||
|
"reset_children": "",
|
||||||
|
"reset_children_help": "",
|
||||||
|
"reset_food_inheritance": "",
|
||||||
|
"reset_food_inheritance_info": "",
|
||||||
|
"substitute_help": "",
|
||||||
|
"substitute_siblings_help": "",
|
||||||
|
"substitute_children_help": "",
|
||||||
|
"substitute_siblings": "",
|
||||||
|
"substitute_children": "",
|
||||||
|
"SubstituteOnHand": "",
|
||||||
|
"ChildInheritFields": "",
|
||||||
|
"ChildInheritFields_help": "",
|
||||||
|
"InheritFields_help": "",
|
||||||
|
"show_ingredient_overview": "",
|
||||||
|
"Ingredient Overview": "",
|
||||||
|
"last_viewed": "",
|
||||||
|
"created_on": "",
|
||||||
|
"updatedon": "",
|
||||||
|
"Imported_From": "",
|
||||||
|
"advanced_search_settings": "",
|
||||||
|
"nothing_planned_today": "",
|
||||||
|
"no_pinned_recipes": "",
|
||||||
|
"Planned": "",
|
||||||
|
"Pinned": "",
|
||||||
|
"Imported": "",
|
||||||
|
"Quick actions": "",
|
||||||
|
"Ratings": "",
|
||||||
|
"Internal": "",
|
||||||
|
"Units": "",
|
||||||
|
"Manage_Emails": "",
|
||||||
|
"Change_Password": "",
|
||||||
|
"Social_Authentication": "",
|
||||||
|
"Random Recipes": "",
|
||||||
|
"parameter_count": "",
|
||||||
|
"select_keyword": "",
|
||||||
|
"add_keyword": "",
|
||||||
|
"select_file": "",
|
||||||
|
"select_recipe": "",
|
||||||
|
"select_unit": "",
|
||||||
|
"select_food": "",
|
||||||
|
"remove_selection": "",
|
||||||
|
"empty_list": "",
|
||||||
|
"Select": "Velg",
|
||||||
|
"Supermarkets": "",
|
||||||
|
"User": "",
|
||||||
|
"Username": "",
|
||||||
|
"First_name": "",
|
||||||
|
"Last_name": "",
|
||||||
|
"Keyword": "Nøkkelord",
|
||||||
|
"Advanced": "",
|
||||||
|
"Page": "",
|
||||||
|
"Single": "",
|
||||||
|
"Multiple": "",
|
||||||
|
"Reset": "",
|
||||||
|
"Disabled": "",
|
||||||
|
"Disable": "",
|
||||||
|
"Options": "",
|
||||||
|
"Create Food": "",
|
||||||
|
"create_food_desc": "",
|
||||||
|
"additional_options": "",
|
||||||
|
"Importer_Help": "",
|
||||||
|
"Documentation": "",
|
||||||
|
"Select_App_To_Import": "",
|
||||||
|
"Import_Supported": "",
|
||||||
|
"Export_Supported": "",
|
||||||
|
"Import_Not_Yet_Supported": "",
|
||||||
|
"Export_Not_Yet_Supported": "",
|
||||||
|
"Import_Result_Info": "",
|
||||||
|
"Recipes_In_Import": "",
|
||||||
|
"Toggle": "",
|
||||||
|
"Import_Error": "",
|
||||||
|
"Warning_Delete_Supermarket_Category": "",
|
||||||
|
"New_Supermarket": "",
|
||||||
|
"New_Supermarket_Category": "",
|
||||||
|
"Are_You_Sure": "",
|
||||||
|
"Valid Until": "",
|
||||||
|
"Split_All_Steps": "",
|
||||||
|
"Combine_All_Steps": "",
|
||||||
|
"Plural": "",
|
||||||
|
"plural_short": "",
|
||||||
|
"Use_Plural_Unit_Always": "",
|
||||||
|
"Use_Plural_Unit_Simple": "",
|
||||||
|
"Use_Plural_Food_Always": "",
|
||||||
|
"Use_Plural_Food_Simple": "",
|
||||||
|
"plural_usage_info": "",
|
||||||
|
"Create Recipe": "",
|
||||||
|
"Import Recipe": ""
|
||||||
|
}
|
@ -16,202 +16,468 @@
|
|||||||
"convert_internal": "Transformați în rețetă internă",
|
"convert_internal": "Transformați în rețetă internă",
|
||||||
"show_only_internal": "Arătați doar rețetele interne",
|
"show_only_internal": "Arătați doar rețetele interne",
|
||||||
"show_split_screen": "Vedere divizată",
|
"show_split_screen": "Vedere divizată",
|
||||||
"Log_Recipe_Cooking": "",
|
"Log_Recipe_Cooking": "Jurnalul rețetelor de pregătire",
|
||||||
"External_Recipe_Image": "",
|
"External_Recipe_Image": "Imagine rețetă externă",
|
||||||
"Add_to_Shopping": "",
|
"Add_to_Shopping": "Adaugare la cumpărături",
|
||||||
"Add_to_Plan": "",
|
"Add_to_Plan": "Adăugare la plan",
|
||||||
"Step_start_time": "",
|
"Step_start_time": "Pasule de începere a orei",
|
||||||
"Sort_by_new": "",
|
"Sort_by_new": "Sortare după nou",
|
||||||
"Table_of_Contents": "",
|
"Table_of_Contents": "Cuprins",
|
||||||
"Recipes_per_page": "",
|
"Recipes_per_page": "Rețete pe pagină",
|
||||||
"Show_as_header": "",
|
"Show_as_header": "Afișare ca antet",
|
||||||
"Hide_as_header": "",
|
"Hide_as_header": "Ascunderea ca antet",
|
||||||
"Add_nutrition_recipe": "",
|
"Add_nutrition_recipe": "Adăugare a nutriției la rețetă",
|
||||||
"Remove_nutrition_recipe": "",
|
"Remove_nutrition_recipe": "Ștergere a nutriției din rețetă",
|
||||||
"Copy_template_reference": "",
|
"Copy_template_reference": "Copie referința șablonului",
|
||||||
"Save_and_View": "",
|
"Save_and_View": "Salvare și vizionare",
|
||||||
"Manage_Books": "",
|
"Manage_Books": "Gestionarea cărților",
|
||||||
"Meal_Plan": "",
|
"Meal_Plan": "Plan de alimentare",
|
||||||
"Select_Book": "",
|
"Select_Book": "Selectare carte",
|
||||||
"Select_File": "",
|
"Select_File": "Selectare fișier",
|
||||||
"Recipe_Image": "",
|
"Recipe_Image": "Imagine a rețetei",
|
||||||
"Import_finished": "",
|
"Import_finished": "Importare finalizată",
|
||||||
"View_Recipes": "",
|
"View_Recipes": "Vizionare rețete",
|
||||||
"Log_Cooking": "",
|
"Log_Cooking": "Jurnal de pregătire",
|
||||||
"New_Recipe": "",
|
"New_Recipe": "Rețetă nouă",
|
||||||
"Url_Import": "",
|
"Url_Import": "Importă URL",
|
||||||
"Reset_Search": "",
|
"Reset_Search": "Resetarea căutării",
|
||||||
"Recently_Viewed": "",
|
"Recently_Viewed": "Vizualizate recent",
|
||||||
"Load_More": "",
|
"Load_More": "Încărcați mai mult",
|
||||||
"New_Keyword": "",
|
"New_Keyword": "Cuvânt cheie nou",
|
||||||
"Delete_Keyword": "",
|
"Delete_Keyword": "Ștergere cuvânt cheie",
|
||||||
"Edit_Keyword": "",
|
"Edit_Keyword": "Editează cuvânt cheie",
|
||||||
"Edit_Recipe": "",
|
"Edit_Recipe": "Editează rețeta",
|
||||||
"Move_Keyword": "",
|
"Move_Keyword": "Mută cuvânt cheie",
|
||||||
"Merge_Keyword": "",
|
"Merge_Keyword": "Unește cuvânt cheie",
|
||||||
"Hide_Keywords": "",
|
"Hide_Keywords": "Ascunde cuvânt cheie",
|
||||||
"Hide_Recipes": "",
|
"Hide_Recipes": "Ascunde rețetele",
|
||||||
"Move_Up": "",
|
"Move_Up": "Deplasați-vă în sus",
|
||||||
"Move_Down": "",
|
"Move_Down": "Deplasați-vă în jos",
|
||||||
"Step_Name": "",
|
"Step_Name": "Nume pas",
|
||||||
"Step_Type": "",
|
"Step_Type": "Tip pas",
|
||||||
"Make_Header": "",
|
"Make_Header": "Creare antet",
|
||||||
"Make_Ingredient": "",
|
"Make_Ingredient": "Create ingredient",
|
||||||
"Enable_Amount": "",
|
"Enable_Amount": "Activare cantitate",
|
||||||
"Disable_Amount": "",
|
"Disable_Amount": "Dezactivare cantitate",
|
||||||
"Add_Step": "",
|
"Add_Step": "Adaugă pas",
|
||||||
"Keywords": "",
|
"Keywords": "Cuvinte cheie",
|
||||||
"Books": "",
|
"Books": "Cărți",
|
||||||
"Proteins": "",
|
"Proteins": "Proteine",
|
||||||
"Fats": "",
|
"Fats": "Grăsimi",
|
||||||
"Carbohydrates": "",
|
"Carbohydrates": "Carbohidrați",
|
||||||
"Calories": "",
|
"Calories": "Calorii",
|
||||||
"Energy": "",
|
"Energy": "Energie",
|
||||||
"Nutrition": "",
|
"Nutrition": "Nutriție",
|
||||||
"Date": "",
|
"Date": "Dată",
|
||||||
"Share": "",
|
"Share": "Împărtășire",
|
||||||
"Automation": "",
|
"Automation": "Automatizare",
|
||||||
"Parameter": "",
|
"Parameter": "Parametru",
|
||||||
"Export": "",
|
"Export": "Exportă",
|
||||||
"Copy": "",
|
"Copy": "Copie",
|
||||||
"Rating": "",
|
"Rating": "Evaluare",
|
||||||
"Close": "",
|
"Close": "Închide",
|
||||||
"Cancel": "",
|
"Cancel": "Anulează",
|
||||||
"Link": "",
|
"Link": "Link",
|
||||||
"Add": "",
|
"Add": "Adaugă",
|
||||||
"New": "",
|
"New": "Nou",
|
||||||
"Note": "",
|
"Note": "Notă",
|
||||||
"Success": "",
|
"Success": "Succes",
|
||||||
"Failure": "",
|
"Failure": "Eșec",
|
||||||
"Ingredients": "",
|
"Ingredients": "Ingrediente",
|
||||||
"Supermarket": "",
|
"Supermarket": "Supermarket",
|
||||||
"Categories": "",
|
"Categories": "Categorii",
|
||||||
"Category": "",
|
"Category": "Categorie",
|
||||||
"Selected": "",
|
"Selected": "Selectat",
|
||||||
"min": "",
|
"min": "min",
|
||||||
"Servings": "",
|
"Servings": "Porții",
|
||||||
"Waiting": "",
|
"Waiting": "Așteptare",
|
||||||
"Preparation": "",
|
"Preparation": "Pregătire",
|
||||||
"External": "",
|
"External": "Extern",
|
||||||
"Size": "",
|
"Size": "Marime",
|
||||||
"Files": "",
|
"Files": "Fișiere",
|
||||||
"File": "",
|
"File": "Fișier",
|
||||||
"Edit": "",
|
"Edit": "Editează",
|
||||||
"Image": "",
|
"Image": "Imagine",
|
||||||
"Delete": "",
|
"Delete": "Șterge",
|
||||||
"Open": "",
|
"Open": "Deschide",
|
||||||
"Ok": "",
|
"Ok": "Ok",
|
||||||
"Save": "",
|
"Save": "Salvare",
|
||||||
"Step": "",
|
"Step": "Pas",
|
||||||
"Search": "",
|
"Search": "Căutare",
|
||||||
"Import": "",
|
"Import": "Importă",
|
||||||
"Print": "",
|
"Print": "Tipărește",
|
||||||
"Settings": "",
|
"Settings": "Setări",
|
||||||
"or": "",
|
"or": "sau",
|
||||||
"and": "",
|
"and": "și",
|
||||||
"Information": "",
|
"Information": "Informație",
|
||||||
"Download": "",
|
"Download": "Descarcă",
|
||||||
"Create": "",
|
"Create": "Creează",
|
||||||
"Advanced Search Settings": "",
|
"Advanced Search Settings": "",
|
||||||
"View": "",
|
"View": "Vizualizare",
|
||||||
"Recipes": "",
|
"Recipes": "Rețete",
|
||||||
"Move": "",
|
"Move": "Mută",
|
||||||
"Merge": "",
|
"Merge": "Unire",
|
||||||
"Parent": "",
|
"Parent": "Părinte",
|
||||||
"delete_confirmation": "",
|
"delete_confirmation": "Sunteți sigur că doriți să ștergeți {source}?",
|
||||||
"move_confirmation": "",
|
"move_confirmation": "Mutare <i>{copil}</i> la părinte <i>{părinte}</i>",
|
||||||
"merge_confirmation": "",
|
"merge_confirmation": "Înlocuiți <i>{source}</i> cu <i>{target}</i>",
|
||||||
"create_rule": "",
|
"create_rule": "și crearea automatizării",
|
||||||
"move_selection": "",
|
"move_selection": "Selectați un părinte {type} pentru a muta {source} în.",
|
||||||
"merge_selection": "",
|
"merge_selection": "Înlocuiți toate aparițiile {source} cu {type} selectat.",
|
||||||
"Root": "",
|
"Root": "Rădăcină",
|
||||||
"Ignore_Shopping": "",
|
"Ignore_Shopping": "Ignoră cumpărăturile",
|
||||||
"Shopping_Category": "",
|
"Shopping_Category": "Categorie de cumpărături",
|
||||||
"Edit_Food": "",
|
"Edit_Food": "Editare mâncare",
|
||||||
"Move_Food": "",
|
"Move_Food": "Mutare mâncare",
|
||||||
"New_Food": "",
|
"New_Food": "Mâncare nouă",
|
||||||
"Hide_Food": "",
|
"Hide_Food": "Ascunde mâncare",
|
||||||
"Food_Alias": "",
|
"Food_Alias": "Pseudonim mâncare",
|
||||||
"Unit_Alias": "",
|
"Unit_Alias": "Pseudonim unitate",
|
||||||
"Keyword_Alias": "",
|
"Keyword_Alias": "Pseudonim cuvânt cheie",
|
||||||
"Delete_Food": "",
|
"Delete_Food": "Ștergere mâncare",
|
||||||
"No_ID": "",
|
"No_ID": "ID-ul nu a fost găsit, nu se poate șterge.",
|
||||||
"Meal_Plan_Days": "",
|
"Meal_Plan_Days": "Planuri de alimentație pe viitor",
|
||||||
"merge_title": "",
|
"merge_title": "Unire {type}",
|
||||||
"move_title": "",
|
"move_title": "Mutare {type}",
|
||||||
"Food": "",
|
"Food": "Mâncare",
|
||||||
"Recipe_Book": "",
|
"Recipe_Book": "Carte de rețete",
|
||||||
"del_confirmation_tree": "",
|
"del_confirmation_tree": "Sunteți sigur că doriți să ștergeți {sursa} și toți copiii săi?",
|
||||||
"delete_title": "",
|
"delete_title": "Ștergere {type}",
|
||||||
"create_title": "",
|
"create_title": "{type} nou",
|
||||||
"edit_title": "",
|
"edit_title": "Editare {type}",
|
||||||
"Name": "",
|
"Name": "Nume",
|
||||||
"Type": "",
|
"Type": "Tip",
|
||||||
"Description": "",
|
"Description": "Descriere",
|
||||||
"Recipe": "",
|
"Recipe": "Rețetă",
|
||||||
"tree_root": "",
|
"tree_root": "Rădăcina copacului",
|
||||||
"Icon": "",
|
"Icon": "Iconiță",
|
||||||
"Unit": "",
|
"Unit": "Unitate",
|
||||||
"No_Results": "",
|
"No_Results": "Fără rezultate",
|
||||||
"New_Unit": "",
|
"New_Unit": "Unitate nouă",
|
||||||
"Create_New_Shopping Category": "",
|
"Create_New_Shopping Category": "Creați o nouă categorie de cumpărături",
|
||||||
"Create_New_Food": "",
|
"Create_New_Food": "Adaugă mâncare nouă",
|
||||||
"Create_New_Keyword": "",
|
"Create_New_Keyword": "Adaugă cuvânt cheie nou",
|
||||||
"Create_New_Unit": "",
|
"Create_New_Unit": "Adaugă unitate nouă",
|
||||||
"Create_New_Meal_Type": "",
|
"Create_New_Meal_Type": "Adaugă tip mâncare nou",
|
||||||
"and_up": "",
|
"and_up": "& Sus",
|
||||||
"Instructions": "",
|
"Instructions": "Instrucțiuni",
|
||||||
"Unrated": "",
|
"Unrated": "Neevaluat",
|
||||||
"Automate": "",
|
"Automate": "Automatizat",
|
||||||
"Empty": "",
|
"Empty": "Gol",
|
||||||
"Key_Ctrl": "",
|
"Key_Ctrl": "Ctrl",
|
||||||
"Key_Shift": "",
|
"Key_Shift": "Shift",
|
||||||
"Time": "",
|
"Time": "Timp",
|
||||||
"Text": "",
|
"Text": "Text",
|
||||||
"Shopping_list": "",
|
"Shopping_list": "Lisă de cumpărături",
|
||||||
"Create_Meal_Plan_Entry": "",
|
"Create_Meal_Plan_Entry": "Crearea înregistrării în planul de alimentare",
|
||||||
"Edit_Meal_Plan_Entry": "",
|
"Edit_Meal_Plan_Entry": "Editarea înregistrării în planul de alimentare",
|
||||||
"Title": "",
|
"Title": "Titlu",
|
||||||
"Week": "",
|
"Week": "Săptămână",
|
||||||
"Month": "",
|
"Month": "Lună",
|
||||||
"Year": "",
|
"Year": "An",
|
||||||
"Planner": "",
|
"Planner": "Planificator",
|
||||||
"Planner_Settings": "",
|
"Planner_Settings": "Setări planificator",
|
||||||
"Period": "",
|
"Period": "Perioadă",
|
||||||
"Plan_Period_To_Show": "",
|
"Plan_Period_To_Show": "Afișați săptămâni, luni sau ani",
|
||||||
"Periods": "",
|
"Periods": "Perioade",
|
||||||
"Plan_Show_How_Many_Periods": "",
|
"Plan_Show_How_Many_Periods": "Câte perioade să afișezi",
|
||||||
"Starting_Day": "",
|
"Starting_Day": "Ziua de început a săptămânii",
|
||||||
"Meal_Types": "",
|
"Meal_Types": "Tipuri de mese",
|
||||||
"Meal_Type": "",
|
"Meal_Type": "Tipul mesei",
|
||||||
"Clone": "",
|
"Clone": "Clonă",
|
||||||
"Drag_Here_To_Delete": "",
|
"Drag_Here_To_Delete": "Mută aici pentru a șterge",
|
||||||
"Meal_Type_Required": "",
|
"Meal_Type_Required": "Tipul mesei este necesar",
|
||||||
"Title_or_Recipe_Required": "",
|
"Title_or_Recipe_Required": "Titlul sau selecția rețetei necesare",
|
||||||
"Color": "",
|
"Color": "Culoare",
|
||||||
"New_Meal_Type": "",
|
"New_Meal_Type": "Tip de masă nou",
|
||||||
"Week_Numbers": "",
|
"Week_Numbers": "Numerele săptămânii",
|
||||||
"Show_Week_Numbers": "",
|
"Show_Week_Numbers": "Afișați numerele săptămânii?",
|
||||||
"Export_As_ICal": "",
|
"Export_As_ICal": "Exportul perioadei curente în format iCal",
|
||||||
"Export_To_ICal": "",
|
"Export_To_ICal": "Exportă .ics",
|
||||||
"Cannot_Add_Notes_To_Shopping": "",
|
"Cannot_Add_Notes_To_Shopping": "Notele nu pot fi adăugate la lista de cumpărături",
|
||||||
"Added_To_Shopping_List": "",
|
"Added_To_Shopping_List": "Adăugat la lista de cumpărături",
|
||||||
"Shopping_List_Empty": "",
|
"Shopping_List_Empty": "Lista de cumpărături este în prezent goală, puteți adăuga articole prin meniul contextual al unei intrări în planul de alimentație (faceți click dreapta pe card sau faceți click stânga pe iconița meniului)",
|
||||||
"Next_Period": "",
|
"Next_Period": "Perioada următoare",
|
||||||
"Previous_Period": "",
|
"Previous_Period": "Perioada precedentă",
|
||||||
"Current_Period": "",
|
"Current_Period": "Perioada curentă",
|
||||||
"Next_Day": "",
|
"Next_Day": "Ziua următoare",
|
||||||
"Previous_Day": "",
|
"Previous_Day": "Ziua precedentă",
|
||||||
"Coming_Soon": "",
|
"Coming_Soon": "În curând",
|
||||||
"Auto_Planner": "",
|
"Auto_Planner": "Planificator automat",
|
||||||
"New_Cookbook": "",
|
"New_Cookbook": "Nouă carte de bucate",
|
||||||
"Hide_Keyword": "",
|
"Hide_Keyword": "Ascunde cuvintele cheie",
|
||||||
"Clear": "",
|
"Clear": "Curățare",
|
||||||
"Plural": "",
|
"Plural": "Plural",
|
||||||
"plural_short": "",
|
"plural_short": "plural",
|
||||||
"Use_Plural_Unit_Always": "",
|
"Use_Plural_Unit_Always": "Utilizarea formei plurale pentru unitate întotdeauna",
|
||||||
"Use_Plural_Unit_Simple": "",
|
"Use_Plural_Unit_Simple": "Utilizarea dinamică a formei plurale pentru unitate",
|
||||||
"Use_Plural_Food_Always": "",
|
"Use_Plural_Food_Always": "Utilizarea formei plurale pentru alimente întotdeauna",
|
||||||
"Use_Plural_Food_Simple": "",
|
"Use_Plural_Food_Simple": "Utilizarea dinamica a formei plurale pentru alimente",
|
||||||
"plural_usage_info": ""
|
"plural_usage_info": "Utilizarea formei plurale pentru unități și alimente în interiorul acestui spațiu.",
|
||||||
|
"last_viewed": "Ultima vizualizare",
|
||||||
|
"created_on": "Creat la data de",
|
||||||
|
"updatedon": "Actualizat la data de",
|
||||||
|
"Imported_From": "Importat din",
|
||||||
|
"and_down": "& Jos",
|
||||||
|
"Warning": "Atenționare",
|
||||||
|
"ShowDelayed": "Afișarea elementelor întârziate",
|
||||||
|
"shopping_share_desc": "Utilizatorii vor vedea toate articolele pe care le adăugați în lista de cumpărături. Ei trebuie să vă adauge pentru a vedea elementele din lista lor.",
|
||||||
|
"mealplan_autoinclude_related_desc": "Atunci când adăugați un plan de alimentare în lista de cumpărături (manual sau automat), includeți toate rețetele asociate.",
|
||||||
|
"SuccessClipboard": "Lista de cumpărături copiată în clipboard",
|
||||||
|
"in_shopping": "În lista de cumpărături",
|
||||||
|
"not": "nu",
|
||||||
|
"Pin": "Fixează",
|
||||||
|
"Create Recipe": "Crearea rețetei",
|
||||||
|
"Import Recipe": "Importă rețeta",
|
||||||
|
"csv_prefix_label": "Prefix a listei",
|
||||||
|
"Click_To_Edit": "Faceți click pentru a edita",
|
||||||
|
"Ingredient Editor": "Editor de ingrediente",
|
||||||
|
"FoodOnHand": "Aveți {food} la îndemână.",
|
||||||
|
"AddFoodToShopping": "Adăugă {food} în lista de cumpărături",
|
||||||
|
"New_Entry": "Înregistrare nouă",
|
||||||
|
"GroupBy": "Grupat de",
|
||||||
|
"CountMore": "...+{count} mai mult",
|
||||||
|
"IgnoreThis": "Nu adăugați niciodată automat {food} la cumpărături",
|
||||||
|
"InheritWarning": "{food} este setat să moștenească, este posibil ca modificările să nu persiste.",
|
||||||
|
"err_move_self": "Nu se poate muta elementul în sine",
|
||||||
|
"CategoryName": "Nume categorie",
|
||||||
|
"Foods": "Alimente",
|
||||||
|
"copy_to_new": "Copiere in rețetă nouă",
|
||||||
|
"reset_children": "Resetarea moștenirii copilului",
|
||||||
|
"err_moving_resource": "A existat o eroare în mutarea unei resurse!",
|
||||||
|
"err_merging_resource": "A existat o eroare la fuzionarea unei resurse!",
|
||||||
|
"success_moving_resource": "Resursă mutată cu succes!",
|
||||||
|
"success_merging_resource": "A fuzionat cu succes o resursă!",
|
||||||
|
"Decimals": "Zecimale",
|
||||||
|
"Default_Unit": "Unitate standard",
|
||||||
|
"Use_Fractions": "Folosire fracțiuni",
|
||||||
|
"Use_Fractions_Help": "Convertiți automat zecimalele în fracții atunci când vizualizați o rețetă.",
|
||||||
|
"RemoveFoodFromShopping": "Șterge {food} din lista de cumpărături",
|
||||||
|
"IgnoredFood": "{food} este setat să ignore cumpărăturile.",
|
||||||
|
"Add_Servings_to_Shopping": "Adăugă {servings} porții la cumpărături",
|
||||||
|
"InheritFields": "Moștenirea valorilor câmpurilor",
|
||||||
|
"Language": "Limba",
|
||||||
|
"Theme": "Tema",
|
||||||
|
"NoCategory": "Nicio categorie selectată.",
|
||||||
|
"OfflineAlert": "Sunteți offline, este posibil ca lista de cumpărături să nu se sincronizeze.",
|
||||||
|
"mealplan_autoinclude_related": "Adăugați rețete asociate",
|
||||||
|
"shopping_auto_sync": "Sincronizare automată",
|
||||||
|
"mealplan_autoadd_shopping": "Adăugare automată a planului de alimentare",
|
||||||
|
"default_delay": "Ore de întârziere implicite",
|
||||||
|
"plan_share_desc": "Noile intrări din Planul de alimentare vor fi partajate automat cu utilizatorii selectați.",
|
||||||
|
"shopping_auto_sync_desc": "Setarea la 0 va dezactiva sincronizarea automată. Atunci când vizualizați o listă de cumpărături, lista este actualizată la fiecare câteva secunde setate pentru a sincroniza modificările pe care altcineva le-ar fi putut face. Util atunci când faceți cumpărături cu mai multe persoane, dar va folosi mai multe date mobile.",
|
||||||
|
"mealplan_autoexclude_onhand_desc": "Atunci când adăugați un plan de alimentare în lista de cumpărături (manual sau automat), excludeți ingredientele care sunt în prezent la îndemână.",
|
||||||
|
"default_delay_desc": "Numărul implicit de ore pentru a întârzia o intrare în lista de cumpărături.",
|
||||||
|
"Hour": "Oră",
|
||||||
|
"Hours": "Ore",
|
||||||
|
"Day": "Zi",
|
||||||
|
"Days": "Zile",
|
||||||
|
"Second": "Secundă",
|
||||||
|
"Seconds": "Secunde",
|
||||||
|
"Users": "Utilizatori",
|
||||||
|
"Invites": "Invită",
|
||||||
|
"nothing": "Nimic de făcut",
|
||||||
|
"err_merge_self": "Nu se poate uni elementul cu el însuși",
|
||||||
|
"download_csv": "Descarcă CSV",
|
||||||
|
"Account": "Cont",
|
||||||
|
"Cosmetic": "Cosmetice",
|
||||||
|
"API": "API",
|
||||||
|
"left_handed_help": "Va optimiza interfața de utilizare pentru utilizare cu mâna stângă.",
|
||||||
|
"Custom Filter": "Filtru personalizat",
|
||||||
|
"recipe_name": "Nume rețetă",
|
||||||
|
"paste_ingredients": "Inserați ingredientele",
|
||||||
|
"Website": "Site web",
|
||||||
|
"Nav_Color_Help": "Modificare culoare navigare.",
|
||||||
|
"Use_Kj": "Utilizare kJ în loc de kcal",
|
||||||
|
"Username": "Nume utilizator",
|
||||||
|
"First_name": "Prenume",
|
||||||
|
"Last_name": "Nume de familie",
|
||||||
|
"Keyword": "Cuvânt cheie",
|
||||||
|
"Advanced": "Avansat",
|
||||||
|
"Page": "Pagină",
|
||||||
|
"User": "Utilizator",
|
||||||
|
"Shopping_Categories": "Categorii de cumpărături",
|
||||||
|
"Single": "Singur",
|
||||||
|
"Multiple": "Multiplu",
|
||||||
|
"Reset": "Resetare",
|
||||||
|
"Disabled": "Dezactivat",
|
||||||
|
"Disable": "Dezactivare",
|
||||||
|
"Importer_Help": "Mai multe informații și ajutor cu privire la acest importator:",
|
||||||
|
"Documentation": "Documentație",
|
||||||
|
"Import_Error": "A apărut o eroare în timpul importului. Vă rugăm să extindeți detaliile din partea de jos a paginii pentru a le vizualiza.",
|
||||||
|
"Warning_Delete_Supermarket_Category": "Ștergerea unei categorii de supermarketuri va șterge, de asemenea, toate relațiile cu alimentele. Sunteți sigur?",
|
||||||
|
"one_url_per_line": "O adresă URL pe linie",
|
||||||
|
"mealplan_autoexclude_onhand": "Excludeți alimentele la îndemână",
|
||||||
|
"shopping_recent_days": "Zilele recente",
|
||||||
|
"download_pdf": "Descarcă PDF",
|
||||||
|
"filter": "Filtru",
|
||||||
|
"Search Settings": "Setări de căutare",
|
||||||
|
"err_deleting_protected_resource": "Obiectul pe care încercați să îl ștergeți este încă utilizat și nu poate fi șters.",
|
||||||
|
"csv_delim_help": "Delimitatorul utilizat pentru exporturile CSV.",
|
||||||
|
"csv_delim_label": "Delimitatorul CSV",
|
||||||
|
"SupermarketCategoriesOnly": "Numai categorii de supermarket-uri",
|
||||||
|
"shopping_category_help": "Supermarket-urile pot fi ordonate și filtrate în funcție de categoria de cumpărături în conformitate cu aspectul culoarului.",
|
||||||
|
"food_recipe_help": "Legarea unei rețete aici va include rețeta legată în orice altă rețetă care utilizează acest aliment",
|
||||||
|
"Private_Recipe": "Rețetă privată",
|
||||||
|
"DelayUntil": "Amână până la",
|
||||||
|
"shared_with": "Împărtășit cu",
|
||||||
|
"asc": "Crescător",
|
||||||
|
"desc": "Descrescător",
|
||||||
|
"date_viewed": "Ultimul vizionat",
|
||||||
|
"show_sortby": "Afișează sortat de",
|
||||||
|
"Quick actions": "Acțiuni rapide",
|
||||||
|
"Internal": "Intern",
|
||||||
|
"parameter_count": "Parametru {count}",
|
||||||
|
"Ratings": "Evaluări",
|
||||||
|
"warning_space_delete": "Puteți șterge spațiul, inclusiv toate rețetele, listele de cumpărături, planurile de alimentare și orice altceva ați creat. Acest lucru nu poate fi anulat! Sunteți sigur că doriți să faceți acest lucru?",
|
||||||
|
"remember_hours": "Ore de reținut",
|
||||||
|
"tree_select": "Utilizarea selecției arborilor",
|
||||||
|
"last_cooked": "Ultimul pregătit",
|
||||||
|
"Auto_Sort": "Sortare automatizată",
|
||||||
|
"Private_Recipe_Help": "Rețeta este arătată doar ție și oamenilor cu care este împărtășită.",
|
||||||
|
"save_filter": "Salvare filtru",
|
||||||
|
"Nav_Color": "Culoare navigare",
|
||||||
|
"Comments_setting": "Afișează comentarii",
|
||||||
|
"search_no_recipes": "Nu a putut găsi nici o rețetă!",
|
||||||
|
"Supermarkets": "Supermarket-uri",
|
||||||
|
"Undefined": "Nedefinit",
|
||||||
|
"Select": "Selectare",
|
||||||
|
"food_inherit_info": "Câmpuri pe alimente care ar trebui să fie moștenite în mod implicit.",
|
||||||
|
"facet_count_info": "Afișarea numărului de rețete pe filtrele de căutare.",
|
||||||
|
"Amount": "Cantitate",
|
||||||
|
"Auto_Sort_Help": "Mutați toate ingredientele la cel mai potrivit pas.",
|
||||||
|
"search_create_help_text": "Creați o rețetă nouă direct în Tandoor.",
|
||||||
|
"reusable_help_text": "Ar trebui link-ul de invitație să poată fi utilizat de mai mulți utilizatori.",
|
||||||
|
"Copy Link": "Copiere link",
|
||||||
|
"AddToShopping": "Adaugă la lista de cumpărături",
|
||||||
|
"FoodNotOnHand": "Nu aveți {food} la îndemână.",
|
||||||
|
"DeleteShoppingConfirm": "Sunteți sigur că doriți să eliminați toate {food} din lista de cumpărături?",
|
||||||
|
"mealplan_autoadd_shopping_desc": "Adăugați automat ingredientele planului de alimentare în lista de cumpărături.",
|
||||||
|
"filter_to_supermarket_desc": "În mod implicit, filtrați lista de cumpărături pentru a include numai categoriile pentru supermarketul selectat.",
|
||||||
|
"CategoryInstruction": "Trageți categoriile pentru a schimba categoriile de comenzi care apar în lista de cumpărături.",
|
||||||
|
"copy_markdown_table": "Copiere ca tabel Markdown",
|
||||||
|
"sql_debug": "Depanare SQL",
|
||||||
|
"remember_search": "Rețineți căutarea",
|
||||||
|
"OnHand_help": "Alimentele sunt în inventar și nu vor fi adăugate automat la o listă de cumpărături. Starea la îndemână este partajată cu utilizatorii de cumpărături.",
|
||||||
|
"show_rating": "Afișează evaluarea",
|
||||||
|
"search_rank": "Rang de căutare",
|
||||||
|
"book_filter_help": "Includeți rețete din filtrul de rețete în plus față de cele atribuite manual.",
|
||||||
|
"Sticky_Nav_Help": "Afișați întotdeauna meniul de navigare din partea de sus a ecranului.",
|
||||||
|
"import_duplicates": "Pentru a preveni duplicatele, rețetele cu același nume ca și cele existente sunt ignorate. Bifați această casetă pentru a importa totul.",
|
||||||
|
"warning_duplicate_filter": "Atenționare: Din cauza limitărilor tehnice care au mai multe filtre de aceeași combinație (și/sau/nu) ar putea da rezultate neașteptate.",
|
||||||
|
"substitute_help": "Înlocuitorii sunt luați în considerare atunci când căutați rețete care pot fi făcute cu ingrediente la îndemână.",
|
||||||
|
"substitute_children": "Înlocuire copii",
|
||||||
|
"SubstituteOnHand": "Ai un înlocuitor la îndemână.",
|
||||||
|
"InheritFields_help": "Valorile acestor câmpuri vor fi moștenite de la părinte (Excepție: categoriile de cumpărături necompletate nu sunt moștenite)",
|
||||||
|
"Social_Authentication": "Autentificare socială",
|
||||||
|
"empty_list": "Lista este goală.",
|
||||||
|
"Select_App_To_Import": "Selectați o aplicație din care să importați",
|
||||||
|
"Recipes_In_Import": "Rețete în fișierul de import",
|
||||||
|
"Split_All_Steps": "Împărțiți toate rândurile în pași separați.",
|
||||||
|
"Description_Replace": "Înlocuire descripție",
|
||||||
|
"Instruction_Replace": "Înlocuire instrucții",
|
||||||
|
"Copy Token": "Copiere token",
|
||||||
|
"ShowUncategorizedFood": "Afișează nedefinit",
|
||||||
|
"MoveCategory": "Mută la: ",
|
||||||
|
"DelayFor": "Întârziere pentru {hours} ore",
|
||||||
|
"Completed": "Completat",
|
||||||
|
"shopping_share": "Partajați lista de cumpărături",
|
||||||
|
"filter_to_supermarket": "Filtrați la supermarket",
|
||||||
|
"show_sql": "Afișează SQL",
|
||||||
|
"SupermarketName": "Numele supermarketului",
|
||||||
|
"FoodInherit": "Câmpuri moștenite de alimente",
|
||||||
|
"mark_complete": "Marcare completată",
|
||||||
|
"shopping_add_onhand_desc": "Marcați mâncarea 'La îndemână' atunci când este bifată de pe lista de cumpărături.",
|
||||||
|
"shopping_add_onhand": "La îndemână automat",
|
||||||
|
"related_recipes": "Rețete înrudite",
|
||||||
|
"ignore_shopping_help": "Nu adăugați niciodată alimente pe lista de cumpărături (ex. apă)",
|
||||||
|
"today_recipes": "Rețete de astăzi",
|
||||||
|
"enable_expert": "Activarea modului Expert",
|
||||||
|
"expert_mode": "Modul Expert",
|
||||||
|
"simple_mode": "Modul Simplu",
|
||||||
|
"advanced": "Avansat",
|
||||||
|
"Unpin": "Anularea fixării",
|
||||||
|
"Protected": "Protejat",
|
||||||
|
"Original_Text": "Text original",
|
||||||
|
"Create_New_Shopping_Category": "Adaugă categorie de cumpărături nouă",
|
||||||
|
"Added_by": "Adăugat de",
|
||||||
|
"Added_on": "Adăugat la",
|
||||||
|
"IngredientInShopping": "Acest ingredient se află în lista de cumpărături.",
|
||||||
|
"NotInShopping": "{food} nu se află în lista de cumpărături.",
|
||||||
|
"OnHand": "În prezent, la îndemână",
|
||||||
|
"Inherit": "Moștenire",
|
||||||
|
"shopping_recent_days_desc": "Zile de intrări recente lista de cumpărături pentru a afișa.",
|
||||||
|
"copy_to_clipboard": "Copierea în Clipboard",
|
||||||
|
"csv_prefix_help": "Prefix de adăugat la copierea listei în clipboard.",
|
||||||
|
"PinnedConfirmation": "{recipe} a fost fixată.",
|
||||||
|
"UnpinnedConfirmation": "Fixarea {recipe} a fost anulată.",
|
||||||
|
"QuickEntry": "Înscriere rapidă",
|
||||||
|
"fields": "Câmpuri",
|
||||||
|
"show_keywords": "Afișează cuvinte cheie",
|
||||||
|
"show_foods": "Afișează mâncări",
|
||||||
|
"show_books": "Afișează cărți",
|
||||||
|
"show_units": "Afișează unitățile",
|
||||||
|
"show_filters": "Afișează filtrele",
|
||||||
|
"filter_name": "Nume filtru",
|
||||||
|
"left_handed": "Modul stângaci",
|
||||||
|
"sort_by": "Sortat de",
|
||||||
|
"times_cooked": "Ori pregătite",
|
||||||
|
"date_created": "Data creării",
|
||||||
|
"make_now": "Creează acum",
|
||||||
|
"recipe_filter": "Filtru rețete",
|
||||||
|
"review_shopping": "Examinați intrările de cumpărături înainte de a salva",
|
||||||
|
"view_recipe": "Vizionează rețeta",
|
||||||
|
"paste_ingredients_placeholder": "Inserați lista de ingrediente aici...",
|
||||||
|
"ingredient_list": "Lista de ingrediente",
|
||||||
|
"explain": "Explicație",
|
||||||
|
"App": "Aplicație",
|
||||||
|
"Message": "Mesaj",
|
||||||
|
"Sticky_Nav": "Navigare lipicioasă",
|
||||||
|
"click_image_import": "Faceți click pe imaginea pe care doriți să o importați pentru această rețetă",
|
||||||
|
"no_more_images_found": "Nu există imagini suplimentare găsite pe site-ul web.",
|
||||||
|
"paste_json": "Inserați sursă JSON sau HTML aici pentru a încărca rețetă.",
|
||||||
|
"search_import_help_text": "Importați o rețetă de pe un site web sau o aplicație externă.",
|
||||||
|
"reset_children_help": "Suprascrieți toți copiii cu valori din câmpurile moștenite. Câmpurile moștenite ale copiilor vor fi setate la câmpuri standard, cu excepția cazului în care sunt setate câmpurile moștenite de copii.",
|
||||||
|
"reset_food_inheritance": "Resetați moștenirea",
|
||||||
|
"reset_food_inheritance_info": "Resetați toate alimentele la câmpurile moștenite implicit și la valorile părinte ale acestora.",
|
||||||
|
"substitute_siblings_help": "Toate alimentele care împărtășesc un părinte al acestui aliment sunt considerate înlocuitori.",
|
||||||
|
"substitute_children_help": "Toate alimentele care sunt copii ai acestui aliment sunt considerate înlocuitori.",
|
||||||
|
"substitute_siblings": "Înlocuire frați",
|
||||||
|
"Bookmarklet": "Marcaj",
|
||||||
|
"ChildInheritFields": "Copiii moștenesc câmpurile",
|
||||||
|
"ChildInheritFields_help": "Copiii vor moșteni aceste câmpuri în mod implicit.",
|
||||||
|
"show_ingredient_overview": "Afișați o listă cu toate ingredientele la începutul rețetei.",
|
||||||
|
"Ingredient Overview": "Prezentare generală a ingredientelor",
|
||||||
|
"advanced_search_settings": "Setări avansate de căutare",
|
||||||
|
"nothing_planned_today": "Nu ai nimic planificat pentru ziua de azi!",
|
||||||
|
"no_pinned_recipes": "Nu ai rețete fixate!",
|
||||||
|
"Planned": "Planificate",
|
||||||
|
"Pinned": "Fixate",
|
||||||
|
"Imported": "Importate",
|
||||||
|
"Units": "Unități",
|
||||||
|
"Manage_Emails": "Gestionarea e-mailurilor",
|
||||||
|
"Change_Password": "Schimbați parola",
|
||||||
|
"Random Recipes": "Rețete aleatoare",
|
||||||
|
"select_keyword": "Selectați cuvânt cheie",
|
||||||
|
"add_keyword": "Adăugare cuvânt cheie",
|
||||||
|
"select_file": "Selectare fișier",
|
||||||
|
"select_recipe": "Selectare rețetă",
|
||||||
|
"select_unit": "Selectare unitate",
|
||||||
|
"select_food": "Selectare mâncare",
|
||||||
|
"remove_selection": "Deselectare",
|
||||||
|
"Options": "Opțiuni",
|
||||||
|
"Create Food": "Creare mâncare",
|
||||||
|
"create_food_desc": "Creați un aliment și conectați-l la această rețetă.",
|
||||||
|
"additional_options": "Opțiuni suplimentare",
|
||||||
|
"Import_Supported": "Import compatibil",
|
||||||
|
"Export_Supported": "Export compatibil",
|
||||||
|
"Import_Not_Yet_Supported": "Importul încă nu este compatibil",
|
||||||
|
"Export_Not_Yet_Supported": "Exportul încă nu este compatibil",
|
||||||
|
"Import_Result_Info": "{imported} din {total} rețete au fost importate",
|
||||||
|
"Toggle": "Comutare",
|
||||||
|
"New_Supermarket": "Creați un supermarket nou",
|
||||||
|
"New_Supermarket_Category": "Creați o nouă categorie de supermarket-uri",
|
||||||
|
"Are_You_Sure": "Sunteți sigur?",
|
||||||
|
"Valid Until": "Valabil până la",
|
||||||
|
"Combine_All_Steps": "Combinați toți pașii într-un singur câmp."
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@
|
|||||||
"expert_mode": "Экспертный режим",
|
"expert_mode": "Экспертный режим",
|
||||||
"enable_expert": "Включить экспертный режим",
|
"enable_expert": "Включить экспертный режим",
|
||||||
"review_shopping": "Просмотрите записи о покупках перед сохранением",
|
"review_shopping": "Просмотрите записи о покупках перед сохранением",
|
||||||
"empty_list": "Список пуст",
|
"empty_list": "Список пуст.",
|
||||||
"default_delay_desc": "Число часов по умолчанию для отсрочки записи в списке покупок.",
|
"default_delay_desc": "Число часов по умолчанию для отсрочки записи в списке покупок.",
|
||||||
"one_url_per_line": "Один URL в строке",
|
"one_url_per_line": "Один URL в строке",
|
||||||
"mealplan_autoinclude_related": "Добавить сопутствующие рецепты",
|
"mealplan_autoinclude_related": "Добавить сопутствующие рецепты",
|
||||||
@ -343,5 +343,8 @@
|
|||||||
"DelayFor": "Отложить на {hours} часов",
|
"DelayFor": "Отложить на {hours} часов",
|
||||||
"New_Entry": "Новая запись",
|
"New_Entry": "Новая запись",
|
||||||
"GroupBy": "Сгруппировать по",
|
"GroupBy": "Сгруппировать по",
|
||||||
"facet_count_info": "Показывать количество рецептов в фильтрах поиска."
|
"facet_count_info": "Показывать количество рецептов в фильтрах поиска.",
|
||||||
|
"food_inherit_info": "Поля для продуктов питания, которые должны наследоваться по умолчанию.",
|
||||||
|
"warning_space_delete": "Вы можете удалить свое пространство, включая все рецепты, списки покупок, планы питания и все остальное, что вы создали. Этого нельзя отменить! Ты уверен, что хочешь это сделать?",
|
||||||
|
"Description_Replace": "Изменить описание"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user