Merge branch 'develop' into feature/unit-conversion

This commit is contained in:
vabene1111
2023-04-02 09:17:38 +02:00
8 changed files with 603 additions and 43 deletions

View File

@ -2,6 +2,7 @@
# when unset: 1 (true) - dont unset this, just for development
DEBUG=0
SQL_DEBUG=0
DEBUG_TOOLBAR=0
# HTTP port to bind to
# TANDOOR_PORT=8080

View File

@ -69,11 +69,13 @@ jobs:
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
if: github.secret_source == 'Actions'
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
if: github.secret_source == 'Actions'
with:
registry: ghcr.io
username: ${{ github.actor }}
@ -100,7 +102,7 @@ jobs:
context: .
file: ${{ matrix.dockerfile }}
pull: true
push: true
push: ${{ github.secret_source == 'Actions' }}
platforms: ${{ matrix.platforms }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -2,24 +2,54 @@ import json
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step
from cookbook.models import Ingredient, Recipe, Step, Keyword, Comment, CookLog
from django.utils.translation import gettext as _
class OpenEats(Integration):
def get_recipe_from_file(self, file):
recipe = Recipe.objects.create(name=file['name'].strip(), created_by=self.request.user, internal=True,
description = file['info']
description_max_length = Recipe._meta.get_field('description').max_length
if len(description) > description_max_length:
description = description[0:description_max_length]
recipe = Recipe.objects.create(name=file['name'].strip(), description=description, created_by=self.request.user, internal=True,
servings=file['servings'], space=self.request.space, waiting_time=file['cook_time'], working_time=file['prep_time'])
instructions = ''
if file["info"] != '':
instructions += file["info"]
if file["directions"] != '':
instructions += file["directions"]
if file["source"] != '':
instructions += file["source"]
instructions += '\n' + _('Recipe source:') + f'[{file["source"]}]({file["source"]})'
cuisine_keyword, created = Keyword.objects.get_or_create(name="Cuisine", space=self.request.space)
if file["cuisine"] != '':
keyword, created = Keyword.objects.get_or_create(name=file["cuisine"].strip(), space=self.request.space)
if created:
keyword.move(cuisine_keyword, pos="last-child")
recipe.keywords.add(keyword)
course_keyword, created = Keyword.objects.get_or_create(name="Course", space=self.request.space)
if file["course"] != '':
keyword, created = Keyword.objects.get_or_create(name=file["course"].strip(), space=self.request.space)
if created:
keyword.move(course_keyword, pos="last-child")
recipe.keywords.add(keyword)
for tag in file["tags"]:
keyword, created = Keyword.objects.get_or_create(name=tag.strip(), space=self.request.space)
recipe.keywords.add(keyword)
for comment in file['comments']:
Comment.objects.create(recipe=recipe, text=comment['text'], created_by=self.request.user)
CookLog.objects.create(recipe=recipe, rating=comment['rating'], created_by=self.request.user, space=self.request.space)
if file["photo"] != '':
recipe.image = f'recipes/openeats-import/{file["photo"]}'
recipe.save()
step = Step.objects.create(instruction=instructions, space=self.request.space,)
@ -38,6 +68,9 @@ class OpenEats(Integration):
recipe_json = json.loads(file.read())
recipe_dict = {}
ingredient_group_dict = {}
cuisine_group_dict = {}
course_group_dict = {}
tag_group_dict = {}
for o in recipe_json:
if o['model'] == 'recipe.recipe':
@ -50,11 +83,27 @@ class OpenEats(Integration):
'cook_time': o['fields']['cook_time'],
'servings': o['fields']['servings'],
'ingredients': [],
'photo': o['fields']['photo'],
'cuisine': o['fields']['cuisine'],
'course': o['fields']['course'],
'tags': o['fields']['tags'],
'comments': [],
}
if o['model'] == 'ingredient.ingredientgroup':
ingredient_group_dict[o['pk']] = o['fields']['recipe']
if o['model'] == 'recipe_groups.cuisine':
cuisine_group_dict[o['pk']] = o['fields']['title']
if o['model'] == 'recipe_groups.course':
course_group_dict[o['pk']] = o['fields']['title']
if o['model'] == 'recipe_groups.tag':
tag_group_dict[o['pk']] = o['fields']['title']
for o in recipe_json:
if o['model'] == 'rating.rating':
recipe_dict[o['fields']['recipe']]["comments"].append({
"text": o['fields']['comment'],
"rating": o['fields']['rating']
})
if o['model'] == 'ingredient.ingredient':
ingredient = {
'food': o['fields']['title'],
@ -63,6 +112,15 @@ class OpenEats(Integration):
}
recipe_dict[ingredient_group_dict[o['fields']['ingredient_group']]]['ingredients'].append(ingredient)
for k, r in recipe_dict.items():
if r["cuisine"] in cuisine_group_dict:
r["cuisine"] = cuisine_group_dict[r["cuisine"]]
if r["course"] in course_group_dict:
r["course"] = course_group_dict[r["course"]]
for index in range(len(r["tags"])):
if r["tags"][index] in tag_group_dict:
r["tags"][index] = tag_group_dict[r["tags"][index]]
return list(recipe_dict.values())
def get_file_from_recipe(self, recipe):

View File

@ -11,8 +11,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
"PO-Revision-Date: 2023-01-08 17:55+0000\n"
"Last-Translator: Joachim Weber <joachim.weber@gmx.de>\n"
"PO-Revision-Date: 2023-03-25 11:32+0000\n"
"Last-Translator: Matěj Kubla <matykubla@gmail.com>\n"
"Language-Team: Czech <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/cs/>\n"
"Language: cs\n"
@ -553,7 +553,7 @@ msgstr "Cesta musí být v následujícím formátu"
#: .\cookbook\templates\batch\monitor.html:27
msgid "Sync Now!"
msgstr "Zahájit synchronizaci"
msgstr "Zahájit synchronizaci!"
#: .\cookbook\templates\batch\waiting.html:4
#: .\cookbook\templates\batch\waiting.html:10
@ -1106,8 +1106,8 @@ msgid ""
"rel=\"noreferrer noopener\" target=\"_blank\">this one.</a>"
msgstr ""
"Ruční vytváření tabulek pomocí značek je složité. Doporučujeme použít "
"například <a href=\"https://www.tablesgenerator.com/markdown_tables\" "
"rel=\"noreferrer noopener\" target=\"_blank\">tento tabulkový editor</a>."
"například <a href=\"https://www.tablesgenerator.com/markdown_tables\" rel="
"\"noreferrer noopener\" target=\"_blank\">tento tabulkový editor.</a>"
#: .\cookbook\templates\markdown_info.html:155
#: .\cookbook\templates\markdown_info.html:157
@ -1256,22 +1256,36 @@ msgid ""
" "
msgstr ""
"\n"
" <p>Modul jídelníčku umožňuje plánovat jídlo pomocí receptů i poznámek.</p>\n"
" <p>Jednoduše vyberte recept ze seznamu naposledy navštívených receptů, nebo ho vyhledejte\n"
" s přetáhněte na požadovaný den v rozvrhu. Můžete také přidat poznámku s popiskem\n"
" a poté přetáhnout recept pro vytvoření plánu s vlatními popisky. Vytvořením samotné poznámky\n"
" je možné přetažením pole poznámky do rozvrhu.</p>\n"
" <p>Kliknutím na recept zobrazíte detailní náhled. Odtud lze také přidat položky\n"
" do nákupního seznamu. Do nákupního seznamu můžete také přidat všechny recepty na daný den\n"
" kliknutím na ikonu nákupního košíku na horní straně tabulky.</p>\n"
" <p>V běžnémípadě se jídelníček plánuje hromadně, proto můžete v nastavení definovat\n"
" se kterými uživateli si přejete jídelníčky sdílet.\n"
" <p>Modul jídelníčku umožňuje plánovat jídlo "
"pomocí receptů i poznámek.</p>\n"
" <p>Jednoduše vyberte recept ze seznamu naposledy "
"navštívených receptů, nebo ho vyhledejte\n"
" s přetáhněte na požadovaný den v rozvrhu. "
"Můžete také přidat poznámku s popiskem\n"
" a poté přetáhnout recept pro vytvoření plánu "
"s vlatními popisky. Vytvořem samotné poznámky\n"
" je možné přetažením pole poznámky do "
"rozvrhu.</p>\n"
" <p>Kliknutím na recept zobrazíte detailní "
"náhled. Odtud lze také přidat položky\n"
" do nákupního seznamu. Do nákupního seznamu "
"můžete také přidat všechny recepty na daný den\n"
" kliknutím na ikonu nákupního košíku na horní "
"straně tabulky.</p>\n"
" <p>V běžném případě se jídelníček plánuje "
"hromadně, proto můžete v nastavení definovat\n"
" se kterými uživateli si přejete jídelníčky "
"sdílet.\n"
" </p>\n"
" <p>Můžete také upravovat typy jídel, které si přejete naplánovat. Pokud budete sdílet jídelníček \n"
" <p>Můžete také upravovat typy jídel, které si "
"přejete naplánovat. Pokud budete sdílet jídelníček \n"
" s někým, kdo\n"
" má přidána jiná jídla, jeho typy jídel se objeví i ve vašem seznamu. Pro předcházení\n"
" má přidána jiná jídla, jeho typy jídel se "
"objeví i ve vašem seznamu. Pro předcházení\n"
" duplicitám (např. Ostatní, Jiná)\n"
" pojmenujte váš typ jídla stejně, jako uživatel se kterým své seznamy sdílíte. Tím budou seznamy sloučeny.</p>\n"
" pojmenujte váš typ jídla stejně, jako "
"uživatel se kterým své seznamy sdílíte. Tím budou seznamy\n"
" sloučeny.</p>\n"
" "
#: .\cookbook\templates\meal_plan_entry.html:6
@ -1333,12 +1347,12 @@ msgstr "Obrázek receptu"
#: .\cookbook\templates\recipes_table.html:46
#: .\cookbook\templates\url_import.html:55
msgid "Preparation time ca."
msgstr "Doba přípravy cca"
msgstr "Doba přípravy cca."
#: .\cookbook\templates\recipes_table.html:52
#: .\cookbook\templates\url_import.html:60
msgid "Waiting time ca."
msgstr "Doba čekání cca"
msgstr "Doba čekání cca."
#: .\cookbook\templates\recipes_table.html:55
msgid "External"
@ -1386,7 +1400,7 @@ msgid ""
" in the following examples:"
msgstr ""
"Použijte tajný klíč jako autorizační hlavičku definovanou slovním klíčem, "
"jak je uvedeno v následujících příkladech."
"jak je uvedeno v následujících příkladech:"
#: .\cookbook\templates\settings.html:94
msgid "or"
@ -1808,7 +1822,7 @@ msgstr "Import není pro tohoto poskytovatele implementován!"
#: .\cookbook\views\import_export.py:58
msgid "Exporting is not implemented for this provider"
msgstr "Eport není pro tohoto poskytovatele implementován!"
msgstr "Export není pro tohoto poskytovatele implementován!"
#: .\cookbook\views\lists.py:42
msgid "Import Log"
@ -1840,7 +1854,7 @@ msgstr "Komentář uložen!"
#: .\cookbook\views\views.py:152
msgid "This recipe is already linked to the book!"
msgstr "Tento recept už v kuchařce existuje."
msgstr "Tento recept už v kuchařce existuje!"
#: .\cookbook\views\views.py:158
msgid "Bookmark saved!"

View File

@ -1471,8 +1471,10 @@ def sync_all(request):
return redirect('list_recipe_import')
@api_view(['GET'])
# @schema(AutoSchema()) #TODO add proper schema
@permission_classes([CustomIsUser & CustomTokenHasReadWriteScope])
def share_link(request, pk):
if request.user.is_authenticated:
if request.space.allow_sharing and has_group_permission(request.user, ('user',)):
recipe = get_object_or_404(Recipe, pk=pk, space=request.space)
link = ShareLink.objects.create(recipe=recipe, created_by=request.user, space=request.space)
@ -1481,8 +1483,6 @@ def share_link(request, pk):
else:
return JsonResponse({'error': 'sharing_disabled'}, status=403)
return JsonResponse({'error': 'not_authenticated'}, status=403)
@group_required('user')
@ajax_request

View File

@ -178,7 +178,7 @@ This zip file can simply be imported into Tandoor.
OpenEats does not provide any way to export the data using the interface. Luckily it is relatively easy to export it from the command line.
You need to run the command `python manage.py dumpdata recipe ingredient` inside of the application api container.
If you followed the default installation method you can use the following command `docker-compose -f docker-prod.yml run --rm --entrypoint 'sh' api ./manage.py dumpdata recipe ingredient`.
This command might also work `docker exec -it openeats_api_1 ./manage.py dumpdata recipe ingredient > recipe_ingredients.json`
This command might also work `docker exec -it openeats_api_1 ./manage.py dumpdata recipe ingredient rating recipe_groups > recipe_ingredients.json`
Store the outputted json string in a `.json` file and simply import it using the importer. The file should look something like this
```json
@ -216,6 +216,8 @@ Store the outputted json string in a `.json` file and simply import it using the
```
To import your images you'll need to create the folder `openeats-import` in your Tandoor's `recipes` media folder (which is usually found inside `/opt/recipes/mediafiles`). After that you'll need to copy the `/code/site-media/upload` folder from the openeats API docker container to the `openeats` folder you created. You should now have the file path `/opt/recipes/mediafiles/recipes/openeats-import/upload/...` in Tandoor.
## Plantoeat
Plan to eat allows you to export a text file containing all your recipes. Simply upload that text file to Tandoor to import all recipes

View File

@ -25,6 +25,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = os.getenv('SECRET_KEY') if os.getenv('SECRET_KEY') else 'INSECURE_STANDARD_KEY_SET_IN_ENV'
DEBUG = bool(int(os.getenv('DEBUG', True)))
DEBUG_TOOLBAR = bool(int(os.getenv('DEBUG_TOOLBAR', True)))
SOCIAL_DEFAULT_ACCESS = bool(int(os.getenv('SOCIAL_DEFAULT_ACCESS', False)))
SOCIAL_DEFAULT_GROUP = os.getenv('SOCIAL_DEFAULT_GROUP', 'guest')
@ -158,7 +159,7 @@ MIDDLEWARE = [
'cookbook.helper.scope_middleware.ScopeMiddleware',
]
if DEBUG:
if DEBUG_TOOLBAR:
MIDDLEWARE += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
INSTALLED_APPS += ('debug_toolbar',)

482
vue/src/locales/cs.json Normal file
View File

@ -0,0 +1,482 @@
{
"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": "",
"warning_space_delete": "",
"food_inherit_info": "",
"facet_count_info": "",
"step_time_minutes": "",
"confirm_delete": "",
"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": "",
"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": "",
"Amount": "",
"Enable_Amount": "",
"Disable_Amount": "",
"Ingredient Editor": "",
"Description_Replace": "",
"Instruction_Replace": "",
"Auto_Sort": "",
"Auto_Sort_Help": "",
"Private_Recipe": "",
"Private_Recipe_Help": "",
"reusable_help_text": "",
"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": "",
"Copy Link": "",
"Copy Token": "",
"delete_confirmation": "",
"move_confirmation": "",
"merge_confirmation": "",
"create_rule": "",
"move_selection": "",
"merge_selection": "",
"Root": "",
"Ignore_Shopping": "",
"Shopping_Category": "",
"Shopping_Categories": "",
"Edit_Food": "",
"Move_Food": "",
"New_Food": "",
"Hide_Food": "",
"Food_Alias": "",
"Unit_Alias": "",
"Keyword_Alias": "",
"Delete_Food": "",
"No_ID": "",
"Meal_Plan_Days": "",
"merge_title": "",
"move_title": "",
"Food": "",
"Original_Text": "",
"Recipe_Book": "",
"del_confirmation_tree": "",
"delete_title": "",
"create_title": "",
"edit_title": "",
"Name": "",
"Type": "",
"Description": "",
"Recipe": "",
"tree_root": "",
"Icon": "",
"Unit": "",
"Decimals": "",
"Default_Unit": "",
"No_Results": "",
"New_Unit": "",
"Create_New_Shopping Category": "",
"Create_New_Food": "",
"Create_New_Keyword": "",
"Create_New_Unit": "",
"Create_New_Meal_Type": "",
"Create_New_Shopping_Category": "",
"and_up": "",
"and_down": "",
"Instructions": "",
"Unrated": "",
"Automate": "",
"Empty": "",
"Key_Ctrl": "",
"Key_Shift": "",
"Time": "",
"Text": "",
"Shopping_list": "",
"Added_by": "",
"Added_on": "",
"AddToShopping": "",
"IngredientInShopping": "",
"NotInShopping": "",
"OnHand": "",
"FoodOnHand": "",
"FoodNotOnHand": "",
"Undefined": "",
"Create_Meal_Plan_Entry": "",
"Edit_Meal_Plan_Entry": "",
"Title": "",
"Week": "",
"Month": "",
"Year": "",
"Planner": "",
"Planner_Settings": "",
"Period": "",
"Plan_Period_To_Show": "",
"Periods": "",
"Plan_Show_How_Many_Periods": "",
"Starting_Day": "",
"Meal_Types": "",
"Meal_Type": "",
"New_Entry": "",
"Clone": "",
"Drag_Here_To_Delete": "",
"Meal_Type_Required": "",
"Title_or_Recipe_Required": "",
"Color": "",
"New_Meal_Type": "",
"Use_Fractions": "",
"Use_Fractions_Help": "",
"AddFoodToShopping": "",
"RemoveFoodFromShopping": "",
"DeleteShoppingConfirm": "",
"IgnoredFood": "",
"Add_Servings_to_Shopping": "",
"Week_Numbers": "",
"Show_Week_Numbers": "",
"Export_As_ICal": "",
"Export_To_ICal": "",
"Cannot_Add_Notes_To_Shopping": "",
"Added_To_Shopping_List": "",
"Shopping_List_Empty": "",
"Next_Period": "",
"Previous_Period": "",
"Current_Period": "",
"Next_Day": "",
"Previous_Day": "",
"Inherit": "",
"InheritFields": "",
"FoodInherit": "",
"ShowUncategorizedFood": "",
"GroupBy": "",
"Language": "",
"Theme": "",
"SupermarketCategoriesOnly": "",
"MoveCategory": "",
"CountMore": "",
"IgnoreThis": "",
"DelayFor": "",
"Warning": "",
"NoCategory": "",
"InheritWarning": "",
"ShowDelayed": "",
"Completed": "",
"OfflineAlert": "",
"shopping_share": "",
"shopping_auto_sync": "",
"one_url_per_line": "",
"mealplan_autoadd_shopping": "",
"mealplan_autoexclude_onhand": "",
"mealplan_autoinclude_related": "",
"default_delay": "",
"plan_share_desc": "",
"shopping_share_desc": "",
"shopping_auto_sync_desc": "",
"mealplan_autoadd_shopping_desc": "",
"mealplan_autoexclude_onhand_desc": "",
"mealplan_autoinclude_related_desc": "",
"default_delay_desc": "",
"filter_to_supermarket": "",
"Coming_Soon": "",
"Auto_Planner": "",
"New_Cookbook": "",
"Hide_Keyword": "",
"Hour": "",
"Hours": "",
"Day": "",
"Days": "",
"Second": "",
"Seconds": "",
"Clear": "",
"Users": "",
"Invites": "",
"err_move_self": "",
"nothing": "",
"err_merge_self": "",
"show_sql": "",
"filter_to_supermarket_desc": "",
"CategoryName": "",
"SupermarketName": "",
"CategoryInstruction": "",
"shopping_recent_days_desc": "",
"shopping_recent_days": "",
"download_pdf": "",
"download_csv": "",
"csv_delim_help": "",
"csv_delim_label": "",
"SuccessClipboard": "",
"copy_to_clipboard": "",
"csv_prefix_help": "",
"csv_prefix_label": "",
"copy_markdown_table": "",
"in_shopping": "",
"DelayUntil": "",
"Pin": "",
"Unpin": "",
"PinnedConfirmation": "",
"UnpinnedConfirmation": "",
"mark_complete": "",
"QuickEntry": "",
"shopping_add_onhand_desc": "",
"shopping_add_onhand": "",
"related_recipes": "",
"today_recipes": "",
"sql_debug": "",
"remember_search": "",
"remember_hours": "",
"tree_select": "",
"OnHand_help": "",
"ignore_shopping_help": "",
"shopping_category_help": "",
"food_recipe_help": "",
"Foods": "",
"Account": "",
"Cosmetic": "",
"API": "",
"enable_expert": "",
"expert_mode": "",
"simple_mode": "",
"advanced": "",
"fields": "",
"show_keywords": "",
"show_foods": "",
"show_books": "",
"show_rating": "",
"show_units": "",
"show_filters": "",
"not": "",
"save_filter": "",
"filter_name": "",
"left_handed": "",
"left_handed_help": "",
"Custom Filter": "",
"shared_with": "",
"sort_by": "",
"asc": "",
"desc": "",
"date_viewed": "",
"last_cooked": "",
"times_cooked": "",
"date_created": "",
"show_sortby": "",
"search_rank": "",
"make_now": "",
"recipe_filter": "",
"book_filter_help": "",
"review_shopping": "",
"view_recipe": "",
"copy_to_new": "",
"recipe_name": "",
"paste_ingredients_placeholder": "",
"paste_ingredients": "",
"ingredient_list": "",
"explain": "",
"filter": "",
"Website": "",
"App": "",
"Message": "",
"Bookmarklet": "",
"Sticky_Nav": "",
"Sticky_Nav_Help": "",
"Nav_Color": "",
"Nav_Color_Help": "",
"Use_Kj": "",
"Comments_setting": "",
"click_image_import": "",
"no_more_images_found": "",
"import_duplicates": "",
"paste_json": "",
"Click_To_Edit": "",
"search_no_recipes": "",
"search_import_help_text": "",
"search_create_help_text": "",
"warning_duplicate_filter": "",
"reset_children": "",
"reset_children_help": "",
"reset_food_inheritance": "",
"reset_food_inheritance_info": "",
"substitute_help": "",
"substitute_siblings_help": "",
"substitute_children_help": "",
"substitute_siblings": "",
"substitute_children": "",
"SubstituteOnHand": "",
"ChildInheritFields": "",
"ChildInheritFields_help": "",
"InheritFields_help": "",
"show_ingredient_overview": "",
"Ingredient Overview": "",
"last_viewed": "",
"created_on": "",
"updatedon": "",
"Imported_From": "",
"advanced_search_settings": "",
"nothing_planned_today": "",
"no_pinned_recipes": "",
"Planned": "",
"Pinned": "",
"Imported": "",
"Quick actions": "",
"Ratings": "",
"Internal": "",
"Units": "",
"Manage_Emails": "",
"Change_Password": "",
"Social_Authentication": "",
"Random Recipes": "",
"parameter_count": "",
"select_keyword": "",
"add_keyword": "",
"select_file": "",
"select_recipe": "",
"select_unit": "",
"select_food": "",
"remove_selection": "",
"empty_list": "",
"Select": "",
"Supermarkets": "",
"User": "",
"Username": "",
"First_name": "",
"Last_name": "",
"Keyword": "",
"Advanced": "",
"Page": "",
"Single": "",
"Multiple": "",
"Reset": "",
"Disabled": "",
"Disable": "",
"Options": "",
"Create Food": "",
"create_food_desc": "",
"additional_options": "",
"Importer_Help": "",
"Documentation": "",
"Select_App_To_Import": "",
"Import_Supported": "",
"Export_Supported": "",
"Import_Not_Yet_Supported": "",
"Export_Not_Yet_Supported": "",
"Import_Result_Info": "",
"Recipes_In_Import": "",
"Toggle": "",
"Import_Error": "",
"Warning_Delete_Supermarket_Category": "",
"New_Supermarket": "",
"New_Supermarket_Category": "",
"Are_You_Sure": "",
"Valid Until": "",
"Split_All_Steps": "",
"Combine_All_Steps": "",
"Plural": "",
"plural_short": "",
"Use_Plural_Unit_Always": "",
"Use_Plural_Unit_Simple": "",
"Use_Plural_Food_Always": "",
"Use_Plural_Food_Simple": "",
"plural_usage_info": "",
"Create Recipe": "",
"Import Recipe": ""
}