Merge branch 'develop' into beta

This commit is contained in:
vabene1111 2022-03-02 09:24:09 +01:00
commit a5cc218b56
14 changed files with 121 additions and 63 deletions

View File

@ -35,8 +35,8 @@ jobs:
publish: true
imageName: vabene1111/recipes
tag: beta
dockerHubUser: ${{ secrets.DOCKER_USERNAME }}
dockerHubPassword: ${{ secrets.DOCKER_PASSWORD }}
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
# Send discord notification
- name: Discord notification
env:

View File

@ -39,5 +39,6 @@ jobs:
publish: true
imageName: vabene1111/recipes
tag: latest
dockerHubUser: ${{ secrets.DOCKER_USERNAME }}
dockerHubPassword: ${{ secrets.DOCKER_PASSWORD }}
platform: linux/amd64,linux/arm64
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}

View File

@ -41,8 +41,9 @@ jobs:
publish: true
imageName: vabene1111/recipes
tag: ${{ steps.get_version.outputs.VERSION }}
dockerHubUser: ${{ secrets.DOCKER_USERNAME }}
dockerHubPassword: ${{ secrets.DOCKER_PASSWORD }}
platform: linux/amd64,linux/arm64
dockerUser: ${{ secrets.DOCKER_USERNAME }}
dockerPassword: ${{ secrets.DOCKER_PASSWORD }}
# Send discord notification
- name: Discord notification
env:

View File

@ -15,11 +15,13 @@ 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 && \
RUN sed -i '/cryptography==/d' ./requirements.txt
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev libressl-dev python3-dev libffi-dev cargo openldap-dev && \
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
python -m venv venv && \
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
venv/bin/pip install wheel==0.36.2 && \
venv/bin/pip install wheel==0.37.1 && \
venv/bin/pip install -r requirements.txt --no-cache-dir &&\
apk --purge del .build-deps

View File

@ -3,6 +3,7 @@ import re
from html import unescape
from unicodedata import decomposition
from django.utils.translation import gettext as _
from django.utils.dateparse import parse_duration
from isodate import parse_duration as iso_parse_duration
from isodate.isoerror import ISO8601Error
@ -147,7 +148,7 @@ def get_from_scraper(scrape, request):
if scrape.url:
recipe_json['url'] = scrape.url
recipe_json['recipeInstructions'] += "\n\nImported from " + scrape.url
recipe_json['recipeInstructions'] += "\n\n" + _("Imported from") + ": " + scrape.url
return recipe_json

View File

@ -4,6 +4,7 @@ from zipfile import ZipFile
from bs4 import BeautifulSoup
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_html_import import get_recipe_from_source
from cookbook.helper.recipe_url_import import iso_duration_to_minutes, parse_servings
@ -60,7 +61,7 @@ class CopyMeThat(Integration):
try:
if file.find("a", {"id": "original_link"}).text != '':
step.instruction += "\n\nImported from: " + file.find("a", {"id": "original_link"}).text
step.instruction += "\n\n" + _("Imported from") + ": " + file.find("a", {"id": "original_link"}).text
step.save()
except AttributeError:
pass

View File

@ -6,6 +6,7 @@ from zipfile import ZipFile
import requests
from django.utils.translation import gettext as _
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
@ -49,7 +50,7 @@ class RecetteTek(Integration):
# Append the original import url to the step (if it exists)
try:
if file['url'] != '':
step.instruction += '\n\nImported from: ' + file['url']
step.instruction += '\n\n' + _('Imported from') + ': ' + file['url']
step.save()
except Exception as e:
print(recipe.name, ': failed to import source url ', str(e))

View File

@ -4,6 +4,7 @@ from zipfile import ZipFile
from bs4 import BeautifulSoup
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import iso_duration_to_minutes, parse_servings
from cookbook.integration.integration import Integration
@ -59,7 +60,7 @@ class RecipeKeeper(Integration):
step.instruction += s.text + ' \n'
if file.find("span", {"itemprop": "recipeSource"}).text != '':
step.instruction += "\n\nImported from: " + file.find("span", {"itemprop": "recipeSource"}).text
step.instruction += "\n\n" + _("Imported from") + ": " + file.find("span", {"itemprop": "recipeSource"}).text
step.save()
recipe.steps.add(step)

