mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-21 22:13:31 -07:00
Merge branch 'mealie-next' into fix-500-error-on-recipe-share-link
This commit is contained in:
commit
5f576dc2c4
66 changed files with 47035 additions and 29218 deletions
114
.github/workflows/locale-sync.yml
vendored
Normal file
114
.github/workflows/locale-sync.yml
vendored
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
name: Automatic Locale Sync
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# Run every Sunday at 2 AM UTC
|
||||||
|
- cron: "0 2 * * 0"
|
||||||
|
workflow_dispatch:
|
||||||
|
# Allow manual triggering from the GitHub UI
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write # To checkout, commit, and push changes
|
||||||
|
pull-requests: write # To create pull requests
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync-locales:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
|
||||||
|
- name: Install Poetry
|
||||||
|
uses: snok/install-poetry@v1
|
||||||
|
with:
|
||||||
|
virtualenvs-create: true
|
||||||
|
virtualenvs-in-project: true
|
||||||
|
|
||||||
|
- name: Load cached venv
|
||||||
|
id: cached-poetry-dependencies
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: .venv
|
||||||
|
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
|
||||||
|
|
||||||
|
- name: Check venv cache
|
||||||
|
id: cache-validate
|
||||||
|
if: steps.cached-poetry-dependencies.outputs.cache-hit == 'true'
|
||||||
|
run: |
|
||||||
|
echo "import fastapi;print('venv good?')" > test.py && poetry run python test.py && echo "cache-hit-success=true" >> $GITHUB_OUTPUT
|
||||||
|
rm test.py
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install libsasl2-dev libldap2-dev libssl-dev
|
||||||
|
poetry install
|
||||||
|
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||||
|
|
||||||
|
- name: Run locale generation
|
||||||
|
run: |
|
||||||
|
cd dev/code-generation
|
||||||
|
poetry run python main.py locales
|
||||||
|
env:
|
||||||
|
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||||
|
|
||||||
|
- name: Check for changes
|
||||||
|
id: changes
|
||||||
|
run: |
|
||||||
|
if git diff --quiet; then
|
||||||
|
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Commit and create PR
|
||||||
|
if: steps.changes.outputs.has_changes == 'true'
|
||||||
|
run: |
|
||||||
|
# Configure git
|
||||||
|
git config --local user.email "action@github.com"
|
||||||
|
git config --local user.name "GitHub Action"
|
||||||
|
|
||||||
|
# Use the current branch as the base
|
||||||
|
BASE_BRANCH="${{ github.ref_name }}"
|
||||||
|
echo "Using base branch: $BASE_BRANCH"
|
||||||
|
|
||||||
|
# Create a new branch from the base branch
|
||||||
|
BRANCH_NAME="auto-locale-sync-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
git checkout -b "$BRANCH_NAME"
|
||||||
|
|
||||||
|
# Add and commit changes
|
||||||
|
git add .
|
||||||
|
git commit -m "chore: automatic locale sync"
|
||||||
|
|
||||||
|
# Push the branch
|
||||||
|
git push origin "$BRANCH_NAME"
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Create PR using GitHub CLI with explicit repository
|
||||||
|
gh pr create \
|
||||||
|
--repo "${{ github.repository }}" \
|
||||||
|
--title "chore: automatic locale sync" \
|
||||||
|
--base "$BASE_BRANCH" \
|
||||||
|
--head "$BRANCH_NAME" \
|
||||||
|
--body "## Summary
|
||||||
|
|
||||||
|
Automatically generated locale updates from the weekly sync job.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
- Updated frontend locale files
|
||||||
|
- Generated from latest translation sources" \
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: No changes detected
|
||||||
|
if: steps.changes.outputs.has_changes == 'false'
|
||||||
|
run: echo "No locale changes detected, skipping PR creation"
|
|
@ -70,7 +70,7 @@ tasks:
|
||||||
dev:generate:
|
dev:generate:
|
||||||
desc: run code generators
|
desc: run code generators
|
||||||
cmds:
|
cmds:
|
||||||
- poetry run python dev/code-generation/main.py
|
- poetry run python dev/code-generation/main.py {{ .CLI_ARGS }}
|
||||||
- task: py:format
|
- task: py:format
|
||||||
|
|
||||||
dev:services:
|
dev:services:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -13,7 +14,7 @@ from mealie.schema._mealie import MealieModel
|
||||||
|
|
||||||
BASE = pathlib.Path(__file__).parent.parent.parent
|
BASE = pathlib.Path(__file__).parent.parent.parent
|
||||||
|
|
||||||
API_KEY = dotenv.get_key(BASE / ".env", "CROWDIN_API_KEY")
|
API_KEY = dotenv.get_key(BASE / ".env", "CROWDIN_API_KEY") or os.environ.get("CROWDIN_API_KEY", "")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -23,19 +24,22 @@ class LocaleData:
|
||||||
|
|
||||||
|
|
||||||
LOCALE_DATA: dict[str, LocaleData] = {
|
LOCALE_DATA: dict[str, LocaleData] = {
|
||||||
"en-US": LocaleData(name="American English"),
|
|
||||||
"en-GB": LocaleData(name="British English"),
|
|
||||||
"af-ZA": LocaleData(name="Afrikaans (Afrikaans)"),
|
"af-ZA": LocaleData(name="Afrikaans (Afrikaans)"),
|
||||||
"ar-SA": LocaleData(name="العربية (Arabic)", dir="rtl"),
|
"ar-SA": LocaleData(name="العربية (Arabic)", dir="rtl"),
|
||||||
|
"bg-BG": LocaleData(name="Български (Bulgarian)"),
|
||||||
"ca-ES": LocaleData(name="Català (Catalan)"),
|
"ca-ES": LocaleData(name="Català (Catalan)"),
|
||||||
"cs-CZ": LocaleData(name="Čeština (Czech)"),
|
"cs-CZ": LocaleData(name="Čeština (Czech)"),
|
||||||
"da-DK": LocaleData(name="Dansk (Danish)"),
|
"da-DK": LocaleData(name="Dansk (Danish)"),
|
||||||
"de-DE": LocaleData(name="Deutsch (German)"),
|
"de-DE": LocaleData(name="Deutsch (German)"),
|
||||||
"el-GR": LocaleData(name="Ελληνικά (Greek)"),
|
"el-GR": LocaleData(name="Ελληνικά (Greek)"),
|
||||||
|
"en-GB": LocaleData(name="British English"),
|
||||||
|
"en-US": LocaleData(name="American English"),
|
||||||
"es-ES": LocaleData(name="Español (Spanish)"),
|
"es-ES": LocaleData(name="Español (Spanish)"),
|
||||||
|
"et-EE": LocaleData(name="Eesti (Estonian)"),
|
||||||
"fi-FI": LocaleData(name="Suomi (Finnish)"),
|
"fi-FI": LocaleData(name="Suomi (Finnish)"),
|
||||||
"fr-FR": LocaleData(name="Français (French)"),
|
|
||||||
"fr-BE": LocaleData(name="Belge (Belgian)"),
|
"fr-BE": LocaleData(name="Belge (Belgian)"),
|
||||||
|
"fr-CA": LocaleData(name="Français canadien (Canadian French)"),
|
||||||
|
"fr-FR": LocaleData(name="Français (French)"),
|
||||||
"gl-ES": LocaleData(name="Galego (Galician)"),
|
"gl-ES": LocaleData(name="Galego (Galician)"),
|
||||||
"he-IL": LocaleData(name="עברית (Hebrew)", dir="rtl"),
|
"he-IL": LocaleData(name="עברית (Hebrew)", dir="rtl"),
|
||||||
"hr-HR": LocaleData(name="Hrvatski (Croatian)"),
|
"hr-HR": LocaleData(name="Hrvatski (Croatian)"),
|
||||||
|
@ -53,6 +57,7 @@ LOCALE_DATA: dict[str, LocaleData] = {
|
||||||
"pt-PT": LocaleData(name="Português (Portuguese)"),
|
"pt-PT": LocaleData(name="Português (Portuguese)"),
|
||||||
"ro-RO": LocaleData(name="Română (Romanian)"),
|
"ro-RO": LocaleData(name="Română (Romanian)"),
|
||||||
"ru-RU": LocaleData(name="Pусский (Russian)"),
|
"ru-RU": LocaleData(name="Pусский (Russian)"),
|
||||||
|
"sk-SK": LocaleData(name="Slovenčina (Slovak)"),
|
||||||
"sl-SI": LocaleData(name="Slovenščina (Slovenian)"),
|
"sl-SI": LocaleData(name="Slovenščina (Slovenian)"),
|
||||||
"sr-SP": LocaleData(name="српски (Serbian)"),
|
"sr-SP": LocaleData(name="српски (Serbian)"),
|
||||||
"sv-SE": LocaleData(name="Svenska (Swedish)"),
|
"sv-SE": LocaleData(name="Svenska (Swedish)"),
|
||||||
|
@ -93,8 +98,8 @@ class CrowdinApi:
|
||||||
project_id = "451976"
|
project_id = "451976"
|
||||||
api_key = API_KEY
|
api_key = API_KEY
|
||||||
|
|
||||||
def __init__(self, api_key: str):
|
def __init__(self, api_key: str | None):
|
||||||
api_key = api_key
|
self.api_key = api_key or API_KEY
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def headers(self) -> dict:
|
def headers(self) -> dict:
|
||||||
|
@ -196,7 +201,7 @@ def inject_registration_validation_values():
|
||||||
|
|
||||||
|
|
||||||
def generate_locales_ts_file():
|
def generate_locales_ts_file():
|
||||||
api = CrowdinApi("")
|
api = CrowdinApi(None)
|
||||||
models = api.get_languages()
|
models = api.get_languages()
|
||||||
tmpl = Template(LOCALE_TEMPLATE)
|
tmpl = Template(LOCALE_TEMPLATE)
|
||||||
rendered = tmpl.render(locales=models)
|
rendered = tmpl.render(locales=models)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import argparse
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import gen_py_pytest_data_paths
|
import gen_py_pytest_data_paths
|
||||||
|
@ -11,15 +12,39 @@ CWD = Path(__file__).parent
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
items = [
|
parser = argparse.ArgumentParser(description="Run code generators")
|
||||||
(gen_py_schema_exports.main, "schema exports"),
|
parser.add_argument(
|
||||||
(gen_ts_types.main, "frontend types"),
|
"generators",
|
||||||
(gen_ts_locales.main, "locales"),
|
nargs="*",
|
||||||
(gen_py_pytest_data_paths.main, "test data paths"),
|
help="Specific generators to run (schema, types, locales, data-paths, routes). If none specified, all will run.", # noqa: E501 - long line
|
||||||
(gen_py_pytest_routes.main, "pytest routes"),
|
)
|
||||||
]
|
args = parser.parse_args()
|
||||||
|
|
||||||
for func, name in items:
|
# Define all available generators
|
||||||
|
all_generators = {
|
||||||
|
"schema": (gen_py_schema_exports.main, "schema exports"),
|
||||||
|
"types": (gen_ts_types.main, "frontend types"),
|
||||||
|
"locales": (gen_ts_locales.main, "locales"),
|
||||||
|
"data-paths": (gen_py_pytest_data_paths.main, "test data paths"),
|
||||||
|
"routes": (gen_py_pytest_routes.main, "pytest routes"),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine which generators to run
|
||||||
|
if args.generators:
|
||||||
|
# Validate requested generators
|
||||||
|
invalid_generators = [g for g in args.generators if g not in all_generators]
|
||||||
|
if invalid_generators:
|
||||||
|
log.error(f"Invalid generator(s): {', '.join(invalid_generators)}")
|
||||||
|
log.info(f"Available generators: {', '.join(all_generators.keys())}")
|
||||||
|
return
|
||||||
|
|
||||||
|
generators_to_run = [(all_generators[g][0], all_generators[g][1]) for g in args.generators]
|
||||||
|
else:
|
||||||
|
# Run all generators (default behavior)
|
||||||
|
generators_to_run = list(all_generators.values())
|
||||||
|
|
||||||
|
# Run the selected generators
|
||||||
|
for func, name in generators_to_run:
|
||||||
log.info(f"Generating {name}...")
|
log.info(f"Generating {name}...")
|
||||||
func()
|
func()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import logging
|
import logging
|
||||||
import re
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -35,7 +34,7 @@ class CodeSlicer:
|
||||||
start: int
|
start: int
|
||||||
end: int
|
end: int
|
||||||
|
|
||||||
indentation: str
|
indentation: str | None
|
||||||
text: list[str]
|
text: list[str]
|
||||||
|
|
||||||
_next_line = None
|
_next_line = None
|
||||||
|
@ -47,15 +46,24 @@ class CodeSlicer:
|
||||||
|
|
||||||
def push_line(self, string: str) -> None:
|
def push_line(self, string: str) -> None:
|
||||||
self._next_line = self._next_line or self.start + 1
|
self._next_line = self._next_line or self.start + 1
|
||||||
self.text.insert(self._next_line, self.indentation + string + "\n")
|
self.text.insert(self._next_line, (self.indentation or "") + string + "\n")
|
||||||
self._next_line += 1
|
self._next_line += 1
|
||||||
|
|
||||||
|
|
||||||
def get_indentation_of_string(line: str, comment_char: str = "//|#") -> str:
|
def get_indentation_of_string(line: str) -> str:
|
||||||
return re.sub(rf"{comment_char}.*", "", line).removesuffix("\n")
|
# Extract everything before the comment
|
||||||
|
if "//" in line:
|
||||||
|
indentation = line.split("//")[0]
|
||||||
|
elif "#" in line:
|
||||||
|
indentation = line.split("#")[0]
|
||||||
|
else:
|
||||||
|
indentation = line
|
||||||
|
|
||||||
|
# Keep only the whitespace, remove any non-whitespace characters
|
||||||
|
return "".join(c for c in indentation if c.isspace())
|
||||||
|
|
||||||
|
|
||||||
def find_start_end(file_text: list[str], gen_id: str) -> tuple[int, int, str]:
|
def find_start_end(file_text: list[str], gen_id: str) -> tuple[int, int, str | None]:
|
||||||
start = None
|
start = None
|
||||||
end = None
|
end = None
|
||||||
indentation = None
|
indentation = None
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
# {{ recipe.name }}
|
|
||||||
{{ recipe.description }}
|
|
||||||
|
|
||||||
## Ingredients
|
|
||||||
{% for ingredient in recipe.recipeIngredient %}
|
|
||||||
- [ ] {{ ingredient }} {% endfor %}
|
|
||||||
|
|
||||||
## Instructions
|
|
||||||
{% for step in recipe.recipeInstructions %}
|
|
||||||
- [ ] {{ step.text }} {% endfor %}
|
|
||||||
|
|
||||||
{% for note in recipe.notes %}
|
|
||||||
**{{ note.title }}:** {{ note.text }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Tags: {{ recipe.tags }}
|
|
||||||
Categories: {{ recipe.categories }}
|
|
||||||
Original URL: {{ recipe.orgURL }}
|
|
75
dev/scripts/convert_seed_files_to_new_format.py
Normal file
75
dev/scripts/convert_seed_files_to_new_format.py
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
|
||||||
|
def get_seed_locale_names() -> set[str]:
|
||||||
|
"""Find all locales in the seed/resources/ folder
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A set of every file name where there's both a seed label and seed food file
|
||||||
|
"""
|
||||||
|
|
||||||
|
LABELS_PATH = "/workspaces/mealie/mealie/repos/seed/resources/labels/locales/"
|
||||||
|
FOODS_PATH = "/workspaces/mealie/mealie/repos/seed/resources/foods/locales/"
|
||||||
|
label_locales = glob.glob("*.json", root_dir=LABELS_PATH)
|
||||||
|
foods_locales = glob.glob("*.json", root_dir=FOODS_PATH)
|
||||||
|
|
||||||
|
# ensure that a locale has both a label and a food seed file
|
||||||
|
return set(label_locales).intersection(foods_locales)
|
||||||
|
|
||||||
|
|
||||||
|
def get_labels_from_file(locale: str) -> list[str]:
|
||||||
|
"""Query a locale to get all of the labels so that they can be added to the new foods seed format
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
All of the labels found within the seed file for a given locale
|
||||||
|
"""
|
||||||
|
|
||||||
|
locale_path = pathlib.Path("/workspaces/mealie/mealie/repos/seed/resources/labels/locales/" + locale)
|
||||||
|
label_names = [label["name"] for label in json.loads(locale_path.read_text(encoding="utf-8"))]
|
||||||
|
return label_names
|
||||||
|
|
||||||
|
|
||||||
|
def transform_foods(locale: str):
|
||||||
|
"""
|
||||||
|
Convert the current food seed file for a locale into a new format which maps each food to a label
|
||||||
|
|
||||||
|
Existing format of foods seed file is a dictionary where each key is a food name and the values are a dictionary
|
||||||
|
of attributes such as name and plural_name
|
||||||
|
|
||||||
|
New format maps each food to a label. The top-level dictionary has each key as a label e.g. "Fruits".
|
||||||
|
Each label key as a value that is a dictionary with an element called "foods"
|
||||||
|
"Foods" is a dictionary of each food for that label, with a key of the english food name e.g. "baking-soda"
|
||||||
|
and a value of attributes, including the translated name of the item e.g. "bicarbonate of soda" for en-GB.
|
||||||
|
"""
|
||||||
|
|
||||||
|
locale_path = pathlib.Path("/workspaces/mealie/mealie/repos/seed/resources/foods/locales/" + locale)
|
||||||
|
|
||||||
|
with open(locale_path, encoding="utf-8") as infile:
|
||||||
|
data = json.load(infile)
|
||||||
|
|
||||||
|
first_value = next(iter(data.values()))
|
||||||
|
if isinstance(first_value, dict) and "foods" in first_value:
|
||||||
|
# Locale is already in the new format, skipping transformation
|
||||||
|
return
|
||||||
|
|
||||||
|
transformed_data = {"": {"foods": dict(data.items())}}
|
||||||
|
|
||||||
|
# Seeding for labels now pulls from the foods file and parses the labels from there (as top-level keys),
|
||||||
|
# thus we need to add all of the existing labels to the new food seed file and give them an empty foods dictionary
|
||||||
|
label_names = get_labels_from_file(locale)
|
||||||
|
for label in label_names:
|
||||||
|
transformed_data[label] = {"foods": {}}
|
||||||
|
|
||||||
|
with open(locale_path, "w", encoding="utf-8") as outfile:
|
||||||
|
json.dump(transformed_data, outfile, indent=4, ensure_ascii=False)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
for locale in get_seed_locale_names():
|
||||||
|
transform_foods(locale)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1052,8 +1052,8 @@
|
||||||
"foods": {
|
"foods": {
|
||||||
"merge-dialog-text": "Combining the selected foods will merge the source food and target food into a single food. The source food will be deleted and all of the references to the source food will be updated to point to the target food.",
|
"merge-dialog-text": "Combining the selected foods will merge the source food and target food into a single food. The source food will be deleted and all of the references to the source food will be updated to point to the target food.",
|
||||||
"merge-food-example": "Merging {food1} into {food2}",
|
"merge-food-example": "Merging {food1} into {food2}",
|
||||||
"seed-dialog-text": "Seed the database with foods based on your local language. This will create 200+ common foods that can be used to organize your database. Foods are translated via a community effort.",
|
"seed-dialog-text": "Seed the database with foods based on your local language. This will create ~2700 common foods that can be used to organize your database. Foods are translated via a community effort.",
|
||||||
"seed-dialog-warning": "You have already have some items in your database. This action will not reconcile duplicates, you will have to manage them manually.",
|
"seed-dialog-warning": "You already have some items in your database. A new item will not be added if an item with the same name already exists.",
|
||||||
"combine-food": "Combine Food",
|
"combine-food": "Combine Food",
|
||||||
"source-food": "Source Food",
|
"source-food": "Source Food",
|
||||||
"target-food": "Target Food",
|
"target-food": "Target Food",
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
CWD = Path(__file__).parent
|
|
||||||
|
|
||||||
recipes_markdown = CWD / "recipes.md"
|
|
|
@ -1,24 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
# {{ recipe.name }}
|
|
||||||
{{ recipe.description }}
|
|
||||||
|
|
||||||
## Ingredients
|
|
||||||
{% for ingredient in recipe.recipeIngredient %}
|
|
||||||
- [ ] {{ ingredient }} {% endfor %}
|
|
||||||
|
|
||||||
## Instructions
|
|
||||||
{% for step in recipe.recipeInstructions %}
|
|
||||||
- [ ] {{ step.text }} {% endfor %}
|
|
||||||
|
|
||||||
{% for note in recipe.notes %}
|
|
||||||
**{{ note.title }}:** {{ note.text }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Tags: {{ recipe.tags }}
|
|
||||||
Categories: {{ recipe.categories }}
|
|
||||||
Original URL: {{ recipe.orgURL }}
|
|
|
@ -1,8 +1,5 @@
|
||||||
import shutil
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from mealie.assets import templates
|
|
||||||
|
|
||||||
|
|
||||||
class AppDirectories:
|
class AppDirectories:
|
||||||
def __init__(self, data_dir: Path) -> None:
|
def __init__(self, data_dir: Path) -> None:
|
||||||
|
@ -38,9 +35,3 @@ class AppDirectories:
|
||||||
|
|
||||||
for dir in required_dirs:
|
for dir in required_dirs:
|
||||||
dir.mkdir(parents=True, exist_ok=True)
|
dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Bootstrap Templates
|
|
||||||
markdown_template = self.TEMPLATE_DIR.joinpath("recipes.md")
|
|
||||||
|
|
||||||
if not markdown_template.exists():
|
|
||||||
shutil.copyfile(templates.recipes_markdown, markdown_template)
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ TRANSLATIONS = CWD / "messages"
|
||||||
|
|
||||||
class Translator(Protocol):
|
class Translator(Protocol):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def t(self, key, default=None, **kwargs):
|
def t(self, key, default=None, **kwargs) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ from uuid import UUID
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
from pydantic import UUID4
|
from pydantic import UUID4
|
||||||
from slugify import slugify
|
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ from mealie.db.models.users.user_to_recipe import UserToRecipe
|
||||||
from mealie.db.models.users.users import User
|
from mealie.db.models.users.users import User
|
||||||
from mealie.schema.cookbook.cookbook import ReadCookBook
|
from mealie.schema.cookbook.cookbook import ReadCookBook
|
||||||
from mealie.schema.recipe import Recipe
|
from mealie.schema.recipe import Recipe
|
||||||
from mealie.schema.recipe.recipe import RecipeCategory, RecipePagination, RecipeSummary
|
from mealie.schema.recipe.recipe import RecipeCategory, RecipePagination, RecipeSummary, create_recipe_slug
|
||||||
from mealie.schema.recipe.recipe_ingredient import IngredientFood
|
from mealie.schema.recipe.recipe_ingredient import IngredientFood
|
||||||
from mealie.schema.recipe.recipe_suggestion import RecipeSuggestionQuery, RecipeSuggestionResponseItem
|
from mealie.schema.recipe.recipe_suggestion import RecipeSuggestionQuery, RecipeSuggestionResponseItem
|
||||||
from mealie.schema.recipe.recipe_tool import RecipeToolOut
|
from mealie.schema.recipe.recipe_tool import RecipeToolOut
|
||||||
|
@ -98,7 +97,7 @@ class RepositoryRecipes(HouseholdRepositoryGeneric[Recipe, RecipeModel]):
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
self.session.rollback()
|
self.session.rollback()
|
||||||
document.name = f"{original_name} ({i})"
|
document.name = f"{original_name} ({i})"
|
||||||
document.slug = slugify(document.name)
|
document.slug = create_recipe_slug(document.name)
|
||||||
|
|
||||||
if i >= max_retries:
|
if i >= max_retries:
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produkte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Graankosse": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vrugte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Groente": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vleis": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Seekos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Drinkgoed": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gebakte goedere": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Geblikte goedere": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Geurmiddels": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Soetgoed": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Suiwelprodukte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bevrore kosse": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gesondheidskos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Huishouding": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vleis produkte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Peuselhappies": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Speserye": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Lekkers": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Drank": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ander": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,692 +1,62 @@
|
||||||
{
|
{
|
||||||
"acorn-squash": {
|
"": {
|
||||||
"name": "acorn squash"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"alfalfa-sprouts": {
|
"خَضْراوات وفواكه": {
|
||||||
"name": "alfalfa sprouts"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"anchovies": {
|
"الحبوب": {
|
||||||
"name": "anchovies"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"apples": {
|
"آلفواكه": {
|
||||||
"name": "apple",
|
"foods": {}
|
||||||
"plural_name": "apples"
|
|
||||||
},
|
},
|
||||||
"artichoke": {
|
"الخضراوات": {
|
||||||
"name": "artichoke"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"arugula": {
|
"اللحوم": {
|
||||||
"name": "arugula"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"asparagus": {
|
"المأكولات البحرية": {
|
||||||
"name": "asparagus"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"avocado": {
|
"المشروبات": {
|
||||||
"name": "avocado",
|
"foods": {}
|
||||||
"plural_name": "avocado"
|
|
||||||
},
|
},
|
||||||
"bacon": {
|
"المخبوزات": {
|
||||||
"name": "bacon"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"baking-powder": {
|
"المعلبات": {
|
||||||
"name": "baking powder"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"baking-soda": {
|
"الباهرات": {
|
||||||
"name": "baking soda"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"baking-sugar": {
|
"الحَلْوَيَات": {
|
||||||
"name": "baking sugar"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"bar-sugar": {
|
"منتجات الألبان": {
|
||||||
"name": "bar sugar"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"basil": {
|
"الأطعمة المجمدة": {
|
||||||
"name": "basil"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"beans": {
|
"الأغذية الصحية": {
|
||||||
"name": "beans"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"bell-peppers": {
|
"المنزل": {
|
||||||
"name": "bell peppers",
|
"foods": {}
|
||||||
"plural_name": "bell peppers"
|
|
||||||
},
|
},
|
||||||
"blackberries": {
|
"منتجات اللحوم": {
|
||||||
"name": "blackberries"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"bok-choy": {
|
"الوجبات الخفيفة": {
|
||||||
"name": "bok choy"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"brassicas": {
|
"التوابل": {
|
||||||
"name": "brassicas"
|
"foods": {}
|
||||||
},
|
},
|
||||||
"bread": {
|
"أخرى": {
|
||||||
"name": "bread"
|
"foods": {}
|
||||||
},
|
|
||||||
"breadfruit": {
|
|
||||||
"name": "breadfruit"
|
|
||||||
},
|
|
||||||
"broccoflower": {
|
|
||||||
"name": "broccoflower"
|
|
||||||
},
|
|
||||||
"broccoli": {
|
|
||||||
"name": "broccoli"
|
|
||||||
},
|
|
||||||
"broccoli-rabe": {
|
|
||||||
"name": "broccoli rabe"
|
|
||||||
},
|
|
||||||
"broccolini": {
|
|
||||||
"name": "broccolini"
|
|
||||||
},
|
|
||||||
"brown-sugar": {
|
|
||||||
"name": "brown sugar"
|
|
||||||
},
|
|
||||||
"brussels-sprouts": {
|
|
||||||
"name": "brussels sprouts"
|
|
||||||
},
|
|
||||||
"butter": {
|
|
||||||
"name": "butter"
|
|
||||||
},
|
|
||||||
"butternut-pumpkin": {
|
|
||||||
"name": "butternut pumpkin"
|
|
||||||
},
|
|
||||||
"butternut-squash": {
|
|
||||||
"name": "butternut squash"
|
|
||||||
},
|
|
||||||
"cabbage": {
|
|
||||||
"name": "cabbage",
|
|
||||||
"plural_name": "cabbages"
|
|
||||||
},
|
|
||||||
"cactus-edible": {
|
|
||||||
"name": "cactus, edible"
|
|
||||||
},
|
|
||||||
"calabrese": {
|
|
||||||
"name": "calabrese"
|
|
||||||
},
|
|
||||||
"cane-sugar": {
|
|
||||||
"name": "cane sugar"
|
|
||||||
},
|
|
||||||
"cannabis": {
|
|
||||||
"name": "cannabis"
|
|
||||||
},
|
|
||||||
"capsicum": {
|
|
||||||
"name": "capsicum"
|
|
||||||
},
|
|
||||||
"caraway": {
|
|
||||||
"name": "caraway"
|
|
||||||
},
|
|
||||||
"carrot": {
|
|
||||||
"name": "carrot",
|
|
||||||
"plural_name": "carrots"
|
|
||||||
},
|
|
||||||
"caster-sugar": {
|
|
||||||
"name": "caster sugar"
|
|
||||||
},
|
|
||||||
"castor-sugar": {
|
|
||||||
"name": "castor sugar"
|
|
||||||
},
|
|
||||||
"catfish": {
|
|
||||||
"name": "catfish"
|
|
||||||
},
|
|
||||||
"cauliflower": {
|
|
||||||
"name": "cauliflower",
|
|
||||||
"plural_name": "cauliflowers"
|
|
||||||
},
|
|
||||||
"cayenne-pepper": {
|
|
||||||
"name": "cayenne pepper"
|
|
||||||
},
|
|
||||||
"celeriac": {
|
|
||||||
"name": "celery root"
|
|
||||||
},
|
|
||||||
"celery": {
|
|
||||||
"name": "celery"
|
|
||||||
},
|
|
||||||
"cereal-grains": {
|
|
||||||
"name": "cereal grains"
|
|
||||||
},
|
|
||||||
"chard": {
|
|
||||||
"name": "chard"
|
|
||||||
},
|
|
||||||
"cheese": {
|
|
||||||
"name": "cheese"
|
|
||||||
},
|
|
||||||
"chicory": {
|
|
||||||
"name": "chicory"
|
|
||||||
},
|
|
||||||
"chilli-peppers": {
|
|
||||||
"name": "chilli pepper",
|
|
||||||
"plural_name": "chilli peppers"
|
|
||||||
},
|
|
||||||
"chinese-leaves": {
|
|
||||||
"name": "chinese leaves"
|
|
||||||
},
|
|
||||||
"chives": {
|
|
||||||
"name": "chives"
|
|
||||||
},
|
|
||||||
"chocolate": {
|
|
||||||
"name": "chocolate"
|
|
||||||
},
|
|
||||||
"cilantro": {
|
|
||||||
"name": "cilantro"
|
|
||||||
},
|
|
||||||
"cinnamon": {
|
|
||||||
"name": "cinnamon"
|
|
||||||
},
|
|
||||||
"clarified-butter": {
|
|
||||||
"name": "clarified butter"
|
|
||||||
},
|
|
||||||
"coconut": {
|
|
||||||
"name": "coconut",
|
|
||||||
"plural_name": "coconuts"
|
|
||||||
},
|
|
||||||
"coconut-milk": {
|
|
||||||
"name": "coconut milk"
|
|
||||||
},
|
|
||||||
"cod": {
|
|
||||||
"name": "cod"
|
|
||||||
},
|
|
||||||
"coffee": {
|
|
||||||
"name": "coffee"
|
|
||||||
},
|
|
||||||
"collard-greens": {
|
|
||||||
"name": "collard greens"
|
|
||||||
},
|
|
||||||
"confectioners-sugar": {
|
|
||||||
"name": "confectioners' sugar"
|
|
||||||
},
|
|
||||||
"coriander": {
|
|
||||||
"name": "coriander"
|
|
||||||
},
|
|
||||||
"corn": {
|
|
||||||
"name": "corn",
|
|
||||||
"plural_name": "corns"
|
|
||||||
},
|
|
||||||
"corn-syrup": {
|
|
||||||
"name": "corn syrup"
|
|
||||||
},
|
|
||||||
"cottonseed-oil": {
|
|
||||||
"name": "cottonseed oil"
|
|
||||||
},
|
|
||||||
"courgette": {
|
|
||||||
"name": "courgette"
|
|
||||||
},
|
|
||||||
"cream-of-tartar": {
|
|
||||||
"name": "cream of tartar"
|
|
||||||
},
|
|
||||||
"cucumber": {
|
|
||||||
"name": "cucumber",
|
|
||||||
"plural_name": "cucumbers"
|
|
||||||
},
|
|
||||||
"cumin": {
|
|
||||||
"name": "cumin"
|
|
||||||
},
|
|
||||||
"daikon": {
|
|
||||||
"name": "daikon",
|
|
||||||
"plural_name": "daikons"
|
|
||||||
},
|
|
||||||
"dairy-products-and-dairy-substitutes": {
|
|
||||||
"name": "dairy products and dairy substitutes"
|
|
||||||
},
|
|
||||||
"dandelion": {
|
|
||||||
"name": "dandelion"
|
|
||||||
},
|
|
||||||
"demerara-sugar": {
|
|
||||||
"name": "demerara sugar"
|
|
||||||
},
|
|
||||||
"dough": {
|
|
||||||
"name": "dough"
|
|
||||||
},
|
|
||||||
"edible-cactus": {
|
|
||||||
"name": "edible cactus"
|
|
||||||
},
|
|
||||||
"eggplant": {
|
|
||||||
"name": "eggplant",
|
|
||||||
"plural_name": "eggplants"
|
|
||||||
},
|
|
||||||
"eggs": {
|
|
||||||
"name": "egg",
|
|
||||||
"plural_name": "eggs"
|
|
||||||
},
|
|
||||||
"endive": {
|
|
||||||
"name": "endive",
|
|
||||||
"plural_name": "endives"
|
|
||||||
},
|
|
||||||
"fats": {
|
|
||||||
"name": "fats"
|
|
||||||
},
|
|
||||||
"fava-beans": {
|
|
||||||
"name": "fava beans"
|
|
||||||
},
|
|
||||||
"fiddlehead": {
|
|
||||||
"name": "fiddlehead"
|
|
||||||
},
|
|
||||||
"fiddlehead-fern": {
|
|
||||||
"name": "fiddlehead fern",
|
|
||||||
"plural_name": "fiddlehead ferns"
|
|
||||||
},
|
|
||||||
"fish": {
|
|
||||||
"name": "fish"
|
|
||||||
},
|
|
||||||
"five-spice-powder": {
|
|
||||||
"name": "five spice powder"
|
|
||||||
},
|
|
||||||
"flour": {
|
|
||||||
"name": "flour"
|
|
||||||
},
|
|
||||||
"frisee": {
|
|
||||||
"name": "frisee"
|
|
||||||
},
|
|
||||||
"fructose": {
|
|
||||||
"name": "fructose"
|
|
||||||
},
|
|
||||||
"fruit": {
|
|
||||||
"name": "fruit"
|
|
||||||
},
|
|
||||||
"fruit-sugar": {
|
|
||||||
"name": "fruit sugar"
|
|
||||||
},
|
|
||||||
"ful": {
|
|
||||||
"name": "ful"
|
|
||||||
},
|
|
||||||
"garam-masala": {
|
|
||||||
"name": "garam masala"
|
|
||||||
},
|
|
||||||
"garlic": {
|
|
||||||
"name": "garlic",
|
|
||||||
"plural_name": "garlics"
|
|
||||||
},
|
|
||||||
"gem-squash": {
|
|
||||||
"name": "gem squash"
|
|
||||||
},
|
|
||||||
"ghee": {
|
|
||||||
"name": "ghee"
|
|
||||||
},
|
|
||||||
"giblets": {
|
|
||||||
"name": "giblets"
|
|
||||||
},
|
|
||||||
"ginger": {
|
|
||||||
"name": "ginger"
|
|
||||||
},
|
|
||||||
"grains": {
|
|
||||||
"name": "grains"
|
|
||||||
},
|
|
||||||
"granulated-sugar": {
|
|
||||||
"name": "granulated sugar"
|
|
||||||
},
|
|
||||||
"grape-seed-oil": {
|
|
||||||
"name": "grape seed oil"
|
|
||||||
},
|
|
||||||
"green-onion": {
|
|
||||||
"name": "green onion",
|
|
||||||
"plural_name": "green onions"
|
|
||||||
},
|
|
||||||
"heart-of-palm": {
|
|
||||||
"name": "heart of palm",
|
|
||||||
"plural_name": "heart of palms"
|
|
||||||
},
|
|
||||||
"hemp": {
|
|
||||||
"name": "قنب والعياذ بالله"
|
|
||||||
},
|
|
||||||
"herbs": {
|
|
||||||
"name": "herbs"
|
|
||||||
},
|
|
||||||
"honey": {
|
|
||||||
"name": "honey"
|
|
||||||
},
|
|
||||||
"isomalt": {
|
|
||||||
"name": "isomalt"
|
|
||||||
},
|
|
||||||
"jackfruit": {
|
|
||||||
"name": "jackfruit",
|
|
||||||
"plural_name": "jackfruits"
|
|
||||||
},
|
|
||||||
"jaggery": {
|
|
||||||
"name": "jaggery"
|
|
||||||
},
|
|
||||||
"jams": {
|
|
||||||
"name": "jams"
|
|
||||||
},
|
|
||||||
"jellies": {
|
|
||||||
"name": "jellies"
|
|
||||||
},
|
|
||||||
"jerusalem-artichoke": {
|
|
||||||
"name": "jerusalem artichoke"
|
|
||||||
},
|
|
||||||
"jicama": {
|
|
||||||
"name": "jicama"
|
|
||||||
},
|
|
||||||
"kale": {
|
|
||||||
"name": "kale"
|
|
||||||
},
|
|
||||||
"kohlrabi": {
|
|
||||||
"name": "kohlrabi"
|
|
||||||
},
|
|
||||||
"kumara": {
|
|
||||||
"name": "kumara"
|
|
||||||
},
|
|
||||||
"leavening-agents": {
|
|
||||||
"name": "leavening agents"
|
|
||||||
},
|
|
||||||
"leek": {
|
|
||||||
"name": "leek",
|
|
||||||
"plural_name": "leeks"
|
|
||||||
},
|
|
||||||
"legumes": {
|
|
||||||
"name": "legumes"
|
|
||||||
},
|
|
||||||
"lemongrass": {
|
|
||||||
"name": "lemongrass"
|
|
||||||
},
|
|
||||||
"lentils": {
|
|
||||||
"name": "lentils"
|
|
||||||
},
|
|
||||||
"lettuce": {
|
|
||||||
"name": "lettuce"
|
|
||||||
},
|
|
||||||
"liver": {
|
|
||||||
"name": "liver",
|
|
||||||
"plural_name": "livers"
|
|
||||||
},
|
|
||||||
"maize": {
|
|
||||||
"name": "maize"
|
|
||||||
},
|
|
||||||
"maple-syrup": {
|
|
||||||
"name": "maple syrup"
|
|
||||||
},
|
|
||||||
"meat": {
|
|
||||||
"name": "meat"
|
|
||||||
},
|
|
||||||
"milk": {
|
|
||||||
"name": "milk"
|
|
||||||
},
|
|
||||||
"mortadella": {
|
|
||||||
"name": "mortadella"
|
|
||||||
},
|
|
||||||
"mushroom": {
|
|
||||||
"name": "mushroom",
|
|
||||||
"plural_name": "mushrooms"
|
|
||||||
},
|
|
||||||
"mussels": {
|
|
||||||
"name": "mussels"
|
|
||||||
},
|
|
||||||
"nanaimo-bar-mix": {
|
|
||||||
"name": "nanaimo bar mix"
|
|
||||||
},
|
|
||||||
"nori": {
|
|
||||||
"name": "nori"
|
|
||||||
},
|
|
||||||
"nutmeg": {
|
|
||||||
"name": "nutmeg"
|
|
||||||
},
|
|
||||||
"nutritional-yeast-flakes": {
|
|
||||||
"name": "nutritional yeast flakes"
|
|
||||||
},
|
|
||||||
"nuts": {
|
|
||||||
"name": "nuts"
|
|
||||||
},
|
|
||||||
"octopuses": {
|
|
||||||
"name": "octopus",
|
|
||||||
"plural_name": "octopuses"
|
|
||||||
},
|
|
||||||
"oils": {
|
|
||||||
"name": "oils"
|
|
||||||
},
|
|
||||||
"okra": {
|
|
||||||
"name": "okra"
|
|
||||||
},
|
|
||||||
"olive": {
|
|
||||||
"name": "olive"
|
|
||||||
},
|
|
||||||
"olive-oil": {
|
|
||||||
"name": "olive oil"
|
|
||||||
},
|
|
||||||
"onion": {
|
|
||||||
"name": "onion"
|
|
||||||
},
|
|
||||||
"onion-family": {
|
|
||||||
"name": "onion family"
|
|
||||||
},
|
|
||||||
"orange-blossom-water": {
|
|
||||||
"name": "orange blossom water"
|
|
||||||
},
|
|
||||||
"oranges": {
|
|
||||||
"name": "orange",
|
|
||||||
"plural_name": "oranges"
|
|
||||||
},
|
|
||||||
"oregano": {
|
|
||||||
"name": "oregano"
|
|
||||||
},
|
|
||||||
"oysters": {
|
|
||||||
"name": "oysters"
|
|
||||||
},
|
|
||||||
"panch-puran": {
|
|
||||||
"name": "panch puran"
|
|
||||||
},
|
|
||||||
"paprika": {
|
|
||||||
"name": "paprika"
|
|
||||||
},
|
|
||||||
"parsley": {
|
|
||||||
"name": "parsley"
|
|
||||||
},
|
|
||||||
"parsnip": {
|
|
||||||
"name": "parsnip",
|
|
||||||
"plural_name": "parsnips"
|
|
||||||
},
|
|
||||||
"pear": {
|
|
||||||
"name": "pear",
|
|
||||||
"plural_name": "pears"
|
|
||||||
},
|
|
||||||
"peas": {
|
|
||||||
"name": "peas"
|
|
||||||
},
|
|
||||||
"pepper": {
|
|
||||||
"name": "pepper",
|
|
||||||
"plural_name": "peppers"
|
|
||||||
},
|
|
||||||
"pineapple": {
|
|
||||||
"name": "pineapple",
|
|
||||||
"plural_name": "pineapples"
|
|
||||||
},
|
|
||||||
"plantain": {
|
|
||||||
"name": "plantain",
|
|
||||||
"plural_name": "plantains"
|
|
||||||
},
|
|
||||||
"poppy-seeds": {
|
|
||||||
"name": "poppy seeds"
|
|
||||||
},
|
|
||||||
"potato": {
|
|
||||||
"name": "potato",
|
|
||||||
"plural_name": "potatoes"
|
|
||||||
},
|
|
||||||
"poultry": {
|
|
||||||
"name": "poultry"
|
|
||||||
},
|
|
||||||
"powdered-sugar": {
|
|
||||||
"name": "powdered sugar"
|
|
||||||
},
|
|
||||||
"pumpkin": {
|
|
||||||
"name": "pumpkin",
|
|
||||||
"plural_name": "pumpkins"
|
|
||||||
},
|
|
||||||
"pumpkin-seeds": {
|
|
||||||
"name": "pumpkin seeds"
|
|
||||||
},
|
|
||||||
"radish": {
|
|
||||||
"name": "radish",
|
|
||||||
"plural_name": "radishes"
|
|
||||||
},
|
|
||||||
"raw-sugar": {
|
|
||||||
"name": "raw sugar"
|
|
||||||
},
|
|
||||||
"refined-sugar": {
|
|
||||||
"name": "refined sugar"
|
|
||||||
},
|
|
||||||
"rice": {
|
|
||||||
"name": "rice"
|
|
||||||
},
|
|
||||||
"rice-flour": {
|
|
||||||
"name": "rice flour"
|
|
||||||
},
|
|
||||||
"rock-sugar": {
|
|
||||||
"name": "rock sugar"
|
|
||||||
},
|
|
||||||
"rum": {
|
|
||||||
"name": "rum"
|
|
||||||
},
|
|
||||||
"salmon": {
|
|
||||||
"name": "salmon"
|
|
||||||
},
|
|
||||||
"salt": {
|
|
||||||
"name": "salt"
|
|
||||||
},
|
|
||||||
"salt-cod": {
|
|
||||||
"name": "salt cod"
|
|
||||||
},
|
|
||||||
"scallion": {
|
|
||||||
"name": "scallion",
|
|
||||||
"plural_name": "scallions"
|
|
||||||
},
|
|
||||||
"seafood": {
|
|
||||||
"name": "seafood"
|
|
||||||
},
|
|
||||||
"seeds": {
|
|
||||||
"name": "seeds"
|
|
||||||
},
|
|
||||||
"sesame-seeds": {
|
|
||||||
"name": "sesame seeds"
|
|
||||||
},
|
|
||||||
"shallot": {
|
|
||||||
"name": "shallot",
|
|
||||||
"plural_name": "shallots"
|
|
||||||
},
|
|
||||||
"skate": {
|
|
||||||
"name": "skate"
|
|
||||||
},
|
|
||||||
"soda": {
|
|
||||||
"name": "soda"
|
|
||||||
},
|
|
||||||
"soda-baking": {
|
|
||||||
"name": "soda, baking"
|
|
||||||
},
|
|
||||||
"soybean": {
|
|
||||||
"name": "soybean"
|
|
||||||
},
|
|
||||||
"spaghetti-squash": {
|
|
||||||
"name": "spaghetti squash",
|
|
||||||
"plural_name": "spaghetti squashes"
|
|
||||||
},
|
|
||||||
"speck": {
|
|
||||||
"name": "speck"
|
|
||||||
},
|
|
||||||
"spices": {
|
|
||||||
"name": "spices"
|
|
||||||
},
|
|
||||||
"spinach": {
|
|
||||||
"name": "spinach"
|
|
||||||
},
|
|
||||||
"spring-onion": {
|
|
||||||
"name": "spring onion",
|
|
||||||
"plural_name": "spring onions"
|
|
||||||
},
|
|
||||||
"squash": {
|
|
||||||
"name": "squash",
|
|
||||||
"plural_name": "squashes"
|
|
||||||
},
|
|
||||||
"squash-family": {
|
|
||||||
"name": "squash family"
|
|
||||||
},
|
|
||||||
"stockfish": {
|
|
||||||
"name": "stockfish"
|
|
||||||
},
|
|
||||||
"sugar": {
|
|
||||||
"name": "sugar"
|
|
||||||
},
|
|
||||||
"sunchoke": {
|
|
||||||
"name": "sunchoke",
|
|
||||||
"plural_name": "sunchokes"
|
|
||||||
},
|
|
||||||
"sunflower-seeds": {
|
|
||||||
"name": "sunflower seeds"
|
|
||||||
},
|
|
||||||
"superfine-sugar": {
|
|
||||||
"name": "superfine sugar"
|
|
||||||
},
|
|
||||||
"sweet-potato": {
|
|
||||||
"name": "sweet potato",
|
|
||||||
"plural_name": "sweet potatoes"
|
|
||||||
},
|
|
||||||
"sweetcorn": {
|
|
||||||
"name": "sweetcorn",
|
|
||||||
"plural_name": "sweetcorns"
|
|
||||||
},
|
|
||||||
"sweeteners": {
|
|
||||||
"name": "sweeteners"
|
|
||||||
},
|
|
||||||
"tahini": {
|
|
||||||
"name": "tahini"
|
|
||||||
},
|
|
||||||
"taro": {
|
|
||||||
"name": "taro",
|
|
||||||
"plural_name": "taroes"
|
|
||||||
},
|
|
||||||
"teff": {
|
|
||||||
"name": "teff"
|
|
||||||
},
|
|
||||||
"tomato": {
|
|
||||||
"name": "tomato",
|
|
||||||
"plural_name": "tomatoes"
|
|
||||||
},
|
|
||||||
"trout": {
|
|
||||||
"name": "trout"
|
|
||||||
},
|
|
||||||
"tubers": {
|
|
||||||
"name": "tuber",
|
|
||||||
"plural_name": "tubers"
|
|
||||||
},
|
|
||||||
"tuna": {
|
|
||||||
"name": "tuna"
|
|
||||||
},
|
|
||||||
"turbanado-sugar": {
|
|
||||||
"name": "turbanado sugar"
|
|
||||||
},
|
|
||||||
"turnip": {
|
|
||||||
"name": "turnip",
|
|
||||||
"plural_name": "turnips"
|
|
||||||
},
|
|
||||||
"unrefined-sugar": {
|
|
||||||
"name": "unrefined sugar"
|
|
||||||
},
|
|
||||||
"vanilla": {
|
|
||||||
"name": "vanilla"
|
|
||||||
},
|
|
||||||
"vegetables": {
|
|
||||||
"name": "vegetables"
|
|
||||||
},
|
|
||||||
"watercress": {
|
|
||||||
"name": "watercress"
|
|
||||||
},
|
|
||||||
"watermelon": {
|
|
||||||
"name": "watermelon",
|
|
||||||
"plural_name": "watermelons"
|
|
||||||
},
|
|
||||||
"white-mushroom": {
|
|
||||||
"name": "white mushroom",
|
|
||||||
"plural_name": "white mushrooms"
|
|
||||||
},
|
|
||||||
"white-sugar": {
|
|
||||||
"name": "white sugar"
|
|
||||||
},
|
|
||||||
"xanthan-gum": {
|
|
||||||
"name": "xanthan gum"
|
|
||||||
},
|
|
||||||
"yam": {
|
|
||||||
"name": "yam",
|
|
||||||
"plural_name": "yams"
|
|
||||||
},
|
|
||||||
"yeast": {
|
|
||||||
"name": "yeast"
|
|
||||||
},
|
|
||||||
"zucchini": {
|
|
||||||
"name": "zucchini",
|
|
||||||
"plural_name": "zucchinis"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Пресни плодове&зеленчуци": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Зърнени култури": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Плодове": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Зеленчуци": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Месо": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Морски дарове": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Напитки": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Печива": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Консерви": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Допълнения": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Сладкарски изделия": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Млечни продукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Замразени храни": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Здравословни храни": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Домакинство": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Местни продукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Лека закуски": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Подправки": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Сладко": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Алкохол": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Други": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Producte fresc": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cereals": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruita": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Verdures": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Carn": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pescateria": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Begudes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Forn": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Conserves": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condiments": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Llepolies": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Productes lactis": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Congelats": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Menjars saludables": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Llar": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Productes càrnics": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Entremesos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Espècies": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dolços": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Celler": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Altres": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "cukety"
|
"plural_name": "cukety"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Ovoce a Zelenina": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zrna": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ovoce": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zelenina": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Maso": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mořské plody": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Nápoje": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pečené jídlo": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konzervované jídlo": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Koření": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cukrovinky": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mléčné Výrobky": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mražené Potraviny": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zdravá Strava": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Domácí": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Masné Výrobky": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Svačiny": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sladkosti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Jiné": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "agern squash"
|
"name": "agern squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "squash"
|
"plural_name": "squash"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Landbrugsprodukt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gryn": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frugter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grøntsager": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kød": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fisk og skaldyr": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Drikkevarer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bagværk": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dåsemad": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tilbehør": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konfekt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mejeriprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frostvarer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Helseprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Husholdning": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kødprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snacks": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Krydderier": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Søde sager": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Andet": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "Eichelkürbis"
|
"name": "Eichelkürbis"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "Zucchinis"
|
"plural_name": "Zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Obst & Gemüse": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Getreide": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Obst": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gemüse": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fleisch": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meeresfrüchte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Getränke": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Backwaren": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konserven": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gewürze": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konditorwaren": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Milchprodukte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tiefkühlware": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bio-Lebensmittel": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Haushalt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fleischprodukte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snacks": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Süßwaren": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sonstiges": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "βελανίδι σκουός"
|
"name": "βελανίδι σκουός"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "κολοκύθια"
|
"plural_name": "κολοκύθια"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Παραγωγής": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Σιτηρά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Φρούτα": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Λαχανικά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Κρέας": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Θαλασσινά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ποτά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Αρτοσκευάσματα": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Κονσερβοποιημένα Αγαθά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Καρυκεύματα": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ζαχαροπλαστική": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Γαλακτοκομικά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Κατεψυγμένα Τρόφιμα": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Υγιεινά τρόφιμα": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Νοικοκυριό": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Κρεατικά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Σνακ": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Μπαχαρικά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Γλυκά": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Αλκοόλ": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Άλλα": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "courgettes"
|
"plural_name": "courgettes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Fresh Produce": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grains": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vegetables": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Seafood": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Beverages": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Baked Goods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Canned Goods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condiments": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confectionery": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dairy Products": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frozen Foods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Health Foods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Household": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meat Products": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snacks": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Spices": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sweets": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Other": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "calabaza bellota"
|
"name": "calabaza bellota"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Frutas y verduras": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cereales": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frutas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Verduras": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pescado y marisco": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bebidas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Panadería y bollería": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Productos enlatados": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condimentos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Repostería": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Productos lácteos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimentos congelados": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimentos saludables": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Limpieza": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Productos cárnicos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Aperitivos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Especias": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dulces": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bodega": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Otros": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Toode": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Teraviljad": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Puuviljad": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Köögiviljad": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Liha": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mereannid": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Joogid": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Küpsetised": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konservid": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Maitseained": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kondiitritooted": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Piimatooted": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sügavkülmutatud toidud": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tervisetoidud": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Leibkond": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Lihatooted": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snäkid": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vürtsid": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Maiustused": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Muu": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"HeVi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Viljat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Hedelmät": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vihannekset": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Liha": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Merenelävät": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Juomat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Leivonnaiset": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Säilykkeet": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Maustekastikkeet": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konditoriatuotteet": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Maitotuotteet": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pakasteet": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Terveysruoka": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kotitalous": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Lihatuotteet": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Välipalat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mausteet": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Makeiset": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkoholi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Muu": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Céréales": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Légumes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Viande": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits de la mer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Boissons": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits cuisinés": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Conserves": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condiments": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confiseries": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits laitiers": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits surgelés": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits healthy": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Foyer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Viandes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Collations": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Épices": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sucrerie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcool": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Autre": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Céréales": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Légumes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Viande": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruits de mer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Boissons": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits cuisinés": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Conserves": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condiments": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confiseries": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits laitiers": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Aliments congelés": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Aliments Santé": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Foyer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Viandes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Collations": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Épices": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sucrerie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcool": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Autre": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "Courgeron"
|
"name": "Courgeron"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "Courgettes"
|
"plural_name": "Courgettes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Céréales": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Légumes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Viande": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits de la mer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Boissons": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits cuisinés": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Conserves": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condiments": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confiseries": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits laitiers": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits surgelés": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produits sains": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Foyer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Viandes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Collations": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Épices": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sucrerie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcool": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Autre": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "cabaza de landra"
|
"name": "cabaza de landra"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "cabaciñas"
|
"plural_name": "cabaciñas"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Froitas e verduras": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grans": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Froitas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vexetais": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Marisco": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bebidas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Padaría": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Latas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condimentos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Repostería": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Lácteos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Conxelados": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimentos saudables": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Casa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produtos cárnicos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Petiscos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Especias": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Doces": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Outros": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "דלעת ערמונים"
|
"name": "דלעת ערמונים"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "קישואים"
|
"plural_name": "קישואים"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"מוצר": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"דגנים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"פירות": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"ירקות": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"בשר": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"מאכלי ים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"משקאות": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"מאפים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"פחיות שימורים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"רטבים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"מתוקים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"מוצרי חלב": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"אוכל קפוא": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"אוכל בריאותי": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"משק בית": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"מוצרי בשר": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"חטיפים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"תבלינים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"ממתקים": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"אלכוהול": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"אחר": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Svježe namirnice": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Žitarice": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Voće": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Povrće": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meso": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Plodovi mora": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Piće": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pečeni proizvodi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konzervirani proizvodi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Začini": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konditorski proizvodi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mliječni proizvod": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Smrznuta hrana": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zdrava Hrana": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kućanstvo": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mesni proizvodi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grickalice": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Slatkiši": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ostalo": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "cukkinik"
|
"plural_name": "cukkinik"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Termesztett növények": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gabonafélék": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gyümölcsök": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zöldségek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Hús": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tenger gyümölcsei": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Italok": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Péksütemény": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konzervek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ételízesítők": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cukrászat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tejtermékek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fagyasztott Ételek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Egészséges Ételek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Háztartás": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Húskészítmények": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Nassolnivalók": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fűszerek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Édességek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Egyéb": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produce": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grains": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruits": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vegetables": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Seafood": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Beverages": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Baked Goods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Canned Goods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condiments": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confectionary": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dairy Products": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frozen Foods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Health Foods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Household": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meat Products": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snacks": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Spices": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sweets": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Other": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "zucca ghianda"
|
"name": "zucca ghianda"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchine"
|
"plural_name": "zucchine"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Prodotti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cereali": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frutta": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Verdure": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frutti di Mare": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bevande": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Prodotti da Forno": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cibi in Scatola": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condimenti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pasticceria": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Latticini": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimenti Congelati": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimenti Per La Salute": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Prodotti per la Casa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Prodotti Di Carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Spuntini": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Spezie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dolci": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Altro": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "どんぐりかぼちゃ"
|
"name": "どんぐりかぼちゃ"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "ズッキーニ"
|
"plural_name": "ズッキーニ"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"青果物": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"穀物": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"果物": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"野菜": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"肉": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"魚介類": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"飲料": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"焼き物": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"缶詰": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"調味料": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"砂糖菓子": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"乳製品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"冷凍食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"健康食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"家庭": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"食肉製品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"おやつ": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"香辛料": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"お菓子": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"お酒": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"その他": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produce": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"곡물": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"과일류": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"채소": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"육류": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"해산물": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"음료": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"제빵 음식": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Canned Goods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"조미료": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confectionary": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"유제품": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frozen Foods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Health Foods": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Household": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meat Products": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"간식": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sweets": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"주류": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"기타": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produktai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grūdai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vaisiai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Daržovės": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mėsa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Jūros gėrybės": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gėrimai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kepiniai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konservuoti produktai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Padažai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konditerijos gaminiai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pieno produktai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Šaldyti produktai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sveikas maistas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Buitinės prekės": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mėsos produktai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Užkandžiai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Prieskoniai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Saldumynai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkoholiniai gėrimai": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kita": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Gatavot": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Labība": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Augļi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dārzeņi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gaļa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Jūras veltes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dzērieni": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ceptas preces": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konservētas preces": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Garšvielas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konditorejas izstrādājumi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Piena produkti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Saldēti pārtikas produkti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Veselīga pārtika": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mājsaimniecība": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gaļas produkti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Uzkodas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Saldumi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohols": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cits": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "eikelpompoen"
|
"name": "eikelpompoen"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "courgettes"
|
"plural_name": "courgettes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Groenten en fruit": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Granen": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fruit": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Groenten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vlees": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zeevruchten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dranken": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gebakken producten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ingeblikt eten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Specerijen": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zoetigheden": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zuivelproducten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bevroren eten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gezond eten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Huishouden": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vleesproducten": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snacks": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kruiden": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snoepgoed": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Anders": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "vintersquash"
|
"name": "vintersquash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "squash"
|
"plural_name": "squash"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Jordbruksprodukt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Korn": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frukt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grønnsaker": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kjøtt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sjømat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Drikkevarer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bakevarer": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Hermetikk": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tilbehør": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konfekt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meieriprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frossen mat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Helsekost": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Husholdning": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kjøttprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Snacks": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Krydder": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Søtsaker": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Annet": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "dynia żołędziowa"
|
"name": "dynia żołędziowa"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "cukinie"
|
"plural_name": "cukinie"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Wyroby": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ziarna": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Owoce": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Warzywa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mięso": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Owoce morza": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Napoje": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Wyroby piekarnicze": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Wyroby puszkowe": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Geurmiddels": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Wyroby cukiernicze": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Nabiał": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mrożona żywność": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Żywność zdrowotna": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Wyroby gospodarstwa domowego": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produkty mięsne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Przekąski": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Przyprawy": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Słodycze": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Inne": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "abóbora-bolota"
|
"name": "abóbora-bolota"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "abobrinhas italianas"
|
"plural_name": "abobrinhas italianas"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Verdura": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grãos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frutas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Legumes": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frutos do mar": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bebidas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produtos cozidos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Enlatados": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condimentos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confeitaria": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Lacticínios": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimentos Congelados": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimentos saudáveis": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Casa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produtos de carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Lanches": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Temperos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Doces": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Álcool": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Outros": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produto": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grãos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frutas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Vegetais": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Marisco": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bebidas": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produtos de pastelaria": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Enlatados": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condimentos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Confeitaria": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Lacticínios": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Congelados": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimentos para Saúde": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Casa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produtos à base de carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Petiscos": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Especiarias": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Doces": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Álcool": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Outros": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "dovleac"
|
"name": "dovleac"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produs": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cereale": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fructe": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Legume": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fructe de Mare": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Băuturi": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produse coapte": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produse conservate": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Condimente": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cofetărie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produse lactate": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alimente congelate": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mâncare Sănătoasă": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gospodărie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Produse din carne": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gustări": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Dulciuri": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alcool": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Altele": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "цуккини"
|
"plural_name": "цуккини"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Свежие Овощи&фрукты": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Крупы": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Фрукты": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Овощи": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Мясо": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Морепродукты": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Напитки": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Выпечка": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Консервы": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Приправы": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Кондитерские изделия": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Молочные продукты": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Замороженные продукты": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Здоровая еда": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Домашняя": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Мясные продукты": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Закуски": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Специи": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Сладости": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Алкоголь": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Другое": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "žaluďová tekvica"
|
"name": "žaluďová tekvica"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "cukety"
|
"plural_name": "cukety"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Produkovať": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zrná": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ovocie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zelenina": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mäso": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Morské plody": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Nápoje": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pečivo": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konzervy": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Koreniny": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cukrovinky": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mliečne výrobky": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mrazené jedlá": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zdravé jedlá": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Domácnosť": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mäsové výrobky": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Občerstvenie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Korenie": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sladkosti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ostatné": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "želodova buča"
|
"name": "želodova buča"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "bučke"
|
"plural_name": "bučke"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Pridelek": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zrna": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sadje": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zelenjava": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meso": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Morska hrana": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pijače": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Pečene dobrote": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konzervirana hrana": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Začimbe": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Slaščičarna": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mlečni produkti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zmrznjena hrana": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Zdrava hrana": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gospodinjstvo": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mesni produkti": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Priboljški": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sladkarije": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Drugo": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Домаћи производи": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Житарице": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Воће": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Поврће": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Месо": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Морски плодови": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Пића": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Пецива": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Конзервирана храна": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Зачини": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Кондиторски производи": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Млечни производи": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Смрзнута храна": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Здрава храна": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Домаћинство": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Месни производи": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Грицкалице": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Слаткиши": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Алкохол": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Остало": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Jordbruksprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Spannmål": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Grönsaker": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kött": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Fisk- och skaldjur": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Drycker": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bakverk": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konserver": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Smaktillsatser": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konfektyr": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Mejeriprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Frysta livsmedel": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Hälsolivsmedel": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Hushåll": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Köttprodukter": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tilltugg": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kryddor": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sötsaker": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkohol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Övrigt": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Sebze-Meyve": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Hububat": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Meyveler": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sebzeler": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Et": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Deniz Ürünleri": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"İçecekler": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Unlu Mamüller": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Konserve Ürünleri": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Çeşniler": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Şekerleme": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Süt Ürünleri": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Donmuş Gıdalar": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sağlıklı Gıdalar": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Ev Halkı": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Et Ürünleri": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Atıştırmalıklar": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Baharatlar": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Tatlılar": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Alkol": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Diğer": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "гарбуз акорн"
|
"name": "гарбуз акорн"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "цукіні"
|
"plural_name": "цукіні"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Продукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Зерна": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Фрукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Овочі": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"М’ясо": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Морепродукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Напої": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Печені страви": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Консерви": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Приправи": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Солодощі": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Молочні продукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Заморожені продукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Здорова їжа": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Сім'я": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"М'ясні Продукти": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Закуски": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Спеції": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cолодощі": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Алкоголь": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Інше": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Rau củ": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Các loại hạt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Trái cây": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Thịt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Hải sản": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Đồ uống": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Bánh": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Đồ hộp": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Đồ gia vị": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Kẹo": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sản phẩm từ sữa": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Đồ đông lạnh": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Đồ tốt cho sức khỏe": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gia đình": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Sản phẩm thịt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Đồ ăn vặt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Gia vị": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Đồ ngọt": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Cồn": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"Khác": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,65 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"农产品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"谷物": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"水果": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"蔬菜": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"肉类": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"海鲜": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"饮料": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"烘焙食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"罐头食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"调味品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"糖果类": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"乳制品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"冷冻食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"健康食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"家庭": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"肉制品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"零食": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"甜食": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"酒类": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"其它": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"": {
|
||||||
|
"foods": {
|
||||||
"acorn-squash": {
|
"acorn-squash": {
|
||||||
"name": "acorn squash"
|
"name": "acorn squash"
|
||||||
},
|
},
|
||||||
|
@ -690,3 +692,68 @@
|
||||||
"plural_name": "zucchinis"
|
"plural_name": "zucchinis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"生產": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"穀物": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"水果": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"蔬菜": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"肉類": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"海鮮": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"飲料": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"烘培食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"罐頭食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"調料": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"甜品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"奶類": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"冷凍食物": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"健康食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"家庭": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"肉類食品": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"零食": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"香料": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"甜食": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"酒精類": {
|
||||||
|
"foods": {}
|
||||||
|
},
|
||||||
|
"其它": {
|
||||||
|
"foods": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,17 @@ import pathlib
|
||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
from mealie.schema.labels import MultiPurposeLabelSave
|
from mealie.schema.labels import MultiPurposeLabelOut, MultiPurposeLabelSave
|
||||||
from mealie.schema.recipe.recipe_ingredient import SaveIngredientFood, SaveIngredientUnit
|
from mealie.schema.recipe.recipe_ingredient import (
|
||||||
|
IngredientFood,
|
||||||
|
IngredientUnit,
|
||||||
|
SaveIngredientFood,
|
||||||
|
SaveIngredientUnit,
|
||||||
|
)
|
||||||
from mealie.services.group_services.labels_service import MultiPurposeLabelService
|
from mealie.services.group_services.labels_service import MultiPurposeLabelService
|
||||||
|
|
||||||
from ._abstract_seeder import AbstractSeeder
|
from ._abstract_seeder import AbstractSeeder
|
||||||
from .resources import foods, labels, units
|
from .resources import foods, units
|
||||||
|
|
||||||
|
|
||||||
class MultiPurposeLabelSeeder(AbstractSeeder):
|
class MultiPurposeLabelSeeder(AbstractSeeder):
|
||||||
|
@ -17,20 +22,24 @@ class MultiPurposeLabelSeeder(AbstractSeeder):
|
||||||
return MultiPurposeLabelService(self.repos)
|
return MultiPurposeLabelService(self.repos)
|
||||||
|
|
||||||
def get_file(self, locale: str | None = None) -> pathlib.Path:
|
def get_file(self, locale: str | None = None) -> pathlib.Path:
|
||||||
locale_path = self.resources / "labels" / "locales" / f"{locale}.json"
|
# Get the labels from the foods seed file now
|
||||||
return locale_path if locale_path.exists() else labels.en_US
|
locale_path = self.resources / "foods" / "locales" / f"{locale}.json"
|
||||||
|
return locale_path if locale_path.exists() else foods.en_US
|
||||||
|
|
||||||
|
def get_all_labels(self) -> list[MultiPurposeLabelOut]:
|
||||||
|
return self.repos.group_multi_purpose_labels.get_all()
|
||||||
|
|
||||||
def load_data(self, locale: str | None = None) -> Generator[MultiPurposeLabelSave, None, None]:
|
def load_data(self, locale: str | None = None) -> Generator[MultiPurposeLabelSave, None, None]:
|
||||||
file = self.get_file(locale)
|
file = self.get_file(locale)
|
||||||
|
|
||||||
seen_label_names = set()
|
current_label_names = {label.name for label in self.get_all_labels()}
|
||||||
for label in json.loads(file.read_text(encoding="utf-8")):
|
# load from the foods locale file and remove any empty strings
|
||||||
if label["name"] in seen_label_names:
|
seed_label_names = set(filter(None, json.loads(file.read_text(encoding="utf-8")).keys())) # type: set[str]
|
||||||
continue
|
# only seed new labels
|
||||||
|
to_seed_labels = seed_label_names - current_label_names
|
||||||
seen_label_names.add(label["name"])
|
for label in to_seed_labels:
|
||||||
yield MultiPurposeLabelSave(
|
yield MultiPurposeLabelSave(
|
||||||
name=label["name"],
|
name=label,
|
||||||
group_id=self.repos.group_id,
|
group_id=self.repos.group_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,10 +57,13 @@ class IngredientUnitsSeeder(AbstractSeeder):
|
||||||
locale_path = self.resources / "units" / "locales" / f"{locale}.json"
|
locale_path = self.resources / "units" / "locales" / f"{locale}.json"
|
||||||
return locale_path if locale_path.exists() else units.en_US
|
return locale_path if locale_path.exists() else units.en_US
|
||||||
|
|
||||||
|
def get_all_units(self) -> list[IngredientUnit]:
|
||||||
|
return self.repos.ingredient_units.get_all()
|
||||||
|
|
||||||
def load_data(self, locale: str | None = None) -> Generator[SaveIngredientUnit, None, None]:
|
def load_data(self, locale: str | None = None) -> Generator[SaveIngredientUnit, None, None]:
|
||||||
file = self.get_file(locale)
|
file = self.get_file(locale)
|
||||||
|
|
||||||
seen_unit_names = set()
|
seen_unit_names = {unit.name for unit in self.get_all_units()}
|
||||||
for unit in json.loads(file.read_text(encoding="utf-8")).values():
|
for unit in json.loads(file.read_text(encoding="utf-8")).values():
|
||||||
if unit["name"] in seen_unit_names:
|
if unit["name"] in seen_unit_names:
|
||||||
continue
|
continue
|
||||||
|
@ -80,20 +92,31 @@ class IngredientFoodsSeeder(AbstractSeeder):
|
||||||
locale_path = self.resources / "foods" / "locales" / f"{locale}.json"
|
locale_path = self.resources / "foods" / "locales" / f"{locale}.json"
|
||||||
return locale_path if locale_path.exists() else foods.en_US
|
return locale_path if locale_path.exists() else foods.en_US
|
||||||
|
|
||||||
|
def get_label(self, value: str) -> MultiPurposeLabelOut | None:
|
||||||
|
return self.repos.group_multi_purpose_labels.get_one(value, "name")
|
||||||
|
|
||||||
|
def get_all_foods(self) -> list[IngredientFood]:
|
||||||
|
return self.repos.ingredient_foods.get_all()
|
||||||
|
|
||||||
def load_data(self, locale: str | None = None) -> Generator[SaveIngredientFood, None, None]:
|
def load_data(self, locale: str | None = None) -> Generator[SaveIngredientFood, None, None]:
|
||||||
file = self.get_file(locale)
|
file = self.get_file(locale)
|
||||||
|
|
||||||
seed_foods_names = set()
|
# get all current unique foods
|
||||||
for food in json.loads(file.read_text(encoding="utf-8")).values():
|
seen_foods_names = {food.name for food in self.get_all_foods()}
|
||||||
if food["name"] in seed_foods_names:
|
for label, values in json.loads(file.read_text(encoding="utf-8")).items():
|
||||||
|
label_out = self.get_label(label)
|
||||||
|
|
||||||
|
for food_name, attributes in values["foods"].items():
|
||||||
|
if food_name in seen_foods_names:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
seed_foods_names.add(food["name"])
|
seen_foods_names.add(food_name)
|
||||||
yield SaveIngredientFood(
|
yield SaveIngredientFood(
|
||||||
group_id=self.repos.group_id,
|
group_id=self.repos.group_id,
|
||||||
name=food["name"],
|
name=attributes["name"],
|
||||||
plural_name=food.get("plural_name"),
|
plural_name=attributes.get("plural_name"),
|
||||||
description="",
|
description="", # description expected to be empty string by UnitFoodBase class
|
||||||
|
label_id=label_out.id if label_out and label_out.id else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
def seed(self, locale: str | None = None) -> None:
|
def seed(self, locale: str | None = None) -> None:
|
||||||
|
|
|
@ -32,7 +32,6 @@ class JSONBytes(JSONResponse):
|
||||||
class FormatResponse(BaseModel):
|
class FormatResponse(BaseModel):
|
||||||
jjson: list[str] = Field(..., alias="json")
|
jjson: list[str] = Field(..., alias="json")
|
||||||
zip: list[str]
|
zip: list[str]
|
||||||
jinja2: list[str]
|
|
||||||
|
|
||||||
|
|
||||||
class BaseRecipeController(BaseCrudController):
|
class BaseRecipeController(BaseCrudController):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import shutil
|
import shutil
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
from fastapi import File, HTTPException, UploadFile, status
|
from fastapi import File, HTTPException, UploadFile, status
|
||||||
from pydantic import UUID4
|
from pydantic import UUID4
|
||||||
|
@ -24,7 +25,10 @@ class UserImageController(BaseUserController):
|
||||||
"""Updates a User Image"""
|
"""Updates a User Image"""
|
||||||
with get_temporary_path() as temp_path:
|
with get_temporary_path() as temp_path:
|
||||||
assert_user_change_allowed(id, self.user, self.user)
|
assert_user_change_allowed(id, self.user, self.user)
|
||||||
temp_img = temp_path.joinpath(profile.filename)
|
|
||||||
|
# use a generated uuid and ignore the filename so we don't
|
||||||
|
# need to worry about sanitizing user inputs.
|
||||||
|
temp_img = temp_path.joinpath(str(uuid4()))
|
||||||
|
|
||||||
with temp_img.open("wb") as buffer:
|
with temp_img.open("wb") as buffer:
|
||||||
shutil.copyfileobj(profile.file, buffer)
|
shutil.copyfileobj(profile.file, buffer)
|
||||||
|
|
|
@ -36,6 +36,22 @@ from .recipe_step import RecipeStep
|
||||||
app_dirs = get_app_dirs()
|
app_dirs = get_app_dirs()
|
||||||
|
|
||||||
|
|
||||||
|
def create_recipe_slug(name: str, max_length: int = 250) -> str:
|
||||||
|
"""Generate a slug from a recipe name, truncating to a reasonable length.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The recipe name to create a slug from
|
||||||
|
max_length: Maximum length for the slug (default: 250)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A truncated slug string
|
||||||
|
"""
|
||||||
|
generated_slug = slugify(name)
|
||||||
|
if len(generated_slug) > max_length:
|
||||||
|
generated_slug = generated_slug[:max_length]
|
||||||
|
return generated_slug
|
||||||
|
|
||||||
|
|
||||||
class RecipeTag(MealieModel):
|
class RecipeTag(MealieModel):
|
||||||
id: UUID4 | None = None
|
id: UUID4 | None = None
|
||||||
group_id: UUID4 | None = None
|
group_id: UUID4 | None = None
|
||||||
|
@ -229,7 +245,7 @@ class Recipe(RecipeSummary):
|
||||||
if not info.data.get("name"):
|
if not info.data.get("name"):
|
||||||
return slug
|
return slug
|
||||||
|
|
||||||
return slugify(info.data["name"])
|
return create_recipe_slug(info.data["name"])
|
||||||
|
|
||||||
@field_validator("recipe_ingredient", mode="before")
|
@field_validator("recipe_ingredient", mode="before")
|
||||||
def validate_ingredients(recipe_ingredient):
|
def validate_ingredients(recipe_ingredient):
|
||||||
|
|
|
@ -9,7 +9,6 @@ from uuid import UUID, uuid4
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from fastapi import UploadFile
|
from fastapi import UploadFile
|
||||||
from slugify import slugify
|
|
||||||
|
|
||||||
from mealie.core import exceptions
|
from mealie.core import exceptions
|
||||||
from mealie.core.config import get_app_settings
|
from mealie.core.config import get_app_settings
|
||||||
|
@ -21,7 +20,7 @@ from mealie.repos.repository_factory import AllRepositories
|
||||||
from mealie.repos.repository_generic import RepositoryGeneric
|
from mealie.repos.repository_generic import RepositoryGeneric
|
||||||
from mealie.schema.household.household import HouseholdInDB, HouseholdRecipeUpdate
|
from mealie.schema.household.household import HouseholdInDB, HouseholdRecipeUpdate
|
||||||
from mealie.schema.openai.recipe import OpenAIRecipe
|
from mealie.schema.openai.recipe import OpenAIRecipe
|
||||||
from mealie.schema.recipe.recipe import CreateRecipe, Recipe
|
from mealie.schema.recipe.recipe import CreateRecipe, Recipe, create_recipe_slug
|
||||||
from mealie.schema.recipe.recipe_ingredient import RecipeIngredient
|
from mealie.schema.recipe.recipe_ingredient import RecipeIngredient
|
||||||
from mealie.schema.recipe.recipe_notes import RecipeNote
|
from mealie.schema.recipe.recipe_notes import RecipeNote
|
||||||
from mealie.schema.recipe.recipe_settings import RecipeSettings
|
from mealie.schema.recipe.recipe_settings import RecipeSettings
|
||||||
|
@ -332,7 +331,7 @@ class RecipeService(RecipeServiceBase):
|
||||||
|
|
||||||
new_name = dup_data.name if dup_data.name else old_recipe.name or ""
|
new_name = dup_data.name if dup_data.name else old_recipe.name or ""
|
||||||
new_recipe.id = uuid4()
|
new_recipe.id = uuid4()
|
||||||
new_recipe.slug = slugify(new_name)
|
new_recipe.slug = create_recipe_slug(new_name)
|
||||||
new_recipe.image = cache.cache_key.new_key() if old_recipe.image else None
|
new_recipe.image = cache.cache_key.new_key() if old_recipe.image else None
|
||||||
new_recipe.recipe_instructions = (
|
new_recipe.recipe_instructions = (
|
||||||
None
|
None
|
||||||
|
@ -447,7 +446,7 @@ class OpenAIRecipeService(RecipeServiceBase):
|
||||||
group_id=self.user.group_id,
|
group_id=self.user.group_id,
|
||||||
household_id=self.household.id,
|
household_id=self.household.id,
|
||||||
name=openai_recipe.name,
|
name=openai_recipe.name,
|
||||||
slug=slugify(openai_recipe.name),
|
slug=create_recipe_slug(openai_recipe.name),
|
||||||
description=openai_recipe.description,
|
description=openai_recipe.description,
|
||||||
recipe_yield=openai_recipe.recipe_yield,
|
recipe_yield=openai_recipe.recipe_yield,
|
||||||
total_time=openai_recipe.total_time,
|
total_time=openai_recipe.total_time,
|
||||||
|
|
|
@ -2,8 +2,6 @@ import enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from jinja2 import Template
|
|
||||||
|
|
||||||
from mealie.schema.recipe import Recipe
|
from mealie.schema.recipe import Recipe
|
||||||
from mealie.schema.recipe.recipe_image_types import RecipeImageTypes
|
from mealie.schema.recipe.recipe_image_types import RecipeImageTypes
|
||||||
from mealie.services._base_service import BaseService
|
from mealie.services._base_service import BaseService
|
||||||
|
@ -11,7 +9,6 @@ from mealie.services._base_service import BaseService
|
||||||
|
|
||||||
class TemplateType(str, enum.Enum):
|
class TemplateType(str, enum.Enum):
|
||||||
json = "json"
|
json = "json"
|
||||||
jinja2 = "jinja2"
|
|
||||||
zip = "zip"
|
zip = "zip"
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +29,6 @@ class TemplateService(BaseService):
|
||||||
Returns a list of all templates available to render.
|
Returns a list of all templates available to render.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
TemplateType.jinja2.value: [x.name for x in self.directories.TEMPLATE_DIR.iterdir() if x.is_file()],
|
|
||||||
TemplateType.json.value: ["raw"],
|
TemplateType.json.value: ["raw"],
|
||||||
TemplateType.zip.value: ["zip"],
|
TemplateType.zip.value: ["zip"],
|
||||||
}
|
}
|
||||||
|
@ -65,16 +61,13 @@ class TemplateService(BaseService):
|
||||||
Args:
|
Args:
|
||||||
t_type (TemplateType): The type of template to render
|
t_type (TemplateType): The type of template to render
|
||||||
recipe (Recipe): The recipe to render
|
recipe (Recipe): The recipe to render
|
||||||
template (str): The template to render **Required for Jinja2 Templates**
|
template (str): The template to render
|
||||||
"""
|
"""
|
||||||
t_type = self.template_type(template)
|
t_type = self.template_type(template)
|
||||||
|
|
||||||
if t_type == TemplateType.json:
|
if t_type == TemplateType.json:
|
||||||
return self._render_json(recipe)
|
return self._render_json(recipe)
|
||||||
|
|
||||||
if t_type == TemplateType.jinja2:
|
|
||||||
return self._render_jinja2(recipe, template)
|
|
||||||
|
|
||||||
if t_type == TemplateType.zip:
|
if t_type == TemplateType.zip:
|
||||||
return self._render_zip(recipe)
|
return self._render_zip(recipe)
|
||||||
|
|
||||||
|
@ -96,41 +89,8 @@ class TemplateService(BaseService):
|
||||||
|
|
||||||
return save_path
|
return save_path
|
||||||
|
|
||||||
def _render_jinja2(self, recipe: Recipe, j2_template: str | None = None) -> Path:
|
|
||||||
"""
|
|
||||||
Renders a Jinja2 Template in a temporary directory and returns
|
|
||||||
the path to the file.
|
|
||||||
"""
|
|
||||||
self.__check_temp(self._render_jinja2)
|
|
||||||
|
|
||||||
if j2_template is None:
|
|
||||||
raise ValueError("Template must be provided for method _render_jinja2")
|
|
||||||
|
|
||||||
j2_path: Path = self.directories.TEMPLATE_DIR / j2_template
|
|
||||||
|
|
||||||
if not j2_path.is_file():
|
|
||||||
raise FileNotFoundError(f"Template '{j2_path}' not found.")
|
|
||||||
|
|
||||||
with open(j2_path) as f:
|
|
||||||
template_text = f.read()
|
|
||||||
|
|
||||||
template = Template(template_text)
|
|
||||||
rendered_text = template.render(recipe=recipe.model_dump(by_alias=True))
|
|
||||||
|
|
||||||
save_name = f"{recipe.slug}{j2_path.suffix}"
|
|
||||||
|
|
||||||
if self.temp is None:
|
|
||||||
raise ValueError("Temporary directory must be provided for method _render_jinja2")
|
|
||||||
|
|
||||||
save_path = self.temp.joinpath(save_name)
|
|
||||||
|
|
||||||
with open(save_path, "w") as f:
|
|
||||||
f.write(rendered_text)
|
|
||||||
|
|
||||||
return save_path
|
|
||||||
|
|
||||||
def _render_zip(self, recipe: Recipe) -> Path:
|
def _render_zip(self, recipe: Recipe) -> Path:
|
||||||
self.__check_temp(self._render_jinja2)
|
self.__check_temp(self._render_zip)
|
||||||
|
|
||||||
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
|
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ def test_seed_invalid_locale(api_client: TestClient, unique_user: TestUser):
|
||||||
|
|
||||||
|
|
||||||
def test_seed_foods(api_client: TestClient, unique_user: TestUser):
|
def test_seed_foods(api_client: TestClient, unique_user: TestUser):
|
||||||
CREATED_FOODS = 214
|
CREATED_FOODS = 2687
|
||||||
database = unique_user.repos
|
database = unique_user.repos
|
||||||
|
|
||||||
# Check that the foods was created
|
# Check that the foods was created
|
||||||
|
@ -44,7 +44,7 @@ def test_seed_units(api_client: TestClient, unique_user: TestUser):
|
||||||
|
|
||||||
|
|
||||||
def test_seed_labels(api_client: TestClient, unique_user: TestUser):
|
def test_seed_labels(api_client: TestClient, unique_user: TestUser):
|
||||||
CREATED_LABELS = 21
|
CREATED_LABELS = 32
|
||||||
database = unique_user.repos
|
database = unique_user.repos
|
||||||
|
|
||||||
# Check that the foods was created
|
# Check that the foods was created
|
||||||
|
|
|
@ -99,7 +99,7 @@ def test_new_label_creates_list_labels_in_all_households(
|
||||||
|
|
||||||
|
|
||||||
def test_seed_label_creates_list_labels(api_client: TestClient, unique_user: TestUser):
|
def test_seed_label_creates_list_labels(api_client: TestClient, unique_user: TestUser):
|
||||||
CREATED_LABELS = 21
|
CREATED_LABELS = 32
|
||||||
database = unique_user.repos
|
database = unique_user.repos
|
||||||
|
|
||||||
# create a list with some labels
|
# create a list with some labels
|
||||||
|
|
|
@ -900,3 +900,50 @@ def test_get_cookbook_recipes(api_client: TestClient, unique_user: utils.TestUse
|
||||||
assert recipe.id in fetched_recipe_ids
|
assert recipe.id in fetched_recipe_ids
|
||||||
for recipe in other_recipes:
|
for recipe in other_recipes:
|
||||||
assert recipe.id not in fetched_recipe_ids
|
assert recipe.id not in fetched_recipe_ids
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_recipe_with_extremely_long_slug(api_client: TestClient, unique_user: TestUser):
|
||||||
|
"""Test creating a recipe with an extremely long name that would generate a very long slug.
|
||||||
|
This reproduces the issue where long slugs cause 500 internal server errors.
|
||||||
|
"""
|
||||||
|
# Create a recipe name that's extremely long like the one in the GitHub issue
|
||||||
|
long_recipe_name = "giallozafferano-on-instagram-il-piatto-vincente-di-simone-barlaam-medaglia-d-oro-e-d-argento-a-parigi-2024-paccheri-tricolore-se-ve-li-siete-persi-dovete-assolutamente-rimediare-lulugargari-ingredienti-paccheri-320-gr-spinacini-500-gr-nocciole-50-gr-ricotta-350-gr-olio-evo-q-b-limone-non-trattato-con-buccia-edibile-q-b-menta-q-b-peperoncino-fresco-q-b-10-pomodorini-ciliegino-preparazione-saltiamo-gli-spinaci-in-padella-lasciamo-raffreddare-e-frulliamo-insieme-a-ricotta-olio-sale-pepe-e-peperoncino-fresco-cuociamo-la-pasta-al-dente-e-mantechiamo-fuori-dal-fuoco-con-la-crema-tostiamo-a-parte-noci-o-nocciole-e-frulliamo-con-scorza-di-limone-impiattiamo-i-paccheri-con-qualche-spinacino-fresco-ciuffetti-di-ricotta-pomodorini-tagliati-in-4-e-la-polvere-di-nocciole-e-limone-buon-appetito-dmtc-pr-finp-nuotoparalimpico-giallozafferano-ricette-olimpiadi-paralimpiadi-atleti-simonebarlaam-cucina-paccheri-pasta-spinaci" # noqa: E501
|
||||||
|
|
||||||
|
# Create the recipe
|
||||||
|
response = api_client.post(api_routes.recipes, json={"name": long_recipe_name}, headers=unique_user.token)
|
||||||
|
assert response.status_code == 201
|
||||||
|
created_slug = json.loads(response.text)
|
||||||
|
|
||||||
|
assert created_slug is not None
|
||||||
|
assert len(created_slug) > 0
|
||||||
|
|
||||||
|
new_name = "Pasta"
|
||||||
|
response = api_client.patch(
|
||||||
|
api_routes.recipes_slug(created_slug), json={"name": new_name}, headers=unique_user.token
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
updated_recipe = json.loads(response.text)
|
||||||
|
assert updated_recipe["name"] == new_name
|
||||||
|
assert updated_recipe["slug"] == slugify(new_name)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_recipe_slug_length_validation(api_client: TestClient, unique_user: TestUser):
|
||||||
|
"""Test that recipe slugs are properly truncated to a reasonable length."""
|
||||||
|
very_long_name = "A" * 500 # 500 character name
|
||||||
|
|
||||||
|
response = api_client.post(api_routes.recipes, json={"name": very_long_name}, headers=unique_user.token)
|
||||||
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
created_slug = json.loads(response.text)
|
||||||
|
|
||||||
|
# The slug should be truncated to a reasonable length
|
||||||
|
# Using 250 characters as a reasonable limit, leaving room for collision suffixes
|
||||||
|
assert len(created_slug) <= 250
|
||||||
|
|
||||||
|
assert created_slug is not None
|
||||||
|
assert len(created_slug) > 0
|
||||||
|
|
||||||
|
response = api_client.get(api_routes.recipes_slug(created_slug), headers=unique_user.token)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
|
@ -18,28 +18,9 @@ def test_get_available_exports(api_client: TestClient, unique_user: TestUser) ->
|
||||||
|
|
||||||
as_json = response.json()
|
as_json = response.json()
|
||||||
|
|
||||||
assert "recipes.md" in as_json["jinja2"]
|
|
||||||
assert "raw" in as_json["json"]
|
assert "raw" in as_json["json"]
|
||||||
|
|
||||||
|
|
||||||
def test_render_jinja_template(api_client: TestClient, unique_user: TestUser) -> None:
|
|
||||||
# Create Recipe
|
|
||||||
recipe_name = random_string()
|
|
||||||
response = api_client.post(api_routes.recipes, json={"name": recipe_name}, headers=unique_user.token)
|
|
||||||
assert response.status_code == 201
|
|
||||||
slug = response.json()
|
|
||||||
|
|
||||||
# Render Template
|
|
||||||
response = api_client.get(
|
|
||||||
api_routes.recipes_slug_exports(slug) + "?template_name=recipes.md", headers=unique_user.token
|
|
||||||
)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
# Assert Template is Rendered Correctly
|
|
||||||
# TODO: More robust test
|
|
||||||
assert f"# {recipe_name}" in response.text
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_recipe_as_zip(api_client: TestClient, unique_user: TestUser) -> None:
|
def test_get_recipe_as_zip(api_client: TestClient, unique_user: TestUser) -> None:
|
||||||
# Create Recipe
|
# Create Recipe
|
||||||
recipe_name = random_string()
|
recipe_name = random_string()
|
||||||
|
@ -61,13 +42,3 @@ def test_get_recipe_as_zip(api_client: TestClient, unique_user: TestUser) -> Non
|
||||||
with zipfile.ZipFile(zip_file, "r") as zip_fp:
|
with zipfile.ZipFile(zip_file, "r") as zip_fp:
|
||||||
with zip_fp.open(f"{slug}.json") as json_fp:
|
with zip_fp.open(f"{slug}.json") as json_fp:
|
||||||
assert json.loads(json_fp.read())["name"] == recipe_name
|
assert json.loads(json_fp.read())["name"] == recipe_name
|
||||||
|
|
||||||
|
|
||||||
# TODO: Allow users to upload templates to their own directory
|
|
||||||
# def test_upload_template(api_client: TestClient, unique_user: TestUser) -> None:
|
|
||||||
# assert False
|
|
||||||
|
|
||||||
|
|
||||||
# # TODO: Allow users to upload templates to their own directory
|
|
||||||
# def test_delete_template(api_client: TestClient, unique_user: TestUser) -> None:
|
|
||||||
# assert False
|
|
||||||
|
|
|
@ -3,6 +3,5 @@ from mealie.services.recipe.template_service import TemplateService, TemplateTyp
|
||||||
|
|
||||||
def test_recipe_export_types() -> None:
|
def test_recipe_export_types() -> None:
|
||||||
ts = TemplateService()
|
ts = TemplateService()
|
||||||
assert ts.template_type("recipes.md") == TemplateType.jinja2.value
|
|
||||||
assert ts.template_type("raw") == TemplateType.json.value
|
assert ts.template_type("raw") == TemplateType.json.value
|
||||||
assert ts.template_type("zip") == TemplateType.zip.value
|
assert ts.template_type("zip") == TemplateType.zip.value
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue