Merge branch 'develop' into feature/vue3

# Conflicts:
#	requirements.txt
This commit is contained in:
vabene1111
2024-04-04 20:58:44 +02:00
11 changed files with 210 additions and 146 deletions

View File

@@ -13,7 +13,7 @@ jobs:
node-version: ["18"]
steps:
- uses: actions/checkout@v4
- uses: awalsh128/cache-apt-pkgs-action@v1.4.1
- uses: awalsh128/cache-apt-pkgs-action@v1.4.2
with:
packages: libsasl2-dev python3-dev libldap2-dev libssl-dev
version: 1.0

View File

@@ -6,6 +6,8 @@ RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg li
#Print all logs without buffering it.
ENV PYTHONUNBUFFERED 1
ENV DOCKER true
#This port will be used by gunicorn.
EXPOSE 8080
@@ -33,6 +35,12 @@ RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-de
#Copy project and execute it.
COPY . ./
# collect the static files
RUN /opt/recipes/venv/bin/python manage.py collectstatic_js_reverse
RUN /opt/recipes/venv/bin/python manage.py collectstatic --noinput
# copy the collected static files to a different location, so they can be moved into a potentially mounted volume
RUN mv /opt/recipes/staticfiles /opt/recipes/staticfiles-collect
# collect information from git repositories
RUN /opt/recipes/venv/bin/python version.py
# delete git repositories to reduce image size

11
boot.sh
View File

