mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2025-12-25 03:13:13 -05:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87c2ff73e8 | ||
|
|
27bb4c9bb8 | ||
|
|
ac647c5ee8 | ||
|
|
3cec891aa1 | ||
|
|
3633b9724b | ||
|
|
420b5c093f | ||
|
|
9bb55dd746 | ||
|
|
1759ad3587 | ||
|
|
956693b7ca | ||
|
|
7b2117c019 | ||
|
|
d48fe26a35 | ||
|
|
7fd5fca0cf | ||
|
|
378938812c | ||
|
|
60b494abeb | ||
|
|
34be1dc1d7 | ||
|
|
d89a4620f0 | ||
|
|
dea83b5720 | ||
|
|
d9ebe3e0fb | ||
|
|
135dde247f | ||
|
|
eb7a667202 | ||
|
|
b3cc9967f5 | ||
|
|
7276cea3d5 | ||
|
|
c0c996622e | ||
|
|
5556555bca | ||
|
|
55a84494c9 | ||
|
|
74d778dcb8 | ||
|
|
156d68f1b8 | ||
|
|
cb59a6340d | ||
|
|
5eb013cc2f | ||
|
|
dafb26b500 | ||
|
|
d9416a42dc | ||
|
|
ad88eff9e3 | ||
|
|
4d4f623adf | ||
|
|
ac9c9cd4e3 | ||
|
|
580eeef6b7 | ||
|
|
f25f5a26cf | ||
|
|
972d43c2a2 | ||
|
|
2a7475c435 | ||
|
|
71b41efe6c | ||
|
|
33a7fee1cc | ||
|
|
fa7fb644ea | ||
|
|
13b996171a | ||
|
|
77bb3870bf | ||
|
|
9863303a5e | ||
|
|
0caccc3da8 | ||
|
|
b75427b86d | ||
|
|
054c4ec61a | ||
|
|
8da21f9914 | ||
|
|
99ba512862 | ||
|
|
eab59fcbd8 | ||
|
|
484da2200e | ||
|
|
330bb6d954 | ||
|
|
d4b6c8da04 | ||
|
|
a5ef438cfe | ||
|
|
de196c716b | ||
|
|
cb248a1f19 | ||
|
|
df2f1b2b7c | ||
|
|
36e26d8009 | ||
|
|
a5973de02b | ||
|
|
68f272bc25 | ||
|
|
b66a5c1ee9 | ||
|
|
bfc42638a4 | ||
|
|
a8c9689b43 | ||
|
|
26ff3f56ea | ||
|
|
a49993e399 | ||
|
|
9f42226224 | ||
|
|
8f4c00df0b | ||
|
|
6cebec86c5 | ||
|
|
8f5b017857 | ||
|
|
483bc8f1b7 | ||
|
|
ba493e3e19 |
48
.github/workflows/docker-publish-beta-raspi.yml
vendored
Normal file
48
.github/workflows/docker-publish-beta-raspi.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: publish beta raspi image docker
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'beta'
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner == 'TandoorRecipes'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
# Update Version number
|
||||
- name: Update version file
|
||||
uses: DamianReeves/write-file-action@v1.0
|
||||
with:
|
||||
path: recipes/version.py
|
||||
contents: |
|
||||
VERSION_NUMBER = 'beta'
|
||||
BUILD_REF = '${{ github.sha }}'
|
||||
write-mode: overwrite
|
||||
# Build Vue frontend
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Install dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn install
|
||||
- name: Build dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn build
|
||||
# Build container
|
||||
- name: Build and publish image
|
||||
uses: ilteoood/docker_buildx@master
|
||||
with:
|
||||
publish: true
|
||||
imageName: vabene1111/recipes
|
||||
tag: beta-raspi
|
||||
dockerFile: Dockerfile-raspi
|
||||
platform: linux/arm/v7
|
||||
dockerUser: ${{ secrets.DOCKER_USERNAME }}
|
||||
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
|
||||
# Send discord notification
|
||||
- name: Discord notification
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_BETA_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.3.2
|
||||
with:
|
||||
args: '🚀 The BETA Image has been updated! 🥳'
|
||||
1
.github/workflows/docker-publish-beta.yml
vendored
1
.github/workflows/docker-publish-beta.yml
vendored
@@ -35,6 +35,7 @@ jobs:
|
||||
publish: true
|
||||
imageName: vabene1111/recipes
|
||||
tag: beta
|
||||
platform: linux/amd64,linux/arm64
|
||||
dockerUser: ${{ secrets.DOCKER_USERNAME }}
|
||||
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
|
||||
# Send discord notification
|
||||
|
||||
45
.github/workflows/docker-publish-latest-raspi.yml
vendored
Normal file
45
.github/workflows/docker-publish-latest-raspi.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: publish latest raspi image docker
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner == 'TandoorRecipes'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Get version number
|
||||
id: get_version
|
||||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}-raspi
|
||||
# Update Version number
|
||||
- name: Update version file
|
||||
uses: DamianReeves/write-file-action@v1.0
|
||||
with:
|
||||
path: recipes/version.py
|
||||
contents: |
|
||||
VERSION_NUMBER = '${{ steps.get_version.outputs.VERSION }}-raspi'
|
||||
BUILD_REF = '${{ github.sha }}'
|
||||
write-mode: overwrite
|
||||
# Build Vue frontend
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Install dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn install
|
||||
- name: Build dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn build
|
||||
# Build container
|
||||
- name: Build and publish image
|
||||
uses: ilteoood/docker_buildx@master
|
||||
with:
|
||||
publish: true
|
||||
imageName: vabene1111/recipes
|
||||
dockerFile: Dockerfile-raspi
|
||||
platform: linux/arm/v7
|
||||
tag: latest-raspi
|
||||
dockerUser: ${{ secrets.DOCKER_USERNAME }}
|
||||
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
|
||||
1
.github/workflows/docker-publish-latest.yml
vendored
1
.github/workflows/docker-publish-latest.yml
vendored
@@ -38,6 +38,7 @@ jobs:
|
||||
with:
|
||||
publish: true
|
||||
imageName: vabene1111/recipes
|
||||
platform: linux/amd64,linux/arm64
|
||||
tag: latest
|
||||
dockerUser: ${{ secrets.DOCKER_USERNAME }}
|
||||
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
47
.github/workflows/docker-publish-release-raspi.yml
vendored
Normal file
47
.github/workflows/docker-publish-release-raspi.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
name: publish tagged raspi release docker
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner == 'TandoorRecipes'
|
||||
runs-on: ubuntu-latest
|
||||
name: Build image job
|
||||
steps:
|
||||
- name: Checkout master
|
||||
uses: actions/checkout@master
|
||||
- name: Get version number
|
||||
id: get_version
|
||||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||
# Update Version number
|
||||
- name: Update version file
|
||||
uses: DamianReeves/write-file-action@v1.0
|
||||
with:
|
||||
path: recipes/version.py
|
||||
contents: |
|
||||
VERSION_NUMBER = '${{ steps.get_version.outputs.VERSION }}'
|
||||
BUILD_REF = '${{ github.sha }}'
|
||||
write-mode: overwrite
|
||||
# Build Vue frontend
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Install dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn install
|
||||
- name: Build dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn build
|
||||
# Build container
|
||||
- name: Build and publish image
|
||||
uses: ilteoood/docker_buildx@master
|
||||
with:
|
||||
publish: true
|
||||
imageName: vabene1111/recipes
|
||||
dockerFile: Dockerfile-raspi
|
||||
platform: linux/arm/v7
|
||||
tag: ${{ steps.get_version.outputs.VERSION }}-raspi
|
||||
dockerUser: ${{ secrets.DOCKER_USERNAME }}
|
||||
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
|
||||
1
.github/workflows/docker-publish-release.yml
vendored
1
.github/workflows/docker-publish-release.yml
vendored
@@ -40,6 +40,7 @@ jobs:
|
||||
with:
|
||||
publish: true
|
||||
imageName: vabene1111/recipes
|
||||
platform: linux/amd64,linux/arm64
|
||||
tag: ${{ steps.get_version.outputs.VERSION }}
|
||||
dockerUser: ${{ secrets.DOCKER_USERNAME }}
|
||||
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
@@ -15,7 +15,7 @@ WORKDIR /opt/recipes
|
||||
|
||||
COPY requirements.txt ./
|
||||
|
||||
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev libressl-dev libffi-dev cargo openssl-dev openldap-dev python3-dev && \
|
||||
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev && \
|
||||
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
|
||||
python -m venv venv && \
|
||||
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
|
||||
|
||||
33
Dockerfile-raspi
Normal file
33
Dockerfile-raspi
Normal file
@@ -0,0 +1,33 @@
|
||||
# builds of cryptography for raspberry pi (or better arm v7) fail for some
|
||||
FROM python:3.9-alpine3.15
|
||||
|
||||
#Install all dependencies.
|
||||
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography openldap gcompat
|
||||
|
||||
#Print all logs without buffering it.
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
#This port will be used by gunicorn.
|
||||
EXPOSE 8080
|
||||
|
||||
#Create app dir and install requirements.
|
||||
RUN mkdir /opt/recipes
|
||||
WORKDIR /opt/recipes
|
||||
|
||||
COPY requirements.txt ./
|
||||
RUN \
|
||||
if [ `apk --print-arch` = "armv7" ]; then \
|
||||
printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \
|
||||
fi
|
||||
RUN apk add --no-cache --virtual .build-deps gcc musl-dev zlib-dev jpeg-dev libwebp-dev python3-dev && \
|
||||
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
|
||||
python -m venv venv && \
|
||||
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
|
||||
venv/bin/pip install wheel==0.37.1 && \
|
||||
venv/bin/pip install -r requirements.txt --no-cache-dir --no-binary=Pillow && \
|
||||
apk --purge del .build-deps
|
||||
|
||||
#Copy project and execute it.
|
||||
COPY . ./
|
||||
RUN chmod +x boot.sh
|
||||
ENTRYPOINT ["/opt/recipes/boot.sh"]
|
||||
@@ -9,6 +9,8 @@ from recipe_scrapers._utils import get_host_name, normalize_string
|
||||
|
||||
from cookbook.helper import recipe_url_import as helper
|
||||
from cookbook.helper.scrapers.scrapers import text_scraper
|
||||
from recipe_scrapers import scrape_me
|
||||
from recipe_scrapers._exceptions import NoSchemaFoundInWildMode
|
||||
|
||||
|
||||
def get_recipe_from_source(text, url, request):
|
||||
@@ -63,34 +65,41 @@ def get_recipe_from_source(text, url, request):
|
||||
html_data = []
|
||||
images = []
|
||||
text = unquote(text)
|
||||
scrape = None
|
||||
|
||||
try:
|
||||
parse_list.append(remove_graph(json.loads(text)))
|
||||
if not url and 'url' in parse_list[0]:
|
||||
url = parse_list[0]['url']
|
||||
scrape = text_scraper("<script type='application/ld+json'>" + text + "</script>", url=url)
|
||||
if url:
|
||||
try:
|
||||
scrape = scrape_me(url_path=url, wild_mode=True)
|
||||
except(NoSchemaFoundInWildMode):
|
||||
pass
|
||||
if not scrape:
|
||||
try:
|
||||
parse_list.append(remove_graph(json.loads(text)))
|
||||
if not url and 'url' in parse_list[0]:
|
||||
url = parse_list[0]['url']
|
||||
scrape = text_scraper("<script type='application/ld+json'>" + text + "</script>", url=url)
|
||||
|
||||
except JSONDecodeError:
|
||||
soup = BeautifulSoup(text, "html.parser")
|
||||
html_data = get_from_html(soup)
|
||||
images += get_images_from_source(soup, url)
|
||||
for el in soup.find_all('script', type='application/ld+json'):
|
||||
el = remove_graph(el)
|
||||
if not url and 'url' in el:
|
||||
url = el['url']
|
||||
if type(el) == list:
|
||||
for le in el:
|
||||
parse_list.append(le)
|
||||
elif type(el) == dict:
|
||||
parse_list.append(el)
|
||||
for el in soup.find_all(type='application/json'):
|
||||
el = remove_graph(el)
|
||||
if type(el) == list:
|
||||
for le in el:
|
||||
parse_list.append(le)
|
||||
elif type(el) == dict:
|
||||
parse_list.append(el)
|
||||
scrape = text_scraper(text, url=url)
|
||||
except JSONDecodeError:
|
||||
soup = BeautifulSoup(text, "html.parser")
|
||||
html_data = get_from_html(soup)
|
||||
images += get_images_from_source(soup, url)
|
||||
for el in soup.find_all('script', type='application/ld+json'):
|
||||
el = remove_graph(el)
|
||||
if not url and 'url' in el:
|
||||
url = el['url']
|
||||
if type(el) == list:
|
||||
for le in el:
|
||||
parse_list.append(le)
|
||||
elif type(el) == dict:
|
||||
parse_list.append(el)
|
||||
for el in soup.find_all(type='application/json'):
|
||||
el = remove_graph(el)
|
||||
if type(el) == list:
|
||||
for le in el:
|
||||
parse_list.append(le)
|
||||
elif type(el) == dict:
|
||||
parse_list.append(el)
|
||||
scrape = text_scraper(text, url=url)
|
||||
|
||||
recipe_json = helper.get_from_scraper(scrape, request)
|
||||
|
||||
|
||||
@@ -114,7 +114,14 @@ def get_from_scraper(scrape, request):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if source_url := scrape.canonical_url():
|
||||
try:
|
||||
source_url = scrape.canonical_url()
|
||||
except Exception:
|
||||
try:
|
||||
source_url = scrape.url
|
||||
except Exception:
|
||||
pass
|
||||
if source_url:
|
||||
recipe_json['source_url'] = source_url
|
||||
try:
|
||||
keywords.append(source_url.replace('http://', '').replace('https://', '').split('/')[0])
|
||||
@@ -129,9 +136,11 @@ def get_from_scraper(scrape, request):
|
||||
ingredient_parser = IngredientParser(request, True)
|
||||
|
||||
recipe_json['steps'] = []
|
||||
|
||||
for i in parse_instructions(scrape.instructions()):
|
||||
recipe_json['steps'].append({'instruction': i, 'ingredients': [], })
|
||||
try:
|
||||
for i in parse_instructions(scrape.instructions()):
|
||||
recipe_json['steps'].append({'instruction': i, 'ingredients': [], })
|
||||
except Exception:
|
||||
pass
|
||||
if len(recipe_json['steps']) == 0:
|
||||
recipe_json['steps'].append({'instruction': '', 'ingredients': [], })
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from json import JSONDecodeError
|
||||
from recipe_scrapers import SCRAPERS, get_host_name
|
||||
from recipe_scrapers import SCRAPERS
|
||||
from recipe_scrapers._factory import SchemaScraperFactory
|
||||
from recipe_scrapers._schemaorg import SchemaOrg
|
||||
|
||||
@@ -15,13 +15,7 @@ SCRAPERS.update(CUSTOM_SCRAPERS)
|
||||
|
||||
|
||||
def text_scraper(text, url=None):
|
||||
domain = None
|
||||
if url:
|
||||
domain = get_host_name(url)
|
||||
if domain in SCRAPERS:
|
||||
scraper_class = SCRAPERS[domain]
|
||||
else:
|
||||
scraper_class = SchemaScraperFactory.SchemaScraper
|
||||
scraper_class = SchemaScraperFactory.SchemaScraper
|
||||
|
||||
class TextScraper(scraper_class):
|
||||
def __init__(
|
||||
|
||||
@@ -6,6 +6,7 @@ from gettext import gettext as _
|
||||
from io import BytesIO
|
||||
|
||||
import requests
|
||||
import validators
|
||||
import yaml
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
@@ -59,8 +60,10 @@ class CookBookApp(Integration):
|
||||
|
||||
if len(images) > 0:
|
||||
try:
|
||||
response = requests.get(images[0])
|
||||
self.import_recipe_image(recipe, BytesIO(response.content))
|
||||
url = images[0]
|
||||
if validators.url(url, public=True):
|
||||
response = requests.get(url)
|
||||
self.import_recipe_image(recipe, BytesIO(response.content))
|
||||
except Exception as e:
|
||||
print('failed to import image ', str(e))
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from io import BytesIO
|
||||
from gettext import gettext as _
|
||||
|
||||
import requests
|
||||
import validators
|
||||
from lxml import etree
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
@@ -28,17 +29,17 @@ class Cookmate(Integration):
|
||||
name=recipe_xml.find('title').text.strip(),
|
||||
created_by=self.request.user, internal=True, space=self.request.space)
|
||||
|
||||
if recipe_xml.find('preptime') is not None:
|
||||
if recipe_xml.find('preptime') is not None and recipe_xml.find('preptime').text is not None:
|
||||
recipe.working_time = parse_time(recipe_xml.find('preptime').text.strip())
|
||||
|
||||
if recipe_xml.find('cooktime') is not None:
|
||||
if recipe_xml.find('cooktime') is not None and recipe_xml.find('cooktime').text is not None:
|
||||
recipe.waiting_time = parse_time(recipe_xml.find('cooktime').text.strip())
|
||||
|
||||
if recipe_xml.find('quantity') is not None:
|
||||
if recipe_xml.find('quantity') is not None and recipe_xml.find('quantity').text is not None:
|
||||
recipe.servings = parse_servings(recipe_xml.find('quantity').text.strip())
|
||||
recipe.servings_text = parse_servings_text(recipe_xml.find('quantity').text.strip())
|
||||
|
||||
if recipe_xml.find('url') is not None:
|
||||
if recipe_xml.find('url') is not None and recipe_xml.find('url').text is not None:
|
||||
recipe.source_url = recipe_xml.find('url').text.strip()
|
||||
|
||||
if recipe_xml.find('description') is not None: # description is a list of <li>'s with text
|
||||
@@ -64,7 +65,9 @@ class Cookmate(Integration):
|
||||
|
||||
if recipe_xml.find('imageurl') is not None:
|
||||
try:
|
||||
response = requests.get(recipe_xml.find('imageurl').text.strip())
|
||||
url = recipe_xml.find('imageurl').text.strip()
|
||||
if validators.url(url, public=True):
|
||||
response = requests.get(url)
|
||||
self.import_recipe_image(recipe, BytesIO(response.content))
|
||||
except Exception as e:
|
||||
print('failed to import image ', str(e))
|
||||
|
||||
@@ -27,7 +27,7 @@ class Paprika(Integration):
|
||||
recipe.description = '' if len(recipe_json['description'].strip()) > 500 else recipe_json['description'].strip()
|
||||
|
||||
try:
|
||||
if 'servings' in recipe_json['servings']:
|
||||
if 'servings' in recipe_json:
|
||||
recipe.servings = parse_servings(recipe_json['servings'])
|
||||
recipe.servings_text = parse_servings_text(recipe_json['servings'])
|
||||
|
||||
|
||||
@@ -78,7 +78,11 @@ class Plantoeat(Integration):
|
||||
current_recipe = ''
|
||||
|
||||
for fl in file.readlines():
|
||||
line = fl.decode("windows-1250")
|
||||
try:
|
||||
line = fl.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
line = fl.decode("windows-1250")
|
||||
|
||||
if line.startswith('--------------'):
|
||||
if current_recipe != '':
|
||||
recipe_list.append(current_recipe)
|
||||
|
||||
@@ -5,6 +5,7 @@ from io import BytesIO
|
||||
from zipfile import ZipFile
|
||||
|
||||
import requests
|
||||
import validators
|
||||
|
||||
from django.utils.translation import gettext as _
|
||||
from cookbook.helper.image_processing import get_filetype
|
||||
@@ -123,11 +124,13 @@ class RecetteTek(Integration):
|
||||
self.import_recipe_image(recipe, BytesIO(import_zip.read(image_file_name)), filetype=get_filetype(image_file_name))
|
||||
else:
|
||||
if file['originalPicture'] != '':
|
||||
response = requests.get(file['originalPicture'])
|
||||
if imghdr.what(BytesIO(response.content)) is not None:
|
||||
self.import_recipe_image(recipe, BytesIO(response.content), filetype=get_filetype(file['originalPicture']))
|
||||
else:
|
||||
raise Exception("Original image failed to download.")
|
||||
url = file['originalPicture']
|
||||
if validators.url(url, public=True):
|
||||
response = requests.get(url)
|
||||
if imghdr.what(BytesIO(response.content)) is not None:
|
||||
self.import_recipe_image(recipe, BytesIO(response.content), filetype=get_filetype(file['originalPicture']))
|
||||
else:
|
||||
raise Exception("Original image failed to download.")
|
||||
except Exception as e:
|
||||
print(recipe.name, ': failed to import image ', str(e))
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import json
|
||||
from io import BytesIO
|
||||
|
||||
import requests
|
||||
import validators
|
||||
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.integration.integration import Integration
|
||||
@@ -51,8 +52,10 @@ class RecipeSage(Integration):
|
||||
|
||||
if len(file['image']) > 0:
|
||||
try:
|
||||
response = requests.get(file['image'][0])
|
||||
self.import_recipe_image(recipe, BytesIO(response.content))
|
||||
url = file['image'][0]
|
||||
if validators.url(url, public=True):
|
||||
response = requests.get(url)
|
||||
self.import_recipe_image(recipe, BytesIO(response.content))
|
||||
except Exception as e:
|
||||
print('failed to import image ', str(e))
|
||||
|
||||
|
||||
BIN
cookbook/locale/bg/LC_MESSAGES/django.mo
Normal file
BIN
cookbook/locale/bg/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
3018
cookbook/locale/bg/LC_MESSAGES/django.po
Normal file
3018
cookbook/locale/bg/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
cookbook/locale/da/LC_MESSAGES/django.mo
Normal file
BIN
cookbook/locale/da/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2983
cookbook/locale/da/LC_MESSAGES/django.po
Normal file
2983
cookbook/locale/da/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -9,21 +9,21 @@
|
||||
# miguel angel <mlopezifu@alumnos.unex.es>, 2020
|
||||
# Miguel Canteras <mcanteras@gmail.com>, 2021
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
||||
"PO-Revision-Date: 2020-06-02 19:28+0000\n"
|
||||
"Last-Translator: Miguel Canteras <mcanteras@gmail.com>, 2021\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/django-recipes/"
|
||||
"teams/110507/es/)\n"
|
||||
"PO-Revision-Date: 2022-05-17 21:32+0000\n"
|
||||
"Last-Translator: Gabriel Tapias <gtapias@gmail.com>\n"
|
||||
"Language-Team: Spanish <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/es/>\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
|
||||
#: .\cookbook\filters.py:23 .\cookbook\templates\forms\ingredients.html:34
|
||||
#: .\cookbook\templates\space.html:49 .\cookbook\templates\stats.html:28
|
||||
@@ -31,16 +31,12 @@ msgid "Ingredients"
|
||||
msgstr "Ingredientes"
|
||||
|
||||
#: .\cookbook\forms.py:56
|
||||
#, fuzzy
|
||||
#| msgid "Default"
|
||||
msgid "Default unit"
|
||||
msgstr "Por defecto"
|
||||
msgstr "Unidad por defecto"
|
||||
|
||||
#: .\cookbook\forms.py:57
|
||||
#, fuzzy
|
||||
#| msgid "System Information"
|
||||
msgid "Use fractions"
|
||||
msgstr "Información del Sistema"
|
||||
msgstr "Usar fracciones"
|
||||
|
||||
#: .\cookbook\forms.py:58
|
||||
msgid "Use KJ"
|
||||
@@ -59,38 +55,28 @@ msgid "Sticky navbar"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:62
|
||||
#, fuzzy
|
||||
#| msgid "Default"
|
||||
msgid "Default page"
|
||||
msgstr "Por defecto"
|
||||
msgstr "Página por defecto"
|
||||
|
||||
#: .\cookbook\forms.py:63
|
||||
#, fuzzy
|
||||
#| msgid "Shopping Recipes"
|
||||
msgid "Show recent recipes"
|
||||
msgstr "Recetas en el carro de la compra"
|
||||
msgstr "Mostrar recetas recientes"
|
||||
|
||||
#: .\cookbook\forms.py:64
|
||||
#, fuzzy
|
||||
#| msgid "Search"
|
||||
msgid "Search style"
|
||||
msgstr "Buscar"
|
||||
msgstr "Estilo de búsqueda"
|
||||
|
||||
#: .\cookbook\forms.py:65
|
||||
msgid "Plan sharing"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:66
|
||||
#, fuzzy
|
||||
#| msgid "Ingredients"
|
||||
msgid "Ingredient decimal places"
|
||||
msgstr "Ingredientes"
|
||||
msgstr "Número de decimales del ingrediente"
|
||||
|
||||
#: .\cookbook\forms.py:67
|
||||
#, fuzzy
|
||||
#| msgid "Shopping list currently empty"
|
||||
msgid "Shopping list auto sync period"
|
||||
msgstr "Lista de la compra vacía"
|
||||
msgstr "Período de sincronización automática de la lista de compras"
|
||||
|
||||
#: .\cookbook\forms.py:68 .\cookbook\templates\recipe_view.html:21
|
||||
#: .\cookbook\templates\space.html:76 .\cookbook\templates\stats.html:47
|
||||
@@ -128,20 +114,14 @@ msgid "Display nutritional energy amounts in joules instead of calories"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:80
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Users with whom newly created meal plan/shopping list entries should be "
|
||||
#| "shared by default."
|
||||
msgid "Users with whom newly created meal plans should be shared by default."
|
||||
msgstr ""
|
||||
"Usuarios con los que las entradas recién creadas del plan de comida/lista de "
|
||||
"la compra deben compartirse de forma predeterminada."
|
||||
"Usuarios con los que las entradas recién creadas del plan de comida deben "
|
||||
"compartirse de forma predeterminada."
|
||||
|
||||
#: .\cookbook\forms.py:81
|
||||
#, fuzzy
|
||||
#| msgid "Open Shopping List"
|
||||
msgid "Users with whom to share shopping lists."
|
||||
msgstr "Abrir Lista de la Compra"
|
||||
msgstr "Usuarios con quienes compartir listas de compra."
|
||||
|
||||
#: .\cookbook\forms.py:83
|
||||
msgid "Show recently viewed recipes on search page."
|
||||
@@ -361,10 +341,8 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:466
|
||||
#, fuzzy
|
||||
#| msgid "Search"
|
||||
msgid "Search Method"
|
||||
msgstr "Buscar"
|
||||
msgstr "Método de Búsqueda"
|
||||
|
||||
#: .\cookbook\forms.py:467
|
||||
msgid "Fuzzy Lookups"
|
||||
@@ -389,10 +367,8 @@ msgid "Fuzzy Search"
|
||||
msgstr "Buscar"
|
||||
|
||||
#: .\cookbook\forms.py:472
|
||||
#, fuzzy
|
||||
#| msgid "Text"
|
||||
msgid "Full Text"
|
||||
msgstr "Texto"
|
||||
msgstr "Texto Completo"
|
||||
|
||||
#: .\cookbook\forms.py:497
|
||||
msgid ""
|
||||
@@ -437,10 +413,8 @@ msgid "Prefix to add when copying list to the clipboard."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:514
|
||||
#, fuzzy
|
||||
#| msgid "Shopping List"
|
||||
msgid "Share Shopping List"
|
||||
msgstr "Lista de la Compra"
|
||||
msgstr "Compartir Lista de la Compra"
|
||||
|
||||
#: .\cookbook\forms.py:515
|
||||
msgid "Autosync"
|
||||
@@ -463,10 +437,8 @@ msgid "Default Delay Hours"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:520
|
||||
#, fuzzy
|
||||
#| msgid "Select Supermarket"
|
||||
msgid "Filter to Supermarket"
|
||||
msgstr "Seleccionar supermercado"
|
||||
msgstr "Filtrar según Supermercado"
|
||||
|
||||
#: .\cookbook\forms.py:521
|
||||
msgid "Recent Days"
|
||||
@@ -499,10 +471,8 @@ msgid "Fields on food that should be inherited by default."
|
||||
msgstr "Alimento que se va a reemplazar."
|
||||
|
||||
#: .\cookbook\forms.py:548
|
||||
#, fuzzy
|
||||
#| msgid "Show recently viewed recipes on search page."
|
||||
msgid "Show recipe counts on search filters"
|
||||
msgstr "Muestra recetas vistas recientemente en la página de búsqueda."
|
||||
msgstr "Mostrar cantidad de recetas en los filtros de búsquedas"
|
||||
|
||||
#: .\cookbook\helper\AllAuthCustomAdapter.py:36
|
||||
msgid ""
|
||||
@@ -546,10 +516,8 @@ msgid "One of queryset or hash_key must be provided"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:152
|
||||
#, fuzzy
|
||||
#| msgid "You must provide at least a recipe or a title."
|
||||
msgid "You must supply a servings size"
|
||||
msgstr "Debe proporcionar al menos una receta o un título."
|
||||
msgstr "Debe proporcionar un tamaño de porción"
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:64
|
||||
#: .\cookbook\helper\template_helper.py:66
|
||||
@@ -586,22 +554,17 @@ msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:235
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Imported new recipe!"
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr "¡Nueva receta importada!"
|
||||
msgstr "Se importaron %s recetas."
|
||||
|
||||
#: .\cookbook\integration\paprika.py:46
|
||||
#, fuzzy
|
||||
#| msgid "Note"
|
||||
msgid "Notes"
|
||||
msgstr "Nota"
|
||||
msgstr "Notas"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:49
|
||||
#, fuzzy
|
||||
#| msgid "Information"
|
||||
msgid "Nutritional Information"
|
||||
msgstr "Información"
|
||||
msgstr "Información Nutricional"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:53
|
||||
msgid "Source"
|
||||
@@ -715,10 +678,8 @@ msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\models.py:1138
|
||||
#, fuzzy
|
||||
#| msgid "Food"
|
||||
msgid "Food Alias"
|
||||
msgstr "Comida"
|
||||
msgstr "Alias de la Comida"
|
||||
|
||||
#: .\cookbook\models.py:1138
|
||||
#, fuzzy
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,10 +13,10 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
|
||||
"PO-Revision-Date: 2022-04-05 10:31+0000\n"
|
||||
"PO-Revision-Date: 2022-05-10 15:32+0000\n"
|
||||
"Last-Translator: Jesse <jesse.kamps@pm.me>\n"
|
||||
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/recipes-"
|
||||
"backend/nl/>\n"
|
||||
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/nl/>\n"
|
||||
"Language: nl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -84,7 +84,7 @@ msgstr "Opmerkingen"
|
||||
|
||||
#: .\cookbook\forms.py:69
|
||||
msgid "Left-handed mode"
|
||||
msgstr ""
|
||||
msgstr "Linkshandigen modus"
|
||||
|
||||
#: .\cookbook\forms.py:73
|
||||
msgid ""
|
||||
@@ -161,7 +161,7 @@ msgstr "Sluit ingrediënten die op voorraad zijn uit."
|
||||
|
||||
#: .\cookbook\forms.py:93
|
||||
msgid "Will optimize the UI for use with your left hand."
|
||||
msgstr ""
|
||||
msgstr "Optimaliseert de gebruikersinterface voor gebruik met je linkerhand."
|
||||
|
||||
#: .\cookbook\forms.py:110
|
||||
msgid ""
|
||||
@@ -547,7 +547,7 @@ msgstr "Sjablooncode kon niet verwerkt worden."
|
||||
#: .\cookbook\integration\copymethat.py:42
|
||||
#: .\cookbook\integration\melarecipes.py:37
|
||||
msgid "Favorite"
|
||||
msgstr ""
|
||||
msgstr "Favoriet"
|
||||
|
||||
#: .\cookbook\integration\copymethat.py:71
|
||||
#: .\cookbook\integration\recettetek.py:53
|
||||
@@ -722,10 +722,8 @@ msgid "Recipe"
|
||||
msgstr "Recept"
|
||||
|
||||
#: .\cookbook\models.py:1163
|
||||
#, fuzzy
|
||||
#| msgid "Foods"
|
||||
msgid "Food"
|
||||
msgstr "Ingrediënten"
|
||||
msgstr "Ingrediënt"
|
||||
|
||||
#: .\cookbook\models.py:1164 .\cookbook\templates\base.html:138
|
||||
msgid "Keyword"
|
||||
@@ -1138,10 +1136,8 @@ msgstr "Geschiedenis"
|
||||
#: .\cookbook\templates\base.html:252
|
||||
#: .\cookbook\templates\ingredient_editor.html:7
|
||||
#: .\cookbook\templates\ingredient_editor.html:13
|
||||
#, fuzzy
|
||||
#| msgid "Ingredients"
|
||||
msgid "Ingredient Editor"
|
||||
msgstr "Ingrediënten"
|
||||
msgstr "Ingrediënteneditor"
|
||||
|
||||
#: .\cookbook\templates\base.html:264
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
@@ -1198,11 +1194,11 @@ msgstr "Uitloggen"
|
||||
|
||||
#: .\cookbook\templates\base.html:342
|
||||
msgid "You are using the free version of Tandor"
|
||||
msgstr ""
|
||||
msgstr "Je gebruikt de gratis versie van Tandoor"
|
||||
|
||||
#: .\cookbook\templates\base.html:342
|
||||
msgid "Upgrade Now"
|
||||
msgstr ""
|
||||
msgstr "Upgrade nu"
|
||||
|
||||
#: .\cookbook\templates\batch\edit.html:6
|
||||
msgid "Batch edit Category"
|
||||
@@ -1731,7 +1727,7 @@ msgstr ""
|
||||
#: .\cookbook\templates\openid\login.html:27
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:27
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
msgstr "Terug"
|
||||
|
||||
#: .\cookbook\templates\recipe_view.html:26
|
||||
msgid "by"
|
||||
@@ -2180,17 +2176,15 @@ msgstr "Maak Superuser acount"
|
||||
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:7
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:23
|
||||
#, fuzzy
|
||||
#| msgid "Social Login"
|
||||
msgid "Social Network Login Failure"
|
||||
msgstr "Socials login"
|
||||
msgstr "Inloggen op sociaal netwerk mislukt"
|
||||
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:25
|
||||
#, fuzzy
|
||||
#| msgid "An error occurred attempting to move "
|
||||
msgid ""
|
||||
"An error occurred while attempting to login via your social network account."
|
||||
msgstr "Er is een error opgetreden bij het verplaatsen "
|
||||
msgstr ""
|
||||
"Er is een fout opgetreden tijdens het inloggen via je sociale netwerk "
|
||||
"account."
|
||||
|
||||
#: .\cookbook\templates\socialaccount\connections.html:4
|
||||
#: .\cookbook\templates\socialaccount\connections.html:15
|
||||
@@ -2542,33 +2536,39 @@ msgstr ""
|
||||
"op volledige tekst ondersteund."
|
||||
|
||||
#: .\cookbook\views\api.py:671
|
||||
#, fuzzy
|
||||
#| msgid "ID of keyword a recipe should have. For multiple repeat parameter."
|
||||
msgid ""
|
||||
"ID of keyword a recipe should have. For multiple repeat parameter. "
|
||||
"Equivalent to keywords_or"
|
||||
msgstr ""
|
||||
"ID van etiket dat een recept moet hebben. Herhaal parameter voor meerdere."
|
||||
"ID van etiket dat een recept moet hebben. Herhaal parameter voor meerdere. "
|
||||
"Gelijkwaardig aan keywords_or"
|
||||
|
||||
#: .\cookbook\views\api.py:674
|
||||
msgid ""
|
||||
"Keyword IDs, repeat for multiple. Return recipes with any of the keywords"
|
||||
msgstr ""
|
||||
"Etiket ID, herhaal voor meerdere. Geeft recepten met elk geselecteerd etiket "
|
||||
"weer"
|
||||
|
||||
#: .\cookbook\views\api.py:677
|
||||
msgid ""
|
||||
"Keyword IDs, repeat for multiple. Return recipes with all of the keywords."
|
||||
msgstr ""
|
||||
"Etiket ID, herhaal voor meerdere. Geeft recepten met alle geselecteerde "
|
||||
"etiketten weer."
|
||||
|
||||
#: .\cookbook\views\api.py:680
|
||||
msgid ""
|
||||
"Keyword IDs, repeat for multiple. Exclude recipes with any of the keywords."
|
||||
msgstr ""
|
||||
"Etiket ID, herhaal voor meerdere. Sluit recepten met één van de etiketten "
|
||||
"uit."
|
||||
|
||||
#: .\cookbook\views\api.py:683
|
||||
msgid ""
|
||||
"Keyword IDs, repeat for multiple. Exclude recipes with all of the keywords."
|
||||
msgstr ""
|
||||
"Etiket ID, herhaal voor meerdere. Sluit recepten met alle etiketten uit."
|
||||
|
||||
#: .\cookbook\views\api.py:685
|
||||
msgid "ID of food a recipe should have. For multiple repeat parameter."
|
||||
@@ -2579,18 +2579,25 @@ msgstr ""
|
||||
#: .\cookbook\views\api.py:688
|
||||
msgid "Food IDs, repeat for multiple. Return recipes with any of the foods"
|
||||
msgstr ""
|
||||
"Ingrediënt ID, herhaal voor meerdere. Geeft recepten met elk ingrediënt weer"
|
||||
|
||||
#: .\cookbook\views\api.py:690
|
||||
msgid "Food IDs, repeat for multiple. Return recipes with all of the foods."
|
||||
msgstr ""
|
||||
"Ingrediënt ID, herhaal voor meerdere. Geef recepten met alle ingrediënten "
|
||||
"weer."
|
||||
|
||||
#: .\cookbook\views\api.py:692
|
||||
msgid "Food IDs, repeat for multiple. Exclude recipes with any of the foods."
|
||||
msgstr ""
|
||||
"Ingrediënt ID, herhaal voor meerdere. sluit recepten met één van de "
|
||||
"ingrediënten uit."
|
||||
|
||||
#: .\cookbook\views\api.py:694
|
||||
msgid "Food IDs, repeat for multiple. Exclude recipes with all of the foods."
|
||||
msgstr ""
|
||||
"Ingrediënt ID, herhaal voor meerdere. Sluit recepten met alle ingrediënten "
|
||||
"uit."
|
||||
|
||||
#: .\cookbook\views\api.py:695
|
||||
msgid "ID of unit a recipe should have."
|
||||
@@ -2600,7 +2607,7 @@ msgstr "ID van eenheid dat een recept moet hebben."
|
||||
msgid ""
|
||||
"Rating a recipe should have or greater. [0 - 5] Negative value filters "
|
||||
"rating less than."
|
||||
msgstr ""
|
||||
msgstr "Een waardering van een recept gaat van 0 tot 5."
|
||||
|
||||
#: .\cookbook\views\api.py:698
|
||||
msgid "ID of book a recipe should be in. For multiple repeat parameter."
|
||||
@@ -2609,19 +2616,20 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:700
|
||||
msgid "Book IDs, repeat for multiple. Return recipes with any of the books"
|
||||
msgstr ""
|
||||
msgstr "Boek ID, herhaal voor meerdere. Geeft recepten uit alle boeken weer"
|
||||
|
||||
#: .\cookbook\views\api.py:702
|
||||
msgid "Book IDs, repeat for multiple. Return recipes with all of the books."
|
||||
msgstr ""
|
||||
msgstr "Boek IDs, herhaal voor meerdere. Geeft recepten weer uit alle boeken."
|
||||
|
||||
#: .\cookbook\views\api.py:704
|
||||
msgid "Book IDs, repeat for multiple. Exclude recipes with any of the books."
|
||||
msgstr ""
|
||||
"Boek IDs, herhaal voor meerdere. Sluit recepten uit elk van de boeken uit."
|
||||
|
||||
#: .\cookbook\views\api.py:706
|
||||
msgid "Book IDs, repeat for multiple. Exclude recipes with all of the books."
|
||||
msgstr ""
|
||||
msgstr "Boek IDs, herhaal voor meerdere. Sluit recepten uit alle boeken uit."
|
||||
|
||||
#: .\cookbook\views\api.py:708
|
||||
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
@@ -2642,37 +2650,46 @@ msgid ""
|
||||
"Filter recipes cooked X times or more. Negative values returns cooked less "
|
||||
"than X times"
|
||||
msgstr ""
|
||||
"Filter recepten X maal of meer bereid. Negatieve waarden geven minder dan X "
|
||||
"keer bereide recepten weer"
|
||||
|
||||
#: .\cookbook\views\api.py:716
|
||||
msgid ""
|
||||
"Filter recipes last cooked on or after YYYY-MM-DD. Prepending - filters on "
|
||||
"or before date."
|
||||
msgstr ""
|
||||
"Filter recepten op laatst bereid op of na JJJJ-MM-DD. Voorafgaand - filters "
|
||||
"op of voor datum."
|
||||
|
||||
#: .\cookbook\views\api.py:718
|
||||
msgid ""
|
||||
"Filter recipes created on or after YYYY-MM-DD. Prepending - filters on or "
|
||||
"before date."
|
||||
msgstr ""
|
||||
"Filter recepten aangemaakt op of na JJJJ-MM-DD. Voorafgaand - filters op of "
|
||||
"voor datum."
|
||||
|
||||
#: .\cookbook\views\api.py:720
|
||||
msgid ""
|
||||
"Filter recipes updated on or after YYYY-MM-DD. Prepending - filters on or "
|
||||
"before date."
|
||||
msgstr ""
|
||||
"Filter recepten op geüpdatet op of na JJJJ-MM-DD. Voorafgaand - filters op "
|
||||
"of voor datum."
|
||||
|
||||
#: .\cookbook\views\api.py:722
|
||||
msgid ""
|
||||
"Filter recipes lasts viewed on or after YYYY-MM-DD. Prepending - filters on "
|
||||
"or before date."
|
||||
msgstr ""
|
||||
"Filter recepten op laatst bekeken op of na JJJJ-MM-DD. Voorafgaand - filters "
|
||||
"op of voor datum."
|
||||
|
||||
#: .\cookbook\views\api.py:724
|
||||
#, fuzzy
|
||||
#| msgid "If only internal recipes should be returned. [true/<b>false</b>]"
|
||||
msgid "Filter recipes that can be made with OnHand food. [true/<b>false</b>]"
|
||||
msgstr ""
|
||||
"Wanneer alleen interne recepten gevonden moeten worden. [waar/<b>onwaar</b>]"
|
||||
"Filter recepten die bereid kunnen worden met ingrediënten die op voorraad "
|
||||
"zijn. [waar/<b>onwaar</b>]"
|
||||
|
||||
#: .\cookbook\views\api.py:880
|
||||
msgid ""
|
||||
@@ -2718,7 +2735,7 @@ msgstr "Verbinding geweigerd."
|
||||
|
||||
#: .\cookbook\views\api.py:1200
|
||||
msgid "Bad URL Schema."
|
||||
msgstr ""
|
||||
msgstr "Verkeerd URL schema."
|
||||
|
||||
#: .\cookbook\views\api.py:1206
|
||||
msgid "No usable data could be found."
|
||||
@@ -2812,10 +2829,8 @@ msgid "Shopping Categories"
|
||||
msgstr "Boodschappencategorieën"
|
||||
|
||||
#: .\cookbook\views\lists.py:187
|
||||
#, fuzzy
|
||||
#| msgid "Filter"
|
||||
msgid "Custom Filters"
|
||||
msgstr "Filtreren"
|
||||
msgstr "Aangepaste filters"
|
||||
|
||||
#: .\cookbook\views\lists.py:224
|
||||
msgid "Steps"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,6 +4,8 @@ import os
|
||||
from datetime import datetime
|
||||
|
||||
import requests
|
||||
import validators
|
||||
|
||||
from cookbook.models import Recipe, RecipeImport, SyncLog
|
||||
from cookbook.provider.provider import Provider
|
||||
|
||||
@@ -104,9 +106,11 @@ class Dropbox(Provider):
|
||||
recipe.link = Dropbox.get_share_link(recipe)
|
||||
recipe.save()
|
||||
|
||||
response = requests.get(recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.'))
|
||||
url = recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.')
|
||||
if validators.url(url, public=True):
|
||||
response = requests.get(url)
|
||||
|
||||
return io.BytesIO(response.content)
|
||||
return io.BytesIO(response.content)
|
||||
|
||||
@staticmethod
|
||||
def rename_file(recipe, new_name):
|
||||
|
||||
@@ -4,6 +4,7 @@ import tempfile
|
||||
from datetime import datetime
|
||||
|
||||
import requests
|
||||
import validators
|
||||
import webdav3.client as wc
|
||||
from cookbook.models import Recipe, RecipeImport, SyncLog
|
||||
from cookbook.provider.provider import Provider
|
||||
@@ -92,20 +93,21 @@ class Nextcloud(Provider):
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
r = requests.get(
|
||||
url,
|
||||
headers=headers,
|
||||
auth=HTTPBasicAuth(
|
||||
recipe.storage.username, recipe.storage.password
|
||||
if validators.url(url, public=True):
|
||||
r = requests.get(
|
||||
url,
|
||||
headers=headers,
|
||||
auth=HTTPBasicAuth(
|
||||
recipe.storage.username, recipe.storage.password
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
response_json = r.json()
|
||||
for element in response_json['ocs']['data']:
|
||||
if element['share_type'] == '3':
|
||||
return element['url']
|
||||
response_json = r.json()
|
||||
for element in response_json['ocs']['data']:
|
||||
if element['share_type'] == '3':
|
||||
return element['url']
|
||||
|
||||
return Nextcloud.create_share_link(recipe)
|
||||
return Nextcloud.create_share_link(recipe)
|
||||
|
||||
@staticmethod
|
||||
def get_file(recipe):
|
||||
|
||||
@@ -104,21 +104,32 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
|
||||
|
||||
@receiver(post_save, sender=MealPlan)
|
||||
def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs):
|
||||
print("MEAL_AUTO_ADD Signal trying to auto add to shopping")
|
||||
if not instance:
|
||||
return
|
||||
user = instance.get_owner()
|
||||
with scope(space=instance.space):
|
||||
slr_exists = instance.shoppinglistrecipe_set.exists()
|
||||
|
||||
if not created and slr_exists:
|
||||
for x in instance.shoppinglistrecipe_set.all():
|
||||
# assuming that permissions checks for the MealPlan have happened upstream
|
||||
if instance.servings != x.servings:
|
||||
SLR = RecipeShoppingEditor(id=x.id, user=user, space=instance.space)
|
||||
SLR.edit_servings(servings=instance.servings)
|
||||
elif not user.userpreference.mealplan_autoadd_shopping or not instance.recipe:
|
||||
print("MEAL_AUTO_ADD Instance is none")
|
||||
return
|
||||
|
||||
if created:
|
||||
SLR = RecipeShoppingEditor(user=user, space=instance.space)
|
||||
SLR.create(mealplan=instance, servings=instance.servings)
|
||||
try:
|
||||
space = instance.get_space()
|
||||
user = instance.get_owner()
|
||||
with scope(space=space):
|
||||
slr_exists = instance.shoppinglistrecipe_set.exists()
|
||||
|
||||
if not created and slr_exists:
|
||||
for x in instance.shoppinglistrecipe_set.all():
|
||||
# assuming that permissions checks for the MealPlan have happened upstream
|
||||
if instance.servings != x.servings:
|
||||
SLR = RecipeShoppingEditor(id=x.id, user=user, space=instance.space)
|
||||
SLR.edit_servings(servings=instance.servings)
|
||||
elif not user.userpreference.mealplan_autoadd_shopping or not instance.recipe:
|
||||
print("MEAL_AUTO_ADD No recipe or no setting")
|
||||
return
|
||||
|
||||
if created:
|
||||
SLR = RecipeShoppingEditor(user=user, space=space)
|
||||
SLR.create(mealplan=instance, servings=instance.servings)
|
||||
print("MEAL_AUTO_ADD Created SLR")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
{% if not request.user.is_authenticated or request.user.userpreference.theme == request.user.userpreference.TANDOOR %}
|
||||
<a class="navbar-brand p-0 me-2 justify-content-center" href="{% base_path request 'base' %}"
|
||||
aria-label="Tandoor">
|
||||
<img class="brand-icon" src="{% static 'assets/brand_logo.svg' %}" alt="Logo">
|
||||
<img class="brand-icon" src="{% static 'assets/brand_logo.png' %}" alt="Logo">
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -91,7 +91,7 @@
|
||||
{% if not request.user.is_authenticated or request.user.userpreference.theme == request.user.userpreference.TANDOOR %}
|
||||
<a class="navbar-brand p-0 me-2 justify-content-center" href="{% base_path request 'base' %}"
|
||||
aria-label="Tandoor">
|
||||
<img class="brand-icon" src="{% static 'assets/brand_logo.svg' %}" alt="Logo">
|
||||
<img class="brand-icon" src="{% static 'assets/brand_logo.png' %}" alt="Logo">
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -15,6 +15,7 @@ from cookbook.helper.mdx_attributes import MarkdownFormatExtension
|
||||
from cookbook.helper.mdx_urlize import UrlizeExtension
|
||||
from cookbook.models import Space, get_model_name
|
||||
from recipes import settings
|
||||
from recipes.settings import STATIC_URL
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@@ -157,7 +158,7 @@ def base_path(request, path_type):
|
||||
elif path_type == 'script':
|
||||
return request.META.get('HTTP_X_SCRIPT_NAME', '')
|
||||
elif path_type == 'static_base':
|
||||
return static('vue/manifest.json').replace('vue/manifest.json', '')
|
||||
return STATIC_URL
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
|
||||
@@ -6,6 +6,7 @@ import uuid
|
||||
from collections import OrderedDict
|
||||
|
||||
import requests
|
||||
import validators
|
||||
from PIL import UnidentifiedImageError
|
||||
from annoying.decorators import ajax_request
|
||||
from annoying.functions import get_object_or_None
|
||||
@@ -14,7 +15,7 @@ from django.contrib.auth.models import User
|
||||
from django.contrib.postgres.search import TrigramSimilarity
|
||||
from django.core.exceptions import FieldError, ValidationError
|
||||
from django.core.files import File
|
||||
from django.db.models import (Case, Count, Exists, F, IntegerField, OuterRef, ProtectedError, Q,
|
||||
from django.db.models import (Case, Count, Exists, OuterRef, ProtectedError, Q,
|
||||
Subquery, Value, When)
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
from django.db.models.functions import Coalesce, Lower
|
||||
@@ -24,7 +25,6 @@ from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django_scopes import scopes_disabled
|
||||
from icalendar import Calendar, Event
|
||||
from recipe_scrapers import NoSchemaFoundInWildMode, WebsiteNotImplementedError, scrape_me
|
||||
from requests.exceptions import MissingSchema
|
||||
from rest_framework import decorators, status, viewsets
|
||||
from rest_framework.exceptions import APIException, PermissionDenied
|
||||
@@ -34,6 +34,7 @@ from rest_framework.renderers import JSONRenderer, TemplateHTMLRenderer
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ViewSetMixin
|
||||
from treebeard.exceptions import InvalidMoveToDescendant, InvalidPosition, PathOverflow
|
||||
from validators import ValidationFailure
|
||||
|
||||
from cookbook.helper.HelperFunctions import str2bool
|
||||
from cookbook.helper.image_processing import handle_image
|
||||
@@ -43,7 +44,6 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, Cus
|
||||
group_required)
|
||||
from cookbook.helper.recipe_html_import import get_recipe_from_source
|
||||
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch, old_search
|
||||
from cookbook.helper.recipe_url_import import get_from_scraper
|
||||
from cookbook.helper.shopping_helper import RecipeShoppingEditor, shopping_helper
|
||||
from cookbook.models import (Automation, BookmarkletImport, CookLog, CustomFilter, ExportLog, Food,
|
||||
FoodInheritField, ImportLog, Ingredient, Keyword, MealPlan, MealType,
|
||||
@@ -774,16 +774,18 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
image = None
|
||||
filetype = ".jpeg" # fall-back to .jpeg, even if wrong, at least users will know it's an image and most image viewers can open it correctly anyways
|
||||
filetype = ".jpeg" # fall-back to .jpeg, even if wrong, at least users will know it's an image and most image viewers can open it correctly anyways
|
||||
|
||||
if 'image' in serializer.validated_data:
|
||||
image = obj.image
|
||||
filetype = mimetypes.guess_extension(serializer.validated_data['image'].content_type) or filetype
|
||||
elif 'image_url' in serializer.validated_data:
|
||||
try:
|
||||
response = requests.get(serializer.validated_data['image_url'])
|
||||
image = File(io.BytesIO(response.content))
|
||||
filetype = mimetypes.guess_extension(response.headers['content-type']) or filetype
|
||||
url = serializer.validated_data['image_url']
|
||||
if validators.url(url, public=True):
|
||||
response = requests.get(url)
|
||||
image = File(io.BytesIO(response.content))
|
||||
filetype = mimetypes.guess_extension(response.headers['content-type']) or filetype
|
||||
except UnidentifiedImageError as e:
|
||||
print(e)
|
||||
pass
|
||||
@@ -799,6 +801,10 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
obj.image = File(img, name=f'{uuid.uuid4()}_{obj.pk}{filetype}')
|
||||
obj.save()
|
||||
return Response(serializer.data)
|
||||
else:
|
||||
obj.image = None
|
||||
obj.save()
|
||||
return Response(serializer.data)
|
||||
|
||||
return Response(serializer.errors, 400)
|
||||
|
||||
@@ -1188,7 +1194,13 @@ def recipe_from_source(request):
|
||||
# in manual mode request complete page to return it later
|
||||
if url:
|
||||
try:
|
||||
data = requests.get(url, headers=external_request_headers).content
|
||||
if validators.url(url, public=True):
|
||||
data = requests.get(url, headers=external_request_headers).content
|
||||
else:
|
||||
return JsonResponse({
|
||||
'error': True,
|
||||
'msg': _('Invalid Url')
|
||||
}, status=400)
|
||||
except requests.exceptions.ConnectionError:
|
||||
return JsonResponse({
|
||||
'error': True,
|
||||
@@ -1199,6 +1211,7 @@ def recipe_from_source(request):
|
||||
'error': True,
|
||||
'msg': _('Bad URL Schema.')
|
||||
}, status=400)
|
||||
|
||||
recipe_json, recipe_tree, recipe_html, recipe_images = get_recipe_from_source(data, url, request)
|
||||
if len(recipe_tree) == 0 and len(recipe_json) == 0:
|
||||
return JsonResponse({
|
||||
|
||||
@@ -343,6 +343,11 @@ ProxyPassReverse / http://localhost:8080/ # replace port
|
||||
!!!info
|
||||
Always wait at least 2-3 minutes after the very first start, since migrations will take some time!
|
||||
|
||||
!!!warning
|
||||
If you want to use Tandoor on a Raspberry Pi running a 32-bit operating system you will need to use the following
|
||||
docker image tags: `latest-raspi`, `beta-raspi` and the versioned `<x.y.z>-raspi`
|
||||
We strongly recommend using the new 64-bit Raspian image as the 32-bit version is not tested.
|
||||
|
||||
If you're having issues with installing Tandoor on your Raspberry Pi or similar device,
|
||||
follow these instructions:
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -366,8 +366,10 @@ USE_TZ = True
|
||||
|
||||
LANGUAGES = [
|
||||
('hy', _('Armenian ')),
|
||||
('bg', _('Bulgarian')),
|
||||
('ca', _('Catalan')),
|
||||
('cs', _('Czech')),
|
||||
('da', _('Danish')),
|
||||
('nl', _('Dutch')),
|
||||
('en', _('English')),
|
||||
('fr', _('French')),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Django==3.2.13
|
||||
cryptography==36.0.2
|
||||
cryptography==37.0.1
|
||||
django-annoying==0.10.6
|
||||
django-autocomplete-light==3.9.4
|
||||
django-cleanup==6.0.0
|
||||
@@ -29,7 +29,7 @@ Jinja2==3.1.1
|
||||
django-webpack-loader==1.4.1
|
||||
django-js-reverse==0.9.1
|
||||
django-allauth==0.50.0
|
||||
recipe-scrapers==13.32.0
|
||||
recipe-scrapers==13.32.1
|
||||
django-scopes==1.2.0
|
||||
pytest==7.1.1
|
||||
pytest-django==4.5.2
|
||||
@@ -43,3 +43,4 @@ python-ldap==3.4.0
|
||||
django-auth-ldap==4.0.0
|
||||
pytest-factoryboy==2.1.0
|
||||
pyppeteer==1.0.2
|
||||
validators==0.19.0
|
||||
43106
vue/package-lock.json
generated
Normal file
43106
vue/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9,12 +9,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/eslint-parser": "^7.16.0",
|
||||
"@kangc/v-md-editor": "^1.7.7",
|
||||
"@kangc/v-md-editor": "^1.7.11",
|
||||
"@kevinfaguiar/vue-twemoji-picker": "^5.7.4",
|
||||
"@popperjs/core": "^2.11.2",
|
||||
"@riophae/vue-treeselect": "^0.4.0",
|
||||
"@vue/cli": "^5.0.4",
|
||||
"axios": "^0.26.1",
|
||||
"babel": "^6.23.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^8.2.5",
|
||||
"bootstrap-vue": "^2.21.2",
|
||||
"core-js": "^3.20.3",
|
||||
"html2pdf.js": "^0.10.1",
|
||||
@@ -30,6 +33,7 @@
|
||||
"vue-infinite-loading": "^2.4.5",
|
||||
"vue-multiselect": "^2.1.6",
|
||||
"vue-property-decorator": "^9.1.2",
|
||||
"vue-sanitize": "^0.2.2",
|
||||
"vue-simple-calendar": "^5.0.1",
|
||||
"vue-template-compiler": "^2.6.14",
|
||||
"vue2-touch-events": "^3.2.2",
|
||||
@@ -86,4 +90,4 @@
|
||||
"@vue/cli-plugin-pwa/workbox-webpack-plugin": "^5.1.3",
|
||||
"coa": "2.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
<label for="id_textarea">{{ $t("Information") }}</label>
|
||||
<textarea id="id_textarea" ref="output_text" class="form-control" style="height: 50vh" v-html="export_info.msg" disabled></textarea>
|
||||
<textarea id="id_textarea" ref="output_text" class="form-control" style="height: 50vh" v-html="$sanitize(export_info.msg)" disabled></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
@@ -65,7 +65,8 @@ import LoadingSpinner from "@/components/LoadingSpinner"
|
||||
import { ApiApiFactory } from "@/utils/openapi/api.ts"
|
||||
|
||||
Vue.use(BootstrapVue)
|
||||
|
||||
import VueSanitize from "vue-sanitize";
|
||||
Vue.use(VueSanitize);
|
||||
export default {
|
||||
name: "ExportResponseView",
|
||||
mixins: [ResolveUrlMixin, ToastMixin],
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
}}!
|
||||
</b-badge>
|
||||
<b-badge variant="primary" v-else class="float-right">
|
||||
{{ $t('Import_running') }}
|
||||
{{ $t('import_running') }}
|
||||
<b-spinner small class="d-inline-block"></b-spinner>
|
||||
</b-badge>
|
||||
</h4>
|
||||
@@ -143,7 +143,7 @@
|
||||
<b-card>
|
||||
<textarea id="id_textarea" ref="output_text" class="form-control"
|
||||
style="height: 50vh"
|
||||
v-html="import_info.msg"
|
||||
v-html="$sanitize(import_info.msg)"
|
||||
disabled></textarea>
|
||||
</b-card>
|
||||
</b-collapse>
|
||||
@@ -168,7 +168,9 @@ import {ResolveUrlMixin, ToastMixin, RandomIconMixin} from "@/utils/utils";
|
||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||
|
||||
import {ApiApiFactory} from "@/utils/openapi/api.ts";
|
||||
import VueSanitize from "vue-sanitize";
|
||||
|
||||
Vue.use(VueSanitize);
|
||||
Vue.use(BootstrapVue)
|
||||
|
||||
export default {
|
||||
|
||||
@@ -54,14 +54,20 @@
|
||||
<div class="col-12 col-md-3 calender-options">
|
||||
<h5>{{ $t("Planner_Settings") }}</h5>
|
||||
<b-form>
|
||||
<b-form-group id="UomInput" :label="$t('Period')" :description="$t('Plan_Period_To_Show')" label-for="UomInput">
|
||||
<b-form-select id="UomInput" v-model="settings.displayPeriodUom" :options="options.displayPeriodUom"></b-form-select>
|
||||
<b-form-group id="UomInput" :label="$t('Period')" :description="$t('Plan_Period_To_Show')"
|
||||
label-for="UomInput">
|
||||
<b-form-select id="UomInput" v-model="settings.displayPeriodUom"
|
||||
:options="options.displayPeriodUom"></b-form-select>
|
||||
</b-form-group>
|
||||
<b-form-group id="PeriodInput" :label="$t('Periods')" :description="$t('Plan_Show_How_Many_Periods')" label-for="PeriodInput">
|
||||
<b-form-select id="PeriodInput" v-model="settings.displayPeriodCount" :options="options.displayPeriodCount"></b-form-select>
|
||||
<b-form-group id="PeriodInput" :label="$t('Periods')"
|
||||
:description="$t('Plan_Show_How_Many_Periods')" label-for="PeriodInput">
|
||||
<b-form-select id="PeriodInput" v-model="settings.displayPeriodCount"
|
||||
:options="options.displayPeriodCount"></b-form-select>
|
||||
</b-form-group>
|
||||
<b-form-group id="DaysInput" :label="$t('Starting_Day')" :description="$t('Starting_Day')" label-for="DaysInput">
|
||||
<b-form-select id="DaysInput" v-model="settings.startingDayOfWeek" :options="dayNames"></b-form-select>
|
||||
<b-form-group id="DaysInput" :label="$t('Starting_Day')" :description="$t('Starting_Day')"
|
||||
label-for="DaysInput">
|
||||
<b-form-select id="DaysInput" v-model="settings.startingDayOfWeek"
|
||||
:options="dayNames"></b-form-select>
|
||||
</b-form-group>
|
||||
<b-form-group id="WeekNumInput" :label="$t('Week_Numbers')">
|
||||
<b-form-checkbox v-model="settings.displayWeekNumbers" name="week_num">
|
||||
@@ -73,19 +79,25 @@
|
||||
<div class="col-12 col-md-9 col-lg-6">
|
||||
<h5>{{ $t("Meal_Types") }}</h5>
|
||||
<div>
|
||||
<draggable :list="meal_types" group="meal_types" :empty-insert-threshold="10" @sort="sortMealTypes()" ghost-class="ghost">
|
||||
<b-card no-body class="mt-1 list-group-item p-2" style="cursor: move" v-for="(meal_type, index) in meal_types" v-hover :key="meal_type.id">
|
||||
<draggable :list="meal_types" group="meal_types" :empty-insert-threshold="10"
|
||||
@sort="sortMealTypes()" ghost-class="ghost">
|
||||
<b-card no-body class="mt-1 list-group-item p-2" style="cursor: move"
|
||||
v-for="(meal_type, index) in meal_types" v-hover :key="meal_type.id">
|
||||
<b-card-header class="p-2 border-0">
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<button type="button" class="btn btn-lg shadow-none"><i class="fas fa-arrows-alt-v"></i></button>
|
||||
<button type="button" class="btn btn-lg shadow-none"><i
|
||||
class="fas fa-arrows-alt-v"></i></button>
|
||||
</div>
|
||||
<div class="col-10">
|
||||
<h5 class="mt-1 mb-1">
|
||||
{{ meal_type.icon }} {{ meal_type.name
|
||||
{{ meal_type.icon }} {{
|
||||
meal_type.name
|
||||
}}<span class="float-right text-primary" style="cursor: pointer"
|
||||
><i class="fa" v-bind:class="{ 'fa-pen': !meal_type.editing, 'fa-save': meal_type.editing }" @click="editOrSaveMealType(index)" aria-hidden="true"></i
|
||||
></span>
|
||||
><i class="fa"
|
||||
v-bind:class="{ 'fa-pen': !meal_type.editing, 'fa-save': meal_type.editing }"
|
||||
@click="editOrSaveMealType(index)" aria-hidden="true"></i
|
||||
></span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,19 +105,27 @@
|
||||
<b-card-body class="p-4" v-if="meal_type.editing">
|
||||
<div class="form-group">
|
||||
<label>{{ $t("Name") }}</label>
|
||||
<input class="form-control" :placeholder="$t('Name')" v-model="meal_type.name" />
|
||||
<input class="form-control" :placeholder="$t('Name')"
|
||||
v-model="meal_type.name"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<emoji-input :field="'icon'" :label="$t('Icon')" :value="meal_type.icon"></emoji-input>
|
||||
<emoji-input :field="'icon'" :label="$t('Icon')"
|
||||
:value="meal_type.icon"></emoji-input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ $t("Color") }}</label>
|
||||
<input class="form-control" type="color" name="Name" :value="meal_type.color" @change="meal_type.color = $event.target.value" />
|
||||
<input class="form-control" type="color" name="Name"
|
||||
:value="meal_type.color"
|
||||
@change="meal_type.color = $event.target.value"/>
|
||||
</div>
|
||||
<b-form-checkbox id="checkbox-1" v-model="meal_type.default" name="default_checkbox" class="mb-2">
|
||||
<b-form-checkbox id="checkbox-1" v-model="meal_type.default"
|
||||
name="default_checkbox" class="mb-2">
|
||||
{{ $t("Default") }}
|
||||
</b-form-checkbox>
|
||||
<button class="btn btn-danger" @click="deleteMealType(index)">{{ $t("Delete") }}</button>
|
||||
<button class="btn btn-danger" @click="deleteMealType(index)">{{
|
||||
$t("Delete")
|
||||
}}
|
||||
</button>
|
||||
<button class="btn btn-primary float-right" @click="editOrSaveMealType(index)">
|
||||
{{ $t("Save") }}
|
||||
</button>
|
||||
@@ -129,7 +149,9 @@
|
||||
openEntryEdit(contextData.originalItem.entry)
|
||||
"
|
||||
>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pen"></i> {{ $t("Edit") }}</a>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pen"></i> {{
|
||||
$t("Edit")
|
||||
}}</a>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
v-if="contextData && contextData.originalItem && contextData.originalItem.entry.recipe != null"
|
||||
@@ -138,7 +160,8 @@
|
||||
openRecipe(contextData.originalItem.entry.recipe)
|
||||
"
|
||||
>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pizza-slice"></i> {{ $t("Recipe") }}</a>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pizza-slice"></i>
|
||||
{{ $t("Recipe") }}</a>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
@click="
|
||||
@@ -146,7 +169,8 @@
|
||||
moveEntryLeft(contextData)
|
||||
"
|
||||
>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-left"></i> {{ $t("Move") }}</a>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-left"></i>
|
||||
{{ $t("Move") }}</a>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
@click="
|
||||
@@ -154,7 +178,8 @@
|
||||
moveEntryRight(contextData)
|
||||
"
|
||||
>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-right"></i> {{ $t("Move") }}</a>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-right"></i>
|
||||
{{ $t("Move") }}</a>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
@click="
|
||||
@@ -164,21 +189,14 @@
|
||||
>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-copy"></i> {{ $t("Clone") }}</a>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
@click="
|
||||
$refs.menu.close()
|
||||
addToShopping(contextData)
|
||||
"
|
||||
>
|
||||
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-shopping-cart"></i> {{ $t("Add_to_Shopping") }}</a>
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
@click="
|
||||
$refs.menu.close()
|
||||
deleteEntry(contextData)
|
||||
"
|
||||
>
|
||||
<a class="dropdown-item p-2 text-danger" href="javascript:void(0)"><i class="fas fa-trash"></i> {{ $t("Delete") }}</a>
|
||||
<a class="dropdown-item p-2 text-danger" href="javascript:void(0)"><i class="fas fa-trash"></i>
|
||||
{{ $t("Delete") }}</a>
|
||||
</ContextMenuItem>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
@@ -190,68 +208,43 @@
|
||||
@delete-entry="deleteEntry"
|
||||
@reload-meal-types="refreshMealTypes"
|
||||
></meal-plan-edit-modal>
|
||||
<template>
|
||||
<div>
|
||||
<b-sidebar id="sidebar-shopping" :title="$t('Shopping_list')" backdrop right shadow="sm">
|
||||
<div class="row p-1 no-gutters">
|
||||
<div class="col-12 mt-1" v-if="shopping_list.length === 0">
|
||||
<p class="p-3">{{ $t("Shopping_List_Empty") }}</p>
|
||||
</div>
|
||||
<div class="col-12 mt-1" v-for="entry in shopping_list" v-bind:key="entry.id">
|
||||
<b-card :header="`${entry.meal_type.icon} ${entry.recipe_name}`" no-body>
|
||||
<template #footer>
|
||||
<small class="text-muted">{{ `${$t("Servings")}: ${entry.servings}` }}</small>
|
||||
</template>
|
||||
</b-card>
|
||||
</div>
|
||||
<div class="col-12 mt-1" v-if="shopping_list.length > 0">
|
||||
<b-button-group>
|
||||
<b-button variant="success" @click="saveShoppingList"
|
||||
><i class="fas fa-external-link-alt"></i>
|
||||
{{ $t("Open") }}
|
||||
</b-button>
|
||||
<b-button variant="danger" @click="shopping_list = []"
|
||||
><i class="fa fa-trash"></i>
|
||||
{{ $t("Clear") }}
|
||||
</b-button>
|
||||
</b-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</b-sidebar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<transition name="slide-fade">
|
||||
<div class="row fixed-bottom p-2 b-1 border-top text-center" style="background: rgba(255, 255, 255, 0.6)" v-if="current_tab === 0">
|
||||
<div class="row fixed-bottom p-2 b-1 border-top text-center" style="background: rgba(255, 255, 255, 0.6)"
|
||||
v-if="current_tab === 0">
|
||||
<div class="col-md-3 col-6">
|
||||
<button class="btn btn-block btn-success shadow-none" @click="createEntryClick(new Date())"><i class="fas fa-calendar-plus"></i> {{ $t("Create") }}</button>
|
||||
</div>
|
||||
<div class="col-md-3 col-6">
|
||||
<button class="btn btn-block btn-primary shadow-none" v-b-toggle.sidebar-shopping><i class="fas fa-shopping-cart"></i> {{ $t("Shopping_list") }}</button>
|
||||
<button class="btn btn-block btn-success shadow-none" @click="createEntryClick(new Date())"><i
|
||||
class="fas fa-calendar-plus"></i> {{ $t("Create") }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-3 col-6">
|
||||
<a class="btn btn-block btn-primary shadow-none" :href="iCalUrl"
|
||||
><i class="fas fa-download"></i>
|
||||
><i class="fas fa-download"></i>
|
||||
{{ $t("Export_To_ICal") }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-3 col-6">
|
||||
<button class="btn btn-block btn-primary shadow-none disabled" v-b-tooltip.focus.top :title="$t('Coming_Soon')">
|
||||
<button class="btn btn-block btn-primary shadow-none disabled" v-b-tooltip.focus.top
|
||||
:title="$t('Coming_Soon')">
|
||||
{{ $t("Auto_Planner") }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-12 d-flex justify-content-center mt-2 d-block d-md-none">
|
||||
<b-button-toolbar key-nav aria-label="Toolbar with button groups">
|
||||
<b-button-group class="mx-1">
|
||||
<b-button v-html="'<<'" @click="setShowDate($refs.header.headerProps.previousPeriod)"></b-button>
|
||||
<b-button v-html="'<'" @click="setStartingDay(-1)"></b-button>
|
||||
<b-button v-html="'<<'" class="p-2 pr-3 pl-3"
|
||||
@click="setShowDate($refs.header.headerProps.previousPeriod)"></b-button>
|
||||
<b-button v-html="'<'" @click="setStartingDay(-1)" class="p-2 pr-3 pl-3"></b-button>
|
||||
</b-button-group>
|
||||
<b-button-group class="mx-1">
|
||||
<b-button @click="setShowDate($refs.header.headerProps.currentPeriod)"><i class="fas fa-home"></i></b-button>
|
||||
<b-button @click="setShowDate($refs.header.headerProps.currentPeriod)"><i
|
||||
class="fas fa-home"></i></b-button>
|
||||
<b-form-datepicker button-only button-variant="secondary"></b-form-datepicker>
|
||||
</b-button-group>
|
||||
<b-button-group class="mx-1">
|
||||
<b-button v-html="'>'" @click="setStartingDay(1)"></b-button>
|
||||
<b-button v-html="'>>'" @click="setShowDate($refs.header.headerProps.nextPeriod)"></b-button>
|
||||
<b-button v-html="'>'" @click="setStartingDay(1)" class="p-2 pr-3 pl-3"></b-button>
|
||||
<b-button v-html="'>>'" class="p-2 pr-3 pl-3"
|
||||
@click="setShowDate($refs.header.headerProps.nextPeriod)"></b-button>
|
||||
</b-button-group>
|
||||
</b-button-toolbar>
|
||||
</div>
|
||||
@@ -262,7 +255,7 @@
|
||||
|
||||
<script>
|
||||
import Vue from "vue"
|
||||
import { BootstrapVue } from "bootstrap-vue"
|
||||
import {BootstrapVue} from "bootstrap-vue"
|
||||
import "bootstrap-vue/dist/bootstrap-vue.css"
|
||||
|
||||
import ContextMenu from "@/components/ContextMenu/ContextMenu"
|
||||
@@ -276,11 +269,11 @@ import moment from "moment"
|
||||
import draggable from "vuedraggable"
|
||||
import VueCookies from "vue-cookies"
|
||||
|
||||
import { ApiMixin, StandardToasts, ResolveUrlMixin } from "@/utils/utils"
|
||||
import { CalendarView, CalendarMathMixin } from "vue-simple-calendar/src/components/bundle"
|
||||
import { ApiApiFactory } from "@/utils/openapi/api"
|
||||
import {ApiMixin, StandardToasts, ResolveUrlMixin} from "@/utils/utils"
|
||||
import {CalendarView, CalendarMathMixin} from "vue-simple-calendar/src/components/bundle"
|
||||
import {ApiApiFactory} from "@/utils/openapi/api"
|
||||
|
||||
const { makeToast } = require("@/utils/utils")
|
||||
const {makeToast} = require("@/utils/utils")
|
||||
|
||||
Vue.prototype.moment = moment
|
||||
Vue.use(BootstrapVue)
|
||||
@@ -318,12 +311,12 @@ export default {
|
||||
current_context_menu_item: null,
|
||||
options: {
|
||||
displayPeriodUom: [
|
||||
{ text: this.$t("Week"), value: "week" },
|
||||
{text: this.$t("Week"), value: "week"},
|
||||
{
|
||||
text: this.$t("Month"),
|
||||
value: "month",
|
||||
},
|
||||
{ text: this.$t("Year"), value: "year" },
|
||||
{text: this.$t("Year"), value: "year"},
|
||||
],
|
||||
displayPeriodCount: [1, 2, 3],
|
||||
entryEditing: {
|
||||
@@ -367,7 +360,7 @@ export default {
|
||||
dayNames: function () {
|
||||
let options = []
|
||||
this.getFormattedWeekdayNames(this.userLocale, "long", 0).forEach((day, index) => {
|
||||
options.push({ text: day, value: index })
|
||||
options.push({text: day, value: index})
|
||||
})
|
||||
return options
|
||||
},
|
||||
@@ -412,27 +405,6 @@ export default {
|
||||
openRecipe: function (recipe) {
|
||||
window.open(this.resolveDjangoUrl("view_recipe", recipe.id))
|
||||
},
|
||||
addToShopping(entry) {
|
||||
if (entry.originalItem.entry.recipe !== null) {
|
||||
this.shopping_list.push(entry.originalItem.entry)
|
||||
makeToast(this.$t("Success"), this.$t("Added_To_Shopping_List"), "success")
|
||||
} else {
|
||||
makeToast(this.$t("Failure"), this.$t("Cannot_Add_Notes_To_Shopping"), "danger")
|
||||
}
|
||||
},
|
||||
saveShoppingList() {
|
||||
let url = window.SHOPPING_URL
|
||||
let first = true
|
||||
for (let se of this.shopping_list) {
|
||||
if (first) {
|
||||
url += `?r=[${se.recipe.id},${se.servings}]`
|
||||
first = false
|
||||
} else {
|
||||
url += `&r=[${se.recipe.id},${se.servings}]`
|
||||
}
|
||||
}
|
||||
window.open(url)
|
||||
},
|
||||
setStartingDay(days) {
|
||||
if (this.settings.startingDayOfWeek + days < 0) {
|
||||
this.settings.startingDayOfWeek = 6
|
||||
@@ -446,12 +418,12 @@ export default {
|
||||
let apiClient = new ApiApiFactory()
|
||||
|
||||
apiClient
|
||||
.createMealType({ name: this.$t("Meal_Type") })
|
||||
.createMealType({name: this.$t("Meal_Type")})
|
||||
.then((e) => {
|
||||
this.periodChangedCallback(this.current_period)
|
||||
})
|
||||
.catch((err) => {
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_UPDATE, err)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||
})
|
||||
|
||||
this.refreshMealTypes()
|
||||
@@ -474,7 +446,7 @@ export default {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_UPDATE, err)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -488,10 +460,10 @@ export default {
|
||||
.updateMealType(this.meal_types[index].id, this.meal_types[index])
|
||||
.then((e) => {
|
||||
this.periodChangedCallback(this.current_period)
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.SUCCESS_UPDATE)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE)
|
||||
})
|
||||
.catch((err) => {
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_UPDATE, err)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||
})
|
||||
} else {
|
||||
this.$set(this.meal_types[index], "editing", true)
|
||||
@@ -504,10 +476,10 @@ export default {
|
||||
.destroyMealType(this.meal_types[index].id)
|
||||
.then((e) => {
|
||||
this.periodChangedCallback(this.current_period)
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.SUCCESS_DELETE)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_DELETE)
|
||||
})
|
||||
.catch((err) => {
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_DELETE, err)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_DELETE, err)
|
||||
})
|
||||
},
|
||||
updateEmoji: function (field, value) {
|
||||
@@ -583,7 +555,7 @@ export default {
|
||||
list.splice(index, 1)
|
||||
})
|
||||
.catch((err) => {
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_UPDATE, err)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -635,7 +607,7 @@ export default {
|
||||
let apiClient = new ApiApiFactory()
|
||||
|
||||
apiClient.updateMealPlan(entry.id, entry).catch((err) => {
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_UPDATE, err)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||
})
|
||||
},
|
||||
createEntry(entry) {
|
||||
@@ -646,7 +618,7 @@ export default {
|
||||
apiClient
|
||||
.createMealPlan(entry)
|
||||
.catch((err) => {
|
||||
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_UPDATE, err)
|
||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
|
||||
})
|
||||
.then((entry_result) => {
|
||||
this.plan_entries.push(entry_result.data)
|
||||
@@ -694,7 +666,7 @@ export default {
|
||||
}
|
||||
|
||||
.calender-row {
|
||||
height: calc(100% - 240px);
|
||||
height: calc(100vh - 240px);
|
||||
}
|
||||
|
||||
.calender-parent {
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
<div v-for="(ingredient, index) in step.ingredients"
|
||||
:key="ingredient.id">
|
||||
<hr class="d-md-none"/>
|
||||
<div class="text-center">
|
||||
<div class="text-center" v-if="ingredient.original_text !== null">
|
||||
<small class="text-muted"><i class="fas fa-globe"></i>
|
||||
{{ ingredient.original_text }}</small>
|
||||
</div>
|
||||
@@ -943,6 +943,7 @@ export default {
|
||||
order: 0,
|
||||
is_header: false,
|
||||
no_amount: false,
|
||||
original_text: null,
|
||||
})
|
||||
this.sortIngredients(step)
|
||||
this.$nextTick(() => document.getElementById(`amount_${this.recipe.steps.indexOf(step)}_${step.ingredients.length - 1}`).select())
|
||||
@@ -1029,11 +1030,11 @@ export default {
|
||||
.listUnits(query, 1, this.options_limit)
|
||||
.then((response) => {
|
||||
this.units = response.data.results
|
||||
|
||||
let unique_units = this.units.map(u => u.name)
|
||||
if (this.recipe !== undefined) {
|
||||
for (let s of this.recipe.steps) {
|
||||
for (let i of s.ingredients) {
|
||||
if (i.unit !== null && i.unit.id === undefined) {
|
||||
if (i.unit !== null && i.unit.id === undefined && !unique_units.includes(i.unit.name) ) {
|
||||
this.units.push(i.unit)
|
||||
}
|
||||
}
|
||||
@@ -1053,11 +1054,11 @@ export default {
|
||||
.listFoods(query, undefined, undefined, 1, this.options_limit)
|
||||
.then((response) => {
|
||||
this.foods = response.data.results
|
||||
|
||||
let unique_foods = this.foods.map(f => f.name)
|
||||
if (this.recipe !== undefined) {
|
||||
for (let s of this.recipe.steps) {
|
||||
for (let i of s.ingredients) {
|
||||
if (i.food !== null && i.food.id === undefined) {
|
||||
if (i.food !== null && i.food.id === undefined && !unique_foods.includes(i.food.name)) {
|
||||
this.foods.push(i.food)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
</thead>
|
||||
<tr v-for="r in Recipes" :key="r.list_recipe">
|
||||
<td>{{ r.recipe_mealplan.name }}</td>
|
||||
<td>{{ r.recipe_mealplan.recipe_name }}</td>
|
||||
<td><a :href="resolveDjangoUrl('view_recipe', r.recipe_mealplan.recipe)">{{ r.recipe_mealplan.recipe_name }}</a></td>
|
||||
<td class="block-inline">
|
||||
<b-form-input min="1" type="number" :debounce="300"
|
||||
:value="r.recipe_mealplan.servings"
|
||||
@@ -291,7 +291,10 @@
|
||||
aria-hidden="true"></i
|
||||
></span>
|
||||
</h5>
|
||||
<span class="text-muted" v-if="supermarket.description !== ''">{{ supermarket.description }}</span>
|
||||
<span class="text-muted"
|
||||
v-if="supermarket.description !== ''">{{
|
||||
supermarket.description
|
||||
}}</span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-card-header>
|
||||
@@ -645,7 +648,7 @@
|
||||
<div class="col-6">
|
||||
<a class="btn btn-block btn-success shadow-none" @click="entrymode = !entrymode; "
|
||||
><i class="fas fa-cart-plus"></i>
|
||||
{{ $t("New Entry") }}
|
||||
{{ $t("New_Entry") }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@@ -778,7 +781,7 @@ import GenericMultiselect from "@/components/GenericMultiselect"
|
||||
import LookupInput from "@/components/Modals/LookupInput"
|
||||
import ShoppingModal from "@/components/Modals/ShoppingModal"
|
||||
|
||||
import {ApiMixin, getUserPreference, StandardToasts, makeToast} from "@/utils/utils"
|
||||
import {ApiMixin, getUserPreference, StandardToasts, makeToast, ResolveUrlMixin} from "@/utils/utils"
|
||||
import {ApiApiFactory} from "@/utils/openapi/api"
|
||||
|
||||
Vue.use(BootstrapVue)
|
||||
@@ -787,7 +790,7 @@ let SETTINGS_COOKIE_NAME = "shopping_settings"
|
||||
|
||||
export default {
|
||||
name: "ShoppingListView",
|
||||
mixins: [ApiMixin],
|
||||
mixins: [ApiMixin,ResolveUrlMixin],
|
||||
components: {
|
||||
ContextMenu,
|
||||
ContextMenuItem,
|
||||
@@ -1026,20 +1029,23 @@ export default {
|
||||
"settings.shopping_auto_sync": function (newVal, oldVal) {
|
||||
clearInterval(this.autosync_id)
|
||||
this.autosync_id = undefined
|
||||
if (!newVal) {
|
||||
window.removeEventListener("online", this.updateOnlineStatus)
|
||||
window.removeEventListener("offline", this.updateOnlineStatus)
|
||||
return
|
||||
} else if (oldVal === 0 && newVal > 0) {
|
||||
window.addEventListener("online", this.updateOnlineStatus)
|
||||
window.addEventListener("offline", this.updateOnlineStatus)
|
||||
}
|
||||
this.autosync_id = setInterval(() => {
|
||||
if (this.online && !this.auto_sync_running) {
|
||||
this.auto_sync_running = true
|
||||
this.getShoppingList(true)
|
||||
if (this.settings.shopping_auto_sync > 0) {
|
||||
if (!newVal) {
|
||||
window.removeEventListener("online", this.updateOnlineStatus)
|
||||
window.removeEventListener("offline", this.updateOnlineStatus)
|
||||
return
|
||||
} else if (oldVal === 0 && newVal > 0) {
|
||||
window.addEventListener("online", this.updateOnlineStatus)
|
||||
window.addEventListener("offline", this.updateOnlineStatus)
|
||||
}
|
||||
}, this.settings.shopping_auto_sync * 1000)
|
||||
this.autosync_id = setInterval(() => {
|
||||
if (this.online && !this.auto_sync_running) {
|
||||
this.auto_sync_running = true
|
||||
this.getShoppingList(true)
|
||||
}
|
||||
}, this.settings.shopping_auto_sync * 1000)
|
||||
}
|
||||
|
||||
},
|
||||
"settings.default_delay": function (newVal, oldVal) {
|
||||
this.delay = Number(newVal)
|
||||
@@ -1446,6 +1452,7 @@ export default {
|
||||
|
||||
if (supermarket.editing) {
|
||||
this.$set(this.supermarkets[index], "editing", false)
|
||||
this.$set(this.supermarkets[index], "category_to_supermarket", this.editing_supermarket_categories)
|
||||
this.editing_supermarket_categories = []
|
||||
|
||||
let apiClient = new ApiApiFactory()
|
||||
@@ -1618,8 +1625,7 @@ export default {
|
||||
|
||||
this.editing_supermarket_categories.forEach((element, index) => {
|
||||
let apiClient = new ApiApiFactory()
|
||||
|
||||
promises.push(apiClient.partialUpdateSupermarketCategoryRelation(element.relation_id, {order: element.order}))
|
||||
promises.push(apiClient.partialUpdateSupermarketCategoryRelation(element.relation_id, {order: index}))
|
||||
})
|
||||
return Promise.all(promises).then(() => {
|
||||
|
||||
@@ -1750,7 +1756,7 @@ export default {
|
||||
flex-grow: 1;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
height: calc(100% - 170px);
|
||||
height: calc(100vh - 170px);
|
||||
}
|
||||
|
||||
#id_base_container {
|
||||
@@ -1758,6 +1764,10 @@ export default {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 991.9px) {
|
||||
#shoppinglist {
|
||||
max-width: none;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<template>
|
||||
<span>
|
||||
<b-button v-if="!item.ignore_shopping" class="btn text-decoration-none fas px-1 py-0 border-0" variant="link" v-b-popover.hover.html :title="Title" :class="IconClass" @click="toggleOnHand" />
|
||||
<b-button v-if="!item.ignore_shopping" class="btn text-decoration-none fas px-1 py-0 border-0" variant="link" v-b-popover.hover.html :title="$sanitize(Title)" :class="IconClass" @click="toggleOnHand" />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ApiMixin } from "@/utils/utils"
|
||||
import Vue from "vue"
|
||||
import VueSanitize from "vue-sanitize";
|
||||
Vue.use(VueSanitize);
|
||||
|
||||
|
||||
export default {
|
||||
name: "OnHandBadge",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<i
|
||||
class="fas"
|
||||
v-b-popover.hover.html
|
||||
:title="[shopping ? $t('RemoveFoodFromShopping', { food: item.name }) : $t('AddFoodToShopping', { food: item.name })]"
|
||||
:title="[shopping ? $t('RemoveFoodFromShopping', { food: $sanitize(item.name) }) : $t('AddFoodToShopping', { food: $sanitize(item.name) })]"
|
||||
:class="[shopping ? 'text-success fa-shopping-cart' : 'text-muted fa-cart-plus']"
|
||||
/>
|
||||
</b-button>
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
<script>
|
||||
import { ApiMixin, StandardToasts } from "@/utils/utils"
|
||||
import Vue from "vue"
|
||||
import VueSanitize from "vue-sanitize";
|
||||
Vue.use(VueSanitize);
|
||||
|
||||
export default {
|
||||
name: "ShoppingBadge",
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="h-20 w-100 border border-primary rounded text-center">
|
||||
<i class="fas fa-eye-slash fa-2x text-primary mt-2"></i>
|
||||
<br/>
|
||||
<a :href="url" target="_blank" rel="noreferrer nofollow" class="mt-4">{{$t('Download')}}</a>
|
||||
<a :href="url" target="_blank" rel="noreferrer nofollow" class="mt-4" download>{{$t('Download')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
"
|
||||
>
|
||||
<i class="fas fa-expand-arrows-alt fa-fw"></i> <b>{{ $t("Move") }}</b
|
||||
>: <span v-html="$t('move_confirmation', { child: source.name, parent: item.name })"></span>
|
||||
>: <span v-html="$t('move_confirmation', { child: $sanitize(source.name), parent: $sanitize(item.name) })"></span>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item
|
||||
v-if="useMerge"
|
||||
@@ -104,7 +104,7 @@
|
||||
"
|
||||
>
|
||||
<i class="fas fa-compress-arrows-alt fa-fw"></i> <b>{{ $t("Merge") }}</b
|
||||
>: <span v-html="$t('merge_confirmation', { source: source.name, target: item.name })"></span>
|
||||
>: <span v-html="$t('merge_confirmation', { source: $sanitize(source.name), target: $sanitize(item.name) })"></span>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item
|
||||
v-if="useMerge"
|
||||
@@ -115,7 +115,7 @@
|
||||
"
|
||||
>
|
||||
<i class="fas fa-robot fa-fw"></i> <b>{{ $t("Merge") }} & {{ $t("Automate") }}</b
|
||||
>: <span v-html="$t('merge_confirmation', { source: source.name, target: item.name })"></span> {{ $t("create_rule") }}
|
||||
>: <span v-html="$t('merge_confirmation', { source: $sanitize(source.name), target: $sanitize(item.name) })"></span> {{ $t("create_rule") }}
|
||||
<b-badge v-b-tooltip.hover :title="$t('warning_feature_beta')">BETA</b-badge>
|
||||
</b-list-group-item>
|
||||
<b-list-group-item action v-on:click="closeMenu()">
|
||||
@@ -134,6 +134,9 @@ import RecipeCard from "@/components/RecipeCard"
|
||||
import { mixin as clickaway } from "vue-clickaway"
|
||||
import { createPopper } from "@popperjs/core"
|
||||
import {ApiMixin} from "@/utils/utils";
|
||||
import Vue from "vue"
|
||||
import VueSanitize from "vue-sanitize";
|
||||
Vue.use(VueSanitize);
|
||||
|
||||
export default {
|
||||
name: "GenericHorizontalCard",
|
||||
|
||||
@@ -59,6 +59,10 @@ import { calculateAmount, ResolveUrlMixin, ApiMixin } from "@/utils/utils"
|
||||
import OnHandBadge from "@/components/Badges/OnHand"
|
||||
import ShoppingBadge from "@/components/Badges/Shopping"
|
||||
|
||||
import Vue from "vue"
|
||||
import VueSanitize from "vue-sanitize";
|
||||
Vue.use(VueSanitize);
|
||||
|
||||
export default {
|
||||
name: "IngredientComponent",
|
||||
components: { OnHandBadge, ShoppingBadge },
|
||||
@@ -124,7 +128,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
calculateAmount: function (x) {
|
||||
return calculateAmount(x, this.ingredient_factor)
|
||||
return this.$sanitize(calculateAmount(x, this.ingredient_factor))
|
||||
},
|
||||
// sends parent recipe ingredient to notify complete has been toggled
|
||||
done: function () {
|
||||
|
||||
@@ -55,6 +55,10 @@
|
||||
<script>
|
||||
|
||||
import {calculateAmount, calculateEnergy, energyHeading} from "@/utils/utils";
|
||||
import Vue from "vue"
|
||||
import VueSanitize from "vue-sanitize";
|
||||
Vue.use(VueSanitize);
|
||||
|
||||
|
||||
export default {
|
||||
name: 'NutritionComponent',
|
||||
@@ -64,13 +68,13 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
calculateAmount: function (x) {
|
||||
return calculateAmount(x, this.ingredient_factor)
|
||||
return this.$sanitize(calculateAmount(x, this.ingredient_factor))
|
||||
},
|
||||
calculateEnergy: function (x) {
|
||||
return calculateEnergy(x, this.ingredient_factor)
|
||||
return this.$sanitize(calculateEnergy(x, this.ingredient_factor))
|
||||
},
|
||||
energy: function (x) {
|
||||
return energyHeading()
|
||||
return this.$sanitize(energyHeading())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
414
vue/src/locales/bg.json
Normal file
414
vue/src/locales/bg.json
Normal file
@@ -0,0 +1,414 @@
|
||||
{
|
||||
"warning_feature_beta": "Тази функция в момента е в състояние на БЕТА (тестване). Моля, очаквайте грешки и евентуално нарушаващи промени в бъдеще (евентуално загуба на данни, свързани с функции), когато използвате тази функция.",
|
||||
"err_fetching_resource": "Възникна грешка при извличането на ресурс!",
|
||||
"err_creating_resource": "Възникна грешка при създаването на ресурс!",
|
||||
"err_updating_resource": "Възникна грешка при актуализирането на ресурс!",
|
||||
"err_deleting_resource": "Възникна грешка при изтриването на ресурс!",
|
||||
"err_deleting_protected_resource": "Обектът, който се опитвате да изтриете, все още се използва и не може да бъде изтрит.",
|
||||
"err_moving_resource": "Възникна грешка при преместването на ресурс!",
|
||||
"err_merging_resource": "Възникна грешка при обединяването на ресурс!",
|
||||
"success_fetching_resource": "Ресурсът бе извлечен успешно!",
|
||||
"success_creating_resource": "Успешно създаден ресурс!",
|
||||
"success_updating_resource": "Успешно актуализиран ресурс!",
|
||||
"success_deleting_resource": "Успешно изтрит ресурс!",
|
||||
"success_moving_resource": "Успешно преместен ресурс!",
|
||||
"success_merging_resource": "Успешно обединен ресурс!",
|
||||
"file_upload_disabled": "Качването на файлове не е активирано за вашето пространство.",
|
||||
"step_time_minutes": "Време за стъпка в минути",
|
||||
"confirm_delete": "Наистина ли искате да изтриете този {object}?",
|
||||
"import_running": "Импортирането се изпълнява, моля, изчакайте!",
|
||||
"all_fields_optional": "Всички полета са незадължителни и могат да бъдат оставени празни.",
|
||||
"convert_internal": "Превърнете във вътрешна рецепта",
|
||||
"show_only_internal": "Показване само на вътрешни рецепти",
|
||||
"show_split_screen": "Разделен изглед",
|
||||
"Log_Recipe_Cooking": "Дневник на Рецепта за готвене",
|
||||
"External_Recipe_Image": "Външно изображение на рецептата",
|
||||
"Add_to_Shopping": "Добавяне към пазаруване",
|
||||
"Add_to_Plan": "Добавяне към плана",
|
||||
"Step_start_time": "Стъпка Начално време",
|
||||
"Sort_by_new": "Сортиране по ново",
|
||||
"Table_of_Contents": "Съдържание",
|
||||
"Recipes_per_page": "Рецепти на страница",
|
||||
"Show_as_header": "Показване като заглавка",
|
||||
"Hide_as_header": "Скриване като заглавка",
|
||||
"Add_nutrition_recipe": "Добавете хранителни стойности към рецептата",
|
||||
"Remove_nutrition_recipe": "Изтрийте хранителните стойности от рецептата",
|
||||
"Copy_template_reference": "Копирайте препратка към шаблона",
|
||||
"Save_and_View": "Запазете и прегледайте",
|
||||
"Manage_Books": "Управление на Книги",
|
||||
"Meal_Plan": "План на хранене",
|
||||
"Select_Book": "Изберете Книга",
|
||||
"Select_File": "Избери файл",
|
||||
"Recipe_Image": "Изображение на рецептата",
|
||||
"Import_finished": "Импортирането приключи",
|
||||
"View_Recipes": "Вижте рецепти",
|
||||
"Log_Cooking": "Дневник на Готвене",
|
||||
"New_Recipe": "Нова рецепта",
|
||||
"Url_Import": "Импортиране на URL адрес",
|
||||
"Reset_Search": "Нулиране на търсенето",
|
||||
"Recently_Viewed": "Наскоро разгледани",
|
||||
"Load_More": "Зареди още",
|
||||
"New_Keyword": "Нова ключова дума",
|
||||
"Delete_Keyword": "Изтриване на ключова дума",
|
||||
"Edit_Keyword": "Редактиране на ключова дума",
|
||||
"Edit_Recipe": "Редактиране на рецепта",
|
||||
"Move_Keyword": "Преместване на ключова дума",
|
||||
"Merge_Keyword": "Обединяване на ключова дума",
|
||||
"Hide_Keywords": "Скриване на ключова дума",
|
||||
"Hide_Recipes": "Скриване на рецепти",
|
||||
"Move_Up": "Премести нагоре",
|
||||
"Move_Down": "Премести надолу",
|
||||
"Step_Name": "Стъпка Име",
|
||||
"Step_Type": "Стъпка Тип",
|
||||
"Make_Header": "Направете заглавие",
|
||||
"Make_Ingredient": "Направете съставка",
|
||||
"Enable_Amount": "Активиране на сумата",
|
||||
"Disable_Amount": "Деактивиране на сумата",
|
||||
"Ingredient Editor": "Редактор на съставки",
|
||||
"Add_Step": "Добавяне Стъпка",
|
||||
"Keywords": "Ключови думи",
|
||||
"Books": "Книги",
|
||||
"Proteins": "Протеини (белтъчини)",
|
||||
"Fats": "Мазнини",
|
||||
"Carbohydrates": "Въглехидрати",
|
||||
"Calories": "Калории",
|
||||
"Energy": "Енергия",
|
||||
"Nutrition": "Хранителни стойности",
|
||||
"Date": "Дата",
|
||||
"Share": "Споделяне",
|
||||
"Automation": "Автоматизация",
|
||||
"Parameter": "Параметър",
|
||||
"Export": "Експортиране",
|
||||
"Copy": "Копиране",
|
||||
"Rating": "Рейтинг",
|
||||
"Close": "Затвори",
|
||||
"Cancel": "Откажи",
|
||||
"Link": "Връзка",
|
||||
"Add": "Добави",
|
||||
"New": "Нов",
|
||||
"Note": "Бележка",
|
||||
"Success": "Успешно",
|
||||
"Failure": "Неуспешно",
|
||||
"Protected": "Защитен",
|
||||
"Ingredients": "Съставки",
|
||||
"Supermarket": "Супермаркет",
|
||||
"Categories": "Категории",
|
||||
"Category": "Категория",
|
||||
"Selected": "Избрано",
|
||||
"min": "мин",
|
||||
"Servings": "Порции",
|
||||
"Waiting": "Очакване",
|
||||
"Preparation": "Подготовка",
|
||||
"External": "Външен",
|
||||
"Size": "Размер",
|
||||
"Files": "Файлове",
|
||||
"File": "Файл",
|
||||
"Edit": "Редактиране",
|
||||
"Image": "Изображение",
|
||||
"Delete": "Изтрий",
|
||||
"Open": "Отвори",
|
||||
"Ok": "Отвори",
|
||||
"Save": "Запази",
|
||||
"Step": "Стъпка",
|
||||
"Search": "Търсене",
|
||||
"Import": "Импортиране",
|
||||
"Print": "Печат",
|
||||
"Settings": "Настройки",
|
||||
"or": "или",
|
||||
"and": "и",
|
||||
"Information": "Информация",
|
||||
"Download": "Изтегляне",
|
||||
"Create": "Създаване",
|
||||
"Search Settings": "Настройки търсене",
|
||||
"View": "Изглед",
|
||||
"Recipes": "Рецепти",
|
||||
"Move": "Премести",
|
||||
"Merge": "Обединяване",
|
||||
"Parent": "Родител",
|
||||
"delete_confirmation": "Сигурни ли сте, че искате да изтриете {source}?",
|
||||
"move_confirmation": "Преместване на <i>{child}</i> към родител <i>{parent}</i>",
|
||||
"merge_confirmation": "Заменете <i>{source}</i> с <i>{target}</i>",
|
||||
"create_rule": "и създават автоматизация",
|
||||
"move_selection": "Изберете родител {type}, към който да преместите {source}.",
|
||||
"merge_selection": "Заменете всички срещания на {source} с избрания {type}.",
|
||||
"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": "Обединяване на {type}",
|
||||
"move_title": "Преместване {type}",
|
||||
"Food": "Храна",
|
||||
"Recipe_Book": "Книга с рецепти",
|
||||
"del_confirmation_tree": "Сигурни ли сте, че искате да изтриете {source} и всички негови последователи?",
|
||||
"delete_title": "Изтриване на {type}",
|
||||
"create_title": "Нов {type}",
|
||||
"edit_title": "Редактиране на {type}",
|
||||
"Name": "Име",
|
||||
"Type": "Тип",
|
||||
"Description": "Описание",
|
||||
"Recipe": "Рецепта",
|
||||
"tree_root": "Корен на дървото",
|
||||
"Icon": "Икона",
|
||||
"Unit": "Единица",
|
||||
"No_Results": "Няма резултати",
|
||||
"New_Unit": "Нова единица",
|
||||
"Create_New_Shopping Category": "Създайте нова категория за пазаруване",
|
||||
"Create_New_Food": "Добавете нова храна",
|
||||
"Create_New_Keyword": "Добавяне на нова ключова дума",
|
||||
"Create_New_Unit": "Добавяне на нова единица",
|
||||
"Create_New_Meal_Type": "Добавете нов тип хранене",
|
||||
"and_up": "и нагоре",
|
||||
"and_down": "и надолу",
|
||||
"Instructions": "Инструкции",
|
||||
"Unrated": "Без оценка",
|
||||
"Automate": "Автоматизация",
|
||||
"Empty": "Празно",
|
||||
"Key_Ctrl": "Контрол",
|
||||
"Key_Shift": "Превключване",
|
||||
"Time": "Време",
|
||||
"Text": "Текст",
|
||||
"Shopping_list": "Списък за пазаруване",
|
||||
"Added_by": "Добавено от",
|
||||
"Added_on": "Добавено",
|
||||
"AddToShopping": "Добавяне към списъка за пазаруване",
|
||||
"IngredientInShopping": "Тази съставка е във вашия списък за пазаруване.",
|
||||
"NotInShopping": "{food} не е в списъка ви за пазаруване.",
|
||||
"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": "Вид хранене",
|
||||
"Clone": "Клониране",
|
||||
"Drag_Here_To_Delete": "Плъзнете тук, за да изтриете",
|
||||
"Meal_Type_Required": "Изисква се вид хранене",
|
||||
"Title_or_Recipe_Required": "Изисква се избор на заглавие или рецепта",
|
||||
"Color": "Цвят",
|
||||
"New_Meal_Type": "Нов вид хранене",
|
||||
"AddFoodToShopping": "Добавете {food} към списъка си за пазаруване",
|
||||
"RemoveFoodFromShopping": "Премахнете {food} от списъка си за пазаруване",
|
||||
"DeleteShoppingConfirm": "Сигурни ли сте, че искате да премахнете цялата {food} от списъка за пазаруване?",
|
||||
"IgnoredFood": "{food} е настроен да игнорира пазаруването.",
|
||||
"Add_Servings_to_Shopping": "Добавете {servings} порции към Пазаруване",
|
||||
"Week_Numbers": "Номера на седмиците",
|
||||
"Show_Week_Numbers": "Показване на номерата на седмиците?",
|
||||
"Export_As_ICal": "Експортирайте текущия период във формат iCal",
|
||||
"Export_To_ICal": "Експортиране на .ics",
|
||||
"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": "Групирай по",
|
||||
"SupermarketCategoriesOnly": "Само категории супермаркети",
|
||||
"MoveCategory": "Премести към: ",
|
||||
"CountMore": "...+{count} още",
|
||||
"IgnoreThis": "Никога не добавяйте автоматично {food} към пазаруване",
|
||||
"DelayFor": "Закъснение за {hours} часа",
|
||||
"Warning": "Внимание",
|
||||
"NoCategory": "Няма избрана категория.",
|
||||
"InheritWarning": "{food} е настроен да наследява, промените може да не продължат.",
|
||||
"ShowDelayed": "Показване на забавени артикули",
|
||||
"Completed": "Завършено",
|
||||
"OfflineAlert": "Вие сте офлайн, списъкът за пазаруване може да не се синхронизира.",
|
||||
"shopping_share": "Споделете списък за пазаруване",
|
||||
"shopping_auto_sync": "Автоматично синхронизиране",
|
||||
"one_url_per_line": "Един URL на ред",
|
||||
"mealplan_autoadd_shopping": "Автоматично добавяне на план за хранене",
|
||||
"mealplan_autoexclude_onhand": "Изключете храната под ръка",
|
||||
"mealplan_autoinclude_related": "Добавете свързани рецепти",
|
||||
"default_delay": "Часове на забавяне по подразбиране",
|
||||
"shopping_share_desc": "Потребителите ще видят всички артикули, които добавите към списъка си за пазаруване. Те трябва да ви добавят, за да видят елементите в техния списък.",
|
||||
"shopping_auto_sync_desc": "Задаването на 0 ще деактивира автоматичното синхронизиране. Когато разглеждате списък за пазаруване, списъкът се актуализира на всеки зададени секунди, за да синхронизира промените, които някой друг може да е направил. Полезно при пазаруване с множество хора, но ще използва мобилни данни.",
|
||||
"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": "Скриване на ключови думи",
|
||||
"Clear": "Изчистване",
|
||||
"err_move_self": "Не може елемента да се премести към себе си",
|
||||
"nothing": "Няма нищо за правене",
|
||||
"err_merge_self": "Не може да се слее елемент със себе си",
|
||||
"show_sql": "Покажи SQL",
|
||||
"filter_to_supermarket_desc": "По подразбиране филтрирайте списъка за пазаруване, за да включва само категории за избран супермаркет.",
|
||||
"CategoryName": "Име на категория",
|
||||
"SupermarketName": "Име на супермаркет",
|
||||
"CategoryInstruction": "Плъзнете категориите, за да промените категориите за поръчки, които се появяват в списъка за пазаруване.",
|
||||
"shopping_recent_days_desc": "Дни на последните записи в списъка за пазаруване за показване.",
|
||||
"shopping_recent_days": "Последни дни",
|
||||
"download_pdf": "Изтегли PDF",
|
||||
"download_csv": "Изтегли CSV",
|
||||
"csv_delim_help": "Ограничител за използване за CSV експортиране.",
|
||||
"csv_delim_label": "CSV разделител",
|
||||
"SuccessClipboard": "Списъкът за пазаруване е копиран в клипборда",
|
||||
"copy_to_clipboard": "Копиране в клипборда",
|
||||
"csv_prefix_help": "Префикс за добавяне при копиране на списък в клипборда.",
|
||||
"csv_prefix_label": "Префикс за списък",
|
||||
"copy_markdown_table": "Копирайте като Markdown Таблица",
|
||||
"in_shopping": "В списъка за пазаруване",
|
||||
"DelayUntil": "Забавяне до",
|
||||
"Pin": "Закачи",
|
||||
"mark_complete": "Маркирането завършено",
|
||||
"QuickEntry": "Бързо влизане",
|
||||
"shopping_add_onhand_desc": "Маркирайте храната „На ръка“, когато сте отметнати от списъка за пазаруване.",
|
||||
"shopping_add_onhand": "Автоматично под ръка",
|
||||
"related_recipes": "Свързани рецепти",
|
||||
"today_recipes": "Днешните рецепти",
|
||||
"sql_debug": "Отстраняване на грешки в SQL",
|
||||
"remember_search": "Запомнете търсенето",
|
||||
"remember_hours": "Часове за запомняне",
|
||||
"tree_select": "Използвайте Избор на дърво",
|
||||
"OnHand_help": "Храната е в инвентара и няма да бъде добавена автоматично към списък за пазаруване. Състоянието на ръка се споделя с пазаруващите потребители.",
|
||||
"ignore_shopping_help": "Никога не добавяйте храна към списъка за пазаруване (например вода)",
|
||||
"shopping_category_help": "Супермаркетите могат да бъдат поръчани и филтрирани по категория за пазаруване според оформлението на пътеките.",
|
||||
"food_recipe_help": "Свързването на рецепта тук ще включва свързаната рецепта във всяка друга рецепта, която използва тази храна",
|
||||
"Foods": "Храни",
|
||||
"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": "Приложение",
|
||||
"Bookmarklet": "Книжен пазар",
|
||||
"click_image_import": "Щракнете върху изображението, което искате да импортирате за тази рецепта",
|
||||
"no_more_images_found": "Няма намерени допълнителни изображения на уебсайта.",
|
||||
"import_duplicates": "За да се предотврати дублирането, рецептите със същото име като съществуващите се игнорират. Поставете отметка в това квадратче, за да импортирате всичко.",
|
||||
"paste_json": "Поставете тук json или html източник, за да заредите рецептата.",
|
||||
"Click_To_Edit": "Кликнете, за да редактирате",
|
||||
"search_no_recipes": "Не можах да намеря никакви рецепти!",
|
||||
"search_import_help_text": "Импортирайте рецепта от външен уебсайт или приложение.",
|
||||
"search_create_help_text": "Създайте нова рецепта директно в Tandoor.",
|
||||
"warning_duplicate_filter": "Предупреждение: Поради технически ограничения наличието на множество филтри от една и съща комбинация (и/или/не) може да доведе до неочаквани резултати.",
|
||||
"reset_children": "Нулиране на наследяването от последователя",
|
||||
"reset_children_help": "Презаписване на всички последователи със стойности от наследени полета. Наследените полета на последователите ще бъдат зададени на наследяване на полета, освен ако последователите наследяват полета не е зададено.",
|
||||
"substitute_help": "Заместителите се вземат предвид при търсене на рецепти, които могат да бъдат направени с подръчни съставки.",
|
||||
"substitute_siblings_help": "Всички храни, които споделят родител на тази храна, се считат за заместители.",
|
||||
"substitute_children_help": "Всички храни, които са последователи на тази храна, се считат за заместители.",
|
||||
"substitute_siblings": "Заместители на сродни",
|
||||
"substitute_children": "Заместители на последователи",
|
||||
"SubstituteOnHand": "Имате заместител под ръка.",
|
||||
"ChildInheritFields": "Последователи наследяват полета",
|
||||
"ChildInheritFields_help": "Последователите ще наследят тези полета по подразбиране.",
|
||||
"InheritFields_help": "Стойностите на тези полета ще бъдат наследени от родител (Изключение: празни категории за пазаруване не се наследяват)",
|
||||
"last_viewed": "Последно разгледан",
|
||||
"created_on": "Създадено на",
|
||||
"updatedon": "Актуализирано на",
|
||||
"Imported_From": "Внесено от",
|
||||
"advanced_search_settings": "Разширени настройки за търсене",
|
||||
"nothing_planned_today": "Нямате нищо планирано за днес!",
|
||||
"no_pinned_recipes": "Нямате закачени рецепти!",
|
||||
"Planned": "Планирано",
|
||||
"Pinned": "Закачено",
|
||||
"Imported": "Импортирано",
|
||||
"Quick actions": "Бързи действия",
|
||||
"Ratings": "Рейтинги",
|
||||
"Internal": "Вътрешен",
|
||||
"Units": "Единици",
|
||||
"Random Recipes": "Случайни рецепти",
|
||||
"parameter_count": "Параметър {count}",
|
||||
"select_keyword": "Изберете Ключова дума",
|
||||
"add_keyword": "Добавяне на ключова дума",
|
||||
"select_file": "Избери файл",
|
||||
"select_recipe": "Изберете рецепта",
|
||||
"select_unit": "Изберете Единица",
|
||||
"select_food": "Изберете Храна",
|
||||
"remove_selection": "Премахнете избора",
|
||||
"empty_list": "Списъкът е празен.",
|
||||
"Select": "Изберете",
|
||||
"Supermarkets": "Супермаркети",
|
||||
"User": "потребител",
|
||||
"Keyword": "Ключова дума",
|
||||
"Advanced": "Разширено",
|
||||
"Page": "Страница",
|
||||
"Single": "Единичен",
|
||||
"Multiple": "Многократни",
|
||||
"Reset": "Нулиране",
|
||||
"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": "Импортирани са {imported} от {total} рецепти",
|
||||
"Recipes_In_Import": "Рецепти във вашия файл за импортиране",
|
||||
"Toggle": "Превключете",
|
||||
"Import_Error": "Възникна грешка по време на импортирането ви. Моля, разгънете подробностите в долната част на страницата, за да ги видите.",
|
||||
"Warning_Delete_Supermarket_Category": "Изтриването на категория супермаркет ще изтрие и всички връзки с храни. Сигурен ли си?",
|
||||
"New_Supermarket": "Създайте нов супермаркет",
|
||||
"New_Supermarket_Category": "Създаване на нова категория супермаркет",
|
||||
"Are_You_Sure": "Сигурен ли си?"
|
||||
}
|
||||
414
vue/src/locales/da.json
Normal file
414
vue/src/locales/da.json
Normal file
@@ -0,0 +1,414 @@
|
||||
{
|
||||
"warning_feature_beta": "Denne funktion er i øjeblikket i BETA (test) stadie. Forvent fejl og fremtidige ændringer (hvor data kan mistes) ved brug af denne funktion.",
|
||||
"err_fetching_resource": "Der opstod en fejl under indlæsning af denne ressource!",
|
||||
"err_creating_resource": "Der opstod en fejl under oprettelsen af denne ressource!",
|
||||
"err_updating_resource": "Der opstod en fejl under opdateringen af denne ressource!",
|
||||
"err_deleting_resource": "Der opstod en fejl under sletningen af denne ressource!",
|
||||
"err_deleting_protected_resource": "Objektet du prøver at slette er stadig i brug, og kan ikke slettes.",
|
||||
"err_moving_resource": "Der opstod en fejl under flytningen af denne ressource!",
|
||||
"err_merging_resource": "Der opstod en fejl under sammenfletningen af denne ressource!",
|
||||
"success_fetching_resource": "Ressourcen blev hentet!",
|
||||
"success_creating_resource": "Ressourcen blev oprettet!",
|
||||
"success_updating_resource": "Ressourcen blev opdateret!",
|
||||
"success_deleting_resource": "Ressourcen blev slettet!",
|
||||
"success_moving_resource": "Ressourcen blev flyttet!",
|
||||
"success_merging_resource": "Ressourcen blev sammenflettet!",
|
||||
"file_upload_disabled": "Upload af filer er ikke slået til i dit rum.",
|
||||
"step_time_minutes": "Trin varighed (minutter)",
|
||||
"confirm_delete": "Er du sikker på at du slette dette {object}?",
|
||||
"import_running": "Importering er i gang, vent venligst!",
|
||||
"all_fields_optional": "Alle felter er valgfri og kan være tomme.",
|
||||
"convert_internal": "Konverter til intern opskrift",
|
||||
"show_only_internal": "Vis kun interne opskrifter",
|
||||
"show_split_screen": "Opdel skærmen",
|
||||
"Log_Recipe_Cooking": "Noter tilberedning af opskrift",
|
||||
"External_Recipe_Image": "Eksternt billede af opskrift",
|
||||
"Add_to_Shopping": "Tilføj til indkøbsliste",
|
||||
"Add_to_Plan": "Tilføj til madplan",
|
||||
"Step_start_time": "Trin starttid",
|
||||
"Sort_by_new": "Sorter efter nylige",
|
||||
"Table_of_Contents": "Indholdsfortegnelse",
|
||||
"Recipes_per_page": "Opskrifter pr. side",
|
||||
"Show_as_header": "Vis som rubrik",
|
||||
"Hide_as_header": "Skjul som rubrik",
|
||||
"Add_nutrition_recipe": "Tilføj næringsindhold til opskrift",
|
||||
"Remove_nutrition_recipe": "Fjern næringsindhold fra opskrift",
|
||||
"Copy_template_reference": "Kopier skabelonsreference",
|
||||
"Save_and_View": "Gem & Vis",
|
||||
"Manage_Books": "Administrer bøger",
|
||||
"Meal_Plan": "Madplan",
|
||||
"Select_Book": "Vælg bog",
|
||||
"Select_File": "Vælg fil",
|
||||
"Recipe_Image": "Opskriftsbillede",
|
||||
"Import_finished": "Importering fuldført",
|
||||
"View_Recipes": "Vis opskrifter",
|
||||
"Log_Cooking": "Noter tilberedning",
|
||||
"New_Recipe": "Ny opskrift",
|
||||
"Url_Import": "Importer fra link",
|
||||
"Reset_Search": "Nulstil søgning",
|
||||
"Recently_Viewed": "Vist for nylig",
|
||||
"Load_More": "Indlæs mere",
|
||||
"New_Keyword": "Nyt nøgleord",
|
||||
"Delete_Keyword": "Slet nøgleord",
|
||||
"Edit_Keyword": "Rediger nøgleord",
|
||||
"Edit_Recipe": "Rediger opskrift",
|
||||
"Move_Keyword": "Flyt nøgleord",
|
||||
"Merge_Keyword": "Sammenflet nøgleord",
|
||||
"Hide_Keywords": "Skjul nøgleord",
|
||||
"Hide_Recipes": "Skjul opskrifter",
|
||||
"Move_Up": "Flyt up",
|
||||
"Move_Down": "Flyt ned",
|
||||
"Step_Name": "Trin navn",
|
||||
"Step_Type": "Trin type",
|
||||
"Make_Header": "Opret rubrik",
|
||||
"Make_Ingredient": "Opret ingredient",
|
||||
"Enable_Amount": "Aktiver antal",
|
||||
"Disable_Amount": "Deaktiver antal",
|
||||
"Ingredient Editor": "Ingrediens redigeringsværktøj",
|
||||
"Add_Step": "Tilføj trin",
|
||||
"Keywords": "Nøgleord",
|
||||
"Books": "Bøger",
|
||||
"Proteins": "Proteiner",
|
||||
"Fats": "Fedtstoffer",
|
||||
"Carbohydrates": "Kulhydrater",
|
||||
"Calories": "Kalorier",
|
||||
"Energy": "Energi",
|
||||
"Nutrition": "Næring",
|
||||
"Date": "Dato",
|
||||
"Share": "Del",
|
||||
"Automation": "Automatisering",
|
||||
"Parameter": "Parameter",
|
||||
"Export": "Eksporter",
|
||||
"Copy": "Kopier",
|
||||
"Rating": "Bedømmelse",
|
||||
"Close": "Luk",
|
||||
"Cancel": "Annuller",
|
||||
"Link": "Link",
|
||||
"Add": "Tilføj",
|
||||
"New": "Ny",
|
||||
"Note": "Note",
|
||||
"Success": "Succes",
|
||||
"Failure": "Mislykkedes",
|
||||
"Protected": "Beskyttet",
|
||||
"Ingredients": "Ingredienser",
|
||||
"Supermarket": "Supermarked",
|
||||
"Categories": "Kategorier",
|
||||
"Category": "Kategori",
|
||||
"Selected": "Valgt",
|
||||
"min": "min",
|
||||
"Servings": "Serveringer",
|
||||
"Waiting": "Venter",
|
||||
"Preparation": "Forberedelse",
|
||||
"External": "Ekstern",
|
||||
"Size": "Størrelse",
|
||||
"Files": "Filer",
|
||||
"File": "Fil",
|
||||
"Edit": "Rediger",
|
||||
"Image": "Billede",
|
||||
"Delete": "Slet",
|
||||
"Open": "Åben",
|
||||
"Ok": "Åben",
|
||||
"Save": "Gem",
|
||||
"Step": "Trin",
|
||||
"Search": "Søg",
|
||||
"Import": "Importer",
|
||||
"Print": "Udskriv",
|
||||
"Settings": "Indstillinger",
|
||||
"or": "eller",
|
||||
"and": "og",
|
||||
"Information": "Information",
|
||||
"Download": "Download",
|
||||
"Create": "Opret",
|
||||
"Search Settings": "Søgningsindstillinger",
|
||||
"View": "Vis",
|
||||
"Recipes": "Opskrifter",
|
||||
"Move": "Flyt",
|
||||
"Merge": "Sammenflet",
|
||||
"Parent": "Forælder",
|
||||
"delete_confirmation": "Er du sikker på at du vil slette {source}?",
|
||||
"move_confirmation": "Flyt <i>{child}</i> til forælder <i>parent</i>",
|
||||
"merge_confirmation": "Erstat <i>{source}</i> med <i>{target}</i>",
|
||||
"create_rule": "og opret automation",
|
||||
"move_selection": "Vælg en forælder {type} som {source} skal flyttes til.",
|
||||
"merge_selection": "Erstat alle forekomster af {source} med det valgte {target}.",
|
||||
"Root": "Rod",
|
||||
"Ignore_Shopping": "Ignorer indkøb",
|
||||
"Shopping_Category": "Indkøbskategori",
|
||||
"Shopping_Categories": "Indkøbskategorier",
|
||||
"Edit_Food": "Rediger mad",
|
||||
"Move_Food": "Flyt mad",
|
||||
"New_Food": "Ny mad",
|
||||
"Hide_Food": "Skjul mad",
|
||||
"Food_Alias": "Alternativt navn til mad",
|
||||
"Unit_Alias": "Alternativt navn til enhed",
|
||||
"Keyword_Alias": "Alternativt navn til nøgleord",
|
||||
"Delete_Food": "Slet mad",
|
||||
"No_ID": "ID findes ikke, kan ikke slette.",
|
||||
"Meal_Plan_Days": "Fremtidige madplaner",
|
||||
"merge_title": "Sammenflet {type}",
|
||||
"move_title": "Flyt {type}",
|
||||
"Food": "Mad",
|
||||
"Recipe_Book": "Opskriftsbog",
|
||||
"del_confirmation_tree": "Er du sikker på at du vil slette {source} og alle dets børn?",
|
||||
"delete_title": "Slet {type}",
|
||||
"create_title": "Ny {type}",
|
||||
"edit_title": "Rediger {type}",
|
||||
"Name": "Navn",
|
||||
"Type": "Type",
|
||||
"Description": "Beskrivelse",
|
||||
"Recipe": "Opskrift",
|
||||
"tree_root": "Roden af træet",
|
||||
"Icon": "Ikon",
|
||||
"Unit": "Enhed",
|
||||
"No_Results": "Ingen resultater",
|
||||
"New_Unit": "Ny enhed",
|
||||
"Create_New_Shopping Category": "Opret ny indkøbskategori",
|
||||
"Create_New_Food": "Tilføj ny mad",
|
||||
"Create_New_Keyword": "Tilføj nyt nøgleord",
|
||||
"Create_New_Unit": "Tilføj ny enhed",
|
||||
"Create_New_Meal_Type": "Tilføj ny måltidstype",
|
||||
"and_up": "& Op",
|
||||
"and_down": "& Ned",
|
||||
"Instructions": "Instruktioner",
|
||||
"Unrated": "Ikke bedømt",
|
||||
"Automate": "Automatiser",
|
||||
"Empty": "Tom",
|
||||
"Key_Ctrl": "Ctrl",
|
||||
"Key_Shift": "Shift",
|
||||
"Time": "Tid",
|
||||
"Text": "Tekst",
|
||||
"Shopping_list": "Indkøbsliste",
|
||||
"Added_by": "Tilføjet af",
|
||||
"Added_on": "Tilføjet d.",
|
||||
"AddToShopping": "Tilføj til indkøbsliste",
|
||||
"IngredientInShopping": "Denne ingrediens er i din indkøbsliste.",
|
||||
"NotInShopping": "{food} er ikke i din indkøbsliste.",
|
||||
"OnHand": "Til rådighed",
|
||||
"FoodOnHand": "Du har {food} til rådighed.",
|
||||
"FoodNotOnHand": "Du har ikke {food} til rådighed.",
|
||||
"Undefined": "Ikke defineret",
|
||||
"Create_Meal_Plan_Entry": "Indsæt punkt i madplan",
|
||||
"Edit_Meal_Plan_Entry": "Rediger punkt i madplan",
|
||||
"Title": "Titel",
|
||||
"Week": "Uge",
|
||||
"Month": "Måned",
|
||||
"Year": "År",
|
||||
"Planner": "Planlægger",
|
||||
"Planner_Settings": "Planlægger indstillinger",
|
||||
"Period": "Periode",
|
||||
"Plan_Period_To_Show": "Vis uger, måneder eller år",
|
||||
"Periods": "Perioder",
|
||||
"Plan_Show_How_Many_Periods": "Hvor mange perioder skal vises",
|
||||
"Starting_Day": "Første dag på ugen",
|
||||
"Meal_Types": "Måltidstyper",
|
||||
"Meal_Type": "Måltidstype",
|
||||
"Clone": "Klon",
|
||||
"Drag_Here_To_Delete": "Træk herhen for at slette",
|
||||
"Meal_Type_Required": "Måltidstype påkrævet",
|
||||
"Title_or_Recipe_Required": "Titel eller valg af opskrift påkrævet",
|
||||
"Color": "Farve",
|
||||
"New_Meal_Type": "Ny måltidstype",
|
||||
"AddFoodToShopping": "Tilføj {food} til indkøbsliste",
|
||||
"RemoveFoodFromShopping": "Fjern {food} fra indkøbsliste",
|
||||
"DeleteShoppingConfirm": "Er du sikker på at du vil fjerne {food} fra indkøbsliste?",
|
||||
"IgnoredFood": "{food} er sat til at ignorere indkøb.",
|
||||
"Add_Servings_to_Shopping": "Tilføj {servings} serveringer til indkøb",
|
||||
"Week_Numbers": "Ugenumre",
|
||||
"Show_Week_Numbers": "Vis ugenumre?",
|
||||
"Export_As_ICal": "Eksporter nuværende periode til iCal format",
|
||||
"Export_To_ICal": "Eksporter .ics",
|
||||
"Cannot_Add_Notes_To_Shopping": "Noter kan ikke tilføjes til indkøbslisten",
|
||||
"Added_To_Shopping_List": "Tilføjet til indkøbslisten",
|
||||
"Shopping_List_Empty": "Din indkøbsliste er i øjeblikket tom, du kan tilføje varer via menuen for et madplanspunkt (højreklik på punktet eller venstreklik på menu ikonet)",
|
||||
"Next_Period": "Næste periode",
|
||||
"Previous_Period": "Forgående periode",
|
||||
"Current_Period": "Nuværende periode",
|
||||
"Next_Day": "Næste dag",
|
||||
"Previous_Day": "Forgående dag",
|
||||
"Inherit": "Nedarve",
|
||||
"InheritFields": "Nedarve feltværdier",
|
||||
"FoodInherit": "Nedarvelige mad felter",
|
||||
"ShowUncategorizedFood": "Vis ikke definerede",
|
||||
"GroupBy": "Grupper efter",
|
||||
"SupermarketCategoriesOnly": "Kun Supermarked kategorier",
|
||||
"MoveCategory": "Flyt til: ",
|
||||
"CountMore": "...+{count} flere",
|
||||
"IgnoreThis": "Aldrig tilføj {food} automatisk til indkøb",
|
||||
"DelayFor": "Udskyd i {hours} hours",
|
||||
"Warning": "Advarsel",
|
||||
"NoCategory": "Ingen kategori valgt.",
|
||||
"InheritWarning": "{food} er sat til at nedarve, ændringer bliver måske ikke gemt.",
|
||||
"ShowDelayed": "Vis udskudte elementer",
|
||||
"Completed": "Afsluttet",
|
||||
"OfflineAlert": "Du er offline, indkøbslisten er måske ikke synkroniseret.",
|
||||
"shopping_share": "Del indkøbsliste",
|
||||
"shopping_auto_sync": "Synkroniser automatisk",
|
||||
"one_url_per_line": "Et link pr. linje",
|
||||
"mealplan_autoadd_shopping": "Tilføj madplan automatisk",
|
||||
"mealplan_autoexclude_onhand": "Ekskluder tilgængeligt mad",
|
||||
"mealplan_autoinclude_related": "Tilføj relaterede opskrifter",
|
||||
"default_delay": "Standard udsættelse i timer",
|
||||
"shopping_share_desc": "Brugere vil se alle varer du tilføjer til din indkøbsliste. De skal tilføje dig for at se varer på deres liste.",
|
||||
"shopping_auto_sync_desc": "Hvis den sættes til 0, bliver automatisk synkronisering slået fra. Når en indkøbsliste vises bliver den opdateret efter den indstillede periode i sekunder, for at synkronisere eventuelle ændringer andre har foretaget. Brugbar når man køber ind sammen med andre, men det bruger mobildata.",
|
||||
"mealplan_autoadd_shopping_desc": "Tilføj madplansingredienser til indkøbsliste automatisk.",
|
||||
"mealplan_autoexclude_onhand_desc": "Når en madplan tilføjes til indkøbslisten (manuelt eller automatisk), ekskluder tilgængelige ingredienser.",
|
||||
"mealplan_autoinclude_related_desc": "Når en madplan tilføjes til indkøbslisten (manuelt eller automatisk), inkluder alle relaterede opskrifter.",
|
||||
"default_delay_desc": "Standard antal timer et punkt på indkøbslisten skal udskydes.",
|
||||
"filter_to_supermarket": "Filtrer til supermarked",
|
||||
"Coming_Soon": "Kommer snart",
|
||||
"Auto_Planner": "Autoplanlægger",
|
||||
"New_Cookbook": "Ny opskriftsbog",
|
||||
"Hide_Keyword": "Skjul nøgleord",
|
||||
"Clear": "Ryd",
|
||||
"err_move_self": "Kan ikke flytte element til sig selv",
|
||||
"nothing": "Intet at gøre",
|
||||
"err_merge_self": "Kan ikke sammenflette element med sig selv",
|
||||
"show_sql": "Vis SQL",
|
||||
"filter_to_supermarket_desc": "Filtrer som standard indkøbslisten til kun at inkludere kategorier fra valgte supermarkeder.",
|
||||
"CategoryName": "Kategorinavn",
|
||||
"SupermarketName": "Navn på supermarked",
|
||||
"CategoryInstruction": "Træk rundt på kategorier, for at ændre på rækkefølgen de opstår i på indkøbslisten.",
|
||||
"shopping_recent_days_desc": "Antal dage seneste varer fra indkøbslister skal vises.",
|
||||
"shopping_recent_days": "Seneste dage",
|
||||
"download_pdf": "Download PDF",
|
||||
"download_csv": "Download CSV",
|
||||
"csv_delim_help": "Tegn der skal afgrænse elementer i CSV eksporteringer.",
|
||||
"csv_delim_label": "CSV afgrænsningstegn",
|
||||
"SuccessClipboard": "Indkøbsliste kopieret til udklipsholder",
|
||||
"copy_to_clipboard": "Kopier til udklipsholder",
|
||||
"csv_prefix_help": "Præfiks som skal tilføjes når der kopieres til udklipsholder.",
|
||||
"csv_prefix_label": "Liste præfiks",
|
||||
"copy_markdown_table": "Kopier som Markdown tabel",
|
||||
"in_shopping": "I indkøbsliste",
|
||||
"DelayUntil": "Udskyd indtil",
|
||||
"Pin": "Fastgør",
|
||||
"mark_complete": "Marker som færdig",
|
||||
"QuickEntry": "Hurtigt indlæg",
|
||||
"shopping_add_onhand_desc": "Marker mad som 'Tilgængeligt' når det bliver krydset af på indkøbslisten.",
|
||||
"shopping_add_onhand": "Automatisk tilgængelig markering",
|
||||
"related_recipes": "Relaterede opskrifter",
|
||||
"today_recipes": "Opskrifter til i dag",
|
||||
"sql_debug": "SQL fejlsøgning",
|
||||
"remember_search": "Husk søgning",
|
||||
"remember_hours": "Timer at gemme i",
|
||||
"tree_select": "Benyt træ vælger",
|
||||
"OnHand_help": "Varen er \"på lager\" og vil ikke automatisk blive tilføjet til indkøbslister. Lagerstatus deles med indkøbsbrugere.",
|
||||
"ignore_shopping_help": "Aldrig tilføj vare til indkøbslisten (f.eks. vand)",
|
||||
"shopping_category_help": "Supermarkeder kan blive filtrerede efter indkøbskategori så det passer med indretningen i butikken.",
|
||||
"food_recipe_help": "Hvis du sammenkæder en opskrift her vil den sammenkædede opskrift blive inkluderet i alle andre opskrifter der bruger denne mad",
|
||||
"Foods": "Mad",
|
||||
"enable_expert": "Slå avanceret tilstand til",
|
||||
"expert_mode": "Avanceret tilstand",
|
||||
"simple_mode": "Simpel tilstand",
|
||||
"advanced": "Avanceret",
|
||||
"fields": "Felter",
|
||||
"show_keywords": "Vis nøgleord",
|
||||
"show_foods": "Vis mad",
|
||||
"show_books": "Vis bøger",
|
||||
"show_rating": "Vis bedømmelse",
|
||||
"show_units": "Vis enheder",
|
||||
"show_filters": "Vis filtre",
|
||||
"not": "ikke",
|
||||
"save_filter": "Gem filter",
|
||||
"filter_name": "Filtrer navn",
|
||||
"left_handed": "Venstrehåndstilstand",
|
||||
"left_handed_help": "Optimerer brugerfladen til benyttelse med din venstre hånd.",
|
||||
"Custom Filter": "Tilpasset filter",
|
||||
"shared_with": "Delt med",
|
||||
"sort_by": "Sorter efter",
|
||||
"asc": "Stigende",
|
||||
"desc": "Faldende",
|
||||
"date_viewed": "Sidst Åbnet",
|
||||
"last_cooked": "Sidst Tilberedt",
|
||||
"times_cooked": "Antal gange tilberedt",
|
||||
"date_created": "Oprettelsesdato",
|
||||
"show_sortby": "Soter efter",
|
||||
"search_rank": "Søg efter rang",
|
||||
"make_now": "Lav nu",
|
||||
"recipe_filter": "Opskriftsfilter",
|
||||
"book_filter_help": "Inkluder opskrifter fra opskriftsfilter udover de manuelt udvalgte.",
|
||||
"review_shopping": "Tjek indkøbsvarer inden der gemmes",
|
||||
"view_recipe": "Vis opskrift",
|
||||
"copy_to_new": "Kopier til ny opskrift",
|
||||
"recipe_name": "Navn på opskrift",
|
||||
"paste_ingredients_placeholder": "Indsæt ingrediensliste her...",
|
||||
"paste_ingredients": "Indsæt ingredienser",
|
||||
"ingredient_list": "Ingrediensliste",
|
||||
"explain": "Forklar",
|
||||
"filter": "Filter",
|
||||
"Website": "Hjemmeside",
|
||||
"App": "App",
|
||||
"Bookmarklet": "Bogmærke",
|
||||
"click_image_import": "Klik på billedet du vil importere til denne opskrift",
|
||||
"no_more_images_found": "Ingen yderligere billeder fundet på hjemmeside.",
|
||||
"import_duplicates": "For at undgå dubletter bliver opskrifter med det samme navn som eksisterende opskrifter ignoreret. Ving den boks af for at tilføje alt.",
|
||||
"paste_json": "Indsæt JSON eller HTML kildekode her for at indlæse opskrift.",
|
||||
"Click_To_Edit": "Klik for at rediger",
|
||||
"search_no_recipes": "Kunne ikke finde nogen opskrifter!",
|
||||
"search_import_help_text": "Importer en opskrift fra en ekstern hjemmeside eller applikation.",
|
||||
"search_create_help_text": "Opret en ny opskrift direkte i Tandoor.",
|
||||
"warning_duplicate_filter": "Advarsel: På grund af tekniske begrænsninger, kan det give uforventede resultater at have flere filtre med den samme kombination af (og/eller/not).",
|
||||
"reset_children": "Nulstil barnets nedarvning",
|
||||
"reset_children_help": "Overskriv alle børn med værdier fra nedarvede felter. Nedarvede felter af børn vil blive sat til at nedarve med mindre de allerede er sat til at nedarve.",
|
||||
"substitute_help": "Erstatninger bliver taget i betragtning når der søges efter opskrifter der kan laves med tilgængelige ingredienser.",
|
||||
"substitute_siblings_help": "Alt mad der deler en forælder med denne mad bliver betragtet som erstatninger.",
|
||||
"substitute_children_help": "Alt mad der er et barn af denne mad bliver betragtet som erstatninger.",
|
||||
"substitute_siblings": "Erstattende søskende",
|
||||
"substitute_children": "Erstattende børn",
|
||||
"SubstituteOnHand": "Du har erstatninger tilgængeligt.",
|
||||
"ChildInheritFields": "Barn nedarvningsfelter",
|
||||
"ChildInheritFields_help": "Børn nedarvede disse felter som standard.",
|
||||
"InheritFields_help": "Værdierne af disse felter vil blive nedarvet fra forælder (Undtagelse: tomme indkøbskategorier bliver ikke nedarvet)",
|
||||
"last_viewed": "Sidst åbnet",
|
||||
"created_on": "Oprettet d.",
|
||||
"updatedon": "Opdateret d.",
|
||||
"Imported_From": "Importeret fra",
|
||||
"advanced_search_settings": "Avancerede søgeindstillinger",
|
||||
"nothing_planned_today": "Du har ikke noget planlagt for i dag!",
|
||||
"no_pinned_recipes": "Du har ingen fastgjorte opskrifter!",
|
||||
"Planned": "Planlagt",
|
||||
"Pinned": "Fastgjort",
|
||||
"Imported": "Importeret",
|
||||
"Quick actions": "Hurtige handlinger",
|
||||
"Ratings": "Bedømmelser",
|
||||
"Internal": "Interne",
|
||||
"Units": "Enheder",
|
||||
"Random Recipes": "Tilfældige opskrifter",
|
||||
"parameter_count": "Parameter {count}",
|
||||
"select_keyword": "Vælg nøgleord",
|
||||
"add_keyword": "Tilføj nøgleord",
|
||||
"select_file": "Vælg fil",
|
||||
"select_recipe": "Vælg opskrift",
|
||||
"select_unit": "Vælg enhed",
|
||||
"select_food": "Vælg mad",
|
||||
"remove_selection": "Fjern markering",
|
||||
"empty_list": "Listen er tom.",
|
||||
"Select": "Vælg",
|
||||
"Supermarkets": "Supermarkeder",
|
||||
"User": "Bruger",
|
||||
"Keyword": "Nøgleord",
|
||||
"Advanced": "Avanceret",
|
||||
"Page": "Side",
|
||||
"Single": "Enkel",
|
||||
"Multiple": "Flere",
|
||||
"Reset": "Nulstil",
|
||||
"Options": "Indstillinger",
|
||||
"Create Food": "Opret mad",
|
||||
"create_food_desc": "Opret mad og sammenkæd den med denne opskrift.",
|
||||
"additional_options": "Yderligere indstillinger",
|
||||
"Importer_Help": "Mere information og hjælp til denne importer:",
|
||||
"Documentation": "Dokumentation",
|
||||
"Select_App_To_Import": "Vælg venligst en App at importere fra",
|
||||
"Import_Supported": "Import understøttet",
|
||||
"Export_Supported": "Eksport understøttet",
|
||||
"Import_Not_Yet_Supported": "Import endnu ikke understøttet",
|
||||
"Export_Not_Yet_Supported": "Eksport endnu ikke understøttet",
|
||||
"Import_Result_Info": "{imported} af {total} opskrifter blev importeret",
|
||||
"Recipes_In_Import": "Opskrifter i din importerede fil",
|
||||
"Toggle": "Skift",
|
||||
"Import_Error": "Der opstod en fejl under din importering. Udvid detaljerne i bunden af siden for at se fejlen.",
|
||||
"Warning_Delete_Supermarket_Category": "At slette en supermarkedskategori vil også slette alle relationer til mad. Er du sikker?",
|
||||
"New_Supermarket": "Opret nyt supermarked",
|
||||
"New_Supermarket_Category": "Opret ny supermarkedskategori",
|
||||
"Are_You_Sure": "Er du sikker?"
|
||||
}
|
||||
@@ -202,6 +202,7 @@
|
||||
"Starting_Day": "Starting day of the week",
|
||||
"Meal_Types": "Meal types",
|
||||
"Meal_Type": "Meal type",
|
||||
"New_Entry": "New Entry",
|
||||
"Clone": "Clone",
|
||||
"Drag_Here_To_Delete": "Drag here to delete",
|
||||
"Meal_Type_Required": "Meal type is required",
|
||||
|
||||
@@ -379,5 +379,40 @@
|
||||
"Reset": "Herstel",
|
||||
"remember_search": "Onthoud zoekopdracht",
|
||||
"tree_select": "Gebruik boomselectie",
|
||||
"sql_debug": "SQL Debug"
|
||||
"sql_debug": "SQL Debug",
|
||||
"Bookmarklet": "Bladwijzer",
|
||||
"no_more_images_found": "Geen extra afbeeldingen gevonden op website.",
|
||||
"import_duplicates": "Om dubbelingen te voorkomen worden recepten met dezelfde naam als bestaande genegeerd. Vink dit vakje aan om alles te importeren.",
|
||||
"paste_json": "Plak json of html bron hier om recept te laden.",
|
||||
"Click_To_Edit": "Klik om te bewerken",
|
||||
"Imported": "Geïmporteerd",
|
||||
"Multiple": "Meerdere",
|
||||
"Single": "Enkele",
|
||||
"Options": "Opties",
|
||||
"Importer_Help": "Meer informatie en hulp over de importtool:",
|
||||
"Documentation": "Documentatie",
|
||||
"Select_App_To_Import": "Selecteer een app om van te importeren",
|
||||
"Import_Supported": "Import ondersteund",
|
||||
"Export_Supported": "Export ondersteund",
|
||||
"Import_Not_Yet_Supported": "Import nog niet ondersteund",
|
||||
"Export_Not_Yet_Supported": "Export nog niet ondersteund",
|
||||
"Import_Result_Info": "{imported} van {total} recepten zijn geïmporteerd",
|
||||
"Recipes_In_Import": "Recepten in je importbestand",
|
||||
"Toggle": "Schakelaar",
|
||||
"New_Supermarket": "Maak nieuwe supermarkt",
|
||||
"New_Supermarket_Category": "Maak nieuwe supermarktcategorie",
|
||||
"Are_You_Sure": "Weet je het zeker?",
|
||||
"Ingredient Editor": "Ingrediënten editor",
|
||||
"App": "App",
|
||||
"click_image_import": "Klik op de afbeelding die je wil importeren voor dit recept",
|
||||
"err_deleting_protected_resource": "Het object dat je probeert te verwijderen is in gebruik en kan daardoor niet verwijderd worden.",
|
||||
"one_url_per_line": "Een URL per regel",
|
||||
"Protected": "Beschermd",
|
||||
"Website": "Website",
|
||||
"Imported_From": "Geïmporteerd van",
|
||||
"Import_Error": "Er is een fout opgetreden tijdens je import. Breid de details aan de onderzijde van de pagina uit om ze te bekijken.",
|
||||
"Warning_Delete_Supermarket_Category": "Een supermarktcategorie verwijderen verwijdert ook alle relaties naar ingrediënten. Weet je het zeker?",
|
||||
"create_food_desc": "Maak een ingrediënt en link aan dit recept.",
|
||||
"additional_options": "Extra opties",
|
||||
"Create Food": "Maak Ingrediënt"
|
||||
}
|
||||
|
||||
@@ -383,5 +383,34 @@
|
||||
"additional_options": "Opcje dodatkowe",
|
||||
"err_deleting_protected_resource": "Obiekt, który próbujesz usunąć, jest nadal używany i nie można go usunąć.",
|
||||
"Protected": "Chroniony",
|
||||
"Ingredient Editor": "Edytor składników"
|
||||
"Ingredient Editor": "Edytor składników",
|
||||
"one_url_per_line": "Jeden URL na linię",
|
||||
"Website": "Strona internetowa",
|
||||
"App": "Aplikacja",
|
||||
"Bookmarklet": "Skryptozakładka",
|
||||
"click_image_import": "Kliknij obraz, który chcesz zaimportować do tego przepisu",
|
||||
"no_more_images_found": "Nie znaleziono dodatkowych zdjęć na stronie internetowej.",
|
||||
"import_duplicates": "Aby zapobiec duplikatom przepisy tej samej nazwie, co istniejące, są ignorowane. Zaznacz to pole, aby zaimportować wszystko.",
|
||||
"paste_json": "Wklej tutaj źródło json lub html, aby załadować przepis.",
|
||||
"Click_To_Edit": "Kliknij aby edytować",
|
||||
"Imported_From": "Zaimportowane z",
|
||||
"Options": "Opcje",
|
||||
"Imported": "Importowany",
|
||||
"Single": "Pojedynczy",
|
||||
"Multiple": "Wiele",
|
||||
"Documentation": "Dokumentacja",
|
||||
"Import_Supported": "Importowanie wspierane",
|
||||
"Export_Supported": "Eksportowanie wspierane",
|
||||
"Import_Not_Yet_Supported": "Importowanie jeszcze nie wspierane",
|
||||
"Export_Not_Yet_Supported": "Eksportowanie jeszcze nie wspierane",
|
||||
"Import_Result_Info": "{imported} z {total} przepisów zostało zaimportowanych",
|
||||
"Recipes_In_Import": "Przepisy w pliku importu",
|
||||
"Toggle": "Przełącznik",
|
||||
"Import_Error": "Podczas importowania wystąpił błąd. Rozwiń Szczegóły na dole strony, aby go wyświetlić.",
|
||||
"Warning_Delete_Supermarket_Category": "Usunięcie kategorii supermarketu spowoduje również usunięcie wszystkich relacji z żywnością. Jesteś pewny?",
|
||||
"New_Supermarket": "Stwórz nowy supermarket",
|
||||
"New_Supermarket_Category": "Utwórz nową kategorię supermarketów",
|
||||
"Are_You_Sure": "Jesteś pewny?",
|
||||
"Importer_Help": "Więcej informacji i pomoc na temat tego importera:",
|
||||
"Select_App_To_Import": "Wybierz aplikację, z której chcesz zaimportować"
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"Show_as_header": "Показывать как заголовок",
|
||||
"Hide_as_header": "Скрыть заголовок",
|
||||
"Copy_template_reference": "Скопировать ссылку на шаблон",
|
||||
"Save_and_View": "Сохронить и показать",
|
||||
"Save_and_View": "Сохранить и показать",
|
||||
"Manage_Books": "Управление книгами",
|
||||
"Meal_Plan": "Планирование блюд",
|
||||
"Select_Book": "Выбрать книгу",
|
||||
@@ -188,18 +188,18 @@
|
||||
"Title_or_Recipe_Required": "Требуется выбор названия или рецепта",
|
||||
"Color": "Цвет",
|
||||
"New_Meal_Type": "Новый тип питания",
|
||||
"Week_Numbers": "",
|
||||
"Show_Week_Numbers": "",
|
||||
"Export_As_ICal": "",
|
||||
"Week_Numbers": "Номер недели",
|
||||
"Show_Week_Numbers": "Показать номера недель?",
|
||||
"Export_As_ICal": "Экспорт текущего периода в 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": "",
|
||||
"Added_To_Shopping_List": "Добавлено в список покупок",
|
||||
"Shopping_List_Empty": "В настоящее время ваш список покупок пуст, вы можете добавить пункты через контекстное меню записи плана питания (щелкните правой кнопкой мыши на карточке или щелкните левой кнопкой мыши на значке меню)",
|
||||
"Next_Period": "Следующий период",
|
||||
"Previous_Period": "Предыдущий период",
|
||||
"Current_Period": "Текущий период",
|
||||
"Next_Day": "Следующий день",
|
||||
"Previous_Day": "Предыдущий день",
|
||||
"Add_nutrition_recipe": "Добавьте питательные вещества в рецепт",
|
||||
"and_down": "Вниз",
|
||||
"Added_by": "Добавлено",
|
||||
@@ -217,6 +217,121 @@
|
||||
"Search Settings": "Искать настройки",
|
||||
"err_merging_resource": "Произошла ошибка при перемещении ресурса!",
|
||||
"Remove_nutrition_recipe": "Уберите питательные вещества из рецепта",
|
||||
"err_moving_resource": "Ошибка при перемещении ресурса!",
|
||||
"NotInShopping": "{food} отсутствует в вашем списке покупок."
|
||||
"err_moving_resource": "Произошла ошибка при перемещении ресурса!",
|
||||
"NotInShopping": "{food} отсутствует в вашем списке покупок.",
|
||||
"RemoveFoodFromShopping": "Удалить {food} из вашего списка покупок",
|
||||
"ShowDelayed": "Показать отложенные элементы",
|
||||
"Completed": "Завершено",
|
||||
"save_filter": "Сохранить фильтр",
|
||||
"sort_by": "Сортировать по",
|
||||
"shared_with": "Совместно с",
|
||||
"Custom Filter": "Пользовательский фильтр",
|
||||
"filter_name": "Имя фильтра",
|
||||
"created_on": "Создано на",
|
||||
"last_viewed": "Последний просмотренный",
|
||||
"select_keyword": "Выбрать ключевое слово",
|
||||
"parameter_count": "Параметр {count}",
|
||||
"Units": "Единицы",
|
||||
"left_handed": "Режим для левшей",
|
||||
"User": "Пользователь",
|
||||
"Page": "Страница",
|
||||
"Advanced": "Расширенный",
|
||||
"Auto_Planner": "Автопланировщик",
|
||||
"Hide_Keyword": "Скрыть ключевые слова",
|
||||
"Clear": "Очистить",
|
||||
"search_rank": "Поисковый рейтинг",
|
||||
"show_rating": "Показать рейтинг",
|
||||
"show_books": "Показать книги",
|
||||
"show_foods": "Показать продукты",
|
||||
"Documentation": "Документация",
|
||||
"Reset": "Сбросить",
|
||||
"Imported": "Импортировано",
|
||||
"no_pinned_recipes": "У Вас нет закреплённых рецептов!",
|
||||
"advanced_search_settings": "Расширенные настройки поиска",
|
||||
"updatedon": "Обновлено",
|
||||
"copy_to_new": "Скопировать в новый рецепт",
|
||||
"recipe_filter": "Фильтр рецептов",
|
||||
"New_Supermarket": "Создание нового супермаркета",
|
||||
"Import_Error": "Во время импорта произошла ошибка. Для просмотра разверните \"Подробности\" в нижней части страницы.",
|
||||
"OfflineAlert": "Вы находитесь вне сети, список покупок может не синхронизироваться.",
|
||||
"Coming_Soon": "Скоро",
|
||||
"Ingredient Editor": "Редактор ингредиентов",
|
||||
"New_Cookbook": "Новая кулинарная книга",
|
||||
"Are_You_Sure": "Вы уверены?",
|
||||
"Protected": "Защищено",
|
||||
"Warning_Delete_Supermarket_Category": "Удаление категории супермаркета также приведет к удалению всех связей с продуктами. Вы уверены?",
|
||||
"Multiple": "Несколько",
|
||||
"add_keyword": "Добавить ключевое слово",
|
||||
"Random Recipes": "Случайные рецепты",
|
||||
"nothing_planned_today": "Вы ничего не запланировали на сегодня!",
|
||||
"book_filter_help": "Включать рецепты из фильтра рецептов в дополнение к назначенным вручную.",
|
||||
"make_now": "Сделать сейчас",
|
||||
"date_created": "Дата создана",
|
||||
"left_handed_help": "Оптимизирует пользовательский интерфейс для использования левой рукой.",
|
||||
"show_keywords": "Показать ключевые слова",
|
||||
"DeleteShoppingConfirm": "Вы уверены, что хотите удалить все {food} из вашего списка покупок?",
|
||||
"Inherit": "Наследовать",
|
||||
"InheritFields": "Наследование значений полей",
|
||||
"FoodInherit": "Наследуемые поля продуктов питания",
|
||||
"ShowUncategorizedFood": "Показать неопределенное",
|
||||
"SupermarketCategoriesOnly": "Только категории супермаркетов",
|
||||
"CountMore": "...+{count} больше",
|
||||
"Warning": "Предупреждение",
|
||||
"mealplan_autoexclude_onhand": "Исключить продукты питания, имеющиеся в наличии",
|
||||
"NoCategory": "Категория не выбрана.",
|
||||
"shopping_share": "Поделиться списком покупок",
|
||||
"shopping_auto_sync": "Автосинхронизация",
|
||||
"mealplan_autoadd_shopping": "Автоматическое добавление плана питания",
|
||||
"food_recipe_help": "Если вы разместите здесь ссылку на рецепт, то он будет включен в любой другой рецепт, в котором используется это блюдо",
|
||||
"expert_mode": "Экспертный режим",
|
||||
"enable_expert": "Включить экспертный режим",
|
||||
"review_shopping": "Просмотрите записи о покупках перед сохранением",
|
||||
"empty_list": "Список пуст",
|
||||
"default_delay_desc": "Число часов по умолчанию для отсрочки записи в списке покупок.",
|
||||
"one_url_per_line": "Один URL в строке",
|
||||
"mealplan_autoinclude_related": "Добавить сопутствующие рецепты",
|
||||
"default_delay": "Часы задержки по умолчанию",
|
||||
"shopping_share_desc": "Пользователи будут видеть все товары, которые вы добавляете в список покупок. Они должны добавить вас, чтобы увидеть предметы в своем списке.",
|
||||
"shopping_auto_sync_desc": "Установка значения 0 отключает автоматическую синхронизацию. При просмотре списка покупок список обновляется каждые несколько секунд, чтобы синхронизировать изменения, которые мог внести кто-то другой. Полезно, когда покупки совершают несколько человек, но при этом используются мобильные данные.",
|
||||
"mealplan_autoadd_shopping_desc": "Автоматическое добавление ингредиентов плана питания в список покупок.",
|
||||
"mealplan_autoexclude_onhand_desc": "При добавлении плана питания в список покупок (вручную или автоматически) исключайте ингредиенты, которые в данный момент есть под рукой.",
|
||||
"mealplan_autoinclude_related_desc": "При добавлении плана питания в список покупок (вручную или автоматически) включайте все связанные с ним рецепты.",
|
||||
"filter_to_supermarket": "Фильтр для супермаркета",
|
||||
"err_move_self": "Невозможно переместить элемент на себя",
|
||||
"nothing": "Нечего делать",
|
||||
"err_merge_self": "Невозможно объединить элемент с самим собой",
|
||||
"show_sql": "Показать SQL",
|
||||
"show_filters": "Показать фильтры",
|
||||
"show_units": "Показать единицы",
|
||||
"fields": "Поля",
|
||||
"advanced": "Расширенный",
|
||||
"simple_mode": "Простой режим",
|
||||
"ingredient_list": "Список ингредиентов",
|
||||
"paste_ingredients": "Добавить ингредиенты",
|
||||
"paste_ingredients_placeholder": "Вставьте сюда список ингредиентов...",
|
||||
"recipe_name": "Название рецепта",
|
||||
"view_recipe": "Посмотреть рецепт",
|
||||
"times_cooked": "Время готовки",
|
||||
"last_cooked": "Последнее приготовленое",
|
||||
"date_viewed": "Последний просмотренный",
|
||||
"Internal": "Внутренний",
|
||||
"Imported_From": "Импортировано из",
|
||||
"Keyword": "Ключевое слово",
|
||||
"Supermarkets": "Супермаркеты",
|
||||
"Select": "Выбрать",
|
||||
"remove_selection": "Отменить выбор",
|
||||
"select_food": "Выберите продукты питания",
|
||||
"select_unit": "Выберите единицу",
|
||||
"select_recipe": "Выбрать рецепт",
|
||||
"select_file": "Выбрать файл",
|
||||
"Ratings": "Рейтинги",
|
||||
"Quick actions": "Быстрые действия",
|
||||
"Pinned": "Прикрепленный",
|
||||
"Planned": "Запланировано",
|
||||
"Options": "Опции",
|
||||
"additional_options": "Дополнительные опции",
|
||||
"create_food_desc": "Создайте блюдо и свяжите его с этим рецептом.",
|
||||
"err_deleting_protected_resource": "Объект, который вы пытаетесь удалить, все еще используется и не может быть удален.",
|
||||
"tree_select": "Выбор дерева для использования",
|
||||
"remember_search": "Запомнить поиск"
|
||||
}
|
||||
|
||||
4429
vue/yarn.lock
4429
vue/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user