View File

@ -337,7 +337,7 @@ class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerial
def create(self, validated_data):
name = validated_data.pop('name').strip()
space = validated_data.pop('space', self.context['request'].space)
obj, created = SupermarketCategory.objects.get_or_create(name__iexact=name, space=space, defaults=validated_data)
obj, created = SupermarketCategory.objects.get_or_create(name=name, space=space)
return obj
def update(self, instance, validated_data):

View File

@ -30,7 +30,7 @@
style="height:50%"
href="{% bookmarklet request %}"
title="{% trans 'Drag me to your bookmarks to import recipes from anywhere' %}">
<img src="{% static 'assets/favicon-16x16.png' %}">{% trans 'Bookmark Me!' %} </a>
<img src="{% static 'assets/favicon-16x16.png' %}" style="margin-right: 1em;">{% trans 'Bookmark Me!' %} </a>
</div>
<nav class="nav nav-pills flex-sm-row mb-2">
<a class="nav-link active" href="#nav-url" data-toggle="tab" role="tab" aria-controls="nav-url"
@ -50,11 +50,11 @@
<div class="tab-pane fade show active" id="nav-url" role="tabpanel">
<div class="btn-group btn-group-toggle mt-2" data-toggle="buttons">
<label class="btn btn-outline-info btn-sm active" @click="automatic=true">
<input type="radio" autocomplete="off" checked> Automatic
<input type="radio" autocomplete="off" checked> {% trans 'Automatic' %}
</label>
<label class="btn btn-outline-info btn-sm" @click="automatic=false">
<input type="radio" autocomplete="off"> Manual
<input type="radio" autocomplete="off"> {% trans 'Manual' %}
</label>
</div>
<div role="group" class="input-group mt-4">

View File