@@ -67,12 +67,21 @@ echo "Migrating database"
python manage.py migrate
echo "Generating static files"
if [[ "${DOCKER}" == "true" ]]; then
echo "Copying cached static files from docker build"
mkdir -p /opt/recipes/staticfiles
rm -rf /opt/recipes/staticfiles/*
mv /opt/recipes/staticfiles-collect/* /opt/recipes/staticfiles
rm -rf /opt/recipes/staticfiles-collect
else
echo "Collecting static files, this may take a while..."
python manage.py collectstatic_js_reverse
python manage.py collectstatic --noinput
echo "Done"
fi
chmod -R 755 /opt/recipes/mediafiles

View File

@@ -1,26 +1,35 @@
import logging
from logging import Logger
from typing import Dict, Tuple
from urllib.parse import urljoin
from homeassistant_api import Client, HomeassistantAPIError, Domain
from aiohttp import ClientError, request
from cookbook.connectors.connector import Connector
from cookbook.models import ShoppingListEntry, ConnectorConfig, Space
class HomeAssistant(Connector):
_domains_cache: dict[str, Domain]
_config: ConnectorConfig
_logger: Logger
_client: Client
def __init__(self, config: ConnectorConfig):
if not config.token or not config.url or not config.todo_entity:
raise ValueError("config for HomeAssistantConnector in incomplete")
self._domains_cache = dict()
if config.url[-1] != "/":
config.url += "/"
self._config = config
self._logger = logging.getLogger("connector.HomeAssistant")
self._client = Client(self._config.url, self._config.token, async_cache_session=False, use_async=True)
async def homeassistant_api_call(self, method: str, path: str, data: Dict) -> str:
headers = {
"Authorization": f"Bearer {self._config.token}",
"Content-Type": "application/json"
}
async with request(method, urljoin(self._config.url, path), headers=headers, json=data) as response:
response.raise_for_status()
return await response.json()
async def on_shopping_list_entry_created(self, space: Space, shopping_list_entry: ShoppingListEntry) -> None:
if not self._config.on_shopping_list_entry_created_enabled:
@@ -28,15 +37,17 @@ class HomeAssistant(Connector):
item, description = _format_shopping_list_entry(shopping_list_entry)
todo_domain = self._domains_cache.get('todo')
try:
if todo_domain is None:
todo_domain = await self._client.async_get_domain('todo')
self._domains_cache['todo'] = todo_domain
logging.debug(f"adding {item=} to {self._config.name}")
logging.debug(f"pushing {item} to {self._config.name}")
await todo_domain.add_item(entity_id=self._config.todo_entity, item=item)
except HomeassistantAPIError as err:
data = {
"entity_id": self._config.todo_entity,
"item": item,
"description": description,
}
try:
await self.homeassistant_api_call("POST", "services/todo/add_item", data)
except ClientError as err:
self._logger.warning(f"[HomeAssistant {self._config.name}] Received an exception from the api: {err=}, {type(err)=}")
async def on_shopping_list_entry_updated(self, space: Space, shopping_list_entry: ShoppingListEntry) -> None:
@@ -48,24 +59,31 @@ class HomeAssistant(Connector):
if not self._config.on_shopping_list_entry_deleted_enabled:
return
item, description = _format_shopping_list_entry(shopping_list_entry)
if not hasattr(shopping_list_entry._state.fields_cache, "food"):
# Sometimes the food foreign key is not loaded, and we cant load it from an async process
self._logger.debug("required property was not present in ShoppingListEntry")
return
item, _ = _format_shopping_list_entry(shopping_list_entry)
logging.debug(f"removing {item=} from {self._config.name}")
data = {
"entity_id": self._config.todo_entity,
"item": item,
}
todo_domain = self._domains_cache.get('todo')
try:
if todo_domain is None:
todo_domain = await self._client.async_get_domain('todo')
self._domains_cache['todo'] = todo_domain
logging.debug(f"deleting {item} from {self._config.name}")
await todo_domain.remove_item(entity_id=self._config.todo_entity, item=item)
except HomeassistantAPIError as err:
self._logger.warning(f"[HomeAssistant {self._config.name}] Received an exception from the api: {err=}, {type(err)=}")
await self.homeassistant_api_call("POST", "services/todo/remove_item", data)
except ClientError as err:
# This error will always trigger if the item is not present/found
self._logger.debug(f"[HomeAssistant {self._config.name}] Received an exception from the api: {err=}, {type(err)=}")
async def close(self) -> None:
await self._client.async_cache_session.close()
pass
def _format_shopping_list_entry(shopping_list_entry: ShoppingListEntry):
def _format_shopping_list_entry(shopping_list_entry: ShoppingListEntry) -> Tuple[str, str]:
item = shopping_list_entry.food.name
if shopping_list_entry.amount > 0:
item += f" ({shopping_list_entry.amount:.2f}".rstrip('0').rstrip('.')
@@ -76,10 +94,10 @@ def _format_shopping_list_entry(shopping_list_entry: ShoppingListEntry):
else:
item += ")"
description = "Imported by TandoorRecipes"
description = "From TandoorRecipes"
if shopping_list_entry.created_by.first_name and len(shopping_list_entry.created_by.first_name) > 0:
description += f", created by {shopping_list_entry.created_by.first_name}"
description += f", by {shopping_list_entry.created_by.first_name}"
else:
description += f", created by {shopping_list_entry.created_by.username}"
description += f", by {shopping_list_entry.created_by.username}"
return item, description

View File

@@ -14,8 +14,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-21 14:39+0100\n"
"PO-Revision-Date: 2023-09-25 09:59+0000\n"
"Last-Translator: Matias Laporte <laportematias+weblate@gmail.com>\n"
"PO-Revision-Date: 2024-03-27 19:02+0000\n"
"Last-Translator: Axel Breiterman <axelbreiterman@gmail.com>\n"
"Language-Team: Spanish <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/es/>\n"
"Language: es\n"
@@ -23,7 +23,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.15\n"
"X-Generator: Weblate 5.4.2\n"
#: .\cookbook\forms.py:45
msgid ""
@@ -97,14 +97,16 @@ msgid ""
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
"profile\">Long Lived Access Token</a> for your HomeAssistant instance"
msgstr ""
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
"profile\">Token de larga duración</a>para tu instancia de HomeAssistant"
#: .\cookbook\forms.py:193
msgid "Something like http://homeassistant.local:8123/api"
msgstr ""
msgstr "Algo similar a http://homeassistant.local:8123/api"
#: .\cookbook\forms.py:205
msgid "http://homeassistant.local:8123/api for example"
msgstr ""
msgstr "por ejemplo http://homeassistant.local:8123/api for example"
#: .\cookbook\forms.py:222 .\cookbook\views\edit.py:117
msgid "Storage"
@@ -279,7 +281,7 @@ msgstr "Ha alcanzado el número máximo de recetas para su espacio."
#: .\cookbook\helper\permission_helper.py:414
msgid "You have more users than allowed in your space."
msgstr ""
msgstr "Tenés mas usuarios que los permitidos en tu espacio"
#: .\cookbook\helper\recipe_url_import.py:304
#, fuzzy
@@ -309,7 +311,7 @@ msgstr "fermentar"
#: .\cookbook\helper\recipe_url_import.py:310
msgid "sous-vide"
msgstr ""
msgstr "sous-vide"
#: .\cookbook\helper\shopping_helper.py:150
msgid "You must supply a servings size"
@@ -318,7 +320,7 @@ msgstr "Debe proporcionar un tamaño de porción"
#: .\cookbook\helper\template_helper.py:95
#: .\cookbook\helper\template_helper.py:97
msgid "Could not parse template code."
msgstr ""
msgstr "No se pudo parsear el código de la planitlla."
#: .\cookbook\integration\copymethat.py:44
#: .\cookbook\integration\melarecipes.py:37
@@ -342,6 +344,8 @@ msgid ""
"An unexpected error occurred during the import. Please make sure you have "
"uploaded a valid file."
msgstr ""
"Ocurrió un error inesperado al importar. Por favor asegurate de haber subido "
"un archivo válido."
#: .\cookbook\integration\integration.py:217
msgid "The following recipes were ignored because they already existed:"
@@ -457,7 +461,7 @@ msgstr "Calorías"
#: .\cookbook\migrations\0190_auto_20230525_1506.py:20
msgid "kcal"
msgstr ""
msgstr "kcal"
#: .\cookbook\models.py:325
msgid ""

View File

@@ -11,8 +11,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-21 14:39+0100\n"
"PO-Revision-Date: 2024-03-03 23:19+0000\n"
"Last-Translator: M Ugur <mugurd@gmail.com>\n"
"PO-Revision-Date: 2024-04-01 22:04+0000\n"
"Last-Translator: atom karinca <atomkarinca@tutanota.com>\n"
"Language-Team: Turkish <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/tr/>\n"
"Language: tr\n"
@@ -20,7 +20,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Weblate 4.15\n"
"X-Generator: Weblate 5.4.2\n"
#: .\cookbook\forms.py:45
msgid ""
@@ -63,42 +63,48 @@ msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
msgstr ""
"Varolan tariflerden benzer isimli olanlar mükerrerliği engellemek için "
"gözardı edilecektir. Tümünü içeri aktarmak için bu kutucuğu işaretleyin."
#: .\cookbook\forms.py:143
msgid "Add your comment: "
msgstr ""
msgstr "Yorum ekleyin: "
#: .\cookbook\forms.py:151
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
msgstr "Dropbox için boş bırakın ve Nextcloud için uygulama şifresini girin."
#: .\cookbook\forms.py:154
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr ""
msgstr "Nextcloud için boş bırakın ve Dropbox için API anahtarını girin."
#: .\cookbook\forms.py:160
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
msgstr ""
"Dropbox için boş bırakın ve Nextcloud için yalnızca ana URL'yi "
"girin(<code>/remote.php/webdav/</code> otomatik olarak eklenir)"
#: .\cookbook\forms.py:188
msgid ""
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
"profile\">Long Lived Access Token</a> for your HomeAssistant instance"
msgstr ""
"HomeAssistant uygulamanız için <a href=\"https://www.home-assistant.io/docs/"
"authentication/#your-account-profile\">Uzun Süreli Erişim Anahtarı</a>"
#: .\cookbook\forms.py:193
msgid "Something like http://homeassistant.local:8123/api"
msgstr ""
msgstr "Örneğin http://homeassistant.local:8123/api"
#: .\cookbook\forms.py:205
msgid "http://homeassistant.local:8123/api for example"
msgstr ""
msgstr "http://homeassistant.local:8123/api örneğin"
#: .\cookbook\forms.py:222 .\cookbook\views\edit.py:117
msgid "Storage"
msgstr ""
msgstr "Depolama"
#: .\cookbook\forms.py:222
msgid "Active"
@@ -106,51 +112,60 @@ msgstr "Aktif"
#: .\cookbook\forms.py:226
msgid "Search String"
msgstr ""
msgstr "Arama Sorgusu"
#: .\cookbook\forms.py:246
msgid "File ID"
msgstr ""
msgstr "Dosya ID"
#: .\cookbook\forms.py:262
msgid "Maximum number of users for this space reached."
msgstr ""
msgstr "Bu alan için maksimum kullanıcı sayısına ulaşıldı."
#: .\cookbook\forms.py:268
msgid "Email address already taken!"
msgstr ""
msgstr "Email adresi zaten alınmış!"
#: .\cookbook\forms.py:275
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
msgstr ""
"Email adresi zorunlu değildir fakat verilmesi halinde davet linki "
"kullanıcıya gönderilecektir."
#: .\cookbook\forms.py:287
msgid "Name already taken."
msgstr ""
msgstr "İsim zaten alınmış."
#: .\cookbook\forms.py:298
msgid "Accept Terms and Privacy"
msgstr ""
msgstr "Koşulları ve Gizliliği Onayla"
#: .\cookbook\forms.py:332
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
msgstr ""
"Trigram benzerlik eşleşmesi kullanılması halinde aramanın ne kadar bulanık "
"olduğunu belirler (ör. düşük değerler daha fazla yazım hatasını gözardı "
"eder)."
#: .\cookbook\forms.py:340
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
msgstr ""
"Arama tipi metodunu seçin. Seçeneklerin tam açıklamasını görmek için <a "
"href=\"/docs/search/\">buraya</a> tıklayın."
#: .\cookbook\forms.py:341
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
msgstr ""
"Tarifleri düzenlerken ve içeri aktarırken birimler, anahtar kelimeler ve "
"malzemelerde bulanık eşleştirme kullan."
#: .\cookbook\forms.py:342
msgid ""

View File

@@ -63,6 +63,8 @@ Modify the below to match your environment and add it to your `docker-compose.ym
``` yaml
pgbackup:
container_name: pgbackup
env_file:
- ./.env
environment:
BACKUP_KEEP_DAYS: "8"
BACKUP_KEEP_MONTHS: "6"

View File

@@ -2,7 +2,7 @@ Django==4.2.11
cryptography===42.0.5
django-annoying==0.10.6
django-cleanup==8.0.0
django-crispy-forms==2.0
django-crispy-forms==2.1
crispy-bootstrap4==2022.1
django-tables2==2.7.0
djangorestframework==3.14.0
@@ -10,12 +10,12 @@ drf-writable-nested==0.7.0
drf-spectacular==0.27.1
drf-spectacular-sidecar==2024.2.1
django-oauth-toolkit==2.3.0
django-debug-toolbar==4.2.0
django-debug-toolbar==4.3.0
bleach==6.0.0
gunicorn==21.2.0
lxml==5.1.0
Markdown==3.5.1
Pillow==10.2.0
Pillow==10.3.0
psycopg2-binary==2.9.9
python-dotenv==1.0.0
requests==2.31.0
@@ -25,14 +25,14 @@ whitenoise==6.6.0
icalendar==5.0.11
pyyaml==6.0.1
uritemplate==4.1.1
beautifulsoup4==4.12.2
beautifulsoup4==4.12.3
microdata==0.8.0
mock==5.1.0
Jinja2==3.1.3
django-webpack-loader==3.0.1
git+https://github.com/BITSOLVER/django-js-reverse@071e304fd600107bc64bbde6f2491f1fe049ec82
django-allauth==0.61.1
recipe-scrapers==14.52.0
recipe-scrapers==14.55.0
django-scopes==2.0.0
django-treebeard==4.7
django-cors-headers==4.3.1
@@ -45,13 +45,13 @@ django-auth-ldap==4.6.0
pyppeteer==2.0.0
validators==0.20.0
pytube==15.0.0
homeassistant-api==4.1.1.post2
django-vite==3.0.3
aiohttp==3.9.3
# Development
pytest==8.0.0
pytest-django==4.8.0
pytest-cov===4.1.0
pytest-cov===5.0.0
pytest-factoryboy==2.6.0
pytest-html==4.1.1
pytest-asyncio==0.23.5

View File

@@ -54,7 +54,7 @@
text-field="name"
value-field="id"
v-model="food.supermarket_category"
@change="detail_modal_visible = false; updateFoodCategory(food)"
@input="detail_modal_visible = false; updateFoodCategory(food)"
></b-form-select>
<b-button variant="info" block

View File

@@ -4,38 +4,38 @@
"err_creating_resource": "Kaynak oluşturulurken bir hata oluştu!",
"err_updating_resource": "Kaynak güncellenirken bir hata oluştu!",
"err_deleting_resource": "Kaynak silinirken bir hata oluştu!",
"err_deleting_protected_resource": "",
"err_moving_resource": "",
"err_merging_resource": "",
"err_deleting_protected_resource": "Silmeye çalıştığınız nesne hala kullanılıyor ve silinemedi.",
"err_moving_resource": "Kaynak taşınırken bir hata oluştu!",
"err_merging_resource": "Kaynak birleştirilirken bir hata oluştu!",
"success_fetching_resource": "Kaynak başarıyla getirildi!",
"success_creating_resource": "Kaynak başarıyla oluşturuldu!",
"success_updating_resource": "",
"success_updating_resource": "Kaynak başarıyla güncellendi!",
"success_deleting_resource": "Kaynak başarıyla silindi!",
"success_moving_resource": "Kaynak başarıyla taşındı!",
"success_merging_resource": "Kaynak başarıyla birleştirildi!",
"file_upload_disabled": "Alanınız için dosya yükleme aktif değil.",
"warning_space_delete": "Tüm tarifler, alışveriş listeleri, yemek planları ve oluşturduğunuz her şey dahil olmak üzere silinecektir. Bu geri alınamaz! Bunu yapmak istediğinizden emin misiniz?",
"food_inherit_info": "",
"warning_space_delete": "Tüm tarifleri, alışveriş listelerini, yemek planlarını ve oluşturduğunuz diğer her şeyi içeren alanınızı silebilirsiniz. Bu geri alınamaz! Bunu yapmak istediğinizden emin misiniz?",
"food_inherit_info": "Yiyeceklerdeki öntanımlı olarak aktarılması gereken alanlar.",
"step_time_minutes": "Dakika olarak adım süresi",
"confirm_delete": "",
"import_running": "",
"all_fields_optional": "",
"confirm_delete": "Bu {object}'yi silmek istediğinizden emin misiniz?",
"import_running": "İçeri aktarım devam ediyor, lütfen bekleyin!",
"all_fields_optional": "Bütün alanlar tercihe bağlıdır ve boş bırakılabilir.",
"convert_internal": "Dahili tarif'e dönüştür",
"show_only_internal": "Sadece dahili tarifler",
"show_only_internal": "Sadece dahili tarifleri göster",
"show_split_screen": "Bölünmüş Görünüm",
"Log_Recipe_Cooking": "",
"External_Recipe_Image": "",
"Log_Recipe_Cooking": "Günlük Tarif Pişirme",
"External_Recipe_Image": "Harici Tarif Resim",
"Add_to_Shopping": "Alışverişe Ekle",
"Add_to_Plan": "",
"Step_start_time": "",
"Add_to_Plan": "Plana ekle",
"Step_start_time": "Adım başlangıç zamanı",
"Sort_by_new": "Yeniye göre sırala",
"Table_of_Contents": "İçindekiler Tablosu",
"Recipes_per_page": "Sayfa Başına Tarif",
"Show_as_header": "Başlığı Göster",
"Hide_as_header": "Başlığı gizle",
"Add_nutrition_recipe": "",
"Remove_nutrition_recipe": "",
"Copy_template_reference": "",
"Show_as_header": "Başlık olarak göster",
"Hide_as_header": "Başlık olarak gizle",
"Add_nutrition_recipe": "Tarife besin değeri ekle",
"Remove_nutrition_recipe": "Tariften besin değeri sil",
"Copy_template_reference": "Şablon referansını kopyala",
"Save_and_View": "Kaydet & Görüntüle",
"Manage_Books": "Kitapları Yönet",
"Meal_Plan": "Yemek Planı",
@@ -44,12 +44,12 @@
"Recipe_Image": "Tarif Resmi",
"Import_finished": "İçeriye Aktarma Bitti",
"View_Recipes": "Tarifleri Görüntüle",
"Log_Cooking": "",
"Log_Cooking": "Günlük Pişirme",
"New_Recipe": "Yeni Tarif",
"Url_Import": "Url İçeri Aktar",
"Reset_Search": "Aramayı Sıfırla",
"Recently_Viewed": "Son Görüntülenen",
"Load_More": "Daha Fazla",
"Load_More": "Daha Fazla Yükle",
"New_Keyword": "Yeni Anahtar Kelime",
"Delete_Keyword": "Anahtar Kelimeyi Sil",
"Edit_Keyword": "Anahtar Kelimeyi Düzenle",
@@ -57,20 +57,20 @@
"Move_Keyword": "Anahtar Kelimeyi Taşı",
"Merge_Keyword": "Anahtar Kelimeyi Birleştir",
"Hide_Keywords": "Anahtar Kelimeyi Gizle",
"Hide_Recipes": "Tarifi Gizle",
"Hide_Recipes": "Tarifleri Gizle",
"Move_Up": "Yukarı Taşı",
"Move_Down": "Aşağıya Taşı",
"Step_Name": "Adım Adı",
"Step_Type": "Adım Tipi",
"Make_Header": "",
"Make_Ingredient": "",
"Make_Header": "Başlık Oluştur",
"Make_Ingredient": "Malzeme Oluştur",
"Enable_Amount": "Tutarı Etkinleştir",
"Disable_Amount": "Tutarı Devre Dışı Bırak",
"Ingredient Editor": "",
"Ingredient Editor": "Malzeme Düzenleyici",
"Private_Recipe": "Özel Tarif",
"Private_Recipe_Help": "",
"reusable_help_text": "",
"Add_Step": "",
"Private_Recipe_Help": "Tarif yalnızca size ve paylaştığınız kişilere gösterilir.",
"reusable_help_text": "Davet bağlantısı birden fazla kullanıcı için kullanılabilir olsun mu.",
"Add_Step": "Adım Ekle",
"Keywords": "Anahtar Kelimeler",
"Books": "Kitaplar",
"Proteins": "Proteinler",
@@ -78,7 +78,7 @@
"Carbohydrates": "Karbonhidratlar",
"Calories": "Kaloriler",
"Energy": "Enerji",
"Nutrition": "Besin",
"Nutrition": "Besin Değeri",
"Date": "Tarih",
"Share": "Paylaş",
"Automation": "Otomasyon",
@@ -93,18 +93,18 @@
"New": "Yeni",
"Note": "Not",
"Success": "Başarılı",
"Failure": "Hata",
"Failure": "Başarısız",
"Protected": "Korumalı",
"Ingredients": "Mazemeler",
"Ingredients": "Malzemeler",
"Supermarket": "Market",
"Categories": "Kategoriler",
"Category": "Kategori",
"Selected": "Seçilen",
"min": "",
"Servings": "",
"Waiting": "",
"Preparation": "",
"External": "",
"min": "min",
"Servings": "Servis Sayısı",
"Waiting": "Bekleniyor",
"Preparation": "Hazırlama",
"External": "Harici",
"Size": "Boyut",
"Files": "Dosyalar",
"File": "Dosya",
@@ -112,7 +112,7 @@
"Image": "Resim",
"Delete": "Sil",
"Open": "Aç",
"Ok": "",
"Ok": "Tamam",
"Save": "Kaydet",
"Step": "Adım",
"Search": "Ara",
@@ -121,7 +121,7 @@
"Settings": "Ayarlar",
"or": "veya",
"and": "ve",
"Information": "bilgi",
"Information": "Bilgi",
"Download": "İndir",
"Create": "Oluştur",
"Search Settings": "Arama Ayarları",
@@ -129,10 +129,10 @@
"Recipes": "Tarifler",
"Move": "Taşı",
"Merge": "Birleştir",
"Parent": "",
"Copy Link": "",
"Copy Token": "",
"delete_confirmation": "",
"Parent": "Üst Öğe",
"Copy Link": "Bağlantıyı Kopyala",
"Copy Token": "Anahtarı Kopyala",
"delete_confirmation": "{source}'ı silmek istediğinizden emin misiniz?",
"move_confirmation": "",
"merge_confirmation": "",
"create_rule": "",
@@ -457,5 +457,41 @@
"New_Supermarket": "Yeni Market",
"New_Supermarket_Category": "Yeni Market Kategorisi",
"Are_You_Sure": "Emin misin?",
"Valid Until": "Geçerlilik Tarihi"
"Valid Until": "Geçerlilik Tarihi",
"err_importing_recipe": "Tarif içeri aktarılırken bir hata oluştu!",
"Data_Import_Info": "Tarif koleksiyonunuzu geliştirmek için topluluk tarafından oluşturulmuş yiyecek, birim ve daha fazlasını olduğu listeleri içeri aktararak Alanlarınızı genişletin.",
"open_data_help_text": "The Tandoor Open Data projesi Tandoor için topluluk tarafından oluşturulmuş verileri sağlar. Bu alan içeri aktarım sırasında otomatik olarak doldurulur ve gelecekte güncellenebilir.",
"Description_Replace": "Açıklama Değiştir",
"FDC_ID": "FDC Kimlik",
"FDC_Search": "FDC Arama",
"FDC_ID_help": "FDC veritabanı Kimlik",
"Auto_Sort": "Otomatik Sırala",
"Welcome": "Hoşgeldiniz",
"recipe_property_info": "Yiyeceklere ayrıca özellikler ekleyebilir ve tarifinize göre bunları otomatik olarak hesaplayabilirsiniz!",
"Amount": "Miktar",
"per_serving": "servis başına",
"Instruction_Replace": "Talimat Değiştir",
"Open_Data_Slug": "Açık Veri Tanım",
"Input": "Giriş",
"Undo": "Geri Al",
"NoMoreUndo": "Yapılacak değişiklik yok.",
"Delete_All": "Tümünü sil",
"Update_Existing_Data": "Mevcut Verileri Güncelleyin",
"Use_Metric": "Metrik Birimler Kullan",
"Learn_More": "Daha Fazla",
"converted_unit": "Dönüştürülmüş Birim",
"converted_amount": "Dönüştürülmüş Miktar",
"base_unit": "Temel Birim",
"Number of Objects": "Nesne Sayısı",
"Datatype": "Veri tipi",
"StartDate": "Başlangıç Tarihi",
"EndDate": "Bitiş Tarihi",
"Auto_Sort_Help": "Tüm malzemeleri en uygun adıma taşı.",
"Open_Data_Import": "Açık Veri İçeri Aktar",
"Properties_Food_Amount": "Özellikler Yiyecek Miktar",
"Properties_Food_Unit": "Özellikler Yiyecek Birim",
"base_amount": "Temel Miktar",
"Calculator": "Hesap Makinesi",
"property_type_fdc_hint": "Yalnızca FDC kimliği olan özellik tipleri FDC veritabanından veri çekebilir",
"Alignment": "Hizalama"
}

View File

@@ -3717,25 +3717,7 @@ bn.js@^5.0.0, bn.js@^5.2.1:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
body-parser@1.20.1:
version "1.20.1"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
dependencies:
bytes "3.1.2"
content-type "~1.0.4"
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
http-errors "2.0.0"
iconv-lite "0.4.24"
on-finished "2.4.1"
qs "6.11.0"
raw-body "2.5.1"
type-is "~1.6.18"
unpipe "1.0.0"
body-parser@^1.19.0:
body-parser@1.20.2, body-parser@^1.19.0:
version "1.20.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
@@ -4511,10 +4493,10 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
cookie@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
cookie@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
copy-concurrently@^1.0.0:
version "1.0.5"
@@ -5652,16 +5634,16 @@ express-history-api-fallback@^2.2.1:
integrity sha512-swxwm3aP8vrOOvlzOdZvHlSZtJGwHKaY94J6AkrAgCTmcbko3IRwbkhLv2wKV1WeZhjxX58aLMpP3atDBnKuZg==
express@^4.17.1, express@^4.17.3:
version "4.18.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
version "4.19.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
body-parser "1.20.1"
body-parser "1.20.2"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.5.0"
cookie "0.6.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
@@ -9351,16 +9333,6 @@ range-parser@^1.2.1, range-parser@~1.2.1:
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
raw-body@2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
dependencies:
bytes "3.1.2"
http-errors "2.0.0"
iconv-lite "0.4.24"
unpipe "1.0.0"
raw-body@2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"