@ -65,8 +65,11 @@
:preserve-search="true"
:internal-search="false"
:limit="options_limit"
placeholder="Select Keyword"
tag-placeholder="Add Keyword"
:placeholder="$t('select_keyword')"
:tag-placeholder="$t('add_keyword')"
:select-label="$t('Select')"
:selected-label="$t('Selected')"
:deselect-label="$t('remove_selection')"
:taggable="true"
@tag="addKeyword"
label="label"
@ -76,6 +79,7 @@
:loading="keywords_loading"
@search-change="searchKeywords"
>
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
</multiselect>
</div>
</div>
@ -244,8 +248,10 @@
:clear-on-select="true"
:allow-empty="true"
:preserve-search="true"
placeholder="Select File"
select-label="Select"
:placeholder="$t('select_file')"
:select-label="$t('Select')"
:selected-label="$t('Selected')"
:deselect-label="$t('remove_selection')"
:id="'id_step_' + step.id + '_file'"
label="name"
track-by="name"
@ -254,6 +260,7 @@
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
@search-change="searchFiles"
>
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
</multiselect>
<b-input-group-append>
<b-button
@ -283,14 +290,17 @@
:preserve-search="true"
:internal-search="false"
:limit="options_limit"
placeholder="Select Recipe"
select-label="Select"
:placeholder="$t('select_recipe')"
:select-label="$t('Select')"
:selected-label="$t('Selected')"
:deselect-label="$t('remove_selection')"
:id="'id_step_' + step.id + '_recipe'"
:custom-label="(opt) => recipes.find((x) => x.id === opt).name"
:multiple="false"
:loading="recipes_loading"
@search-change="searchRecipes"
>
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
</multiselect>
</div>
</div>
@ -338,9 +348,11 @@
:preserve-search="true"
:internal-search="false"
:limit="options_limit"
placeholder="Select Unit"
tag-placeholder="Create"
select-label="Select"
:placeholder="$t('select_unit')"
:tag-placeholder="$t('Create')"
:select-label="$t('Select')"
:selected-label="$t('Selected')"
:deselect-label="$t('remove_selection')"
:taggable="true"
@tag="addUnitType"
:id="`unit_${step_index}_${index}`"
@ -350,6 +362,7 @@
:loading="units_loading"
@search-change="searchUnits"
>
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
</multiselect>
</div>
<div class="col-lg-4 col-md-6 small-padding" v-if="!ingredient.is_header">
@ -365,9 +378,11 @@
:preserve-search="true"
:internal-search="false"
:limit="options_limit"
placeholder="Select Food"
tag-placeholder="Create"
select-label="Select"
:placeholder="$t('select_food')"
:tag-placeholder="$t('Create')"
:select-label="$t('Select')"
:selected-label="$t('Selected')"
:deselect-label="$t('remove_selection')"
:taggable="true"
@tag="addFoodType"
:id="`ingredient_${step_index}_${index}`"
@ -377,6 +392,7 @@
:loading="foods_loading"
@search-change="searchFoods"
>
<template v-slot:noOptions>{{ $t("empty_list") }}</template>
</multiselect>
</div>
<div class="small-padding" v-bind:class="{ 'col-lg-4 col-md-6': !ingredient.is_header, 'col-lg-12 col-md-12': ingredient.is_header }">
@ -802,7 +818,7 @@ export default {
no_amount: false,
})
this.sortIngredients(step)
this.$nextTick(() => document.getElementById(`amount_${this.recipe.steps.indexOf(step)}_${step.ingredients.length - 1}`).focus())
this.$nextTick(() => document.getElementById(`amount_${this.recipe.steps.indexOf(step)}_${step.ingredients.length - 1}`).select())
},
removeIngredient: function (step, ingredient) {
if (confirm(this.$t("confirm_delete", { object: this.$t("Ingredient") }))) {

View File

@ -60,24 +60,24 @@
<b-popover target="id_settings_button" triggers="click" placement="bottom">
<b-tabs content-class="mt-1 text-nowrap" small>
<b-tab :title="$t('Settings')" active :title-link-class="['mx-0']">
<b-form-group v-bind:label="$t('Recently_Viewed')" label-for="popover-input-1" label-cols="6" class="mb-1">
<b-form-input type="number" v-model="ui.recently_viewed" id="popover-input-1" size="sm"></b-form-input>
<b-form-group v-bind:label="$t('Recently_Viewed')" label-for="popover-input-1" label-cols="8" class="mb-1">
<b-form-input type="number" v-model="ui.recently_viewed" id="popover-input-1" size="sm" class="mt-1"></b-form-input>
</b-form-group>
<b-form-group v-bind:label="$t('Recipes_per_page')" label-for="popover-input-page-count" label-cols="6" class="mb-1">
<b-form-input type="number" v-model="ui.page_size" id="popover-input-page-count" size="sm"></b-form-input>
<b-form-group v-bind:label="$t('Recipes_per_page')" label-for="popover-input-page-count" label-cols="8" class="mb-1">
<b-form-input type="number" v-model="ui.page_size" id="popover-input-page-count" size="sm" class="mt-1"></b-form-input>
</b-form-group>
<b-form-group v-bind:label="$t('Meal_Plan')" label-for="popover-input-2" label-cols="6" class="mb-1">
<b-form-checkbox switch v-model="ui.show_meal_plan" id="popover-input-2" size="sm"></b-form-checkbox>
<b-form-group v-bind:label="$t('Meal_Plan')" label-for="popover-input-2" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_meal_plan" id="popover-input-2" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-if="ui.show_meal_plan" v-bind:label="$t('Meal_Plan_Days')" label-for="popover-input-5" label-cols="6" class="mb-1">
<b-form-input type="number" v-model="ui.meal_plan_days" id="popover-input-5" size="sm"></b-form-input>
<b-form-group v-if="ui.show_meal_plan" v-bind:label="$t('Meal_Plan_Days')" label-for="popover-input-5" label-cols="8" class="mb-1">
<b-form-input type="number" v-model="ui.meal_plan_days" id="popover-input-5" size="sm" class="mt-1"></b-form-input>
</b-form-group>
<b-form-group v-bind:label="$t('Sort_by_new')" label-for="popover-input-3" label-cols="6" class="mb-1">
<b-form-checkbox switch v-model="ui.sort_by_new" id="popover-input-3" size="sm"></b-form-checkbox>
<b-form-group v-bind:label="$t('Sort_by_new')" label-for="popover-input-3" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.sort_by_new" id="popover-input-3" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<div class="row" style="margin-top: 1vh">
<div class="col-12">
@ -87,58 +87,58 @@
</b-tab>
<b-tab :title="$t('fields')" :title-link-class="['mx-0']">
<b-form-group v-bind:label="$t('show_keywords')" label-for="popover-show_keywords" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_keywords" id="popover-show_keywords" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_keywords" id="popover-show_keywords" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('show_foods')" label-for="popover-show_foods" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_foods" id="popover-show_foods" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_foods" id="popover-show_foods" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('show_books')" label-for="popover-input-show_books" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_books" id="popover-input-show_books" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_books" id="popover-input-show_books" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('show_rating')" label-for="popover-show_rating" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_rating" id="popover-show_rating" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_rating" id="popover-show_rating" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('show_units')" label-for="popover-show_units" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_units" id="popover-show_units" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_units" id="popover-show_units" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('show_filters')" label-for="popover-show_filters" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_filters" id="popover-show_filters" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_filters" id="popover-show_filters" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('show_sortby')" label-for="popover-show_sortby" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_sortby" id="popover-show_sortby" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_sortby" id="popover-show_sortby" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('times_cooked')" label-for="popover-show_timescooked" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_timescooked" id="popover-show_cooked" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_timescooked" id="popover-show_cooked" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('make_now')" label-for="popover-show_makenow" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_makenow" id="popover-show_makenow" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_makenow" id="popover-show_makenow" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('last_cooked')" label-for="popover-show_cookedon" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_cookedon" id="popover-show_cookedon" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_cookedon" id="popover-show_cookedon" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('last_viewed')" label-for="popover-show_viewedon" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_viewedon" id="popover-show_viewedon" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_viewedon" id="popover-show_viewedon" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('created_on')" label-for="popover-show_createdon" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_createdon" id="popover-show_createdon" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_createdon" id="popover-show_createdon" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-bind:label="$t('updatedon')" label-for="popover-show_updatedon" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.show_updatedon" id="popover-show_updatedon" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.show_updatedon" id="popover-show_updatedon" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
</b-tab>
<b-tab :title="$t('advanced')" :title-link-class="['mx-0']">
<b-form-group v-bind:label="$t('remember_search')" label-for="popover-rem-search" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.remember_search" id="popover-rem-search" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.remember_search" id="popover-rem-search" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-if="ui.remember_search" v-bind:label="$t('remember_hours')" label-for="popover-input-rem-hours" label-cols="8" class="mb-1">
<b-form-input type="number" v-model="ui.remember_hours" id="popover-rem-hours" size="sm"></b-form-input>
<b-form-input type="number" v-model="ui.remember_hours" id="popover-rem-hours" size="sm" class="mt-1"></b-form-input>
</b-form-group>
<b-form-group v-bind:label="$t('tree_select')" label-for="popover-input-treeselect" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.tree_select" id="popover-input-treeselect" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.tree_select" id="popover-input-treeselect" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
<b-form-group v-if="debug" v-bind:label="$t('sql_debug')" label-for="popover-input-sqldebug" label-cols="8" class="mb-1">
<b-form-checkbox switch v-model="ui.sql_debug" id="popover-input-sqldebug" size="sm"></b-form-checkbox>
<b-form-checkbox switch v-model="ui.sql_debug" id="popover-input-sqldebug" size="sm" class="mt-2"></b-form-checkbox>
</b-form-group>
</b-tab>
</b-tabs>
@ -231,7 +231,7 @@
@change="refreshData(false)"
class="shadow-none"
switch
style="width: 4em"
style="width: 5em"
>
<span class="text-uppercase" v-if="search.search_keywords[a].operator">{{ $t("or") }}</span>
<span class="text-uppercase" v-else>{{ $t("and") }}</span>
@ -293,7 +293,7 @@
/>
<b-input-group-append>
<b-input-group-text>
<b-form-checkbox v-model="search.search_foods[i].operator" name="check-button" @change="refreshData(false)" class="shadow-none" switch style="width: 4em">
<b-form-checkbox v-model="search.search_foods[i].operator" name="check-button" @change="refreshData(false)" class="shadow-none" switch style="width: 5em">
<span class="text-uppercase" v-if="search.search_foods[i].operator">{{ $t("or") }}</span>
<span class="text-uppercase" v-else>{{ $t("and") }}</span>
</b-form-checkbox>
@ -339,7 +339,7 @@
></generic-multiselect>
<b-input-group-append>
<b-input-group-text>
<b-form-checkbox v-model="search.search_books[i].operator" name="check-button" @change="refreshData(false)" class="shadow-none" style="width: 4em" switch>
<b-form-checkbox v-model="search.search_books[i].operator" name="check-button" @change="refreshData(false)" class="shadow-none" style="width: 5em" switch>
<span class="text-uppercase" v-if="search.search_books[i].operator">{{ $t("or") }}</span>
<span class="text-uppercase" v-else>{{ $t("and") }}</span>
</b-form-checkbox>
@ -371,7 +371,7 @@
/>
<b-input-group-append>
<b-input-group-text>
<b-form-checkbox v-model="search.search_rating_gte" name="check-button" @change="refreshData(false)" class="shadow-none" switch style="width: 4em">
<b-form-checkbox v-model="search.search_rating_gte" name="check-button" @change="refreshData(false)" class="shadow-none" switch style="width: 5em">
<span class="text-uppercase" v-if="search.search_rating_gte">&gt;=</span>
<span class="text-uppercase" v-else>&lt;=</span>
</b-form-checkbox>

View File

@ -249,7 +249,7 @@
"shopping_auto_sync_desc": "Bei 0 wird Auto-Sync deaktiviert. Beim Betrachten einer Einkaufsliste wird die Liste alle gesetzten Sekunden aktualisiert, um mögliche Änderungen anderer zu zeigen. Nützlich, wenn mehrere Personen einkaufen und mobile Daten nutzen.",
"MoveCategory": "Verschieben nach: ",
"mealplan_autoadd_shopping_desc": "Essensplan-Zutaten automatisch zur Einkaufsliste hinzufügen.",
"Pin": "Pin",
"Pin": "Anheften",
"mark_complete": "Vollständig markieren",
"shopping_add_onhand_desc": "Markiere Lebensmittel als \"Vorrätig\", wenn von der Einkaufsliste abgehakt wurden.",
"left_handed": "Linkshänder-Modus",
@ -335,5 +335,24 @@
"sort_by": "Sortiere nach",
"Random Recipes": "Zufällige Rezepte",
"recipe_filter": "Rezept-Filter",
"parameter_count": "Parameter {count}"
"parameter_count": "Parameter {count}",
"select_keyword": "Stichwort auswählen",
"add_keyword": "Stichwort hinzufügen",
"select_file": "Datei auswählen",
"select_recipe": "Rezept auswählen",
"select_unit": "Einheit wählen",
"select_food": "Zutat auswählen",
"remove_selection": "Abwählen",
"empty_list": "Liste ist leer.",
"Select": "Auswählen",
"Supermarkets": "Supermärkte",
"User": "Benutzer",
"Keyword": "Schlüsselwort",
"Advanced": "Erweitert",
"Substitutes": "Zusätze",
"copy_to_new": "Kopiere zu neuem Rezept",
"Page": "Seite",
"Reset": "Zurücksetzen",
"search_rank": "Such-Rang",
"paste_ingredients": "Zutaten einfügen"
}

View File

@ -361,5 +361,20 @@
"Internal": "Internal",
"Units": "Units",
"Random Recipes": "Random Recipes",
"parameter_count": "Parameter {count}"
"parameter_count": "Parameter {count}",
"select_keyword": "Select Keyword",
"add_keyword": "Add Keyword",
"select_file": "Select File",
"select_recipe": "Select Recipe",
"select_unit": "Select Unit",
"select_food": "Select Food",
"remove_selection": "Deselect",
"empty_list": "List is empty.",
"Select": "Select",
"Supermarkets": "Supermarkets",
"User": "User",
"Keyword": "Keyword",
"Advanced": "Advanced",
"Page": "Page",
"Reset": "Reset"
}