Compare commits

...

127 Commits
2.3.0 ... 2.3.6

Author SHA1 Message Date
vabene1111
fc40b5220b Merge branch 'develop' 2025-11-24 20:40:07 +01:00
vabene1111
0046233b6f open print with servings 2025-11-24 20:39:53 +01:00
vabene1111
78ede7b601 Merge pull request #4237 from Orycterope/fix_servings
open meal plan recipe with right amount of servings
2025-11-24 20:29:15 +01:00
vabene1111
7e7e133604 Merge branch 'develop' into fix_servings 2025-11-24 20:28:22 +01:00
vabene1111
b0ec569a00 fixed meal master importer 2025-11-24 20:24:44 +01:00
vabene1111
7674084ae0 potentially fixed redirect issue 2025-11-24 20:14:37 +01:00
vabene1111
798e2ac48b fixed mealie import 2025-11-24 20:05:58 +01:00
vabene1111
714d4a32a9 Merge branch 'weblate-develop' into develop
# Conflicts:
#	vue3/src/locales/sv.json
2025-11-24 19:51:27 +01:00
Andreas Ljungberg
66b5097872 Translated using Weblate (Swedish)
Currently translated at 69.8% (607 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sv/
2025-11-22 20:03:33 +00:00
SerhiiOS
c1d4fed142 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (488 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/uk/
2025-11-22 20:03:33 +00:00
vabene1111
c0d172574d Merge branch 'develop' 2025-11-19 21:53:16 +01:00
vabene1111
1cc0806729 remove empty default ingredient when using paste improt 2025-11-19 21:50:47 +01:00
vabene1111
09487a0e94 improved ical export 2025-11-19 21:47:23 +01:00
vabene1111
89e58edcad fixed SLR's without entries 2025-11-19 21:30:20 +01:00
vabene1111
887d7fe9f0 no more unaccent on sqlite 2025-11-19 21:18:23 +01:00
vabene1111
14696e3ce8 fixed times cooked in saved serarch and improved frontend query binding 2025-11-19 21:02:16 +01:00
vabene1111
dd56bb4b35 fixed property detail dialog serving scaling 2025-11-19 20:17:39 +01:00
vabene1111
8ec0ba9541 fixed help view not navigatbale on mobile 2025-11-19 20:06:39 +01:00
vabene1111
c105c9190e ignore defunct websites in url list import mode 2025-11-18 16:16:39 +01:00
vabene1111
9c1700adb9 fixed copying recipes would link data 2025-11-18 16:07:36 +01:00
vabene1111
b43a87a7e3 improved mealie importer 2025-11-18 15:59:15 +01:00
vabene1111
01e78baecf fixed property helper error 2025-11-18 15:48:39 +01:00
vabene1111
0ee241524d some more print mode tweaks 2025-11-18 15:42:19 +01:00
vabene1111
84fd3055ea Merge branch 'develop' 2025-11-18 15:29:08 +01:00
vabene1111
2bd60a6f13 tiny fix 2025-11-18 15:29:02 +01:00
orycterope
e0196f17da open meal plan recipe with given servings
Fix https://github.com/TandoorRecipes/recipes/issues/3787

Adds a '?servings=42' query param to RecipeViewPage, and propagates it
to child views via a prop. The ingredientFactor is computed based on
this param if it is present, and defaults to recipe servings otherwise.

This query param is set when comming from:

* Home page's HorizontalRecipeWindow
* MealPlanEditor

This commit also makes the RecipeView's Activity form reactive on
the number of servings, before creating a comment.
2025-11-18 14:10:52 +01:00
SerhiiOS
fe75052baa Translated using Weblate (Ukrainian)
Currently translated at 100.0% (869 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/uk/
2025-11-18 07:01:59 +00:00
SerhiiOS
0a3b750294 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (488 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/uk/
2025-11-18 07:01:59 +00:00
Vincenzo Reale
fcd3918b5f Translated using Weblate (Italian)
Currently translated at 100.0% (373 of 373 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/it/
2025-11-18 07:01:59 +00:00
vabene1111
e7aac06ca7 improved print view 2025-11-17 07:51:31 +01:00
Vincenzo Reale
67e1f57723 Translated using Weblate (Italian)
Currently translated at 100.0% (869 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2025-11-17 06:42:04 +00:00
Vincenzo Reale
10581329e8 Translated using Weblate (Italian)
Currently translated at 87.9% (328 of 373 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/it/
2025-11-17 06:42:04 +00:00
SerhiiOS
553c06f291 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (869 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/uk/
2025-11-16 01:59:51 +00:00
SerhiiOS
e0cbfd824c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (488 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/uk/
2025-11-16 01:59:51 +00:00
Matjaž T.
a5a522d378 Translated using Weblate (Slovenian)
Currently translated at 100.0% (869 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sl/
2025-11-15 12:08:14 +00:00
Matjaž T.
8502bb235b Translated using Weblate (Slovenian)
Currently translated at 100.0% (373 of 373 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sl/
2025-11-15 12:08:14 +00:00
SerhiiOS
42f2ad624f Translated using Weblate (Ukrainian)
Currently translated at 62.7% (545 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/uk/
2025-11-14 19:01:59 +00:00
SerhiiOS
3b95bf40da Translated using Weblate (Ukrainian)
Currently translated at 80.7% (394 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/uk/
2025-11-14 19:01:58 +00:00
SerhiiOS
81a6837b06 Translated using Weblate (Ukrainian)
Currently translated at 43.6% (379 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/uk/
2025-11-13 13:33:58 +00:00
SerhiiOS
a95e352250 Translated using Weblate (Ukrainian)
Currently translated at 62.7% (306 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/uk/
2025-11-13 13:33:58 +00:00
Justin Straver
a4ca66d287 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 91.4% (795 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/zh_Hant/
2025-11-12 12:02:00 +00:00
Justin Straver
ec30b81ae5 Translated using Weblate (Russian)
Currently translated at 91.1% (792 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ru/
2025-11-12 12:02:00 +00:00
Justin Straver
92211b1f51 Translated using Weblate (Portuguese (Brazil))
Currently translated at 75.4% (656 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt_BR/
2025-11-12 12:02:00 +00:00
Justin Straver
8eeea42057 Translated using Weblate (Italian)
Currently translated at 99.3% (863 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2025-11-12 12:02:00 +00:00
Justin Straver
7e76a71ccc Translated using Weblate (French)
Currently translated at 88.7% (771 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2025-11-12 12:02:00 +00:00
Justin Straver
b397c94f0a Translated using Weblate (Spanish)
Currently translated at 87.5% (761 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/es/
2025-11-12 12:02:00 +00:00
Justin Straver
9552564e59 Translated using Weblate (German)
Currently translated at 99.7% (867 of 869 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2025-11-12 12:02:00 +00:00
SerhiiOS
4ecf323e4f Translated using Weblate (Ukrainian)
Currently translated at 31.5% (154 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/uk/
2025-11-12 12:02:00 +00:00
vabene1111
d5d5c2c52b Merge pull request #4159 from erikbledsoe/patch-1
documentation typo
2025-11-11 15:42:05 +01:00
vabene1111
7ffabfe711 Merge pull request #4166 from EifX/docs/apache-reverse-proxy
feat: add apache reverse proxy documentation
2025-11-11 15:41:13 +01:00
vabene1111
49e0b5b962 improve handling of vuetify locale 2025-11-11 15:40:50 +01:00
vabene1111
a05f1ece24 updated recipe scrapers 2025-11-11 14:45:34 +01:00
vabene1111
748b91bb8a improve servings parsing and AI failure logging 2025-11-11 14:44:09 +01:00
vabene1111
bd2e9cc3d9 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2025-11-11 14:16:37 +01:00
vabene1111
c40bb20a7a fixed copying meal plans did not add to shopping 2025-11-11 14:16:32 +01:00
vabene1111
b377d2cd35 Merge pull request #4192 from Daan5556/patch-1
Docs: Added trailing slash to `system` path
2025-11-11 14:12:17 +01:00
vabene1111
dc0e91d0f9 Merge pull request #4193 from ThomasLeister/patch-1
Update manual setup instructions: vue is now vue3
2025-11-11 14:11:26 +01:00
vabene1111
5f12907544 fixed edge case where no recipe is displayed in a mostly empty space 2025-11-11 14:09:02 +01:00
vabene1111
889ddac7dc remove debug button from message dialog and added button to open it 2025-11-11 13:41:14 +01:00
vabene1111
b369e2618a fixed decimals in share view 2025-11-11 13:06:56 +01:00
vabene1111
5a4e0204c9 fixed debug toolbar setup 2025-11-11 12:59:45 +01:00
vabene1111
bfc2e96b54 Merge pull request #4101 from TandoorRecipes/dependabot/npm_and_yarn/vue3/vuetify-3.10.3
Bump vuetify from 3.9.7 to 3.10.3 in /vue3
2025-11-11 12:51:23 +01:00
vabene1111
f065ef80aa Merge pull request #4100 from TandoorRecipes/dependabot/npm_and_yarn/vue3/vueuse/router-13.9.0
Bump @vueuse/router from 13.6.0 to 13.9.0 in /vue3
2025-11-11 12:51:11 +01:00
vabene1111
61c14b8b05 Merge pull request #4099 from TandoorRecipes/dependabot/npm_and_yarn/vue3/vue/tsconfig-0.8.1
Bump @vue/tsconfig from 0.7.0 to 0.8.1 in /vue3
2025-11-11 12:51:03 +01:00
vabene1111
35d5d64809 Merge pull request #4096 from TandoorRecipes/dependabot/pip/lxml-6.0.2
Bump lxml from 5.3.1 to 6.0.2
2025-11-11 12:50:52 +01:00
vabene1111
63c711d18c Merge pull request #4094 from TandoorRecipes/dependabot/pip/pytest-8.4.2
Bump pytest from 8.4.1 to 8.4.2
2025-11-11 12:50:42 +01:00
vabene1111
59e3ea70d1 Merge pull request #4095 from TandoorRecipes/dependabot/pip/django-debug-toolbar-6.0.0
Bump django-debug-toolbar from 4.3.0 to 6.0.0
2025-11-11 12:50:19 +01:00
vabene1111
6771662a9f Merge pull request #4092 from TandoorRecipes/dependabot/pip/pyyaml-6.0.3
Bump pyyaml from 6.0.2 to 6.0.3
2025-11-11 12:49:29 +01:00
vabene1111
9b792a1393 Merge pull request #4093 from TandoorRecipes/dependabot/pip/drf-spectacular-0.28.0
Bump drf-spectacular from 0.27.1 to 0.28.0
2025-11-11 12:49:19 +01:00
vabene1111
862957c121 Merge pull request #4098 from TandoorRecipes/dependabot/github_actions/actions/setup-python-6
Bump actions/setup-python from 5 to 6
2025-11-11 12:48:50 +01:00
vabene1111
bdcbafd52f Merge pull request #4200 from TandoorRecipes/dependabot/github_actions/github/codeql-action-4
Bump github/codeql-action from 3 to 4
2025-11-11 12:48:26 +01:00
vabene1111
5e454a5212 Merge pull request #4201 from TandoorRecipes/dependabot/github_actions/actions/setup-node-6
Bump actions/setup-node from 4 to 6
2025-11-11 12:48:18 +01:00
vabene1111
20bea63997 Merge pull request #4202 from TandoorRecipes/dependabot/github_actions/awalsh128/cache-apt-pkgs-action-1.6.0
Bump awalsh128/cache-apt-pkgs-action from 1.5.3 to 1.6.0
2025-11-11 12:48:09 +01:00
vabene1111
8a265772c0 Merge pull request #4211 from TandoorRecipes/dependabot/pip/django-5.2.8
Bump django from 5.2.7 to 5.2.8
2025-11-11 12:47:16 +01:00
vabene1111
6febb4e3e8 Merge pull request #4174 from TandoorRecipes/dependabot/npm_and_yarn/vue3/vite-7.1.11
Bump vite from 7.1.5 to 7.1.11 in /vue3
2025-11-11 12:47:00 +01:00
vabene1111
04f9167fd8 Merge branch 'develop-weblate' into develop
# Conflicts:
#	cookbook/locale/nl/LC_MESSAGES/django.po
#	cookbook/locale/uk/LC_MESSAGES/django.po
#	vue3/src/locales/de.json
#	vue3/src/locales/en.json
#	vue3/src/locales/nl.json
#	vue3/src/locales/sl.json
#	vue3/src/locales/uk.json
2025-11-11 12:27:48 +01:00
dependabot[bot]
8f29e01daf Bump django from 5.2.7 to 5.2.8
Bumps [django](https://github.com/django/django) from 5.2.7 to 5.2.8.
- [Commits](https://github.com/django/django/compare/5.2.7...5.2.8)

---
updated-dependencies:
- dependency-name: django
  dependency-version: 5.2.8
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-05 20:17:31 +00:00
Erik Bledsoe
e810363b22 Merge branch 'develop' into patch-1 2025-11-01 07:05:19 -04:00
tan
b5a2120bdf Added translation using Weblate (Korean) 2025-11-01 10:09:09 +00:00
tan
643fcbad9b Added translation using Weblate (Korean) 2025-11-01 10:09:09 +00:00
dependabot[bot]
4a3b834463 Bump awalsh128/cache-apt-pkgs-action from 1.5.3 to 1.6.0
Bumps [awalsh128/cache-apt-pkgs-action](https://github.com/awalsh128/cache-apt-pkgs-action) from 1.5.3 to 1.6.0.
- [Release notes](https://github.com/awalsh128/cache-apt-pkgs-action/releases)
- [Commits](https://github.com/awalsh128/cache-apt-pkgs-action/compare/v1.5.3...v1.6.0)

---
updated-dependencies:
- dependency-name: awalsh128/cache-apt-pkgs-action
  dependency-version: 1.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-01 00:02:12 +00:00
dependabot[bot]
003149133a Bump actions/setup-node from 4 to 6
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-01 00:02:10 +00:00
dependabot[bot]
a43de0ca4d Bump github/codeql-action from 3 to 4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-01 00:02:06 +00:00
Thomas Leister
e05aaed75c Update manual setup instructions: vue is now vue3
The documentation has not been updated: "vue" directory is now "vue3".
2025-10-27 13:36:57 +01:00
Daan5556
4984e3e31b Added trailing slash to system path 2025-10-27 13:03:53 +01:00
dependabot[bot]
11dce4c6ad Bump vite from 7.1.5 to 7.1.11 in /vue3
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.5 to 7.1.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.11
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-20 22:56:53 +00:00
Alexander Eifler
8d0d338ea2 feat: add apache reverse proxy documentation 2025-10-15 20:56:39 +02:00
vabene1111
d22b5a4a39 Merge branch 'develop' 2025-10-15 15:18:13 +02:00
vabene1111
d09e629415 fixed input type 2025-10-15 15:10:59 +02:00
vabene1111
53ef2ef99f fixed ingredient input decimals 2025-10-15 15:02:19 +02:00
Erik Bledsoe
d7b26d1b29 documentation typo 2025-10-13 13:44:15 -04:00
vabene1111
602f0a8bf0 Merge branch 'master' of https://github.com/TandoorRecipes/recipes 2025-10-11 11:59:11 +02:00
vabene1111
673d12d233 increased default max body size for file uploads to 512 MB 2025-10-11 11:57:32 +02:00
vabene1111
6359245925 Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2025-10-11 11:56:51 +02:00
vabene1111
a7c4822322 fixed cannoit create steps if none are present 2025-10-11 11:56:47 +02:00
vabene1111
e94419f320 Merge pull request #4138 from KoMa1012/KoMa1012-gunicorn-timeoutconfig
Update boot.sh
2025-10-11 11:55:48 +02:00
vabene1111
01f46483ff clearer batch delete warning 2025-10-11 11:52:52 +02:00
vabene1111
d6da5688af fixed 0 servings 2025-10-11 11:47:10 +02:00
vabene1111
680ae39201 fixed import button not switching to loading in app import 2025-10-11 11:38:58 +02:00
vabene1111
2472ee9c26 fixed api setting example 2025-10-11 11:05:20 +02:00
vabene1111
4428b06d4a fixed properties edge case with missing conversions 2025-10-11 11:04:00 +02:00
vabene1111
e9c38d7d5e added bottom margin to properties editor 2025-10-11 09:22:43 +02:00
vabene1111
6f28d58807 fixed and imporved food properties 2025-10-11 09:20:58 +02:00
vabene1111
88db611f0a Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2025-10-11 09:02:14 +02:00
vabene1111
f3302b4014 fixed start page and ingredient templater 2025-10-11 09:02:10 +02:00
vabene1111
d4bb161275 Merge pull request #4147 from TandoorRecipes/dependabot/pip/python-ldap-3.4.5
Bump python-ldap from 3.4.4 to 3.4.5
2025-10-11 08:36:03 +02:00
dependabot[bot]
32f1538938 Bump python-ldap from 3.4.4 to 3.4.5
Bumps [python-ldap](https://github.com/python-ldap/python-ldap) from 3.4.4 to 3.4.5.
- [Release notes](https://github.com/python-ldap/python-ldap/releases)
- [Changelog](https://github.com/python-ldap/python-ldap/blob/python-ldap-3.4.5/CHANGES)
- [Commits](https://github.com/python-ldap/python-ldap/compare/python-ldap-3.4.4...python-ldap-3.4.5)

---
updated-dependencies:
- dependency-name: python-ldap
  dependency-version: 3.4.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-10 22:55:18 +00:00
KoMa1012
029baea4c7 Update configuration.md
added explanation for GUNICORN_TIMEOUT environmental variable
2025-10-09 12:51:25 +02:00
KoMa1012
38d1b7cef5 Update boot.sh
made gunicorn timout configurable via environmental variable GUNICORN_TIMEOUT this can help in scenarios where e.g. the LLM takes too much time to answer when using a local LLM
2025-10-08 20:09:51 +02:00
vabene1111
856f417d1b Merge branch 'develop' 2025-10-08 07:57:59 +02:00
vabene1111
85821bcc94 nginx config update 2025-10-08 07:42:09 +02:00
dependabot[bot]
e292b72e34 Bump vuetify from 3.9.7 to 3.10.3 in /vue3
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.9.7 to 3.10.3.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.10.3/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-version: 3.10.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:34:43 +00:00
dependabot[bot]
4e795ecf55 Bump @vueuse/router from 13.6.0 to 13.9.0 in /vue3
Bumps [@vueuse/router](https://github.com/vueuse/vueuse/tree/HEAD/packages/router) from 13.6.0 to 13.9.0.
- [Release notes](https://github.com/vueuse/vueuse/releases)
- [Commits](https://github.com/vueuse/vueuse/commits/v13.9.0/packages/router)

---
updated-dependencies:
- dependency-name: "@vueuse/router"
  dependency-version: 13.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:34:23 +00:00
dependabot[bot]
e3c2a66723 Bump @vue/tsconfig from 0.7.0 to 0.8.1 in /vue3
Bumps [@vue/tsconfig](https://github.com/vuejs/tsconfig) from 0.7.0 to 0.8.1.
- [Release notes](https://github.com/vuejs/tsconfig/releases)
- [Commits](https://github.com/vuejs/tsconfig/compare/v0.7.0...v0.8.1)

---
updated-dependencies:
- dependency-name: "@vue/tsconfig"
  dependency-version: 0.8.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:33:58 +00:00
dependabot[bot]
eec3e97f97 Bump actions/setup-python from 5 to 6
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:04:39 +00:00
dependabot[bot]
3f481d6922 Bump lxml from 5.3.1 to 6.0.2
Bumps [lxml](https://github.com/lxml/lxml) from 5.3.1 to 6.0.2.
- [Release notes](https://github.com/lxml/lxml/releases)
- [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/lxml/lxml/compare/lxml-5.3.1...lxml-6.0.2)

---
updated-dependencies:
- dependency-name: lxml
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:01:38 +00:00
dependabot[bot]
0810ab7210 Bump django-debug-toolbar from 4.3.0 to 6.0.0
Bumps [django-debug-toolbar](https://github.com/django-commons/django-debug-toolbar) from 4.3.0 to 6.0.0.
- [Release notes](https://github.com/django-commons/django-debug-toolbar/releases)
- [Changelog](https://github.com/django-commons/django-debug-toolbar/blob/main/docs/changes.rst)
- [Commits](https://github.com/django-commons/django-debug-toolbar/compare/4.3...6.0.0)

---
updated-dependencies:
- dependency-name: django-debug-toolbar
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:01:32 +00:00
dependabot[bot]
abd621145c Bump pytest from 8.4.1 to 8.4.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.4.1 to 8.4.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.4.1...8.4.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 8.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:01:29 +00:00
dependabot[bot]
7d218aa93d Bump drf-spectacular from 0.27.1 to 0.28.0
Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.27.1 to 0.28.0.
- [Release notes](https://github.com/tfranzel/drf-spectacular/releases)
- [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.27.1...0.28.0)

---
updated-dependencies:
- dependency-name: drf-spectacular
  dependency-version: 0.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:01:24 +00:00
dependabot[bot]
1b41bd9115 Bump pyyaml from 6.0.2 to 6.0.3
Bumps [pyyaml](https://github.com/yaml/pyyaml) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/yaml/pyyaml/releases)
- [Changelog](https://github.com/yaml/pyyaml/blob/6.0.3/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/6.0.2...6.0.3)

---
updated-dependencies:
- dependency-name: pyyaml
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 00:01:21 +00:00
S
d4f654554b Translated using Weblate (Ukrainian)
Currently translated at 43.9% (380 of 864 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/uk/
2025-09-23 19:45:37 +00:00
Matjaž T.
c8115545b8 Translated using Weblate (Slovenian)
Currently translated at 100.0% (864 of 864 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sl/
2025-09-23 19:45:37 +00:00
Justin Straver
6dbf0871ec Translated using Weblate (Dutch)
Currently translated at 99.5% (860 of 864 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nl/
2025-09-23 19:45:36 +00:00
Justin Straver
f1c5c8bc43 Translated using Weblate (German)
Currently translated at 99.1% (857 of 864 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2025-09-23 19:45:36 +00:00
S
22e0108992 Translated using Weblate (Ukrainian)
Currently translated at 18.6% (91 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/uk/
2025-09-23 19:45:36 +00:00
Justin Straver
e2e05c8d1d Translated using Weblate (Dutch)
Currently translated at 100.0% (488 of 488 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nl/
2025-09-23 19:45:36 +00:00
Justin Straver
b02b36812d Translated using Weblate (English)
Currently translated at 100.0% (864 of 864 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/en/
2025-09-23 19:45:36 +00:00
94 changed files with 8281 additions and 3631 deletions

View File

@@ -35,7 +35,7 @@ jobs:
fi
# Build Vue 3 frontend
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: '22'
cache: yarn

View File

@@ -13,14 +13,14 @@ jobs:
node-version: ["22"]
steps:
- uses: actions/checkout@v5
- uses: awalsh128/cache-apt-pkgs-action@v1.5.3
- uses: awalsh128/cache-apt-pkgs-action@v1.6.0
with:
packages: libsasl2-dev python3-dev libxml2-dev libxmlsec1-dev libxslt-dev libxmlsec1-openssl libxslt-dev libldap2-dev libssl-dev gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev xmlsec-dev xmlsec build-base g++ curl
version: 1.0
# Setup python & dependencies
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
@@ -43,7 +43,7 @@ jobs:
# Build Vue frontend & Dependencies
- name: Set up Node ${{ matrix.node-version }}
if: steps.django_cache.outputs.cache-hit != 'true'
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"

View File

@@ -25,7 +25,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
# Override language selection by uncommenting this and choosing your languages
with:
languages: python, javascript
@@ -47,6 +47,6 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
languages: javascript, python

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: 3.x
- run: pip install mkdocs-material mkdocs-include-markdown-plugin

View File

@@ -104,5 +104,5 @@ chmod -R 755 ${MEDIA_ROOT:-/opt/recipes/mediafiles}
ipv6_disable=$(cat /sys/module/ipv6/parameters/disable)
echo "Starting gunicorn"
exec gunicorn --bind unix:/run/tandoor.sock --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi
exec gunicorn --bind unix:/run/tandoor.sock --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --timeout ${GUNICORN_TIMEOUT:-30} --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi

View File

@@ -48,7 +48,7 @@ class FoodPropertyHelper:
found_property = False
# if food has a value for the given property type (no matter if conversion is possible)
has_property_value = False
if i.food.properties_food_amount == 0 or i.food.properties_food_unit is None and not (i.amount == 0 or i.no_amount): # if food is configured incorrectly
if (i.food.properties_food_amount == 0 or i.food.properties_food_unit is None) and not (i.amount == 0 or i.no_amount): # if food is configured incorrectly
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': None}
computed_properties[pt.id]['missing_value'] = True
else:
@@ -56,15 +56,16 @@ class FoodPropertyHelper:
if p.property_type == pt and p.property_amount is not None:
has_property_value = True
for c in conversions:
if c.unit == i.food.properties_food_unit:
if c.unit == i.food.properties_food_unit and i.food.properties_food_amount != 0:
found_property = True
computed_properties[pt.id]['total_value'] += (c.amount / i.food.properties_food_amount) * p.property_amount
computed_properties[pt.id]['food_values'] = self.add_or_create(
computed_properties[p.property_type.id]['food_values'], c.food.id, (c.amount / i.food.properties_food_amount) * p.property_amount, c.food)
if not found_property:
# if no amount and food does not exist yet add it but don't count as missing
if i.amount == 0 or i.no_amount and i.food.id not in computed_properties[pt.id]['food_values']:
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': 0}
if i.amount == 0 or i.no_amount:
if i.food.id not in computed_properties[pt.id]['food_values']:
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': 0}
# if amount is present but unit is missing indicate it in the result
elif i.unit is None:
if i.food.id not in computed_properties[pt.id]['food_values']:
@@ -72,7 +73,8 @@ class FoodPropertyHelper:
computed_properties[pt.id]['food_values'][i.food.id]['missing_unit'] = True
else:
computed_properties[pt.id]['missing_value'] = True
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': None}
if i.food.id not in computed_properties[pt.id]['food_values']:
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': {'id': i.food.id, 'name': i.food.name}, 'value': None}
if has_property_value and i.unit is not None:
computed_properties[pt.id]['food_values'][i.food.id]['missing_conversion'] = {'base_unit': {'id': i.unit.id, 'name': i.unit.name}, 'converted_unit': {'id': i.food.properties_food_unit.id, 'name': i.food.properties_food_unit.name}}
@@ -82,8 +84,12 @@ class FoodPropertyHelper:
# TODO move to central helper ? --> use defaultdict
@staticmethod
def add_or_create(d, key, value, food):
if key in d and d[key]['value']:
d[key]['value'] += value
if key in d:
# value can be None if a previous instance of the same food was missing a conversion
if d[key]['value']:
d[key]['value'] += value
else:
d[key]['value'] = value
else:
d[key] = {'id': food.id, 'food': {'id': food.id, 'name': food.name}, 'value': value}
return d

View File

@@ -324,9 +324,9 @@ class RecipeSearch():
self._queryset = self._queryset.annotate(recent=Coalesce(Max(Case(When(pk__in=num_recent_recipes.values('recipe'), then='viewlog__pk'))), Value(0)))
def _favorite_recipes(self):
if self._sort_includes('favorite') or self._timescooked or self._timescooked_gte or self._timescooked_lte:
if self._sort_includes('favorite') or self._timescooked is not None or self._timescooked_gte is not None or self._timescooked_lte is not None:
less_than = self._timescooked_lte and not self._sort_includes('-favorite')
if less_than or self._timescooked == 0:
if less_than:
default = 1000
else:
default = 0
@@ -338,11 +338,11 @@ class RecipeSearch():
)
self._queryset = self._queryset.annotate(favorite=Coalesce(Subquery(favorite_recipes), default))
if self._timescooked:
if self._timescooked is not None:
self._queryset = self._queryset.filter(favorite=self._timescooked)
elif self._timescooked_lte:
elif self._timescooked_lte is not None:
self._queryset = self._queryset.filter(favorite__lte=int(self._timescooked_lte)).exclude(favorite=0)
elif self._timescooked_gte:
elif self._timescooked_gte is not None:
self._queryset = self._queryset.filter(favorite__gte=int(self._timescooked_gte))
def keyword_filters(self, **kwargs):

View File

@@ -69,15 +69,8 @@ def get_from_scraper(scrape, request):
recipe_json['description'] = parse_description(description)
recipe_json['description'] = automation_engine.apply_regex_replace_automation(recipe_json['description'], Automation.DESCRIPTION_REPLACE)
# assign servings attributes
try:
# dont use scrape.yields() as this will always return "x servings" or "x items", should be improved in scrapers directly
servings = scrape.schema.data.get('recipeYield') or 1
except Exception:
servings = 1
recipe_json['servings'] = parse_servings(servings)
recipe_json['servings_text'] = parse_servings_text(servings)
recipe_json['servings'] = parse_servings(scrape.schema.data.get('recipeYield'))
recipe_json['servings_text'] = parse_servings_text(scrape.schema.data.get('recipeYield'))
# assign time attributes
try:
@@ -406,7 +399,7 @@ def parse_servings(servings):
def parse_servings_text(servings):
if isinstance(servings, str):
try:
servings = re.sub("\\d+", '', servings).strip()
servings = re.sub("\\d+", '', servings, 1).strip()
except Exception:
servings = ''
if isinstance(servings, list):

View File

@@ -75,7 +75,8 @@ class RecipeShoppingEditor():
@staticmethod
def get_shopping_list_recipe(id, user, space):
return ShoppingListRecipe.objects.filter(id=id).filter(entries__space=space).filter(
# TODO this sucks since it wont find SLR's that no longer have any entries
return ShoppingListRecipe.objects.filter(id=id, space=space).filter(
Q(entries__created_by=user)
| Q(entries__created_by__in=list(user.get_shopping_share()))
).prefetch_related('entries').first()
@@ -136,7 +137,8 @@ class RecipeShoppingEditor():
self.servings = servings
self._delete_ingredients(ingredients=ingredients)
if self.servings != self._shopping_list_recipe.servings:
# need to check if there is a SLR because its possible it cant be found if all entries are deleted
if self._shopping_list_recipe and self.servings != self._shopping_list_recipe.servings:
self.edit_servings()
self._add_ingredients(ingredients=ingredients)
return True

View File

@@ -96,14 +96,20 @@ class Mealie1(Integration):
self.import_log.msg += f"Ignoring {r['name']} because a recipe with this name already exists.\n"
self.import_log.save()
else:
servings = 1
try:
servings = r['recipe_servings'] if r['recipe_servings'] and r['recipe_servings'] != 0 else 1
except KeyError:
pass
recipe = Recipe.objects.create(
waiting_time=parse_time(r['perform_time']),
working_time=parse_time(r['prep_time']),
description=r['description'][:512],
name=r['name'],
source_url=r['org_url'],
servings=r['recipe_servings'] if r['recipe_servings'] and r['recipe_servings'] != 0 else 1,
servings_text=r['recipe_yield'].strip() if r['recipe_yield'] else "",
servings=servings,
servings_text=r['recipe_yield'].strip()[:32] if r['recipe_yield'] else "",
internal=True,
created_at=r['created_at'],
space=self.request.space,
@@ -131,7 +137,7 @@ class Mealie1(Integration):
step_id_dict = {}
for s in mealie_database['recipe_instructions']:
if s['recipe_id'] in recipes_dict:
step = Step.objects.create(instruction=(s['text'] if s['text'] else "") + (f" \n {s['summary']}" if s['summary'] else ""),
step = Step.objects.create(instruction=(s['text'] if s['text'] else "") + (f" \n {s['summary']}" if 'summary' in s and s['summary'] else ""),
order=s['position'],
name=s['title'],
space=self.request.space)
@@ -153,7 +159,7 @@ class Mealie1(Integration):
for n in mealie_database['notes']:
if n['recipe_id'] in recipes_dict:
step = Step.objects.create(instruction=n['text'],
name=n['title'],
name=n['title'][:128] if n['title'] else "",
order=100,
space=self.request.space)
steps_relation.append(Recipe.steps.through(recipe_id=recipes_dict[n['recipe_id']], step_id=step.pk))
@@ -243,7 +249,7 @@ class Mealie1(Integration):
for r in mealie_database['recipe_nutrition']:
if r['recipe_id'] in recipes_dict:
for key in property_types_dict:
if r[key]:
if key in r and r[key]:
properties_relation.append(
Property(property_type_id=property_types_dict[key].pk,
property_amount=Decimal(str(r[key])) / (

View File

@@ -63,7 +63,15 @@ class MealMaster(Integration):
current_recipe = ''
for fl in file.readlines():
line = fl.decode("windows-1250")
line = ""
try:
line = fl.decode("UTF-8")
except UnicodeDecodeError:
try:
line = fl.decode("windows-1250")
except Exception as e:
line = "ERROR DECODING LINE"
if (line.startswith('MMMMM') or line.startswith('-----')) and 'meal-master' in line.lower():
if current_recipe != '':
recipe_list.append(current_recipe)

View File

@@ -12,7 +12,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-22 20:15+0200\n"
"PO-Revision-Date: 2025-09-22 10:09+0000\n"
"PO-Revision-Date: 2025-11-18 07:01+0000\n"
"Last-Translator: Vincenzo Reale <smart2128vr@gmail.com>\n"
"Language-Team: Italian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/it/>\n"
@@ -21,7 +21,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 5.13.1\n"
"X-Generator: Weblate 5.13.3\n"
#: .\cookbook\forms.py:50
msgid "Default"
@@ -126,54 +126,52 @@ msgid "ferment"
msgstr "fermentare"
#: .\cookbook\helper\recipe_url_import.py:325
#, fuzzy
#| msgid "Last cooked"
msgid "slow cook"
msgstr "Cucinato di recente"
msgstr "cottura lenta"
#: .\cookbook\helper\recipe_url_import.py:326
msgid "egg boiler"
msgstr ""
msgstr "bollitore per uova"
#: .\cookbook\helper\recipe_url_import.py:327
msgid "kettle"
msgstr ""
msgstr "teiera"
#: .\cookbook\helper\recipe_url_import.py:328
msgid "blend"
msgstr ""
msgstr "miscela"
#: .\cookbook\helper\recipe_url_import.py:329
msgid "pre-clean"
msgstr ""
msgstr "pre-pulizia"
#: .\cookbook\helper\recipe_url_import.py:330
msgid "high temperature"
msgstr ""
msgstr "alta temperatura"
#: .\cookbook\helper\recipe_url_import.py:331
msgid "rice cooker"
msgstr ""
msgstr "cuociriso"
#: .\cookbook\helper\recipe_url_import.py:332
msgid "caramelize"
msgstr ""
msgstr "caramellare"
#: .\cookbook\helper\recipe_url_import.py:333
msgid "peeler"
msgstr ""
msgstr "pelapatate"
#: .\cookbook\helper\recipe_url_import.py:334
msgid "slicer"
msgstr ""
msgstr "affettatrice"
#: .\cookbook\helper\recipe_url_import.py:335
msgid "grater"
msgstr ""
msgstr "grattugia"
#: .\cookbook\helper\recipe_url_import.py:336
msgid "spiralizer"
msgstr ""
msgstr "tagliaverdure a spirale"
#: .\cookbook\helper\recipe_url_import.py:337
msgid "sous-vide"
@@ -235,7 +233,7 @@ msgstr "Carboidrati"
#: .\cookbook\integration\mealie1.py:212
msgid "Cholesterol"
msgstr ""
msgstr "Colesterolo"
#: .\cookbook\integration\mealie1.py:213
#: .\cookbook\migrations\0190_auto_20230525_1506.py:17
@@ -244,33 +242,31 @@ msgstr "Grassi"
#: .\cookbook\integration\mealie1.py:214
msgid "Fiber"
msgstr ""
msgstr "Fibra"
#: .\cookbook\integration\mealie1.py:215
#, fuzzy
#| msgid "Proteins"
msgid "Protein"
msgstr "Proteine"
msgstr "Proteina"
#: .\cookbook\integration\mealie1.py:216
msgid "Saturated Fat"
msgstr ""
msgstr "Grasso saturo"
#: .\cookbook\integration\mealie1.py:217
msgid "Sodium"
msgstr ""
msgstr "Sodio"
#: .\cookbook\integration\mealie1.py:218
msgid "Sugar"
msgstr ""
msgstr "Zucchero"
#: .\cookbook\integration\mealie1.py:219
msgid "Trans Fat"
msgstr ""
msgstr "Grasso trans"
#: .\cookbook\integration\mealie1.py:220
msgid "Unsaturated Fat"
msgstr ""
msgstr "Grasso insaturo"
#: .\cookbook\integration\openeats.py:28
msgid "Recipe source:"
@@ -484,7 +480,7 @@ msgstr "Hai raggiungo il limite per il caricamento dei file."
#: .\cookbook\serializer.py:281
msgid "The given file type is not allowed."
msgstr ""
msgstr "Il tipo di filo specificato non è consentito."
#: .\cookbook\serializer.py:421 .\cookbook\views\views.py:94
msgid ""
@@ -493,7 +489,7 @@ msgstr "Hai raggiunto il numero massimo di istanze di tua proprietà."
#: .\cookbook\serializer.py:434
msgid "Space Name must be unique."
msgstr ""
msgstr "Il nome dello spazio deve essere univoco."
#: .\cookbook\serializer.py:469
msgid "Cannot modify Space owner permission."
@@ -847,10 +843,8 @@ msgid "We are sorry, but the sign up is currently closed."
msgstr "Spiacenti, al momento le iscrizioni sono chiuse."
#: .\cookbook\templates\frontend\tandoor.html:15
#, fuzzy
#| msgid "Tandoor Recipes Invite"
msgid "Tandoor Recipe Manager"
msgstr "Invito per Tandoor Recipes"
msgstr "Gestore delle ricette Tandoor"
#: .\cookbook\templates\index.html:28
msgid "Search recipe ..."
@@ -1442,8 +1436,6 @@ msgstr ""
" %(site_name)s. Per finire, completa il modulo seguente:"
#: .\cookbook\templates\socialaccount\signup.html:32
#, fuzzy
#| msgid "I accept the follwoing"
msgid "I accept the following"
msgstr "Accetto i seguenti"
@@ -1529,15 +1521,6 @@ msgid "System"
msgstr "Sistema"
#: .\cookbook\templates\system.html:24
#, fuzzy
#| msgid ""
#| "\n"
#| " Django Recipes is an open source free software application. It "
#| "can be found on\n"
#| " <a href=\"https://github.com/vabene1111/recipes\">GitHub</a>.\n"
#| " Changelogs can be found <a href=\"https://github.com/vabene1111/"
#| "recipes/releases\">here</a>.\n"
#| " "
msgid ""
"\n"
" Tandoor Recipes is an open source free software application. It can "
@@ -1548,11 +1531,11 @@ msgid ""
" "
msgstr ""
"\n"
" Django Recipes è una applicazione gratuita e open source. È "
" Tandoor Recipes è una applicazione gratuita e open source. È "
"disponibile su\n"
" <a href=\"https://github.com/vabene1111/recipes\">GitHub</a>.\n"
" Puoi consultare le ultime novità <a href=\"https://github.com/"
"vabene1111/recipes/releases\">qui</a>.\n"
" <a href=\"https://github.com/TandoorRecipes/recipes\">GitHub</a>.\n"
" Puoi consultare le ultime novità <a href="
"\"https://github.com/TandoorRecipes/recipes/releases\">qui</a>.\n"
" "
#: .\cookbook\templates\system.html:30
@@ -1574,7 +1557,7 @@ msgstr ""
#: .\cookbook\templates\system.html:56
msgid "Plugins"
msgstr ""
msgstr "Estensioni"
#: .\cookbook\templates\system.html:67
msgid "Media Serving"
@@ -1802,18 +1785,12 @@ msgid "{obj.name} was added to the shopping list."
msgstr "{obj.name} è stato aggiunto alla lista della spesa."
#: .\cookbook\views\api.py:1239
#, fuzzy
#| msgid "Filter meal plans from date (inclusive) in the format of YYYY-MM-DD."
msgid "Filter meal plans from date (inclusive)."
msgstr ""
"Filtra i piani alimentari in base alla data (inclusa) nel formato AAAA-MM-GG."
msgstr "Filtra i piani alimentari dalla data (inclusa)."
#: .\cookbook\views\api.py:1241
#, fuzzy
#| msgid "Filter meal plans to date (inclusive) in the format of YYYY-MM-DD."
msgid "Filter meal plans to date (inclusive)."
msgstr ""
"Filtra i piani alimentari fino alla data (inclusa) nel formato AAAA-MM-GG."
msgstr "Filtra i piani alimentari fino alla data (inclusa)."
#: .\cookbook\views\api.py:1244
msgid "Filter meal plans with MealType ID. For multiple repeat parameter."
@@ -1940,115 +1917,70 @@ msgstr "ID dell'unità che una ricetta dovrebbe avere."
#: .\cookbook\views\api.py:1464
msgid "Exact rating of recipe"
msgstr ""
msgstr "Valutazione precisa della ricetta"
#: .\cookbook\views\api.py:1465
#, fuzzy
#| msgid "ID of unit a recipe should have."
msgid "Rating a recipe should have or greater."
msgstr "ID dell'unità che una ricetta dovrebbe avere."
msgstr "La valutazione che una ricetta dovrebbe avere o superiore."
#: .\cookbook\views\api.py:1466
#, fuzzy
#| msgid "ID of unit a recipe should have."
msgid "Rating a recipe should have or smaller."
msgstr "ID dell'unità che una ricetta dovrebbe avere."
msgstr "La valutazione che una ricetta dovrebbe avere o inferiore."
#: .\cookbook\views\api.py:1468
msgid "Filter recipes cooked X times."
msgstr ""
msgstr "Filtra le ricette cucinate N volte."
#: .\cookbook\views\api.py:1469
#, fuzzy
#| msgid ""
#| "Filter recipes cooked X times or more. Negative values returns cooked "
#| "less than X times"
msgid "Filter recipes cooked X times or more."
msgstr ""
"Filtra le ricette cucinate X volte o più. I valori negativi restituiscono "
"ricette cucinate meno di X volte"
msgstr "Filtra le ricette cucinate N volte o più."
#: .\cookbook\views\api.py:1470
msgid "Filter recipes cooked X times or less."
msgstr ""
msgstr "Filtra le ricette cucinate N volte o meno."
#: .\cookbook\views\api.py:1472
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Filter recipes created on the given date."
msgstr "Filtra le voci con la ricetta specificata"
msgstr "Filtra create alla data specificata."
#: .\cookbook\views\api.py:1473
#, fuzzy
#| msgid ""
#| "Filter recipes created on or after YYYY-MM-DD. Prepending - filters on or "
#| "before date."
msgid "Filter recipes created on the given date or after."
msgstr ""
"Filtra le ricette create il o dopo AAAA-MM-GG. Anteponendo: filtra alla data "
"o prima della data."
msgstr "Filtra le ricette create alla data specificata o dopo."
#: .\cookbook\views\api.py:1474
#, fuzzy
#| msgid ""
#| "Filter recipes created on or after YYYY-MM-DD. Prepending - filters on or "
#| "before date."
msgid "Filter recipes created on the given date or before."
msgstr ""
"Filtra le ricette create il o dopo AAAA-MM-GG. Anteponendo: filtra alla data "
"o prima della data."
msgstr "Filtra le ricette create alla data specificata o prima."
#: .\cookbook\views\api.py:1476 .\cookbook\views\api.py:1477
#: .\cookbook\views\api.py:1478
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Filter recipes updated on the given date."
msgstr "Filtra le voci con la ricetta specificata"
msgstr "Filtra le ricette aggiornate alla data specificata."
#: .\cookbook\views\api.py:1480
#, fuzzy
#| msgid ""
#| "Filter recipes last cooked on or after YYYY-MM-DD. Prepending - filters "
#| "on or before date."
msgid "Filter recipes last cooked on the given date or after."
msgstr ""
"Filtra le ricette cucinate l'ultima volta il o dopo AAAA-MM-GG. Anteponendo "
"- filtra alla data o prima della data."
msgstr "Filtra le ricette cucinate l'ultima volta alla data specificata o dopo."
#: .\cookbook\views\api.py:1481
#, fuzzy
#| msgid ""
#| "Filter recipes last cooked on or after YYYY-MM-DD. Prepending - filters "
#| "on or before date."
msgid "Filter recipes last cooked on the given date or before."
msgstr ""
"Filtra le ricette cucinate l'ultima volta il o dopo AAAA-MM-GG. Anteponendo "
"- filtra alla data o prima della data."
"Filtra le ricette cucinate l'ultima volta alla data specificata o prima."
#: .\cookbook\views\api.py:1483 .\cookbook\views\api.py:1484
#, fuzzy
#| msgid ""
#| "Filter recipes lasts viewed on or after YYYY-MM-DD. Prepending - filters "
#| "on or before date."
msgid "Filter recipes lasts viewed on the given date."
msgstr ""
"Filtra le ricette visualizzate per ultime il o dopo AAAA-MM-GG. Anteponendo "
"- filtra alla data o prima della data."
msgstr "Filtra le ricette visualizzate per ultime alla data specificata."
#: .\cookbook\views\api.py:1486
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Filter recipes for ones created by the given user ID"
msgstr "Filtra le voci con la ricetta specificata"
msgstr "Filtra le ricette create dall'ID utente specificato"
#: .\cookbook\views\api.py:1487
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
msgstr ""
"Se devono essere restituite solo le ricette interne. [vero/<b>falso</b>]"
"Se devono essere restituite solo le ricette interne. [true/<b>false</b>]"
#: .\cookbook\views\api.py:1488
msgid "Returns the results in randomized order. [true/<b>false</b>]"
msgstr "Restituisce i risultati in ordine casuale. [vero/<b>falso</b>]"
msgstr "Restituisce i risultati in ordine casuale. [true/<b>false</b>]"
#: .\cookbook\views\api.py:1490
msgid ""
@@ -2056,6 +1988,9 @@ msgid ""
"lastcooked,-lastcooked,rating,-rating,times_cooked,-times_cooked,created_at,-"
"created_at,lastviewed,-lastviewed"
msgstr ""
"Determina l'ordine dei risultati. Le opzioni sono: "
"score,-score,name,-name,lastcooked,-lastcooked,rating,-rating,times_cooked,-times_cooked,created_at,-created_at,lastviewed,-lastviewed"
""
#: .\cookbook\views\api.py:1492
msgid "Returns new results first in search results. [true/<b>false</b>]"
@@ -2068,10 +2003,14 @@ msgid ""
"Returns the given number of recently viewed recipes before search results "
"(if given)"
msgstr ""
"Restituisce il numero specificato di ricette visualizzate di recente prima "
"dei risultati di ricerca (se indicati)"
#: .\cookbook\views\api.py:1494
msgid "ID of a custom filter. Returns all recipes matched by that filter."
msgstr ""
"ID di un filtro personalizzato. Restituisce tutte le ricette verificate da "
"quel filtro."
#: .\cookbook\views\api.py:1495
msgid "Filter recipes that can be made with OnHand food. [true/<b>false</b>]"
@@ -2084,48 +2023,47 @@ msgid ""
"Return the PropertyTypes matching the property category. Repeat for "
"multiple."
msgstr ""
"Restituisci i PropertyTypes corrispondenti alla categoria di proprietà. "
"Ripeti per più di uno."
#: .\cookbook\views\api.py:1804 .\cookbook\views\api.py:1860
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Returns only entries associated with the given mealplan id"
msgstr "Filtra le voci con la ricetta specificata"
msgstr ""
"Restituisce solo le voci associate all'ID del piano alimentare specificato"
#: .\cookbook\views\api.py:1858
msgid ""
"Returns only elements updated after the given timestamp in ISO 8601 format."
msgstr ""
"Restituisce solo gli elementi aggiornati dopo la marca temporale specificata "
"nel formato ISO 8601."
#: .\cookbook\views\api.py:2031
#, fuzzy
#| msgid ""
#| "Return the Automations matching the automation type. Multiple values "
#| "allowed."
msgid ""
"Return the Automations matching the automation type. Repeat for multiple."
msgstr ""
"Restituisce le automazioni corrispondenti al tipo di automazione. Sono "
"consentiti più valori."
"Restituisci le automazioni corrispondenti al tipo di automazione. Ripeti per "
"più automazioni."
#: .\cookbook\views\api.py:2048
msgid ""
"Text field to store data that gets carried over to the UserSpace created "
"from the InviteLink"
msgstr ""
"Campo di testo per memorizzare i dati che vengono trasferiti allo spazio "
"utente creato dal collegamento di invito"
#: .\cookbook\views\api.py:2049
msgid "Only return InviteLinks that have not been used yet."
msgstr ""
"Restituisci solo i collegamenti di invito che non sono ancora stati "
"utilizzati."
#: .\cookbook\views\api.py:2076
#, fuzzy
#| msgid ""
#| "Return the Automations matching the automation type. Multiple values "
#| "allowed."
msgid "Return the CustomFilters matching the model type. Repeat for multiple."
msgstr ""
"Restituisce le automazioni corrispondenti al tipo di automazione. Sono "
"consentiti più valori."
"Restituisci i CustomFilters corrispondenti al tipo di modello. Ripeti per "
"più di un modello."
#: .\cookbook\views\api.py:2176
msgid "Nothing to do."
@@ -2149,13 +2087,15 @@ msgstr "Nessuna informazione utilizzabile è stata trovata."
#: .\cookbook\views\api.py:2286 .\cookbook\views\api.py:2434
msgid "You must select an AI provider to perform your request."
msgstr ""
msgstr "Devi selezionare un fornitore AI per eseguire la tua richiesta."
#: .\cookbook\views\api.py:2293 .\cookbook\views\api.py:2441
msgid ""
"You don't have any credits remaining to use AI or AI features are not "
"enabled for your space."
msgstr ""
"Non hai credito rimanente per utilizzare l'AI o le funzionalità di AI "
"abilitate per il tuo spazio."
#: .\cookbook\views\api.py:2499 .\cookbook\views\api.py:2667
msgid "File is above space limit"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-22 20:15+0200\n"
"PO-Revision-Date: 2024-11-19 06:58+0000\n"
"PO-Revision-Date: 2025-11-15 12:08+0000\n"
"Last-Translator: \"Matjaž T.\" <matjaz@moj-svet.si>\n"
"Language-Team: Slovenian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/sl/>\n"
@@ -16,9 +16,9 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
"%100==4 ? 2 : 3;\n"
"X-Generator: Weblate 5.6.2\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || "
"n%100==4 ? 2 : 3;\n"
"X-Generator: Weblate 5.13.3\n"
#: .\cookbook\forms.py:50
msgid "Default"
@@ -123,51 +123,51 @@ msgstr "fermentiramo"
#: .\cookbook\helper\recipe_url_import.py:325
msgid "slow cook"
msgstr ""
msgstr "počasno kuhanje"
#: .\cookbook\helper\recipe_url_import.py:326
msgid "egg boiler"
msgstr ""
msgstr "kuhalnik jajc"
#: .\cookbook\helper\recipe_url_import.py:327
msgid "kettle"
msgstr ""
msgstr "kotel"
#: .\cookbook\helper\recipe_url_import.py:328
msgid "blend"
msgstr ""
msgstr "mešanica"
#: .\cookbook\helper\recipe_url_import.py:329
msgid "pre-clean"
msgstr ""
msgstr "predhodno čiščenje"
#: .\cookbook\helper\recipe_url_import.py:330
msgid "high temperature"
msgstr ""
msgstr "visoka temperatura"
#: .\cookbook\helper\recipe_url_import.py:331
msgid "rice cooker"
msgstr ""
msgstr "kuhalnik riža"
#: .\cookbook\helper\recipe_url_import.py:332
msgid "caramelize"
msgstr ""
msgstr "karamelizirati"
#: .\cookbook\helper\recipe_url_import.py:333
msgid "peeler"
msgstr ""
msgstr "lupilec"
#: .\cookbook\helper\recipe_url_import.py:334
msgid "slicer"
msgstr ""
msgstr "rezalnik"
#: .\cookbook\helper\recipe_url_import.py:335
msgid "grater"
msgstr ""
msgstr "strgalo"
#: .\cookbook\helper\recipe_url_import.py:336
msgid "spiralizer"
msgstr ""
msgstr "spiralizator"
#: .\cookbook\helper\recipe_url_import.py:337
msgid "sous-vide"
@@ -229,7 +229,7 @@ msgstr "Ogljikovi hidrati"
#: .\cookbook\integration\mealie1.py:212
msgid "Cholesterol"
msgstr ""
msgstr "Holesterol"
#: .\cookbook\integration\mealie1.py:213
#: .\cookbook\migrations\0190_auto_20230525_1506.py:17
@@ -238,33 +238,31 @@ msgstr "Maščoba"
#: .\cookbook\integration\mealie1.py:214
msgid "Fiber"
msgstr ""
msgstr "Vlaknine"
#: .\cookbook\integration\mealie1.py:215
#, fuzzy
#| msgid "Proteins"
msgid "Protein"
msgstr "Beljakovine"
#: .\cookbook\integration\mealie1.py:216
msgid "Saturated Fat"
msgstr ""
msgstr "Nasičene maščobe"
#: .\cookbook\integration\mealie1.py:217
msgid "Sodium"
msgstr ""
msgstr "Natrij"
#: .\cookbook\integration\mealie1.py:218
msgid "Sugar"
msgstr ""
msgstr "Sladkor"
#: .\cookbook\integration\mealie1.py:219
msgid "Trans Fat"
msgstr ""
msgstr "Trans maščobe"
#: .\cookbook\integration\mealie1.py:220
msgid "Unsaturated Fat"
msgstr ""
msgstr "Nenasičene maščobe"
#: .\cookbook\integration\openeats.py:28
msgid "Recipe source:"
@@ -478,7 +476,7 @@ msgstr "Dosegli ste omejitev nalaganja datotek."
#: .\cookbook\serializer.py:281
msgid "The given file type is not allowed."
msgstr ""
msgstr "Navedena vrsta datoteke ni dovoljena."
#: .\cookbook\serializer.py:421 .\cookbook\views\views.py:94
msgid ""
@@ -487,7 +485,7 @@ msgstr "Dosegli ste največje število prostorov, ki so lahko v vaši lasti."
#: .\cookbook\serializer.py:434
msgid "Space Name must be unique."
msgstr ""
msgstr "Ime prostora mora biti edinstveno."
#: .\cookbook\serializer.py:469
msgid "Cannot modify Space owner permission."
@@ -838,10 +836,8 @@ msgid "We are sorry, but the sign up is currently closed."
msgstr "Žal nam je, vendar so registracije trenutno zaprte."
#: .\cookbook\templates\frontend\tandoor.html:15
#, fuzzy
#| msgid "Tandoor Recipes Invite"
msgid "Tandoor Recipe Manager"
msgstr "Tandoor Recepti vabilo"
msgstr "Urejevalnik Tandoor Recepti"
#: .\cookbook\templates\index.html:28
msgid "Search recipe ..."
@@ -1428,8 +1424,6 @@ msgstr ""
" %(site_name)s. Kot zadnji korak izpolnite naslednji obrazec:"
#: .\cookbook\templates\socialaccount\signup.html:32
#, fuzzy
#| msgid "I accept the follwoing"
msgid "I accept the following"
msgstr "Sprejemam naslednje"
@@ -1514,15 +1508,6 @@ msgid "System"
msgstr "Sistem"
#: .\cookbook\templates\system.html:24
#, fuzzy
#| msgid ""
#| "\n"
#| " Django Recipes is an open source free software application. It "
#| "can be found on\n"
#| " <a href=\"https://github.com/vabene1111/recipes\">GitHub</a>.\n"
#| " Changelogs can be found <a href=\"https://github.com/vabene1111/"
#| "recipes/releases\">here</a>.\n"
#| " "
msgid ""
"\n"
" Tandoor Recipes is an open source free software application. It can "
@@ -1533,11 +1518,11 @@ msgid ""
" "
msgstr ""
"\n"
" Django Recipes je odprtokodna brezplačna programska aplikacija. "
"Najdete ga na GitHub\n"
" <a href=\"https://github.com/vabene1111/recipes\"></a>.\n"
" Dnevnike sprememb lahko najdete tukaj <a href=\"https://github.com/"
"vabene1111/recipes/releases\"></a>.\n"
" Tandoor Recipes je odprtokodna brezplačna programska oprema. Najdete "
"jo na\n"
" <a href=\"https://github.com/TandoorRecipes/recipes\">GitHub</a>.\n"
" Dnevnike sprememb najdete <a href="
"\"https://github.com/TandoorRecipes/recipes/releases\">tukaj</a>.\n"
" "
#: .\cookbook\templates\system.html:30
@@ -1559,7 +1544,7 @@ msgstr ""
#: .\cookbook\templates\system.html:56
msgid "Plugins"
msgstr ""
msgstr "Vtičniki"
#: .\cookbook\templates\system.html:67
msgid "Media Serving"
@@ -1789,16 +1774,12 @@ msgid "{obj.name} was added to the shopping list."
msgstr "{obj.name} je bil dodan na nakupovalni seznam."
#: .\cookbook\views\api.py:1239
#, fuzzy
#| msgid "Filter meal plans from date (inclusive) in the format of YYYY-MM-DD."
msgid "Filter meal plans from date (inclusive)."
msgstr "Filtrirajte načrte obrokov od datuma (vključno) v obliki LLLL-MM-DD."
msgstr "Filtriraj načrte obrokov od datuma (vključno)."
#: .\cookbook\views\api.py:1241
#, fuzzy
#| msgid "Filter meal plans to date (inclusive) in the format of YYYY-MM-DD."
msgid "Filter meal plans to date (inclusive)."
msgstr "Filtrirajte dosedanje načrte obrokov (vključno) v obliki LLLL-MM-DD."
msgstr "Filtriraj načrte obrokov do danes (vključno)."
#: .\cookbook\views\api.py:1244
msgid "Filter meal plans with MealType ID. For multiple repeat parameter."
@@ -1905,106 +1886,62 @@ msgstr "ID enote, ki bi jo moral imeti recept."
#: .\cookbook\views\api.py:1464
msgid "Exact rating of recipe"
msgstr ""
msgstr "Natančna ocena recepta"
#: .\cookbook\views\api.py:1465
#, fuzzy
#| msgid "ID of unit a recipe should have."
msgid "Rating a recipe should have or greater."
msgstr "ID enote, ki bi jo moral imeti recept."
msgstr "Ocena, ki bi jo moral imeti recept, ali višja."
#: .\cookbook\views\api.py:1466
#, fuzzy
#| msgid "ID of unit a recipe should have."
msgid "Rating a recipe should have or smaller."
msgstr "ID enote, ki bi jo moral imeti recept."
msgstr "Ocena, ki jo mora imeti recept, je 1 ali manjša."
#: .\cookbook\views\api.py:1468
msgid "Filter recipes cooked X times."
msgstr ""
msgstr "Filtriraj recepte, kuhane X-krat."
#: .\cookbook\views\api.py:1469
#, fuzzy
#| msgid ""
#| "Filter recipes cooked X times or more. Negative values returns cooked "
#| "less than X times"
msgid "Filter recipes cooked X times or more."
msgstr ""
"Filtrirajte recepte, kuhane X-krat ali večkrat. Negativne vrednosti se "
"vrnejo kuhane manj kot X-krat"
msgstr "Filtriraj recepte, kuhane X-krat ali večkrat."
#: .\cookbook\views\api.py:1470
msgid "Filter recipes cooked X times or less."
msgstr ""
msgstr "Filtriraj recepte, kuhane X-krat ali manj."
#: .\cookbook\views\api.py:1472
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Filter recipes created on the given date."
msgstr "Filter za vnose z danim receptom"
msgstr "Filtriraj recepte, ustvarjene na določen datum."
#: .\cookbook\views\api.py:1473
#, fuzzy
#| msgid ""
#| "Filter recipes created on or after YYYY-MM-DD. Prepending - filters on or "
#| "before date."
msgid "Filter recipes created on the given date or after."
msgstr ""
"Filtrirajte recepte, ustvarjene LLLL-MM-DD ali pozneje. Pred - filtrira na "
"ali pred datumom."
msgstr "Filtriraj recepte, ustvarjene na določen datum ali pozneje."
#: .\cookbook\views\api.py:1474
#, fuzzy
#| msgid ""
#| "Filter recipes created on or after YYYY-MM-DD. Prepending - filters on or "
#| "before date."
msgid "Filter recipes created on the given date or before."
msgstr ""
"Filtrirajte recepte, ustvarjene LLLL-MM-DD ali pozneje. Pred - filtrira na "
"ali pred datumom."
msgstr "Filtriraj recepte, ustvarjene na določen datum ali prej."
#: .\cookbook\views\api.py:1476 .\cookbook\views\api.py:1477
#: .\cookbook\views\api.py:1478
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Filter recipes updated on the given date."
msgstr "Filter za vnose z danim receptom"
msgstr "Filtriraj recepte, posodobljene na navedeni datum."
#: .\cookbook\views\api.py:1480
#, fuzzy
#| msgid ""
#| "Filter recipes last cooked on or after YYYY-MM-DD. Prepending - filters "
#| "on or before date."
msgid "Filter recipes last cooked on the given date or after."
msgstr ""
"Filtriraj recepte, nazadnje kuhane LLLL-MM-DD ali pozneje. Pred - filtrira "
"na ali pred datumom."
"Filtriraj recepte, ki so bili nazadnje kuhani na določen datum ali pozneje."
#: .\cookbook\views\api.py:1481
#, fuzzy
#| msgid ""
#| "Filter recipes last cooked on or after YYYY-MM-DD. Prepending - filters "
#| "on or before date."
msgid "Filter recipes last cooked on the given date or before."
msgstr ""
"Filtriraj recepte, nazadnje kuhane LLLL-MM-DD ali pozneje. Pred - filtrira "
"na ali pred datumom."
"Filtriraj recepte, ki so bili nazadnje kuhani na določen datum ali prej."
#: .\cookbook\views\api.py:1483 .\cookbook\views\api.py:1484
#, fuzzy
#| msgid ""
#| "Filter recipes lasts viewed on or after YYYY-MM-DD. Prepending - filters "
#| "on or before date."
msgid "Filter recipes lasts viewed on the given date."
msgstr ""
"Recepti filtrov so zadnjič prikazani LLLL-MM-DD ali pozneje. Pred - filtrira "
"na ali pred datumom."
msgstr "Filtriraj recepte, ki so bili nazadnje ogledani na določen datum."
#: .\cookbook\views\api.py:1486
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Filter recipes for ones created by the given user ID"
msgstr "Filter za vnose z danim receptom"
msgstr "Filtriraj recepte po tistih, ki jih je ustvaril dani uporabniški ID"
#: .\cookbook\views\api.py:1487
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
@@ -2021,6 +1958,9 @@ msgid ""
"lastcooked,-lastcooked,rating,-rating,times_cooked,-times_cooked,created_at,-"
"created_at,lastviewed,-lastviewed"
msgstr ""
"Določa vrstni red rezultatov. Možnosti so: "
"score,-score,name,-name,lastcooked,-lastcooked,rating,-rating,times_cooked,-times_cooked,created_at,-created_at,lastviewed,-lastviewed"
""
#: .\cookbook\views\api.py:1492
msgid "Returns new results first in search results. [true/<b>false</b>]"
@@ -2031,10 +1971,12 @@ msgid ""
"Returns the given number of recently viewed recipes before search results "
"(if given)"
msgstr ""
"Vrne podano število nedavno ogledanih receptov pred rezultati iskanja "
"(če je podano)"
#: .\cookbook\views\api.py:1494
msgid "ID of a custom filter. Returns all recipes matched by that filter."
msgstr ""
msgstr "ID filtra po meri. Vrne vse recepte, ki se ujemajo s tem filtrom."
#: .\cookbook\views\api.py:1495
msgid "Filter recipes that can be made with OnHand food. [true/<b>false</b>]"
@@ -2047,48 +1989,43 @@ msgid ""
"Return the PropertyTypes matching the property category. Repeat for "
"multiple."
msgstr ""
"Vrne vrste lastnosti (PropertyTypes), ki ustrezajo kategoriji lastnosti. "
"Ponovite za več vrst lastnosti."
#: .\cookbook\views\api.py:1804 .\cookbook\views\api.py:1860
#, fuzzy
#| msgid "Filter for entries with the given recipe"
msgid "Returns only entries associated with the given mealplan id"
msgstr "Filter za vnose z danim receptom"
msgstr "Vrne samo vnose, povezane z danim ID-jem načrta obrokov"
#: .\cookbook\views\api.py:1858
msgid ""
"Returns only elements updated after the given timestamp in ISO 8601 format."
msgstr ""
"Vrne samo elemente, posodobljene po danem časovnem žigu v formatu ISO 8601."
#: .\cookbook\views\api.py:2031
#, fuzzy
#| msgid ""
#| "Return the Automations matching the automation type. Multiple values "
#| "allowed."
msgid ""
"Return the Automations matching the automation type. Repeat for multiple."
msgstr ""
"Vrnite avtomatizacije, ki ustrezajo vrsti avtomatizacije. Dovoljenih je "
"več vrednosti."
"Vrne avtomatizacije, ki ustrezajo vrsti avtomatizacije. Ponovite za več "
"avtomatizacij."
#: .\cookbook\views\api.py:2048
msgid ""
"Text field to store data that gets carried over to the UserSpace created "
"from the InviteLink"
msgstr ""
"Besedilno polje za shranjevanje podatkov, ki se prenesejo v uporabniški "
"prostor, ustvarjen iz InviteLink"
#: .\cookbook\views\api.py:2049
msgid "Only return InviteLinks that have not been used yet."
msgstr ""
msgstr "Vrni samo povezave InviteLink, ki še niso bile uporabljene."
#: .\cookbook\views\api.py:2076
#, fuzzy
#| msgid ""
#| "Return the Automations matching the automation type. Multiple values "
#| "allowed."
msgid "Return the CustomFilters matching the model type. Repeat for multiple."
msgstr ""
"Vrnite avtomatizacije, ki ustrezajo vrsti avtomatizacije. Dovoljenih je "
"več vrednosti."
"Vrne filtre CustomFilters, ki ustrezajo vrsti modela. Ponovite za več "
"filtrov."
#: .\cookbook\views\api.py:2176
msgid "Nothing to do."
@@ -2112,13 +2049,15 @@ msgstr "Uporabnih podatkov ni bilo mogoče najti."
#: .\cookbook\views\api.py:2286 .\cookbook\views\api.py:2434
msgid "You must select an AI provider to perform your request."
msgstr ""
msgstr "Za izvedbo vaše zahteve morate izbrati ponudnika umetne inteligence."
#: .\cookbook\views\api.py:2293 .\cookbook\views\api.py:2441
msgid ""
"You don't have any credits remaining to use AI or AI features are not "
"enabled for your space."
msgstr ""
"Nimate več kreditov za uporabo umetne inteligence ali pa funkcije umetne "
"inteligence niso omogočene za vaš prostor."
#: .\cookbook\views\api.py:2499 .\cookbook\views\api.py:2667
msgid "File is above space limit"

File diff suppressed because it is too large Load Diff

View File

@@ -307,7 +307,8 @@ class FuzzyFilterMixin(viewsets.ModelViewSet, ExtendedRecipeMixin):
filter = Q(name__icontains=query)
if self.request.user.is_authenticated:
if any([self.model.__name__.lower() in x for x in
self.request.user.searchpreference.unaccent.values_list('field', flat=True)]):
self.request.user.searchpreference.unaccent.values_list('field', flat=True)]) and (
settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql'):
filter |= Q(name__unaccent__icontains=query)
self.queryset = (
@@ -2562,6 +2563,13 @@ class AiImportView(APIView):
'msg': "Error parsing AI results. Response Text:\n\n" + response_text
}
return Response(RecipeFromSourceResponseSerializer(context={'request': request}).to_representation(response), status=status.HTTP_400_BAD_REQUEST)
except Exception:
traceback.print_exc()
response = {
'error': True,
'msg': "Error processing AI results. Response Text:\n\n" + response_text + "\n\n" + traceback.format_exc()
}
return Response(RecipeFromSourceResponseSerializer(context={'request': request}).to_representation(response), status=status.HTTP_400_BAD_REQUEST)
else:
response = {
'error': True,
@@ -3049,11 +3057,20 @@ def meal_plans_to_ical(queryset, filename):
for p in queryset:
event = Event()
event['uid'] = p.id
event.add('dtstart', p.from_date)
start_date_time = p.from_date
end_date_time = p.from_date
if p.to_date:
event.add('dtend', p.to_date)
else:
event.add('dtend', p.from_date)
end_date_time = p.to_date
if p.meal_type.time:
start_date_time = datetime.datetime.combine(p.from_date, p.meal_type.time)
end_date_time = datetime.datetime.combine(p.to_date, p.meal_type.time) + datetime.timedelta(minutes=60)
event.add('dtstart', start_date_time)
event.add('dtend', end_date_time)
event['summary'] = f'{p.meal_type.name}: {p.get_label()}'
event['description'] = p.note
cal.add_component(event)

View File

@@ -43,7 +43,10 @@ def index(request, path=None, resource=None):
return HttpResponseRedirect(reverse_lazy('view_setup'))
if 'signup_token' in request.session:
return HttpResponseRedirect(reverse('view_invite', args=[request.session.pop('signup_token', '')]))
value = request.session['signup_token']
del request.session['signup_token']
request.session.modified = True
return HttpResponseRedirect(reverse('view_invite', args=[value]))
if request.user.is_authenticated or re.search(r'/recipe/\d+/', request.path[:512]) and request.GET.get('share'):
return render(request, 'frontend/tandoor.html', {})

View File

@@ -33,4 +33,4 @@ Convert pictures of recipes to a structure that can be imported to Tandoor with
Maintained by [smilerz](https://github.com/smilerz/tandoor-menu-generator)
Generate a mealplan tbased on complex criteria and optionally insert it into an SVG menu template.
Generate a meal plan based on complex criteria and optionally insert it into an SVG menu template.

View File

@@ -36,7 +36,7 @@ then make sure you have set [all required headers](install/docker.md#required-he
If that doesn't fix it, you can also refer to the appropriate sub section in the [reverse proxy documentation](install/docker.md#reverse-proxy) and verify your general webserver configuration.
### Required Headers
Navigate to `/system` and review the headers listed in the DEBUG section. At a minimum, if you are using a reverse proxy the headers must match the below conditions.
Navigate to `/system/` and review the headers listed in the DEBUG section. At a minimum, if you are using a reverse proxy the headers must match the below conditions.
| Header | Requirement |
| :--- | :---- |

View File

@@ -69,8 +69,6 @@ wget https://raw.githubusercontent.com/vabene1111/recipes/develop/docs/install/d
Most deployments will likely use a reverse proxy.
If your reverse proxy is not listed below, please refer to chapter [Others](#others).
#### **Traefik**
If you use Traefik, this configuration is the one for you.
@@ -115,6 +113,17 @@ wget https://raw.githubusercontent.com/vabene1111/recipes/develop/docs/install/d
{% include "./docker/nginx-proxy/docker-compose.yml" %}
~~~
#### **Apache proxy**
If you use Apache as a reverse proxy, this configuration is the one for you.
~~~yaml
{% include "./docker/apache-proxy/docker-compose.yml" %}
~~~
Keep in mind, that the port configured for the service `web_recipes` should be the same as in chapter [Required Headers: Apache](#apache).
## **DockSTARTer**
The main goal of [DockSTARTer](https://dockstarter.com/) is to make it quick and easy to get up and running with Docker.
@@ -139,7 +148,8 @@ if you manually change it/bind the folder as a volume.
Please be sure to supply all required headers in your nginx/Apache/Caddy/... configuration!
nginx:
#### **nginx**
```nginx
location / {
proxy_set_header Host $http_host; # try $host instead if this doesn't work
@@ -149,7 +159,8 @@ location / {
}
```
Apache:
#### **Apache**
```apache
RequestHeader set X-Forwarded-Proto "https"
Header always set Access-Control-Allow-Origin "*"

View File

@@ -0,0 +1,24 @@
services:
db_recipes:
restart: always
image: postgres:16-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
- ./.env
web_recipes:
restart: always
image: vabene1111/recipes
ports:
- 127.0.0.1:8080:80 # replace port
env_file:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
volumes:
staticfiles:

View File

@@ -77,10 +77,10 @@ Using binaries from the virtual env:
/var/www/recipes/bin/pip3 install -r requirements.txt
```
You will also need to install front end requirements and build them. For this navigate to the `./vue` folder and run
You will also need to install front end requirements and build them. For this navigate to the `./vue3` folder and run
```shell
cd ./vue
cd ./vue3
yarn install
yarn build
```
@@ -224,7 +224,7 @@ bin/python3 manage.py migrate
bin/python3 manage.py collectstatic --no-input
bin/python3 manage.py collectstatic_js_reverse
# change to frontend directory
cd vue
cd vue3
# install and build frontend
yarn install
yarn build

View File

@@ -189,6 +189,19 @@ See [Gunicorn docs](https://docs.gunicorn.org/en/stable/design.html#how-many-wor
GUNICORN_THREADS=2
```
#### Gunicorn Timeout
> default `30` - options `1-X`
Set the timeout in seconds of gunicorn when starting using `boot.sh` (all container installations).
The default is likely appropriate for most installations. However, if you are using a LLM which high response times gunicornmight time out during the wait until the LLM finished, in such cases you might want to increase the timeout.
See [Gunicorn docs]([https://docs.gunicorn.org/en/stable/design.html#how-many-workers](https://docs.gunicorn.org/en/stable/settings.html#timeout)) for default settings.
```
GUNICORN_TIMEOUT=30
```
#### Gunicorn Media
> default `0` - options `0`, `1`

View File

@@ -3,7 +3,7 @@ server {
listen [::]:${TANDOOR_PORT} ipv6only=on;
server_name localhost;
client_max_body_size 128M;
client_max_body_size 512M;
# serve media files
location /media {
@@ -21,6 +21,9 @@ server {
proxy_set_header Host $http_host;
proxy_pass http://unix:/run/tandoor.sock;
# param needed by django allauth sessions to log IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# disabled for now because it redirects to the error page and not back, also not showing html
#error_page 502 /errors/http502.html;
}

View File

@@ -675,4 +675,4 @@ DISABLE_EXTERNAL_CONNECTORS = extract_bool('DISABLE_EXTERNAL_CONNECTORS', False)
EXTERNAL_CONNECTORS_QUEUE_SIZE = int(os.getenv('EXTERNAL_CONNECTORS_QUEUE_SIZE', 100))
mimetypes.add_type("text/javascript", ".js", True)
mimetypes.add_type("text/javascript", ".mjs", True)
mimetypes.add_type("text/javascript", ".mjs", True)

View File

@@ -34,7 +34,7 @@ urlpatterns = [
),
]
if settings.DEBUG:
if settings.DEBUG and settings.DEBUG_TOOLBAR:
urlpatterns += path('__debug__/', include('debug_toolbar.urls')),
if settings.ENABLE_METRICS:

View File

@@ -1,18 +1,18 @@
Django==5.2.7
Django==5.2.8
cryptography===45.0.5
django-annoying==0.10.6
django-cleanup==9.0.0
django-crispy-forms==2.4
crispy-bootstrap4==2025.6
djangorestframework==3.16.1
drf-spectacular==0.27.1
drf-spectacular==0.28.0
drf-spectacular-sidecar==2025.8.1
drf-writable-nested==0.7.2
django-oauth-toolkit==2.4.0
django-debug-toolbar==4.3.0
django-debug-toolbar==6.0.0
bleach==6.2.0
gunicorn==23.0.0
lxml==5.3.1
lxml==6.0.2
Markdown==3.7
Pillow==11.3.0
psycopg2-binary==2.9.10
@@ -22,14 +22,14 @@ six==1.17.0
webdavclient3==3.14.6
whitenoise==6.8.2
icalendar==6.3.1
pyyaml==6.0.2
pyyaml==6.0.3
uritemplate==4.1.1
beautifulsoup4==4.12.3
microdata==0.8.0
mock==5.2.0
Jinja2==3.1.6
django-allauth[mfa,socialaccount]==65.9.0
recipe-scrapers==15.8.0
recipe-scrapers==15.10.0
django-scopes==2.0.0
django-treebeard==4.7.1
django-cors-headers==4.6.0
@@ -37,7 +37,7 @@ django-storages==1.14.6
boto3==1.28.75
django-prometheus==2.4.1
django-hCaptcha==0.2.0
python-ldap==3.4.4
python-ldap==3.4.5
django-auth-ldap==4.6.0
pyppeteer==2.0.0
pytubefix==9.2.2
@@ -53,7 +53,7 @@ django-vite==3.1.0
litellm==1.64.1
# Development
pytest==8.4.1
pytest==8.4.2
pytest-django==4.11.0
pytest-cov===6.2.1
pytest-factoryboy==2.8.1

View File

@@ -13,7 +13,7 @@
"@types/sortablejs": "^1.15.8",
"@vueform/multiselect": "^2.6.11",
"@vueuse/core": "^13.6.0",
"@vueuse/router": "^13.6.0",
"@vueuse/router": "^13.9.0",
"luxon": "^3.7.1",
"mavon-editor": "^3.0.1",
"pinia": "^3.0.2",
@@ -23,7 +23,7 @@
"vue-router": "^4.5.0",
"vue-simple-calendar": "7.1.0",
"vuedraggable": "^4.1.0",
"vuetify": "^3.9.7"
"vuetify": "^3.10.3"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
@@ -31,11 +31,11 @@
"@types/jsdom": "^21.1.7",
"@types/node": "^24.0.8",
"@vitejs/plugin-vue": "^6.0.0",
"@vue/tsconfig": "^0.7.0",
"@vue/tsconfig": "^0.8.1",
"esbuild-register": "^3.6.0",
"jsdom": "^26.1.0",
"typescript": "^5.8.3",
"vite": "7.1.5",
"vite": "7.1.11",
"vite-plugin-pwa": "^1.0.3",
"vite-plugin-vuetify": "^2.1.1",
"vue-tsc": "^3.0.6",

View File

@@ -1,10 +1,10 @@
<template>
<v-app>
<v-app-bar color="tandoor" flat density="comfortable" v-if="!useUserPreferenceStore().isAuthenticated">
<v-app-bar color="tandoor" flat density="comfortable" v-if="!useUserPreferenceStore().isAuthenticated && !useUserPreferenceStore().isPrintMode">
</v-app-bar>
<v-app-bar :color="useUserPreferenceStore().activeSpace.navBgColor ? useUserPreferenceStore().activeSpace.navBgColor : useUserPreferenceStore().userSettings.navBgColor"
flat density="comfortable" v-if="useUserPreferenceStore().isAuthenticated" :scroll-behavior="useUserPreferenceStore().userSettings.navSticky ? '' : 'hide'">
flat density="comfortable" v-if="useUserPreferenceStore().isAuthenticated && !useUserPreferenceStore().isPrintMode" :scroll-behavior="useUserPreferenceStore().userSettings.navSticky ? '' : 'hide'">
<router-link :to="{ name: 'StartPage', params: {} }">
<v-img src="../../assets/brand_logo.svg" width="140px" class="ms-2"
v-if="useUserPreferenceStore().userSettings.navShowLogo && !useUserPreferenceStore().activeSpace.navLogo"></v-img>
@@ -58,7 +58,7 @@
</p>
</v-app-bar>
<v-app-bar color="info" density="compact" v-if="useUserPreferenceStore().isAuthenticated && useUserPreferenceStore().activeSpace.message != ''">
<v-app-bar color="info" density="compact" v-if="useUserPreferenceStore().isAuthenticated && useUserPreferenceStore().activeSpace.message != '' && !useUserPreferenceStore().isPrintMode">
<p class="text-center w-100">
{{ useUserPreferenceStore().activeSpace.message }}
</p>
@@ -69,7 +69,7 @@
</v-main>
<!-- completely hide in print mode because setting d-print-node keeps layout -->
<v-navigation-drawer v-if="lgAndUp && useUserPreferenceStore().isAuthenticated && !isPrintMode">
<v-navigation-drawer v-if="lgAndUp && useUserPreferenceStore().isAuthenticated && !useUserPreferenceStore().isPrintMode">
<v-list nav>
<v-list-item :to="{ name: 'SettingsPage', params: {} }">
<template #prepend>
@@ -96,7 +96,7 @@
</v-navigation-drawer>
<v-bottom-navigation grow v-if="useUserPreferenceStore().isAuthenticated && !lgAndUp">
<v-bottom-navigation grow v-if="useUserPreferenceStore().isAuthenticated && !lgAndUp && !useUserPreferenceStore().isPrintMode">
<v-btn value="recent" :to="{ name: 'StartPage', params: {} }">
<v-icon icon="fa-fw fas fa-book "/>
</v-btn>
@@ -131,43 +131,44 @@
<script lang="ts" setup>
import GlobalSearchDialog from "@/components/inputs/GlobalSearchDialog.vue"
import {useDisplay} from "vuetify"
import {useDisplay, useLocale} from "vuetify"
import VSnackbarQueued from "@/components/display/VSnackbarQueued.vue";
import MessageListDialog from "@/components/dialogs/MessageListDialog.vue";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import NavigationDrawerContextMenu from "@/components/display/NavigationDrawerContextMenu.vue";
import {useDjangoUrls} from "@/composables/useDjangoUrls";
import {nextTick, onMounted} from "vue";
import {nextTick, onMounted, ref} from "vue";
import {isSpaceAboveLimit} from "@/utils/logic_utils";
import {useMediaQuery, useTitle} from "@vueuse/core";
import {useTitle} from "@vueuse/core";
import HelpDialog from "@/components/dialogs/HelpDialog.vue";
import {NAVIGATION_DRAWER} from "@/utils/navigation.ts";
import {useNavigation} from "@/composables/useNavigation.ts";
import {useRouter} from "vue-router";
import {useI18n} from "vue-i18n";
const {lgAndUp} = useDisplay()
const {getDjangoUrl} = useDjangoUrls()
const {t} = useI18n()
const title = useTitle()
const router = useRouter()
const isPrintMode = useMediaQuery('print')
onMounted(() => {
useUserPreferenceStore().init().then(() => {
if (useUserPreferenceStore().activeSpace.spaceSetupCompleted != undefined && !useUserPreferenceStore().activeSpace.spaceSetupCompleted) {
router.push({name: 'WelcomePage'})
}
})
const {current} = useLocale()
let locale = document.querySelector('html')!.getAttribute('lang')
if (locale != null) {
current.value = locale
}
})
/**
* global title update handler, might be overridden by page specific handlers
*/
router.afterEach((to, from) => {
if(to.name == 'StartPage' && useUserPreferenceStore().initCompleted && !useUserPreferenceStore().activeSpace.spaceSetupCompleted != undefined &&!useUserPreferenceStore().activeSpace.spaceSetupCompleted && useUserPreferenceStore().activeSpace.createdBy.id! == useUserPreferenceStore().userSettings.user.id!){
if (to.name == 'StartPage' && useUserPreferenceStore().initCompleted && !useUserPreferenceStore().activeSpace.spaceSetupCompleted != undefined && !useUserPreferenceStore().activeSpace.spaceSetupCompleted && useUserPreferenceStore().activeSpace.createdBy.id! == useUserPreferenceStore().userSettings.user.id!) {
router.push({name: 'WelcomePage'})
}
nextTick(() => {

View File

@@ -79,7 +79,7 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn @click="useMessageStore().deleteAllMessages()" color="error">{{$t('Delete_All')}}</v-btn>
<v-btn @click="addTestMessage()" color="warning">{{$t('Add')}}</v-btn>
<!-- <v-btn @click="addTestMessage()" color="warning">{{$t('Add')}}</v-btn>-->
<v-btn @click="isActive.value = false">{{ $t('Close')}}</v-btn>
</v-card-actions>
</v-card>

View File

@@ -10,15 +10,15 @@
<!-- <v-text-field density="compact" variant="outlined" class="pt-2 pb-2" :label="$t('Search')" hide-details clearable></v-text-field>-->
<!-- </v-list-item>-->
<!-- <v-divider></v-divider>-->
<v-list-item link title="Start" @click="window = 'start'" prepend-icon="fa-solid fa-house"></v-list-item>
<v-list-item link title="Space" @click="window = 'space'" prepend-icon="fa-solid fa-database"></v-list-item>
<v-list-item link :title="$t('Start')" @click="window = 'start'" prepend-icon="fa-solid fa-house"></v-list-item>
<v-list-item link :title="$t('Space')" @click="window = 'space'" prepend-icon="fa-solid fa-database"></v-list-item>
<v-list-item link :title="$t('Recipes')" @click="window = 'recipes'" prepend-icon="$recipes"></v-list-item>
<v-list-item link :title="$t('Import')" @click="window = 'import'" prepend-icon="$import"></v-list-item>
<v-list-item link :title="$t('AI')" @click="window = 'ai'" prepend-icon="$ai"></v-list-item>
<v-list-item link :title="$t('Unit')" @click="window = 'unit'" prepend-icon="fa-solid fa-scale-balanced"></v-list-item>
<v-list-item link :title="$t('Food')" @click="window = 'food'" prepend-icon="fa-solid fa-carrot"></v-list-item>
<v-list-item link :title="$t('Keyword')" @click="window = 'keyword'" prepend-icon="fa-solid fa-tags"></v-list-item>
<v-list-item link title="Recipe Structure" @click="window = 'recipe_structure'" prepend-icon="fa-solid fa-diagram-project"></v-list-item>
<v-list-item link :title="$t('Recipe Structure')" @click="window = 'recipe_structure'" prepend-icon="fa-solid fa-diagram-project"></v-list-item>
<v-list-item link :title="$t('Properties')" @click="window = 'properties'" prepend-icon="fa-solid fa-database"></v-list-item>
<v-list-item link :title="$t('Search')" @click="window = 'recipe_search'" prepend-icon="$search"></v-list-item>
<v-list-item link :title="$t('SavedSearch')" @click="window = 'search_filter'" prepend-icon="fa-solid fa-sd-card"></v-list-item>
@@ -31,6 +31,8 @@
<v-main>
<v-container>
<v-select v-model="window" :items="mobileMenuItems" class="d-block d-lg-none"> </v-select>
<v-window v-model="window">
<v-window-item value="start">
<h2>Welcome to Tandoor 2</h2>
@@ -46,7 +48,8 @@
<v-btn class="mt-2 ms-2" color="info" href="https://github.com/TandoorRecipes/recipes" target="_blank" prepend-icon="fa-solid fa-code-branch">GitHub
</v-btn>
<v-alert class="mt-3" border="start" variant="tonal" color="success" v-if="(!useUserPreferenceStore().serverSettings.hosted && !useUserPreferenceStore().activeSpace.demo)">
<v-alert class="mt-3" border="start" variant="tonal" color="success"
v-if="(!useUserPreferenceStore().serverSettings.hosted && !useUserPreferenceStore().activeSpace.demo)">
<v-alert-title>Did you know?</v-alert-title>
Tandoor is Open Source and available to anyone for free to host on their own server. Thousands of hours have been spend
making Tandoor what it is today. You can help make Tandoor even better by contributing or helping financing the effort.
@@ -60,10 +63,12 @@
</v-window-item>
<v-window-item value="space">
<p class="mt-3">All your data is stored in a Space where you can invite other people to collaborate on your recipe database. Typcially the members of a space
<p class="mt-3">All your data is stored in a Space where you can invite other people to collaborate on your recipe database. Typcially the members of a
space
belong to one family/household/organization.</p>
<p class="mt-3">While everyone can access all recipes by default, Books, Shopping Lists and Mealplans are not shared by default. You can share them with other
<p class="mt-3">While everyone can access all recipes by default, Books, Shopping Lists and Mealplans are not shared by default. You can share them with
other
members of your space
using the settings.
</p>
@@ -77,19 +82,24 @@
</v-window-item>
<v-window-item value="recipes">
<p class="mt-3">Recipes are the foundation of your Tandoor space. A Recipe has one or more steps that contain ingredients, instructions and other information.
<p class="mt-3">Recipes are the foundation of your Tandoor space. A Recipe has one or more steps that contain ingredients, instructions and other
information.
Ingredients in turn consist of an amount, a unit and a food, allowing recipes to be scaled, nutrition's to be calculated and shopping to be organized.
</p>
<p class="mt-3">Besides manually creating them you can also import them from various different places.
</p>
<p class="mt-3">Recipes, by default, are visible to all members of your space. Setting them to private means only you can see it. After setting it to private you
<p class="mt-3">Recipes, by default, are visible to all members of your space. Setting them to private means only you can see it. After setting it to
private you
can manually specify the people who should be able to view the recipe.
You can also create a share link for the recipe to share it with everyone that has access to the link.
</p>
<p class="mt-3"></p>
<v-btn color="primary" variant="tonal" prepend-icon="$create" class="me-2" :to="{name: 'ModelEditPage', params: {model: 'Recipe'}}">{{ $t('Create') }}</v-btn>
<v-btn color="primary" variant="tonal" prepend-icon="$create" class="me-2" :to="{name: 'ModelEditPage', params: {model: 'Recipe'}}">{{
$t('Create')
}}
</v-btn>
<v-btn color="primary" variant="tonal" prepend-icon="$search" class="me-2" :to="{name: 'SearchPage'}">{{ $t('Search') }}</v-btn>
</v-window-item>
@@ -119,7 +129,8 @@
</p>
<p class="mt-3" v-if="useUserPreferenceStore().serverSettings.hosted">
To prevent accidental AI cost you can review your AI usage using the AI Log. The Server Administrator can also set AI usage limits for your space (either monthly or using a balance).
To prevent accidental AI cost you can review your AI usage using the AI Log. The Server Administrator can also set AI usage limits for your space
(either monthly or using a balance).
</p>
<p class="mt-3" v-if="!useUserPreferenceStore().serverSettings.hosted">
Depending on your subscription you will have different AI Credits available for your space every month. Additionally you might have a Credit balance
@@ -153,7 +164,8 @@
<v-btn color="primary" variant="tonal" prepend-icon="fa-solid fa-scale-balanced" class="me-2" :to="{name: 'ModelListPage', params: {model: 'Unit'}}">
{{ $t('Unit') }}
</v-btn>
<v-btn color="primary" variant="tonal" prepend-icon="fa-solid fa-exchange-alt" class="me-2" :to="{name: 'ModelListPage', params: {model: 'UnitConversion'}}">
<v-btn color="primary" variant="tonal" prepend-icon="fa-solid fa-exchange-alt" class="me-2"
:to="{name: 'ModelListPage', params: {model: 'UnitConversion'}}">
{{ $t('Conversion') }}
</v-btn>
@@ -223,7 +235,8 @@
calculate the property amount if a Food is given in a different unit (e.g. 1kg or 1 cup).
</p>
<v-btn color="primary" variant="tonal" prepend-icon="fa-solid fa-database" class="me-2 mt-2 mb-2" :to="{name: 'ModelListPage', params: {model: 'PropertyType'}}">
<v-btn color="primary" variant="tonal" prepend-icon="fa-solid fa-database" class="me-2 mt-2 mb-2"
:to="{name: 'ModelListPage', params: {model: 'PropertyType'}}">
{{ $t('Property') }}
</v-btn>
<h3>Editor</h3>
@@ -294,7 +307,8 @@
</p>
<p class="mt-3">
You can assign Supermarket Categories to your Foods, either trough the Food Editor or directly by clicking on a Shopping List Entry, to automatically sort the list
You can assign Supermarket Categories to your Foods, either trough the Food Editor or directly by clicking on a Shopping List Entry, to automatically
sort the list
according to the Category Order defined in the Supermarket.
</p>
@@ -333,7 +347,8 @@
<p class="mt-3">
When selecting a Recipe in a Meal Plan you can automatically add its ingredients to the shopping list. You can also manually add more entries trough the
shopping tab in the Meal Plan editor. When deleting a Meal Plan all Shopping List Entries associated with that Meal Plan are deleted as well. When changing the
shopping tab in the Meal Plan editor. When deleting a Meal Plan all Shopping List Entries associated with that Meal Plan are deleted as well. When
changing the
number of servings in a Meal Plan the Servings of the connected Recipe in the Shopping list are automatically changed as well.
</p>
@@ -368,10 +383,30 @@
import {ref} from "vue";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
import {useI18n} from "vue-i18n";
const {t} = useI18n()
const drawer = defineModel()
const window = ref('start')
const mobileMenuItems = ref([
{title: t('Start'), props: {prependIcon: 'fa-solid fa-house'}, value: 'start'},
{title: t('Space'), props: {prependIcon: 'fa-solid fa-database'}, value: 'space'},
{title: t('Recipes'), props: {prependIcon: '$recipes'}, value: 'recipes'},
{title: t('Import'), props: {prependIcon: '$import'}, value: 'import'},
{title: t('AI'), props: {prependIcon: '$ai'}, value: 'ai'},
{title: t('Unit'), props: {prependIcon: 'fa-solid fa-scale-balanced'}, value: 'unit'},
{title: t('Food'), props: {prependIcon: 'fa-solid fa-carrot'}, value: 'food'},
{title: t('Keyword'), props: {prependIcon: 'fa-solid fa-tags'}, value: 'keyword'},
{title: t('RecipeStructure'), props: {prependIcon: 'fa-solid fa-diagram-project'}, value: 'recipe_structure'},
{title: t('Properties'), props: {prependIcon: 'fa-solid fa-database'}, value: 'properties'},
{title: t('Search'), props: {prependIcon: '$search'}, value: 'recipe_search'},
{title: t('SavedSearch'), props: {prependIcon: 'fa-solid fa-sd-card'}, value: 'search_filter'},
{title: t('Books'), props: {prependIcon: '$books'}, value: 'books'},
{title: t('Shopping'), props: {prependIcon: '$shopping'}, value: 'shopping'},
{title: t('Meal_Plan'), props: {prependIcon: '$mealplan'}, value: 'meal_plan'}
])
</script>

View File

@@ -146,7 +146,11 @@ onMounted(() => {
function clickMealPlan(plan: MealPlan) {
if (plan.recipe) {
router.push({name: 'RecipeViewPage', params: {id: plan.recipe.id}})
router.push({
name: 'RecipeViewPage',
params: { id: String(plan.recipe.id) }, // keep id in params
query: { servings: String(plan.servings ?? '') } // pass servings as query
})
}
}

View File

@@ -54,15 +54,13 @@
</router-link>
<a v-else-if="i.food.url" :href="i.food.url" target="_blank">{{ ingredientToFoodString(i, ingredientFactor) }}</a>
<span v-else>{{ ingredientToFoodString(i, ingredientFactor) }}</span>
<template v-if="i.note != '' && i.note != undefined">
<span class="d-none d-print-block text-disabled font-italic">&nbsp;{{ i.note }}</span>
</template>
</template>
</td>
<td style="width: 1%; text-wrap: nowrap" class="d-print-none">
<td v-if="useUserPreferenceStore().isPrintMode">
<span class="text-disabled font-italic"> {{ i.note }}</span>
</td>
<td style="width: 1%; text-wrap: nowrap" v-if="!useUserPreferenceStore().isPrintMode">
<v-icon class="far fa-comment float-right" v-if="i.note != '' && i.note != undefined">
<v-tooltip activator="parent" open-on-click location="start">{{ i.note }}</v-tooltip>
</v-icon>

View File

@@ -157,6 +157,7 @@ function dropCalendarItemOnDate(undefinedItem: IMealPlanNormalizedCalendarItem,
let new_entry = Object.assign({}, mealPlan)
new_entry.fromDate = targetDate
new_entry.toDate = DateTime.fromJSDate(targetDate).plus(fromToDiff).toJSDate()
new_entry.addshopping = mealPlan.shopping
useMealPlanStore().createObject(new_entry)
} else {
mealPlan.fromDate = targetDate

View File

@@ -37,15 +37,15 @@
<v-dialog max-width="900px" v-model="dialog">
<v-card v-if="dialogProperty" :loading="loading">
<v-closable-card-title :title="`${dialogProperty.propertyAmountTotal} ${dialogProperty.unit} ${dialogProperty.name}`" :sub-title="$t('total')" icon="$properties"
<v-closable-card-title :title="`${dialogProperty.propertyAmountTotal} ${(dialogProperty.unit != null) ? dialogProperty.unit : ''} ${dialogProperty.name}`" :sub-title="$t('total')" icon="$properties"
v-model="dialog"></v-closable-card-title>
<v-card-text>
<v-list>
<v-list-item border v-for="fv in dialogProperty.foodValues" :key="`${dialogProperty.id}_${fv.id}`">
<template #prepend>
<v-progress-circular size="55" width="5" :model-value="(fv.value/dialogProperty.propertyAmountTotal)*100"
:color="colorScale((fv.value/dialogProperty.propertyAmountTotal)*100)" v-if="fv.value != null && dialogProperty.propertyAmountTotal > 0">
{{ Math.round((fv.value / dialogProperty.propertyAmountTotal) * 100) }}%
<v-progress-circular size="55" width="5" :model-value="(fv.value* props.ingredientFactor/dialogProperty.propertyAmountTotal)*100"
:color="colorScale((fv.value* props.ingredientFactor/dialogProperty.propertyAmountTotal)*100)" v-if="fv.value != null && dialogProperty.propertyAmountTotal > 0">
{{ Math.round((fv.value* props.ingredientFactor / dialogProperty.propertyAmountTotal) * 100) }}%
</v-progress-circular>
<v-progress-circular size="55" width="5" v-if="fv.value == null">?</v-progress-circular>
</template>
@@ -53,13 +53,13 @@
{{ fv.food.name }}
</span>
<template #append>
<v-chip v-if="fv.value != undefined">{{ $n(fv.value) }} {{ dialogProperty.unit }}</v-chip>
<v-chip color="create" v-else-if="fv.missing_conversion" class="cursor-pointer" prepend-icon="$create">
<v-chip color="create" v-if="fv.missing_conversion" class="cursor-pointer" prepend-icon="$create">
{{ $t('Conversion') }}: {{ fv.missing_conversion.base_unit.name }} <i class="fa-solid fa-arrow-right me-1 ms-1"></i>
{{ fv.missing_conversion.converted_unit.name }}
<model-edit-dialog model="UnitConversion" @create="refreshRecipe()"
:item-defaults="{baseAmount: 1, baseUnit: fv.missing_conversion.base_unit, convertedUnit: fv.missing_conversion.converted_unit, food: fv.food}"></model-edit-dialog>
</v-chip>
<v-chip v-else-if="fv.value != undefined">{{ $n(fv.value * props.ingredientFactor) }} {{ dialogProperty.unit }}</v-chip>
<v-chip color="warning" prepend-icon="$edit" class="cursor-pointer" :to="{name: 'ModelEditPage', params: {model: 'Recipe', id: recipe.id}}" v-else-if="fv.missing_unit">
{{ $t('NoUnit') }}
</v-chip>
@@ -101,7 +101,10 @@ type PropertyWrapper = {
}
const props = defineProps({
servings: {type: Number, required: true,},
ingredientFactor: {
type: Number,
required: true,
},
})
const recipe = defineModel<Recipe>({required: true})
@@ -143,7 +146,7 @@ const propertyList = computed(() => {
description: rp.propertyType.description,
foodValues: [],
propertyAmountPerServing: rp.propertyAmount,
propertyAmountTotal: rp.propertyAmount * recipe.value.servings * (props.servings / recipe.value.servings),
propertyAmountTotal: rp.propertyAmount * recipe.value.servings * props.ingredientFactor,
missingValue: false,
unit: rp.propertyType.unit,
type: rp.propertyType,
@@ -161,7 +164,7 @@ const propertyList = computed(() => {
icon: fp.icon,
foodValues: fp.food_values,
propertyAmountPerServing: fp.total_value / recipe.value.servings,
propertyAmountTotal: fp.total_value * (props.servings / recipe.value.servings),
propertyAmountTotal: fp.total_value * props.ingredientFactor,
missingValue: fp.missing_value,
unit: fp.unit,
type: fp,

View File

@@ -1,5 +1,5 @@
<template>
<v-card class="mt-1 d-print-none" v-if="useUserPreferenceStore().isAuthenticated" :loading="loading">
<v-card class="mt-1" v-if="useUserPreferenceStore().isAuthenticated && !useUserPreferenceStore().isPrintMode" :loading="loading">
<v-card-text>
<v-textarea :label="$t('Comment')" rows="2" v-model="newCookLog.comment" auto-grow></v-textarea>
<v-row dense>
@@ -69,7 +69,7 @@
<script setup lang="ts">
import {onMounted, PropType, ref} from "vue";
import {onMounted, PropType, ref, watch} from "vue";
import {ApiApi, CookLog, Recipe} from "@/openapi";
import {DateTime} from "luxon";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
@@ -82,6 +82,10 @@ const props = defineProps({
type: Object as PropType<Recipe>,
required: true
},
servings: {
type: Number,
required: true
}
})
const newCookLog = ref({} as CookLog);
@@ -121,7 +125,7 @@ function recLoadCookLog(recipeId: number, page: number = 1) {
*/
function resetForm() {
newCookLog.value = {} as CookLog
newCookLog.value.servings = props.recipe.servings
newCookLog.value.servings = props.servings
newCookLog.value.createdAt = new Date()
newCookLog.value.recipe = props.recipe.id!
}
@@ -140,6 +144,13 @@ function saveCookLog() {
})
}
/**
* watch for changes in servings prop and update the servings input field
*/
watch(() => props.servings, (newVal) => {
newCookLog.value.servings = newVal
})
</script>
<style scoped>

View File

@@ -1,7 +1,7 @@
<template>
<template v-if="!props.loading">
<router-link :to="{name: 'RecipeViewPage', params: {id: props.recipe.id}}" :target="linkTarget">
<router-link :to="dest" :target="linkTarget">
<recipe-image :style="{height: props.height}" :recipe="props.recipe" rounded="lg" class="mr-3 ml-3">
</recipe-image>
@@ -36,7 +36,7 @@
</div>
<v-card :to="{name: 'RecipeViewPage', params: {id: props.recipe.id}}" :style="{'height': props.height}" v-if="false">
<v-card :to="dest" :style="{'height': props.height}" v-if="false">
<v-tooltip
class="align-center justify-center"
location="top center" origin="overlap"
@@ -97,7 +97,7 @@
</template>
<script setup lang="ts">
import {PropType} from 'vue'
import {computed, PropType} from 'vue'
import KeywordsComponent from "@/components/display/KeywordsBar.vue";
import {Recipe, RecipeOverview} from "@/openapi";
@@ -113,20 +113,29 @@ const props = defineProps({
show_description: {type: Boolean, required: false},
height: {type: String, required: false, default: '15vh'},
linkTarget: {type: String, required: false, default: ''},
showMenu: {type: Boolean, default: true, required: false}
showMenu: {type: Boolean, default: true, required: false},
servings: {type: Number, required: false},
})
const router = useRouter()
const dest = computed(() => {
const route: any = { name: 'RecipeViewPage', params: { id: props.recipe.id } };
if (props.servings !== undefined) {
route.query = { servings: String(props.servings) };
}
return route;
})
/**
* open the recipe either in the same tab or in a new tab depending on the link target prop
*/
function openRecipe() {
if (props.linkTarget != '') {
const routeData = router.resolve({name: 'RecipeViewPage', params: {id: props.recipe.id}});
const routeData = router.resolve(dest.value);
window.open(routeData.href, props.linkTarget);
} else {
router.push({name: 'RecipeViewPage', params: {id: props.recipe.id}})
router.push(dest.value);
}
}

View File

@@ -10,7 +10,7 @@
<template v-if="recipe.name != undefined">
<template class="d-block d-lg-none">
<template class="d-block d-lg-none d-print-none">
<!-- mobile layout -->
<v-card class="rounded-0">
@@ -25,7 +25,7 @@
<span class="ps-2 text-h5 flex-grow-1 pa-1" :class="{'text-truncate': !showFullRecipeName}" @click="showFullRecipeName = !showFullRecipeName">
{{ recipe.name }}
</span>
<recipe-context-menu :recipe="recipe" v-if="useUserPreferenceStore().isAuthenticated"></recipe-context-menu>
<recipe-context-menu :recipe="recipe" :servings="servings" v-if="useUserPreferenceStore().isAuthenticated"></recipe-context-menu>
</v-sheet>
<keywords-component variant="flat" class="ms-1" :keywords="recipe.keywords"></keywords-component>
<private-recipe-badge :users="recipe.shared" v-if="recipe._private"></private-recipe-badge>
@@ -61,7 +61,7 @@
</v-card>
</template>
<!-- Desktop horizontal layout -->
<template class="d-none d-lg-block">
<template class="d-none d-lg-block d-print-block">
<v-row dense>
<v-col cols="8">
<recipe-image
@@ -75,7 +75,7 @@
<v-card-text class="flex-grow-1">
<div class="d-flex">
<h1 class="flex-column flex-grow-1">{{ recipe.name }}</h1>
<recipe-context-menu :recipe="recipe" v-if="useUserPreferenceStore().isAuthenticated"
<recipe-context-menu :recipe="recipe" :servings="servings" v-if="useUserPreferenceStore().isAuthenticated"
class="flex-column mb-auto mt-2 float-right"></recipe-context-menu>
</div>
<p>
@@ -118,13 +118,13 @@
</v-row>
</template>
<template v-if="recipe.filePath">
<template v-if="recipe.filePath && !useUserPreferenceStore().isPrintMode">
<external-recipe-viewer class="mt-2" :recipe="recipe"></external-recipe-viewer>
<v-card :title="$t('AI')" prepend-icon="$ai" :loading="fileApiLoading || loading" :disabled="fileApiLoading || loading || !useUserPreferenceStore().activeSpace.aiEnabled"
<v-card :title="$t('AI')" prepend-icon="$ai" :loading="fileApiLoading || loading" :disabled="fileApiLoading || loading || !useUserPreferenceStore().activeSpace.aiEnabled"
v-if="!recipe.internal">
<v-card-text>
{{$t('ConvertUsingAI')}}
{{ $t('ConvertUsingAI') }}
<model-select model="AiProvider" v-model="selectedAiProvider">
<template #append>
@@ -135,7 +135,8 @@
</v-card>
</template>
<v-card class="mt-1" v-if="(recipe.steps.length > 1 || (recipe.steps.length == 1 && !recipe.steps[0].showIngredientsTable)) && recipe.showIngredientOverview">
<v-card class="mt-1"
v-if="(recipe.steps.length > 1 || (recipe.steps.length == 1 && !recipe.steps[0].showIngredientsTable)) && recipe.showIngredientOverview && !useUserPreferenceStore().isPrintMode">
<steps-overview :steps="recipe.steps" :ingredient-factor="ingredientFactor"></steps-overview>
</v-card>
@@ -143,12 +144,12 @@
<step-view v-model="recipe.steps[index]" :step-number="index+1" :ingredientFactor="ingredientFactor"></step-view>
</v-card>
<property-view v-model="recipe" :servings="servings"></property-view>
<property-view v-model="recipe" :ingredientFactor="ingredientFactor"></property-view>
<v-card class="mt-2">
<v-card-text>
<v-row>
<v-col cols="12" md="3">
<v-row dense>
<v-col cols="12" :sm="(recipe.sourceUrl) ? 3 : 4">
<v-card
variant="outlined"
:title="$t('CreatedBy')"
@@ -157,7 +158,7 @@
:to="(useUserPreferenceStore().isAuthenticated) ? {name: 'SearchPage', query: {createdby: recipe.createdBy.id!}}: undefined">
</v-card>
</v-col>
<v-col cols="12" md="3">
<v-col cols="12" :sm="(recipe.sourceUrl) ? 3 : 4">
<v-card
variant="outlined"
:title="$t('Created')"
@@ -166,7 +167,7 @@
:to="(useUserPreferenceStore().isAuthenticated) ? {name: 'SearchPage', query: {createdon: DateTime.fromJSDate(recipe.createdAt).toISODate()}} : undefined">
</v-card>
</v-col>
<v-col cols="12" md="3">
<v-col cols="12" :sm="(recipe.sourceUrl) ? 3 : 4">
<v-card
variant="outlined"
:title="$t('Updated')"
@@ -175,7 +176,7 @@
:to="(useUserPreferenceStore().isAuthenticated) ? {name: 'SearchPage', query: {updatedon: DateTime.fromJSDate(recipe.updatedAt).toISODate()}}: undefined">
</v-card>
</v-col>
<v-col cols="12" md="3" v-if="recipe.sourceUrl">
<v-col cols="12" :sm="(recipe.sourceUrl) ? 3 : 4" v-if="recipe.sourceUrl">
<v-card
variant="outlined"
:title="$t('Imported_From')"
@@ -189,7 +190,7 @@
</v-card-text>
</v-card>
<recipe-activity :recipe="recipe" v-if="useUserPreferenceStore().userSettings.comments"></recipe-activity>
<recipe-activity :recipe="recipe" :servings="servings" v-if="useUserPreferenceStore().userSettings.comments"></recipe-activity>
</template>
</template>
@@ -219,8 +220,11 @@ const {doAiImport, fileApiLoading} = useFileApi()
const loading = ref(false)
const recipe = defineModel<Recipe>({required: true})
const props = defineProps<{
servings: {type: Number, required: false},
}>()
const servings = ref(1)
const servings = ref(props.servings ?? recipe.value.servings ?? 1)
const showFullRecipeName = ref(false)
const selectedAiProvider = ref<undefined | AiProvider>(useUserPreferenceStore().activeSpace.aiDefaultProvider)
@@ -229,17 +233,19 @@ const selectedAiProvider = ref<undefined | AiProvider>(useUserPreferenceStore().
* factor for multiplying ingredient amounts based on recipe base servings and user selected servings
*/
const ingredientFactor = computed(() => {
return servings.value / ((recipe.value.servings != undefined) ? recipe.value.servings : 1)
return servings.value / ((recipe.value.servings != undefined) ? Math.max(recipe.value.servings, 1) : 1)
})
/**
* change servings when recipe servings are changed
*/
watch(() => recipe.value.servings, () => {
if (recipe.value.servings) {
servings.value = recipe.value.servings
}
})
if (props.servings === undefined) {
watch(() => recipe.value.servings, () => {
if (recipe.value.servings) {
servings.value = recipe.value.servings
}
})
}
onMounted(() => {
//keep screen on while viewing a recipe
@@ -257,7 +263,7 @@ onBeforeUnmount(() => {
function aiConvertRecipe() {
let api = new ApiApi()
doAiImport(selectedAiProvider.value.id!,null, '', recipe.value.id!).then(r => {
doAiImport(selectedAiProvider.value.id!, null, '', recipe.value.id!).then(r => {
if (r.recipe) {
recipe.value.internal = true
recipe.value.steps = r.recipe.steps

View File

@@ -22,10 +22,10 @@
<timer :seconds="step.time != undefined ? step.time*60 : 0" @stop="timerRunning = false" v-if="timerRunning"></timer>
<v-card-text v-if="step.ingredients.length > 0 || step.instruction != ''">
<v-row>
<v-col cols="12" md="6" v-if="step.ingredients.length > 0 && (step.showIngredientsTable || step.show_ingredients_table)">
<v-col :cols="(useUserPreferenceStore().isPrintMode) ? 6 : 12" md="6" v-if="step.ingredients.length > 0 && (step.showIngredientsTable || step.show_ingredients_table)">
<ingredients-table v-model="step.ingredients" :ingredient-factor="ingredientFactor"></ingredients-table>
</v-col>
<v-col cols="12" md="6" class="markdown-body">
<v-col :cols="(useUserPreferenceStore().isPrintMode) ? 6 : 12" md="6" class="markdown-body">
<instructions :instructions_html="step.instructionsMarkdown" :ingredient_factor="ingredientFactor"
v-if="step.instructionsMarkdown != undefined"></instructions>
<!-- sub recipes dont have a correct schema, thus they use different variable naming -->
@@ -62,6 +62,7 @@ import {Step} from "@/openapi";
import Instructions from "@/components/display/Instructions.vue";
import Timer from "@/components/display/Timer.vue";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
const step = defineModel<Step>({required: true})

View File

@@ -1,6 +1,6 @@
<template>
<v-btn-group density="compact">
<v-btn color="create" @click="editingObj.properties.push({} as Property)" prepend-icon="$create">{{ $t('Add') }}</v-btn>
<v-btn color="create" @click="editingObj.properties.push({} as Property); addPropertiesFoodUnit()" prepend-icon="$create">{{ $t('Add') }}</v-btn>
<v-btn color="secondary" @click="addAllProperties" prepend-icon="fa-solid fa-list">{{ $t('AddAll') }}</v-btn>
<ai-action-button color="info" @selected="propertiesFromAi" :loading="aiLoading" prepend-icon="$ai">{{ $t('AI') }}</ai-action-button>
</v-btn-group>
@@ -41,12 +41,13 @@
<script setup lang="ts">
import {ApiApi, Food, Property, Recipe} from "@/openapi";
import {ApiApi, Food, Property, Recipe, Unit} from "@/openapi";
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
import ModelSelect from "@/components/inputs/ModelSelect.vue";
import {computed, onMounted, ref} from "vue";
import {computed, nextTick, onMounted, ref} from "vue";
import AiActionButton from "@/components/buttons/AiActionButton.vue";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore.ts";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
const props = defineProps({
amountFor: {type: String, required: true},
@@ -78,9 +79,11 @@ function deleteProperty(property: Property) {
function addAllProperties() {
const api = new ApiApi()
if (editingObj.value.properties) {
editingObj.value.properties = []
}
// if (editingObj.value.properties) {
// editingObj.value.properties = []
// }
addPropertiesFoodUnit()
api.apiPropertyTypeList().then(r => {
r.results.forEach(pt => {
@@ -98,6 +101,9 @@ function propertiesFromAi(providerId: number) {
if (isFood.value) {
api.apiFoodAipropertiesCreate({id: editingObj.value.id!, food: editingObj.value, provider: providerId}).then(r => {
editingObj.value = r
nextTick(() => {
addPropertiesFoodUnit()
})
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
}).finally(() => {
@@ -115,6 +121,17 @@ function propertiesFromAi(providerId: number) {
}
/**
* if its empty add the properties food unit
*/
function addPropertiesFoodUnit(){
console.log('ADDING UNIT', !editingObj.value.propertiesFoodUnit)
if (isFood.value && !editingObj.value.propertiesFoodUnit) {
console.log('ADDING UNIT ACTUALLY')
editingObj.value.propertiesFoodUnit = (useUserPreferenceStore().defaultUnitObj != null) ? useUserPreferenceStore().defaultUnitObj! : {name: 'g'} as Unit
}
}
</script>

View File

@@ -26,11 +26,9 @@
<v-progress-circular v-if="duplicateLoading" indeterminate size="small"></v-progress-circular>
</template>
</v-list-item>
<!-- TODO when calling print() some timing or whatever issue makes it so the useMediaQuery does not work and the sidebar is still shown -->
<!-- <v-list-item prepend-icon="fa-solid fa-print" @click="openPrintView()">-->
<!-- {{ $t('Print') }}-->
<!-- </v-list-item>-->
<v-list-item :to="{ name: 'RecipeViewPage', params: { id: recipe.id}, query: {print: 'true', servings: props.servings} }" :active="false" target="_blank" prepend-icon="fa-solid fa-print">
{{ $t('Print') }}
</v-list-item>
</v-list>
</v-menu>
</v-btn>
@@ -49,22 +47,21 @@ import AddToShoppingDialog from "@/components/dialogs/AddToShoppingDialog.vue";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore.ts";
import {useRouter} from "vue-router";
import {useFileApi} from "@/composables/useFileApi.ts";
import {useI18n} from "vue-i18n";
const router = useRouter()
const {t} = useI18n()
const {updateRecipeImage} = useFileApi()
const props = defineProps({
recipe: {type: Object as PropType<Recipe | RecipeOverview>, required: true},
servings: {type: Number, default: undefined},
size: {type: String, default: 'medium'},
})
const mealPlanDialog = ref(false)
const duplicateLoading = ref(false)
function openPrintView() {
print()
}
/**
* create a duplicate of the recipe by pulling its current data and creating a new recipe with the same data
*/
@@ -72,7 +69,27 @@ function duplicateRecipe() {
let api = new ApiApi()
duplicateLoading.value = true
api.apiRecipeRetrieve({id: props.recipe.id!}).then(originalRecipe => {
api.apiRecipeCreate({recipe: originalRecipe}).then(newRecipe => {
let recipe = {...originalRecipe, ...{id: undefined, name: originalRecipe.name + `(${t('Copy')})`}}
recipe.steps = recipe.steps.map((step) => {
return {
...step,
...{
id: undefined,
ingredients: step.ingredients.map((ingredient) => {
return {...ingredient, ...{id: undefined}}
}),
},
}
})
if (recipe.properties != null) {
recipe.properties = recipe.properties.map((p) => {
return {...p, ...{id: undefined}}
})
}
api.apiRecipeCreate({recipe: recipe}).then(newRecipe => {
if (originalRecipe.image) {
updateRecipeImage(newRecipe.id!, null, originalRecipe.image).then(r => {

View File

@@ -67,13 +67,13 @@
</div>
<div class="d-flex flex-nowrap">
<div class="flex-col flex-grow-0 ma-1" style="min-width: 15%" v-if="!ingredient.isHeader">
<v-text-field :id="`id_input_amount_${props.stepIndex}_${index}`" :label="$t('Amount')" type="number" v-model="ingredient.amount" density="compact"
hide-details :disabled="ingredient.noAmount">
<v-number-input :id="`id_input_amount_${props.stepIndex}_${index}`" :label="$t('Amount')" v-model="ingredient.amount" density="compact"
hide-details control-variant="hidden" :disabled="ingredient.noAmount" :precision="useUserPreferenceStore().userSettings.ingredientDecimals">
<template #prepend>
<v-icon icon="$dragHandle" class="drag-handle cursor-grab"></v-icon>
</template>
</v-text-field>
</v-number-input>
</div>
<div class="flex-col flex-grow-0 ma-1" style="min-width: 15%" v-if="!ingredient.isHeader ">
<model-select model="Unit" v-model="ingredient.unit" density="compact" allow-create hide-details :disabled="ingredient.noAmount"></model-select>
@@ -195,7 +195,7 @@
<v-text-field :label="$t('Original_Text')" readonly v-model="step.ingredients[editingIngredientIndex].originalText"
v-if="step.ingredients[editingIngredientIndex].originalText"></v-text-field>
<v-number-input v-model="step.ingredients[editingIngredientIndex].amount" inset control-variant="stacked" autofocus :label="$t('Amount')"
:min="0" :precision="2" v-if="!step.ingredients[editingIngredientIndex].isHeader"></v-number-input>
:min="0" :precision="useUserPreferenceStore().userSettings.ingredientDecimals" v-if="!step.ingredients[editingIngredientIndex].isHeader"></v-number-input>
<model-select model="Unit" v-model="step.ingredients[editingIngredientIndex].unit" :label="$t('Unit')" v-if="!step.ingredients[editingIngredientIndex].isHeader"
allow-create></model-select>
<model-select model="Food" v-model="step.ingredients[editingIngredientIndex].food" :label="$t('Food')" v-if="!step.ingredients[editingIngredientIndex].isHeader"
@@ -283,8 +283,9 @@ function parseAndInsertIngredients() {
}
})
Promise.allSettled(promises).then(r => {
step.value.ingredients = step.value.ingredients.filter(i => i.food != null || i.note != null || i.amount != 0)
r.forEach(i => {
console.log(i)
step.value.ingredients.push({
originalText: i.value.originalText,
amount: i.value.amount,

View File

@@ -17,10 +17,10 @@
<v-list density="compact">
<v-list-subheader>{{$t('Ingredients')}}</v-list-subheader>
<v-list-item
v-for="template in templates"
@click="insertTextAtPosition(template.template + ' ')"
v-for="t in templates"
@click="insertTextAtPosition(t.template + ' ')"
>
<ingredient-string :ingredient="template.ingredient"></ingredient-string>
<ingredient-string :ingredient="t.ingredient"></ingredient-string>
</v-list-item>
</v-list>
</v-menu>
@@ -65,7 +65,7 @@ const templates = computed(() => {
function insertTextAtPosition(text: string){
let textarea = markdownEditor.value.getTextareaDom()
let position = textarea.selectionStart
if (step.value.instruction){
if (step.value.instruction != undefined){
step.value.instruction = step.value.instruction.slice(0, position) + text + step.value.instruction.slice(position)
nextTick(() => {

View File

@@ -226,7 +226,7 @@ function initializeEditor() {
setupState(props.item, props.itemId, {
newItemFunction: () => {
editingObj.value.propertiesFoodAmount = 100
editingObj.value.propertiesFoodUnit = {name: (useUserPreferenceStore().userSettings.defaultUnit != undefined ? useUserPreferenceStore().userSettings.defaultUnit : 'g')} as Unit
editingObj.value.propertiesFoodUnit = (useUserPreferenceStore().defaultUnitObj != null) ? useUserPreferenceStore().defaultUnitObj! : {name: 'g'} as Unit
},
itemDefaults: props.itemDefaults,
})

View File

@@ -29,7 +29,7 @@
@update:modelValue="editingObj.servings = editingObj.recipe ? editingObj.recipe.servings : 1"></ModelSelect>
<!-- <v-number-input label="Days" control-variant="split" :min="1"></v-number-input>-->
<!--TODO create days input with +/- synced to date -->
<recipe-card :recipe="editingObj.recipe" v-if="editingObj && editingObj.recipe" link-target="_blank"></recipe-card>
<recipe-card :recipe="editingObj.recipe" :servings="editingObj.servings" v-if="editingObj && editingObj.recipe" link-target="_blank"></recipe-card>
<v-btn prepend-icon="$shopping" color="create" class="mt-1" v-if="!editingObj.shopping && editingObj.recipe && isUpdate()">
{{$t('Add')}}
<add-to-shopping-dialog :recipe="editingObj.recipe" :meal-plan="editingObj" @created="loadShoppingListEntries(); editingObj.shopping = true;"></add-to-shopping-dialog>

View File

@@ -87,6 +87,12 @@
</v-row>
<v-form :disabled="loading || fileApiLoading">
<v-row v-if="editingObj.steps.length == 0">
<v-col class="text-center">
<v-btn icon="$create" variant="outlined" size="x-small" @click="addStep(i+1)"></v-btn>
</v-col>
</v-row>
<v-row v-for="(s,i ) in editingObj.steps" :key="s.id" dense>
<v-col>
<step-editor v-model="editingObj.steps[i]" v-model:recipe="editingObj" :step-index="i" @delete="deleteStepAtIndex(i)" @move="dialogStepManager = true"></step-editor>

View File

@@ -29,7 +29,11 @@
<v-checkbox v-model="useUserPreferenceStore().deviceSettings.start_showMealPlan" :label="$t('ShowMealPlanOnStartPage')"></v-checkbox>
<v-btn @click="useUserPreferenceStore().resetDeviceSettings()" color="warning">{{ $t('Reset') }}</v-btn> <br/>
<v-btn @click="useUserPreferenceStore().deviceSettings.general_closedHelpAlerts = []" color="warning" class="mt-1">{{ $t('ResetHelp') }}</v-btn>
<v-btn @click="useUserPreferenceStore().deviceSettings.general_closedHelpAlerts = []" color="warning" class="mt-1">{{ $t('ResetHelp') }}</v-btn> <br/>
<v-btn color="info" class="mt-1">
<message-list-dialog></message-list-dialog>
{{ $t('Messages') }}
</v-btn>
</v-form>
</template>
@@ -43,6 +47,7 @@ import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/Messa
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {useDjangoUrls} from "@/composables/useDjangoUrls";
import ThankYouNote from "@/components/display/ThankYouNote.vue";
import MessageListDialog from "@/components/dialogs/MessageListDialog.vue";
const {getDjangoUrl} = useDjangoUrls()

View File

@@ -26,7 +26,7 @@
Authentication works by proving the word <code>Bearer</code> followed by an API Token as a request Authorization
header as shown below. <br/>
<code>Authorization: Bearer TOKEN</code> -or-<br/>
<code>curl -X GET http://your.domain.com/api/recipes/ -H 'Authorization:
<code>curl -X GET http://your.domain.com/api/recipe/ -H 'Authorization:
Bearer TOKEN'</code>
<br/>

View File

@@ -124,6 +124,8 @@ export function useFileApi() {
* @returns Promise resolving to the import ID of the app import
*/
function doAppImport(files: File[], app: string, includeDuplicates: boolean, mealPlans: boolean = true, shoppingLists: boolean = true, nutritionPerServing: boolean = false,) {
fileApiLoading.value = true
let formData = new FormData()
formData.append('type', app);
formData.append('duplicates', includeDuplicates ? 'true' : 'false')

View File

@@ -267,6 +267,7 @@
"Ratings": "",
"Recently_Viewed": "",
"Recipe": "",
"RecipeStructure": "",
"Recipe_Book": "",
"Recipe_Image": "",
"Recipes": "",
@@ -314,6 +315,7 @@
"SpaceMembersHelp": "",
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Start": "",
"Starting_Day": "",
"StartsWith": "",
"StartsWithHelp": "",

View File

@@ -260,6 +260,7 @@
"Ratings": "Рейтинги",
"Recently_Viewed": "Наскоро разгледани",
"Recipe": "Рецепта",
"RecipeStructure": "",
"Recipe_Book": "Книга с рецепти",
"Recipe_Image": "Изображение на рецептата",
"Recipes": "Рецепти",
@@ -307,6 +308,7 @@
"SpaceMembersHelp": "",
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Start": "",
"Starting_Day": "Начален ден от седмицата",
"StartsWith": "",
"StartsWithHelp": "",

View File

@@ -337,6 +337,7 @@
"Ratings": "Avaluació",
"Recently_Viewed": "Vistos recentment",
"Recipe": "Recepta",
"RecipeStructure": "",
"Recipe_Book": "Llibre de receptes",
"Recipe_Image": "Imatge de la recepta",
"Recipes": "Receptes",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Un administrador de l'espai podria canviar algunes configuracions estètiques i tindrien prioritat sobre la configuració dels usuaris per a aquest espai.",
"Split_All_Steps": "Dividir totes les files en passos separats.",
"Start": "",
"StartDate": "Data d'inici",
"Starting_Day": "Dia d'inici de la setmana",
"StartsWith": "",

View File

@@ -334,6 +334,7 @@
"Ratings": "Hodnocení",
"Recently_Viewed": "Naposledy prohlížené",
"Recipe": "Recept",
"RecipeStructure": "",
"Recipe_Book": "Kuchařka",
"Recipe_Image": "Obrázek k receptu",
"Recipes": "Recepty",
@@ -389,6 +390,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Některá kosmetická nastavení mohou měnit správci prostoru a budou mít přednost před nastavením klienta pro daný prostor.",
"Split_All_Steps": "Rozdělit každý řádek do samostatného kroku.",
"Start": "",
"StartDate": "Počáteční datum",
"Starting_Day": "První den v týdnu",
"StartsWith": "",

View File

@@ -337,6 +337,7 @@
"Ratings": "Bedømmelser",
"Recently_Viewed": "Vist for nylig",
"Recipe": "Opskrift",
"RecipeStructure": "",
"Recipe_Book": "Opskriftsbog",
"Recipe_Image": "Opskriftsbillede",
"Recipes": "Opskrifter",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Visse kosmetiske indstillinger kan ændres af område-administratorer og vil overskrive klient-indstillinger for pågældende område.",
"Split_All_Steps": "Opdel rækker i separate trin.",
"Start": "",
"StartDate": "Startdato",
"Starting_Day": "Første dag på ugen",
"StartsWith": "",

View File

@@ -57,7 +57,7 @@
"BaseUnit": "Basiseinheit",
"BaseUnitHelp": "Optionale Standardeinheit zur automatischen Umrechnung",
"Basics": "Grundlagen",
"BatchDeleteConfirm": "Möchtest du alle angezeigten Objekte löschen? Dies kann nicht rückgängig gemacht werden!",
"BatchDeleteConfirm": "Möchtest du alle angezeigten Objekte löschen? Dies kann nicht rückgängig gemacht werden! ACHTUNG: Es ist möglich das Objekte gelöscht werden die an anderen Stellen verwendet werden!",
"BatchDeleteHelp": "Wenn ein Objekt nicht gelöscht werden kann, wird es noch irgendwo verwendet. ",
"BatchEdit": "Massenbearbeitung",
"BatchEditUpdatingItemsCount": "Bearbeite {count} {type}",
@@ -454,6 +454,7 @@
"RecipeBookHelp": "Rezeptbücher enthalten Rezeptbucheinträge oder können über hinterlegte gespeicherte Suchen automatisch gefüllt werden. ",
"RecipeHelp": "Rezepte sind die Grundlage von Tandoor und bestehen aus allgemeinen Informationen und Schritten, die wiederrum aus Zutaten, Texten und mehr bestehen. ",
"RecipeStepsHelp": "Zutaten, Anleitungen und mehr können unter dem Tab Schritte hinzugefügt werden.",
"RecipeStructure": "Rezept Struktur",
"Recipe_Book": "Kochbuch",
"Recipe_Image": "Rezeptbild",
"Recipes": "Rezepte",
@@ -541,6 +542,7 @@
"Space_Cosmetic_Settings": "Kosmetische Einstellungen auf Space Ebene überschreiben die Einstellungen der einzelnen Nutzer.",
"Split": "Aufteilen",
"Split_All_Steps": "Teile alle Zeilen in separate Schritte auf.",
"Start": "Start",
"StartDate": "Startdatum",
"Starting_Day": "Wochenbeginn am",
"StartsWith": "Beginnt mit",
@@ -594,7 +596,7 @@
"TrigramThresholdHelp": "Steuert bei der Verwendung unscharfer Suche wie viele Unterschiede zugelasen werden. Niedrigere Werte führen zu mehr Ergebnissen/größerer Unschärfe.",
"Tuesday": "Dienstag",
"Type": "Typ",
"UPDATE_ERROR": "Fehler beim aktualisieren",
"UPDATE_ERROR": "Fehler beim Aktualisieren",
"Unchanged": "Unverändert",
"Undefined": "undefiniert",
"Undo": "Rückgängig",

View File

@@ -337,6 +337,7 @@
"Ratings": "Βαθμολογίες",
"Recently_Viewed": "Προβλήθηκαν πρόσφατα",
"Recipe": "Συνταγή",
"RecipeStructure": "",
"Recipe_Book": "Βιβλίο συνταγών",
"Recipe_Image": "Εικόνα συνταγής",
"Recipes": "Συνταγές",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Ορισμένες ρυθμίσεις εμφάνισης μπορούν να αλλάξουν από τους διαχειριστές του χώρου και θα παρακάμψουν τις ρυθμίσεις πελάτη για αυτόν τον χώρο.",
"Split_All_Steps": "Διαχωρισμός όλων των γραμμών σε χωριστά βήματα.",
"Start": "",
"StartDate": "Ημερομηνία Έναρξης",
"Starting_Day": "Πρώτη μέρα της εβδομάδας",
"StartsWith": "",

View File

@@ -55,7 +55,7 @@
"BaseUnit": "Base Unit",
"BaseUnitHelp": "Standard unit for automatic unit conversion",
"Basics": "Basics",
"BatchDeleteConfirm": "Do you want to delete all shown items? This cannot be undone!",
"BatchDeleteConfirm": "Do you want to delete all shown items? This cannot be undone! WARNING: It is possible that this deletes objects that are used elsewhere. ",
"BatchDeleteHelp": "If an item cannot be deleted it is used somewhere. ",
"BatchEdit": "Batch Edit",
"BatchEditUpdatingItemsCount": "Editing {count} {type}",
@@ -452,6 +452,7 @@
"RecipeBookHelp": "Recipebooks contain recipe book entries or can be automatically populated by using saved search filters. ",
"RecipeHelp": "Recipes are the foundation of Tandoor and consist of general information and steps, made up of ingredients, instructions and more. ",
"RecipeStepsHelp": "Ingredients, Instructions and more can be edited in the tab Steps.",
"RecipeStructure": "Recipe Structure",
"Recipe_Book": "Recipe Book",
"Recipe_Image": "Recipe Image",
"Recipes": "Recipes",
@@ -539,6 +540,7 @@
"Space_Cosmetic_Settings": "Some cosmetic settings can be changed by space administrators and will override client settings for that space.",
"Split": "Split",
"Split_All_Steps": "Split all rows into separate steps.",
"Start": "Start",
"StartDate": "Start Date",
"Starting_Day": "Starting day of the week",
"StartsWith": "Starts with",

View File

@@ -439,6 +439,7 @@
"RecipeBookHelp": "Los recetarios contienen entradas de recetas o pueden ser rellenados automáticamente usando filtros de búsqueda guardados. ",
"RecipeHelp": "Las recetas son la base de Tandoor y consisten de información general y pasos, que incluyen ingredientes, instrucciones y más. ",
"RecipeStepsHelp": "Los ingredientes, las instrucciones y más se pueden editar en la pestaña «Pasos».",
"RecipeStructure": "",
"Recipe_Book": "Libro de recetas",
"Recipe_Image": "Imagen de la receta",
"Recipes": "Recetas",
@@ -521,6 +522,7 @@
"Space_Cosmetic_Settings": "Algunos ajustes de apariencia pueden ser cambiados por los administradores del espacio y anularán los ajustes del cliente para ese espacio.",
"Split": "Dividir",
"Split_All_Steps": "Dividir todas las filas en pasos separados.",
"Start": "",
"StartDate": "Fecha de Inicio",
"Starting_Day": "Día de comienzo de la semana",
"Step": "Paso",

View File

@@ -326,6 +326,7 @@
"Ratings": "Luokitukset",
"Recently_Viewed": "Äskettäin katsotut",
"Recipe": "Resepti",
"RecipeStructure": "",
"Recipe_Book": "Keittokirja",
"Recipe_Image": "Reseptin Kuva",
"Recipes": "Reseptit",
@@ -381,6 +382,7 @@
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Split_All_Steps": "Jaa kaikki rivit erillisiin vaiheisiin.",
"Start": "",
"StartDate": "Aloituspäivä",
"Starting_Day": "Viikon aloituspäivä",
"StartsWith": "",

View File

@@ -449,6 +449,7 @@
"RecipeBookHelp": "Les livres de recettes contiennent des entrées de livre de recettes ou peuvent être automatiquement remplis à l'aide de filtres de recherche enregistrés. ",
"RecipeHelp": "Les recettes sont la base de Tandoor et se composent d'informations générales et d'étapes, elles-mêmes composées d'ingrédients, d'instructions et plus encore. ",
"RecipeStepsHelp": "Les ingrédients, les instructions et plus encore, peuvent être modifiés dans l'onglet Étapes.",
"RecipeStructure": "",
"Recipe_Book": "Livre de recettes",
"Recipe_Image": "Image de la recette",
"Recipes": "Recettes",
@@ -536,6 +537,7 @@
"Space_Cosmetic_Settings": "Certains paramètres cosmétiques peuvent être modifiés par un administrateur de l'espace et seront prioritaires sur les paramètres des utilisateurs pour cet espace.",
"Split": "Diviser",
"Split_All_Steps": "Diviser toutes les lignes en étapes séparées.",
"Start": "",
"StartDate": "Date de début",
"Starting_Day": "Jour de début de la semaine",
"StartsWith": "Commence par",

View File

@@ -337,6 +337,7 @@
"Ratings": "דירוג",
"Recently_Viewed": "נצפו לאחרונה",
"Recipe": "מתכון",
"RecipeStructure": "",
"Recipe_Book": "ספר מתכון",
"Recipe_Image": "תמונת מתכון",
"Recipes": "מתכונים",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "חלק מהגדרות הקוסמטיות יכולות להיות מעודכנות על ידי מנהל המרחב וידרסו את הגדרות הקליינט עבור מרחב זה.",
"Split_All_Steps": "פצל את כל השורות לצעדים נפרדים.",
"Start": "",
"StartDate": "תאריך התחלה",
"Starting_Day": "יום תחילת השבוע",
"StartsWith": "",

View File

@@ -337,6 +337,7 @@
"Ratings": "Ocjene",
"Recently_Viewed": "Nedavno pogledano",
"Recipe": "Recept",
"RecipeStructure": "",
"Recipe_Book": "Knjiga recepata",
"Recipe_Image": "Slika recepta",
"Recipes": "Recepti",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Neke kozmetičke postavke mogu promijeniti administratori prostora i one će poništiti postavke klijenta za taj prostor.",
"Split_All_Steps": "Podijeli sve retke u zasebne korake.",
"Start": "",
"StartDate": "Početni datum",
"Starting_Day": "Početni dan u tjednu",
"StartsWith": "",

View File

@@ -310,6 +310,7 @@
"Ratings": "Értékelések",
"Recently_Viewed": "Nemrég megtekintett",
"Recipe": "Recept",
"RecipeStructure": "",
"Recipe_Book": "Szakácskönyv",
"Recipe_Image": "Receptkép",
"Recipes": "Receptek",
@@ -360,6 +361,7 @@
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Split_All_Steps": "Ossza fel az összes sort különálló lépésekbe.",
"Start": "",
"StartDate": "Kezdés dátuma",
"Starting_Day": "A hét kezdőnapja",
"StartsWith": "",

View File

@@ -143,6 +143,7 @@
"Rating": "",
"Recently_Viewed": "Վերջերս դիտած",
"Recipe": "Բաղադրատոմս",
"RecipeStructure": "",
"Recipe_Book": "Բաղադրատոմսերի գիրք",
"Recipe_Image": "Բաղադրատոմսի նկար",
"Recipes": "Բաղադրատոմսեր",
@@ -177,6 +178,7 @@
"SpaceMembersHelp": "",
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Start": "",
"StartsWith": "",
"StartsWithHelp": "",
"Step": "",

View File

@@ -286,6 +286,7 @@
"Ratings": "",
"Recently_Viewed": "baru saja dilihat",
"Recipe": "",
"RecipeStructure": "",
"Recipe_Book": "",
"Recipe_Image": "Gambar Resep",
"Recipes": "Resep",
@@ -336,6 +337,7 @@
"SpaceMembersHelp": "",
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Start": "",
"Starting_Day": "",
"StartsWith": "",
"StartsWithHelp": "",

View File

@@ -336,6 +336,7 @@
"Ratings": "",
"Recently_Viewed": "",
"Recipe": "",
"RecipeStructure": "",
"Recipe_Book": "",
"Recipe_Image": "",
"Recipes": "",
@@ -392,6 +393,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "",
"Split_All_Steps": "",
"Start": "",
"StartDate": "",
"Starting_Day": "",
"StartsWith": "",

View File

@@ -6,7 +6,7 @@
"APIKey": "Chiave API",
"API_Browser": "Navigatore API",
"API_Documentation": "Documentazione API",
"AboutTandoor": "",
"AboutTandoor": "Tandoor è una piattaforma Open Source per gestire ricette, piani alimentari, liste della spesa e altro.",
"AccessTokenHelp": "Chiavi di accesso per le API REST.",
"Access_Token": "Token di accesso",
"Account": "Account",
@@ -56,7 +56,7 @@
"BaseUnit": "Unità di base",
"BaseUnitHelp": "Unità standard per la conversione automatica di unità",
"Basics": "Informazioni di base",
"BatchDeleteConfirm": "Vuoi eliminare tutti gli elementi mostrati? Questo non può essere annullato!",
"BatchDeleteConfirm": "Vuoi eliminare tutti gli elementi mostrati? Questo non può essere annullato. AVVISO: è possibile che ciò elimini oggetti che sono utilizzati altrove. ",
"BatchDeleteHelp": "Se un elemento non può essere eliminato, è utilizzato altrove. ",
"BatchEdit": "Modifica massiva",
"BatchEditUpdatingItemsCount": "Modifica di {count} {type}",
@@ -117,7 +117,7 @@
"Create": "Crea",
"Create Food": "Crea alimento",
"Create Recipe": "Crea ricetta",
"CreateAccount": "",
"CreateAccount": "Crea account",
"CreateFirstRecipe": "Crea la tua prima ricetta utilizzando l'editor delle ricette.",
"CreateInvitation": "Crea un invito",
"Create_Meal_Plan_Entry": "Crea voce nel piano alimentare",
@@ -211,7 +211,7 @@
"Fats": "Grassi",
"File": "File",
"Files": "File",
"Finish": "",
"Finish": "Fine",
"FinishedAt": "Finito alle",
"First": "Primo",
"First_name": "Nome",
@@ -260,7 +260,7 @@
"ImportAll": "Importa tutto",
"ImportFirstRecipe": "Importa la tua prima ricetta da una delle migliaia di siti web o utilizza uno degli importatori per importare le collezioni esistenti, documenti o eventi di URL.",
"ImportIntoTandoor": "Importa in Tandoor",
"ImportIntoTandoorHelp": "",
"ImportIntoTandoorHelp": "Per importare questa ricetta nella tua raccolta di Tandoor, procedi con i passaggi seguenti.",
"ImportMealPlans": "Importa piani alimentari",
"ImportShoppingList": "Imposta liste della spesa",
"Import_Error": "Si è verificato un errore durante l'importazione. Per avere maggiori informazioni, espandi la sezione dettagli in fondo alla pagina.",
@@ -453,6 +453,7 @@
"RecipeBookHelp": "I ricettari contengono voci di ricette oppure possono essere compilati automaticamente utilizzando filtri di ricerca salvati. ",
"RecipeHelp": "Le ricette sono la base del Tandoor e sono composte da informazioni generali e passaggi, oltre che da ingredienti, istruzioni e altro ancora. ",
"RecipeStepsHelp": "Ingredienti, istruzioni e altro possono essere modificati nella scheda Step.",
"RecipeStructure": "",
"Recipe_Book": "Libro di ricette",
"Recipe_Image": "Immagine ricetta",
"Recipes": "Ricette",
@@ -492,7 +493,7 @@
"Select_File": "Seleziona file",
"Selected": "Selezionato",
"SelectedCategories": "Categorie selezionate",
"SelfHosted": "",
"SelfHosted": "Autonomo",
"Serving": "Porzione",
"Servings": "Porzioni",
"ServingsText": "Testo porzioni",
@@ -540,6 +541,7 @@
"Space_Cosmetic_Settings": "Alcune impostazioni cosmetiche possono essere modificate dagli amministratori dell'istanza e sovrascriveranno le impostazioni client per quell'istanza.",
"Split": "Dividi",
"Split_All_Steps": "Divide tutte le righe in step separati.",
"Start": "",
"StartDate": "Data d'inizio",
"Starting_Day": "Giorno di inizio della settimana",
"StartsWith": "Inizia con",

868
vue3/src/locales/ko.json Normal file
View File

@@ -0,0 +1,868 @@
{
"AI": "",
"AIImportSubtitle": "",
"AISettingsHostedHelp": "",
"API": "",
"APIKey": "",
"API_Browser": "",
"API_Documentation": "",
"AccessTokenHelp": "",
"Access_Token": "",
"Account": "",
"Actions": "",
"Active": "",
"Activity": "",
"Add": "",
"AddAll": "",
"AddChild": "",
"AddFilter": "",
"AddFoodToShopping": "",
"AddMany": "",
"AddToShopping": "",
"Add_Servings_to_Shopping": "",
"Add_Step": "",
"Add_nutrition_recipe": "",
"Add_to_Plan": "",
"Add_to_Shopping": "",
"Added_To_Shopping_List": "",
"Added_by": "",
"Added_on": "",
"Admin": "",
"Advanced": "",
"AiCreditsBalance": "",
"AiLog": "",
"AiLogHelp": "",
"AiModelHelp": "",
"AiProvider": "",
"AiProviderHelp": "",
"Alignment": "",
"AllRecipes": "",
"Amount": "",
"App": "",
"AppImportSubtitle": "",
"Apply": "",
"Are_You_Sure": "",
"Auto_Planner": "",
"Auto_Sort": "",
"Auto_Sort_Help": "",
"Automate": "",
"Automation": "",
"AutomationHelp": "",
"Available": "",
"AvailableCategories": "",
"Back": "",
"BaseUnit": "",
"BaseUnitHelp": "",
"Basics": "",
"BatchDeleteConfirm": "",
"BatchDeleteHelp": "",
"BatchEdit": "",
"BatchEditUpdatingItemsCount": "",
"Blocking": "",
"BlockingHelp": "",
"Book": "",
"Bookmarklet": "",
"BookmarkletHelp1": "",
"BookmarkletHelp2": "",
"BookmarkletHelp3": "",
"BookmarkletImportSubtitle": "",
"Books": "",
"CREATE_ERROR": "",
"Calculator": "",
"Calories": "",
"Cancel": "",
"Cannot_Add_Notes_To_Shopping": "",
"Carbohydrates": "",
"Cards": "",
"Cascading": "",
"CascadingHelp": "",
"Categories": "",
"Category": "",
"CategoryInstruction": "",
"CategoryName": "",
"Change_Password": "",
"Changing": "",
"ChildInheritFields": "",
"ChildInheritFields_help": "",
"Choose_Category": "",
"Clear": "",
"Click_To_Edit": "",
"Clone": "",
"Close": "",
"Color": "",
"Combine_All_Steps": "",
"Coming_Soon": "",
"Comment": "",
"Comments_setting": "",
"Completed": "",
"Confirm": "",
"ConnectorConfig": "",
"ConnectorConfigHelp": "",
"Continue": "",
"Conversion": "",
"ConversionsHelp": "",
"ConvertUsingAI": "",
"CookLog": "",
"CookLogHelp": "",
"Cooked": "",
"Copied": "",
"Copy": "",
"Copy Link": "",
"Copy Token": "",
"Copy_template_reference": "",
"Cosmetic": "",
"CountMore": "",
"Create": "",
"Create Food": "",
"Create Recipe": "",
"CreateFirstRecipe": "",
"CreateInvitation": "",
"Create_Meal_Plan_Entry": "",
"Create_New_Food": "",
"Create_New_Keyword": "",
"Create_New_Meal_Type": "",
"Create_New_Shopping Category": "",
"Create_New_Shopping_Category": "",
"Create_New_Unit": "",
"Created": "",
"CreatedBy": "",
"Credits": "",
"Ctrl+K": "",
"Current_Period": "",
"Custom Filter": "",
"CustomImageHelp": "",
"CustomLogoHelp": "",
"CustomLogos": "",
"CustomNavLogoHelp": "",
"CustomTheme": "",
"CustomThemeHelp": "",
"DELETE_ERROR": "",
"Data_Import_Info": "",
"Database": "",
"DatabaseHelp": "",
"Datatype": "",
"Date": "",
"Day": "",
"Days": "",
"Decimals": "",
"Default": "",
"DefaultPage": "",
"Default_Unit": "",
"DelayFor": "",
"DelayUntil": "",
"Delete": "",
"DeleteConfirmQuestion": "",
"DeleteShoppingConfirm": "",
"DeleteSomething": "",
"Delete_All": "",
"Delete_Food": "",
"Delete_Keyword": "",
"Deleted": "",
"Description": "",
"Description_Replace": "",
"DeviceSettings": "",
"DeviceSettingsHelp": "",
"Disable": "",
"Disable_Amount": "",
"Disabled": "",
"Documentation": "",
"DontChange": "",
"Down": "",
"Download": "",
"DragToUpload": "",
"Drag_Here_To_Delete": "",
"Duplicate": "",
"DuplicateFoundInfo": "",
"Edit": "",
"Edit_Food": "",
"Edit_Keyword": "",
"Edit_Meal_Plan_Entry": "",
"Edit_Recipe": "",
"Email": "",
"Empty": "",
"Enable": "",
"Enable_Amount": "",
"Enabled": "",
"EndDate": "",
"Energy": "",
"Entries": "",
"Error": "",
"ErrorUrlListImport": "",
"Events": "",
"Export": "",
"Export_As_ICal": "",
"Export_Not_Yet_Supported": "",
"Export_Supported": "",
"Export_To_ICal": "",
"External": "",
"ExternalRecipe": "",
"ExternalRecipeImport": "",
"ExternalRecipeImportHelp": "",
"ExternalStorage": "",
"External_Recipe_Image": "",
"FDC_ID": "",
"FDC_ID_help": "",
"FDC_Search": "",
"FETCH_ERROR": "",
"Failure": "",
"Fats": "",
"File": "",
"Files": "",
"FinishedAt": "",
"First": "",
"First_name": "",
"Food": "",
"FoodHelp": "",
"FoodInherit": "",
"FoodNotOnHand": "",
"FoodOnHand": "",
"Food_Alias": "",
"Food_Replace": "",
"Foods": "",
"Friday": "",
"FromBalance": "",
"Fulltext": "",
"FulltextHelp": "",
"Fuzzy": "",
"FuzzySearchHelp": "",
"GettingStarted": "",
"Global": "",
"GlobalHelp": "",
"Group": "",
"GroupBy": "",
"HeaderWarning": "",
"Headline": "",
"Help": "",
"Hide_External": "",
"Hide_Food": "",
"Hide_Keyword": "",
"Hide_Keywords": "",
"Hide_Recipes": "",
"Hide_as_header": "",
"Hierarchy": "",
"History": "",
"HostedFreeVersion": "",
"Hour": "",
"Hours": "",
"Icon": "",
"IgnoreAccents": "",
"IgnoreAccentsHelp": "",
"IgnoreThis": "",
"Ignore_Shopping": "",
"IgnoredFood": "",
"Image": "",
"Import": "",
"Import Recipe": "",
"ImportAll": "",
"ImportFirstRecipe": "",
"ImportIntoTandoor": "",
"ImportMealPlans": "",
"ImportShoppingList": "",
"Import_Error": "",
"Import_Not_Yet_Supported": "",
"Import_Result_Info": "",
"Import_Supported": "",
"Import_finished": "",
"Imported": "",
"Imported_From": "",
"Importer_Help": "",
"Information": "",
"Ingredient": "",
"Ingredient Editor": "",
"Ingredient Overview": "",
"IngredientEditorHelp": "",
"IngredientHelp": "",
"IngredientInShopping": "",
"Ingredients": "",
"Inherit": "",
"InheritFields": "",
"InheritFields_help": "",
"InheritWarning": "",
"Input": "",
"Instruction_Replace": "",
"Instructions": "",
"InstructionsEditHelp": "",
"Internal": "",
"InviteLinkHelp": "",
"Invite_Link": "",
"Invites": "",
"Key_Ctrl": "",
"Key_Shift": "",
"Keyword": "",
"KeywordHelp": "",
"Keyword_Alias": "",
"Keywords": "",
"Language": "",
"Last": "",
"Last_name": "",
"Learn_More": "",
"LeaveSpace": "",
"Link": "",
"Load": "",
"Load_More": "",
"LogCredits": "",
"LogCreditsHelp": "",
"Log_Cooking": "",
"Log_Recipe_Cooking": "",
"Logo": "",
"Logout": "",
"Make_Header": "",
"Make_Ingredient": "",
"ManageSubscription": "",
"Manage_Books": "",
"Manage_Emails": "",
"MealPlanHelp": "",
"MealPlanShoppingHelp": "",
"MealTypeHelp": "",
"Meal_Plan": "",
"Meal_Plan_Days": "",
"Meal_Type": "",
"Meal_Type_Required": "",
"Meal_Types": "",
"Merge": "",
"MergeAutomateHelp": "",
"MergeInsteadOfDelete": "",
"Merge_Keyword": "",
"Message": "",
"Messages": "",
"Miscellaneous": "",
"MissingConversion": "",
"MissingProperties": "",
"Model": "",
"ModelSelectResultsHelp": "",
"Monday": "",
"Month": "",
"MonthlyCredits": "",
"MonthlyCreditsUsed": "",
"More": "",
"Move": "",
"MoveCategory": "",
"MoveToStep": "",
"Move_Down": "",
"Move_Food": "",
"Move_Keyword": "",
"Move_Up": "",
"Multiple": "",
"Name": "",
"Name_Replace": "",
"Nav_Color": "",
"Nav_Color_Help": "",
"Nav_Text_Mode": "",
"Nav_Text_Mode_Help": "",
"Never_Unit": "",
"New": "",
"New_Cookbook": "",
"New_Entry": "",
"New_Food": "",
"New_Keyword": "",
"New_Meal_Type": "",
"New_Recipe": "",
"New_Supermarket": "",
"New_Supermarket_Category": "",
"New_Unit": "",
"Next": "",
"Next_Day": "",
"Next_Period": "",
"No": "",
"NoCategory": "",
"NoMoreUndo": "",
"NoUnit": "",
"No_ID": "",
"No_Results": "",
"NotFound": "",
"NotFoundHelp": "",
"NotInShopping": "",
"Note": "",
"NullingHelp": "",
"Number of Objects": "",
"Nutrition": "",
"NutritionsPerServing": "",
"NutritionsPerServingHelp": "",
"OfflineAlert": "",
"Ok": "",
"OnHand": "",
"OnHand_help": "",
"Open": "",
"Open_Data_Import": "",
"Open_Data_Slug": "",
"Options": "",
"Order": "",
"OrderInformation": "",
"Original_Text": "",
"Owner": "",
"Page": "",
"Parameter": "",
"Parent": "",
"PartialMatch": "",
"PartialMatchHelp": "",
"Password": "",
"Path": "",
"PerPage": "",
"Period": "",
"Periods": "",
"Pin": "",
"Pinned": "",
"PinnedConfirmation": "",
"Plan_Period_To_Show": "",
"Plan_Show_How_Many_Periods": "",
"Planned": "",
"Planner": "",
"Planner_Settings": "",
"Planning&Shopping": "",
"Plural": "",
"Postpone": "",
"PostponedUntil": "",
"PrecisionSearchHelp": "",
"Preferences": "",
"Preparation": "",
"Preview": "",
"Previous_Day": "",
"Previous_Period": "",
"Print": "",
"Private": "",
"Private_Recipe": "",
"Private_Recipe_Help": "",
"Profile": "",
"Properties": "",
"PropertiesFoodHelp": "",
"Properties_Food_Amount": "",
"Properties_Food_Unit": "",
"Property": "",
"PropertyHelp": "",
"PropertyType": "",
"PropertyTypeHelp": "",
"Property_Editor": "",
"Protected": "",
"Proteins": "",
"Quick actions": "",
"QuickEntry": "",
"Random Recipes": "",
"RandomOrder": "",
"RateLimit": "",
"RateLimitHelp": "",
"Rating": "",
"Ratings": "",
"Recently_Viewed": "",
"Recipe": "",
"RecipeBookEntryHelp": "",
"RecipeBookHelp": "",
"RecipeHelp": "",
"RecipeStepsHelp": "",
"RecipeStructure": "",
"Recipe_Book": "",
"Recipe_Image": "",
"Recipes": "",
"Recipes_In_Import": "",
"Recipes_per_page": "",
"Refresh": "",
"Remove": "",
"RemoveAllType": "",
"RemoveFoodFromShopping": "",
"RemoveParent": "",
"Remove_nutrition_recipe": "",
"Reset": "",
"ResetHelp": "",
"Reset_Search": "",
"Reusable": "",
"Role": "",
"Root": "",
"Saturday": "",
"Save": "",
"Save/Load": "",
"Save_and_View": "",
"SavedSearch": "",
"SavedSearchHelp": "",
"ScalableNumber": "",
"Search": "",
"Search Settings": "",
"SearchMethod": "",
"SearchSettingsOverview": "",
"SearchSettingsWarning": "",
"Second": "",
"Seconds": "",
"Select": "",
"SelectAll": "",
"SelectNone": "",
"Select_App_To_Import": "",
"Select_Book": "",
"Select_File": "",
"Selected": "",
"SelectedCategories": "",
"Serving": "",
"Servings": "",
"ServingsText": "",
"Settings": "",
"SettingsOnlySuperuser": "",
"Share": "",
"ShopLater": "",
"ShopNow": "",
"ShoppingBackgroundSyncWarning": "",
"ShoppingListEntry": "",
"ShoppingListEntryHelp": "",
"ShoppingListRecipe": "",
"Shopping_Categories": "",
"Shopping_Category": "",
"Shopping_List_Empty": "",
"Shopping_input_placeholder": "",
"Shopping_list": "",
"ShowDelayed": "",
"ShowIngredients": "",
"ShowMealPlanOnStartPage": "",
"ShowRecentlyCompleted": "",
"ShowUncategorizedFood": "",
"Show_Logo": "",
"Show_Logo_Help": "",
"Show_Week_Numbers": "",
"Show_as_header": "",
"Single": "",
"Size": "",
"Skip": "",
"Social_Authentication": "",
"Sort_by_new": "",
"Source": "",
"SourceImportHelp": "",
"SourceImportSubtitle": "",
"Space": "",
"SpaceHelp": "",
"SpaceLimitExceeded": "",
"SpaceLimitReached": "",
"SpaceMemberHelp": "",
"SpaceMembers": "",
"SpaceMembersHelp": "",
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"SpaceSettings": "",
"Space_Cosmetic_Settings": "",
"Split": "",
"Split_All_Steps": "",
"Start": "",
"StartDate": "",
"Starting_Day": "",
"StartsWith": "",
"StartsWithHelp": "",
"Step": "",
"StepHelp": "",
"Step_Name": "",
"Step_Type": "",
"Step_start_time": "",
"Steps": "",
"StepsOverview": "",
"Sticky_Nav": "",
"Sticky_Nav_Help": "",
"Storage": "",
"StorageHelp": "",
"StoragePasswordTokenHelp": "",
"Structured": "",
"SubstituteOnHand": "",
"Substitutes": "",
"Success": "",
"SuccessClipboard": "",
"Summary": "",
"Sunday": "",
"Supermarket": "",
"SupermarketCategoriesOnly": "",
"SupermarketCategoryHelp": "",
"SupermarketHelp": "",
"SupermarketName": "",
"Supermarkets": "",
"SupportsDescriptionField": "",
"SyncLog": "",
"SyncLogHelp": "",
"SyncedPath": "",
"SyncedPathHelp": "",
"System": "",
"Table": "",
"Table_of_Contents": "",
"Text": "",
"ThankYou": "",
"ThanksTextHosted": "",
"ThanksTextSelfhosted": "",
"Theme": "",
"Thursday": "",
"Time": "",
"Title": "",
"Title_or_Recipe_Required": "",
"Today": "",
"Toggle": "",
"Transpose_Words": "",
"TrigramThreshold": "",
"TrigramThresholdHelp": "",
"Tuesday": "",
"Type": "",
"UPDATE_ERROR": "",
"Unchanged": "",
"Undefined": "",
"Undo": "",
"Unit": "",
"UnitConversion": "",
"UnitConversionHelp": "",
"UnitHelp": "",
"Unit_Alias": "",
"Unit_Replace": "",
"Units": "",
"Unpin": "",
"UnpinnedConfirmation": "",
"Unrated": "",
"Up": "",
"Update": "",
"Update_Existing_Data": "",
"Updated": "",
"UpgradeNow": "",
"Url": "",
"UrlImportSubtitle": "",
"UrlList": "",
"UrlListSubtitle": "",
"Url_Import": "",
"Use_Fractions": "",
"Use_Fractions_Help": "",
"Use_Kj": "",
"Use_Metric": "",
"Use_Plural_Food_Always": "",
"Use_Plural_Food_Simple": "",
"Use_Plural_Unit_Always": "",
"Use_Plural_Unit_Simple": "",
"User": "",
"UserFileHelp": "",
"UserHelp": "",
"Username": "",
"Users": "",
"Valid Until": "",
"View": "",
"ViewLogHelp": "",
"View_Recipes": "",
"Viewed": "",
"Visibility": "",
"Waiting": "",
"WaitingTime": "",
"WarnPageLeave": "",
"Warning": "",
"WarningRecipeBookEntryDuplicate": "",
"Warning_Delete_Supermarket_Category": "",
"Website": "",
"Wednesday": "",
"Week": "",
"Week_Numbers": "",
"Welcome": "",
"WelcomeSettingsHelp": "",
"WelcometoTandoor": "",
"WorkingTime": "",
"Year": "",
"Yes": "",
"YourSpaces": "",
"active": "",
"add_keyword": "",
"additional_options": "",
"advanced": "",
"advanced_search_settings": "",
"after": "",
"all": "",
"all_fields_optional": "",
"and": "",
"and_down": "",
"and_up": "",
"any": "",
"asc": "",
"base_amount": "",
"base_unit": "",
"before": "",
"book_filter_help": "",
"click_image_import": "",
"confirm_delete": "",
"convert_internal": "",
"converted_amount": "",
"converted_unit": "",
"copy_markdown_table": "",
"copy_to_clipboard": "",
"copy_to_new": "",
"create_food_desc": "",
"create_rule": "",
"create_title": "",
"created_by": "",
"created_on": "",
"csv_delim_help": "",
"csv_delim_label": "",
"csv_prefix_help": "",
"csv_prefix_label": "",
"date_created": "",
"date_viewed": "",
"default_delay": "",
"default_delay_desc": "",
"del_confirmation_tree": "",
"delete_confirmation": "",
"delete_title": "",
"desc": "",
"download_csv": "",
"download_pdf": "",
"edit_title": "",
"empty_list": "",
"enable_expert": "",
"err_creating_resource": "",
"err_deleting_protected_resource": "",
"err_deleting_resource": "",
"err_fetching_resource": "",
"err_importing_recipe": "",
"err_merge_self": "",
"err_merging_resource": "",
"err_move_self": "",
"err_moving_resource": "",
"err_updating_resource": "",
"exact": "",
"exclude": "",
"expert_mode": "",
"explain": "",
"fields": "",
"file_upload_disabled": "",
"filter": "",
"filter_name": "",
"filter_to_supermarket": "",
"filter_to_supermarket_desc": "",
"fluid_ounce": "",
"food_inherit_info": "",
"food_recipe_help": "",
"g": "",
"gallon": "",
"hide_step_ingredients": "",
"hours": "",
"ignore_shopping_help": "",
"imperial_fluid_ounce": "",
"imperial_gallon": "",
"imperial_pint": "",
"imperial_quart": "",
"imperial_tbsp": "",
"imperial_tsp": "",
"import_duplicates": "",
"import_running": "",
"in_shopping": "",
"ingredient_list": "",
"kg": "",
"l": "",
"last_cooked": "",
"last_viewed": "",
"left_handed": "",
"left_handed_help": "",
"make_now": "",
"make_now_count": "",
"mark_complete": "",
"mealplan_autoadd_shopping": "",
"mealplan_autoadd_shopping_desc": "",
"mealplan_autoexclude_onhand": "",
"mealplan_autoexclude_onhand_desc": "",
"mealplan_autoinclude_related": "",
"mealplan_autoinclude_related_desc": "",
"merge_confirmation": "",
"merge_selection": "",
"merge_title": "",
"min": "",
"ml": "",
"move_confirmation": "",
"move_selection": "",
"move_title": "",
"no_more_images_found": "",
"no_pinned_recipes": "",
"not": "",
"nothing": "",
"nothing_planned_today": "",
"on": "",
"one_url_per_line": "",
"open_data_help_text": "",
"or": "",
"ounce": "",
"parameter_count": "",
"paste_ingredients": "",
"paste_ingredients_placeholder": "",
"paste_json": "",
"per_serving": "",
"pint": "",
"plan_share_desc": "",
"plural_short": "",
"plural_usage_info": "",
"pound": "",
"property_type_fdc_hint": "",
"quart": "",
"recipe_filter": "",
"recipe_name": "",
"recipe_property_info": "",
"related_recipes": "",
"remember_hours": "",
"remember_search": "",
"remove_selection": "",
"reset_children": "",
"reset_children_help": "",
"reset_food_inheritance": "",
"reset_food_inheritance_info": "",
"reusable_help_text": "",
"review_shopping": "",
"save_filter": "",
"searchFilterCreatedByHelp": "",
"searchFilterObjectsAndHelp": "",
"searchFilterObjectsAndNotHelp": "",
"searchFilterObjectsHelp": "",
"searchFilterObjectsOrNotHelp": "",
"search_create_help_text": "",
"search_import_help_text": "",
"search_no_recipes": "",
"search_rank": "",
"seconds": "",
"select_file": "",
"select_food": "",
"select_keyword": "",
"select_recipe": "",
"select_unit": "",
"shared_with": "",
"shopping_add_onhand": "",
"shopping_add_onhand_desc": "",
"shopping_auto_sync": "",
"shopping_auto_sync_desc": "",
"shopping_category_help": "",
"shopping_recent_days": "",
"shopping_recent_days_desc": "",
"shopping_share": "",
"shopping_share_desc": "",
"show_books": "",
"show_filters": "",
"show_foods": "",
"show_ingredient_overview": "",
"show_ingredients_table": "",
"show_keywords": "",
"show_only_internal": "",
"show_rating": "",
"show_sortby": "",
"show_split_screen": "",
"show_sql": "",
"show_step_ingredients": "",
"show_step_ingredients_setting": "",
"show_step_ingredients_setting_help": "",
"show_units": "",
"simple_mode": "",
"sort_by": "",
"sql_debug": "",
"step_time_minutes": "",
"substitute_children": "",
"substitute_children_help": "",
"substitute_help": "",
"substitute_siblings": "",
"substitute_siblings_help": "",
"success_creating_resource": "",
"success_deleting_resource": "",
"success_fetching_resource": "",
"success_merging_resource": "",
"success_moving_resource": "",
"success_updating_resource": "",
"tbsp": "",
"theUsernameCannotBeChanged": "",
"times_cooked": "",
"to_close": "",
"to_navigate": "",
"to_select": "",
"today_recipes": "",
"total": "",
"tree_root": "",
"tree_select": "",
"tsp": "",
"unsaved": "",
"updatedon": "",
"view_recipe": "",
"warning_duplicate_filter": "",
"warning_feature_beta": "",
"warning_space_delete": ""
}

View File

@@ -314,6 +314,7 @@
"Ratings": "",
"Recently_Viewed": "Neseniai Žiūrėta",
"Recipe": "",
"RecipeStructure": "",
"Recipe_Book": "",
"Recipe_Image": "Recepto nuotrauka",
"Recipes": "",
@@ -365,6 +366,7 @@
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Split_All_Steps": "",
"Start": "",
"StartDate": "",
"Starting_Day": "",
"StartsWith": "",

View File

@@ -337,6 +337,7 @@
"Ratings": "",
"Recently_Viewed": "",
"Recipe": "",
"RecipeStructure": "",
"Recipe_Book": "",
"Recipe_Image": "",
"Recipes": "",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "",
"Split_All_Steps": "",
"Start": "",
"StartDate": "",
"Starting_Day": "",
"StartsWith": "",

View File

@@ -321,6 +321,7 @@
"Ratings": "",
"Recently_Viewed": "Nylig vist",
"Recipe": "Oppskrift",
"RecipeStructure": "",
"Recipe_Book": "Oppskriftsbok",
"Recipe_Image": "Oppskriftsbilde",
"Recipes": "Oppskrift",
@@ -375,6 +376,7 @@
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Split_All_Steps": "",
"Start": "",
"StartDate": "Startdato",
"Starting_Day": "Dag uken skal state på",
"StartsWith": "",

View File

@@ -1,11 +1,11 @@
{
"AI": "AI",
"AIImportSubtitle": "Gebruik Al om afbeeldingen van recepten te importeren.",
"AISettingsHostedHelp": "",
"AISettingsHostedHelp": "Je kunt AI-functies inschakelen of beschikbare credits aanpassen door je abonnement te beheren.",
"API": "API",
"API_Browser": "",
"API_Documentation": "",
"AboutTandoor": "",
"APIKey": "API-sleutel",
"API_Browser": "API-browser",
"API_Documentation": "API-documentatie",
"AccessTokenHelp": "Toegangssleutels voor de REST API.",
"Access_Token": "Toegangstoken",
"Account": "Account",
@@ -14,7 +14,7 @@
"Activity": "Activiteit",
"Add": "Voeg toe",
"AddAll": "Voeg alles toe",
"AddChild": "",
"AddChild": "Subitem toevoegen",
"AddFilter": "Voeg filter toe",
"AddFoodToShopping": "Voeg {food} toe aan je boodschappenlijst",
"AddMany": "Voeg meerdere toe",
@@ -31,12 +31,12 @@
"Admin": "Beheer",
"Advanced": "Geavanceerd",
"Advanced Search Settings": "Geavanceerde zoekinstellingen",
"AiCreditsBalance": "",
"AiLog": "",
"AiLogHelp": "",
"AiModelHelp": "",
"AiProvider": "",
"AiProviderHelp": "",
"AiCreditsBalance": "Creditbalans",
"AiLog": "AI-log",
"AiLogHelp": "Overzicht van AI-verzoeken in je ruimtes. ",
"AiModelHelp": "De lijst bevat modellen die officieel getest en ondersteund zijn. Je kunt extra modellen toevoegen als je wilt.",
"AiProvider": "AI-provider",
"AiProviderHelp": "Je kunt meerdere AI-providers configureren naar jouw voorkeuren. Ze kunnen zelfs werken in meerdere ruimtes.",
"Alignment": "Afstemming",
"AllRecipes": "Alle recepten",
"Amount": "Hoeveelheid",
@@ -56,12 +56,12 @@
"BaseUnit": "Basiseenheid",
"BaseUnitHelp": "Standaardeenheid om automatische eenheden om te rekenen",
"Basics": "Basisprincipes",
"BatchDeleteConfirm": "",
"BatchDeleteHelp": "",
"BatchEdit": "",
"BatchEditUpdatingItemsCount": "",
"Blocking": "",
"BlockingHelp": "",
"BatchDeleteConfirm": "Wil je alle getoonde items verwijderen? Dit kan niet ongedaan worden gemaakt!",
"BatchDeleteHelp": "Als een item niet verwijderd kan worden, wordt het ergens gebruikt. ",
"BatchEdit": "Batchbewerking",
"BatchEditUpdatingItemsCount": "{count} {type} bewerken",
"Blocking": "Blokkeren",
"BlockingHelp": "De volgende objecten voorkomen het verwijderen van het geselecteerde {type}.",
"Book": "Boek",
"Bookmarklet": "Bladwijzer",
"BookmarkletHelp1": "Sleep de onderstaande knop naar je bladwijzerbalk",
@@ -69,21 +69,21 @@
"BookmarkletHelp3": "Klik op de bladwijzer om de import uit te voeren.",
"BookmarkletImportSubtitle": "Gebruik een bladwijzer om te importeren van niet-openbare paginas.",
"Books": "Kookboeken",
"CREATE_ERROR": "",
"CREATE_ERROR": "Fout bij aanmaken",
"Calculator": "Rekenmachine",
"Calories": "Calorieën",
"Cancel": "Annuleer",
"Cannot_Add_Notes_To_Shopping": "Notities kunnen niet aan de boodschappenlijst toegevoegd worden",
"Carbohydrates": "Koolhydraten",
"Cards": "Kaarten",
"Cascading": "",
"CascadingHelp": "",
"Cascading": "Cascadering",
"CascadingHelp": "De volgende objecten worden verwijderd als je het geselecteerde {type} verwijdert",
"Categories": "Categorieën",
"Category": "Categorie",
"CategoryInstruction": "Versleep categorieën om de volgorde waarin ze in de boodschappenlijst getoond worden aan te passen.",
"CategoryName": "Categorienaam",
"Change_Password": "Wachtwoord veranderen",
"Changing": "",
"Changing": "Wijziging",
"ChildInheritFields": "Afgeleiden Erven Velden",
"ChildInheritFields_help": "Afgeleiden zullen deze velden standaard overnemen.",
"Choose_Category": "Kies categorie",
@@ -103,7 +103,7 @@
"Continue": "Doorgaan",
"Conversion": "Omrekening",
"ConversionsHelp": "Met omrekeningen kun je de hoeveelheid van een ingrediënt in verschillende eenheden berekenen. Momenteel wordt dit alleen gebruikt voor het berekenen van eigenschappen, later kan het ook in andere onderdelen van Tandoor gebruikt worden. ",
"ConvertUsingAI": "",
"ConvertUsingAI": "Zet om met AI",
"CookLog": "Kooklogboek",
"CookLogHelp": "Items in het kooklogboek voor recepten. ",
"Cooked": "Gekookt",
@@ -117,9 +117,8 @@
"Create": "Aanmaken",
"Create Food": "Maak voedingsmiddel",
"Create Recipe": "Maak recept",
"CreateAccount": "",
"CreateFirstRecipe": "",
"CreateInvitation": "",
"CreateFirstRecipe": "Maak je eerste recept met de recepteneditor.",
"CreateInvitation": "Uitnodiging maken",
"Create_Meal_Plan_Entry": "Maak maaltijdplan",
"Create_New_Food": "Voeg nieuw voedingsmiddel toe",
"Create_New_Keyword": "Voeg nieuw trefwoord toe",
@@ -129,17 +128,17 @@
"Create_New_Unit": "Voeg nieuwe eenheid toe",
"Created": "Gemaakt",
"CreatedBy": "Gemaakt door",
"Credits": "",
"Credits": "Credits",
"Ctrl+K": "Ctrl+K",
"Current_Period": "Huidige periode",
"Custom Filter": "Aangepast filter",
"CustomImageHelp": "Upload een afbeelding om te tonen in het Ruimte overzicht.",
"CustomImageHelp": "Upload een afbeelding om te tonen in het ruimteoverzicht.",
"CustomLogoHelp": "Upload vierkante afbeeldingen in verschillende groottes om het logo in het browser tabblad en geïnstalleerde web apps aan te passen.",
"CustomLogos": "Aangepaste Logo's",
"CustomNavLogoHelp": "Upload een afbeelding om als logo te gebruiken in de navigatiebalk. (140x56px)",
"CustomTheme": "Aangepast thema",
"CustomThemeHelp": "Overschrijf de stijl van het thema door een aangepast CSS bestand te uploaden.",
"DELETE_ERROR": "",
"DELETE_ERROR": "Fout bij verwijderen",
"Data_Import_Info": "Verbeter je Ruimte door een door de community samengestelde lijst van voedingsmiddelen, eenheden en meer te importeren om je receptenverzameling te verbeteren.",
"Database": "Database",
"DatabaseHelp": "Tandoor gebruikt veel verschillende onderdelen om je te laten werken met recepten, boodschappenlijstjes, maaltijdplannen en meer. Hier kun je al deze modellen beheren.",
@@ -156,7 +155,7 @@
"Delete": "Verwijder",
"DeleteConfirmQuestion": "Weet je zeker dat je dit object wilt verwijderen?",
"DeleteShoppingConfirm": "Weet je zeker dat je {food} van de boodschappenlijst wil verwijderen?",
"DeleteSomething": "",
"DeleteSomething": "Verwijder {item}",
"Delete_All": "Verwijder allen",
"Delete_Food": "Verwijder voedingsmiddel",
"Delete_Keyword": "Verwijder trefwoord",
@@ -169,13 +168,13 @@
"Disable_Amount": "Schakel hoeveelheid uit",
"Disabled": "Gedeactiveerd",
"Documentation": "Documentatie",
"DontChange": "",
"DontChange": "Niet wijzigen",
"Down": "Omlaag",
"Download": "Download",
"DragToUpload": "Slepen en neerzetten of klik om te selecteren",
"Drag_Here_To_Delete": "Sleep hierheen om te verwijderen",
"Duplicate": "Dupliceer",
"DuplicateFoundInfo": "Er is al een recept met deze URL gevonden in je ruimte. Toch doorgaan?",
"DuplicateFoundInfo": "Er is al een recept met deze URL gevonden in je Ruimte. Toch doorgaan?",
"Edit": "Bewerken",
"Edit_Food": "Bewerk voedingsmiddel",
"Edit_Keyword": "Bewerk trefwoord",
@@ -198,7 +197,7 @@
"Export_Supported": "Export ondersteund",
"Export_To_ICal": "Exporteer .ics",
"External": "Externe",
"ExternalRecipe": "",
"ExternalRecipe": "Extern recept",
"ExternalRecipeImport": "Externe receptimport",
"ExternalRecipeImportHelp": "Bestanden in gesynchroniseerde mappen op externe opslag worden niet direct geïmporteerd, maar tijdelijk opgeslagen als externe receptimport. Hier kun je snel nieuw gevonden bestanden bekijken en bewerken voordat ze naar de hoofdcollectie worden verplaatst. ",
"ExternalStorage": "Externe opslag",
@@ -206,12 +205,11 @@
"FDC_ID": "FDC ID",
"FDC_ID_help": "FDC database ID",
"FDC_Search": "FDC Zoeken",
"FETCH_ERROR": "",
"FETCH_ERROR": "Fout bij ophalen",
"Failure": "Storing",
"Fats": "Vetten",
"File": "Bestand",
"Files": "Bestanden",
"Finish": "",
"FinishedAt": "Afgerond op",
"First": "Eerste",
"First_name": "Voornaam",
@@ -224,15 +222,15 @@
"Food_Replace": "Voedingsmiddelen vervangen",
"Foods": "Voedingsmiddelen",
"Friday": "Vrijdag",
"FromBalance": "",
"FromBalance": "Van balans",
"Fulltext": "Volledige tekst",
"FulltextHelp": "Velden voor volledige tekstzoekopdrachten. Opmerking: de zoekmethoden web, zin en ruw werken alleen met volledige tekstvelden.",
"Fuzzy": "Fuzzy",
"FuzzySearchHelp": "Gebruik fuzzy search om items te vinden, zelfs als het woord anders is gespeld.",
"GettingStarted": "Aan de slag",
"Global": "",
"GlobalHelp": "",
"Group": "",
"Global": "Globaal",
"GlobalHelp": "Globale AI-providers kunnen door gebruikers van alle ruimtes gebruikt worden. Ze kunnen alleen door supergebruikers worden aangemaakt en bewerkt. ",
"Group": "Groep",
"GroupBy": "Groepeer per",
"HeaderWarning": "Waarschuwing: Het wijzigen naar een kop verwijdert de hoeveelheid/eenheid/voedingsmiddel",
"Headline": "Koptekst",
@@ -258,11 +256,10 @@
"Import": "Importeer",
"Import Recipe": "Recept importeren",
"ImportAll": "Alles importeren",
"ImportFirstRecipe": "",
"ImportFirstRecipe": "Importeer je eerste recept van een van de duizenden websites of gebruik een van de andere importeurs om je bestaande collectie, documenten of URL-lijsten te importeren.",
"ImportIntoTandoor": "Importeer in Tandoor",
"ImportIntoTandoorHelp": "",
"ImportMealPlans": "",
"ImportShoppingList": "",
"ImportMealPlans": "Maaltijdplannen importeren",
"ImportShoppingList": "Boodschappenlijsten importeren",
"Import_Error": "Er is een fout opgetreden tijdens je import. Breid de details aan de onderzijde van de pagina uit om ze te bekijken.",
"Import_Not_Yet_Supported": "Import nog niet ondersteund",
"Import_Result_Info": "{imported} van {total} recepten zijn geïmporteerd",
@@ -288,7 +285,7 @@
"Instructions": "Instructies",
"InstructionsEditHelp": "Klik hier om instructies toe te voegen. ",
"Internal": "Interne",
"InviteLinkHelp": "Links om nieuwe mensen uit te nodigen voor je ruimte. ",
"InviteLinkHelp": "Links om nieuwe mensen uit te nodigen voor je Ruimte. ",
"Invite_Link": "Uitnodigingslink",
"Invites": "Uitnodigingen",
"Key_Ctrl": "Ctrl",
@@ -301,12 +298,12 @@
"Last": "Laatste",
"Last_name": "Achternaam",
"Learn_More": "Meer informatie",
"LeaveSpace": "",
"LeaveSpace": "Ruimte verlaten",
"Link": "Link",
"Load": "Laden",
"Load_More": "Laad meer",
"LogCredits": "",
"LogCreditsHelp": "",
"LogCredits": "Credits loggen.",
"LogCreditsHelp": "Creditkosten van AI-verzoeken loggen. Zonder deze kunnen gebruikers onbeperkt AI-verzoeken uitvoeren. ",
"Log_Cooking": "Registreer bereiding",
"Log_Recipe_Cooking": "Bereiding registreren",
"Logo": "Logo",
@@ -316,7 +313,7 @@
"ManageSubscription": "Abonnement beheren",
"Manage_Books": "Beheer kookboeken",
"Manage_Emails": "E-mail beheren",
"MealPlanHelp": "Een maaltijdplanner is een agendaitem waarmee je maaltijden plant. Het moet een recept of titel bevatten en kan gekoppeld worden aan boodschappenlijstjes. ",
"MealPlanHelp": "Een maaltijdplanner is een agenda-item waarmee je maaltijden plant. Het moet een recept of titel bevatten en kan gekoppeld worden aan boodschappenlijstjes. ",
"MealPlanShoppingHelp": "Items op je boodschappenlijst kunnen worden gekoppeld aan een maaltijdplanner, zodat je de lijst kunt sorteren of alles in één keer kunt bijwerken/verwijderen. Wanneer je een maaltijdplanner met een recept aanmaakt, kunnen de bijbehorende boodschappen automatisch aan de lijst worden toegevoegd (instelling). ",
"MealTypeHelp": "Maaltijdtypen maken het mogelijk om je maaltijdplannen te sorteren. ",
"Meal_Plan": "Maaltijdplan",
@@ -326,18 +323,19 @@
"Meal_Types": "Maaltijd types",
"Merge": "Samenvoegen",
"MergeAutomateHelp": "Maak een automatisering aan die toekomstige objecten van dit type vervangt door het geselecteerde object.",
"MergeInsteadOfDelete": "",
"MergeInsteadOfDelete": "In plaats van dit {type} te verwijderen, kun je het samenvoegen met een ander bestaand {type}.",
"Merge_Keyword": "Voeg trefwoord samen",
"Message": "Bericht",
"Messages": "Berichten",
"Miscellaneous": "Diversen",
"MissingConversion": "Ontbrekende conversie",
"MissingProperties": "Ontbrekende eigenschappen",
"Model": "Model",
"ModelSelectResultsHelp": "Zoek naar meer resultaten",
"Monday": "Maandag",
"Month": "Maand",
"MonthlyCredits": "",
"MonthlyCreditsUsed": "",
"MonthlyCredits": "Maandelijkse credits",
"MonthlyCreditsUsed": "Maandelijkse gebruikte credits",
"More": "Meer",
"Move": "Verplaats",
"MoveCategory": "Verplaats naar: ",
@@ -367,7 +365,7 @@
"Next": "Volgende",
"Next_Day": "Volgende dag",
"Next_Period": "Volgende periode",
"No": "",
"No": "Nee",
"NoCategory": "Geen categorie geselecteerd",
"NoMoreUndo": "Geen veranderingen om ongedaan te maken.",
"NoUnit": "Geen eenheid",
@@ -377,11 +375,11 @@
"NotFoundHelp": "De pagina of het object dat je zoekt, is niet gevonden.",
"NotInShopping": "{food} staat niet op je boodschappenlijst.",
"Note": "Notitie",
"NullingHelp": "",
"NullingHelp": "Het geselecteerde {type} wordt verwijderd uit de volgende objecten als het verwijderd wordt.",
"Number of Objects": "Aantal objecten",
"Nutrition": "Voedingswaarde",
"NutritionsPerServing": "",
"NutritionsPerServingHelp": "",
"NutritionsPerServing": "Voedingswaarden per portie",
"NutritionsPerServingHelp": "Sommige toepassingen geven niet aan of voedingswaarden per recept of per portie zijn. Standaard behandelt Tandoor deze als per recept. Vink dit aan om per portie te gebruiken. ",
"OfflineAlert": "Je bent offline, boodschappenlijst synchroniseert mogelijk niet.",
"Ok": "Ok",
"OnHand": "Momenteel op voorraad",
@@ -396,7 +394,7 @@
"Owner": "Eigenaar",
"Page": "Pagina",
"Parameter": "Parameter",
"Parent": "Ouder",
"Parent": "Hoofdcategorie",
"PartialMatch": "Gedeeltelijke overeenkomst",
"PartialMatchHelp": "Velden voor gedeeltelijke overeenkomsten om op deelwoorden te zoeken. (Bijvoorbeeld: zoeken op taart geeft resultaten als taart, taartje en worteltaart.)",
"Password": "Wachtwoord",
@@ -423,9 +421,9 @@
"Previous_Day": "Vorige dag",
"Previous_Period": "Vorige periode",
"Print": "Afdrukken",
"Private": "",
"Private": "Privė",
"Private_Recipe": "Privé recept",
"Private_Recipe_Help": "Recept is alleen zichtbaar voor jou en de mensen waar je het mee gedeeld hebt.",
"Private_Recipe_Help": "Privérecepten zijn alleen zichtbaar voor jou en de mensen met wie je ze deelt.",
"Profile": "Profiel",
"Properties": "Eigenschappen",
"PropertiesFoodHelp": "Eigenschappen op voedingsmiddelen worden automatisch berekend op basis van hun hoeveelheid in het recept.",
@@ -452,16 +450,17 @@
"RecipeBookHelp": "Receptboeken bevatten receptenboekitems of kunnen automatisch gevuld worden met behulp van opgeslagen zoekfilters. ",
"RecipeHelp": "Recepten vormen de basis van Tandoor en bestaan uit algemene informatie en stappen, opgebouwd uit ingrediënten, instructies en meer. ",
"RecipeStepsHelp": "Ingrediënten, instructies en meer kun je bewerken in het tabblad stappen.",
"RecipeStructure": "",
"Recipe_Book": "Kookboek",
"Recipe_Image": "Receptafbeelding",
"Recipes": "Recepten",
"Recipes_In_Import": "Recepten in je importbestand",
"Recipes_per_page": "Recepten per pagina",
"Refresh": "",
"Refresh": "Vernieuwen",
"Remove": "Verwijder",
"RemoveAllType": "",
"RemoveAllType": "Alle {type} verwijderen",
"RemoveFoodFromShopping": "Verwijder {food} van je boodschappenlijst",
"RemoveParent": "",
"RemoveParent": "Verwijder hoofdcategorie",
"Remove_nutrition_recipe": "Verwijder voedingswaarde van recept",
"Reset": "Herstel",
"ResetHelp": "Hulp herstellen",
@@ -491,12 +490,11 @@
"Select_File": "Selecteer bestand",
"Selected": "Geselecteerd",
"SelectedCategories": "Geselecteerde categorieën",
"SelfHosted": "",
"Serving": "Portie",
"Servings": "Porties",
"ServingsText": "Portie tekst",
"Settings": "Instellingen",
"SettingsOnlySuperuser": "",
"SettingsOnlySuperuser": "Sommige instellingen kunnen alleen door de serverbeheerder worden gewijzigd.",
"Share": "Deel",
"ShopLater": "Later boodschappen doen",
"ShopNow": "Nu boodschappen doen",
@@ -520,25 +518,26 @@
"Show_as_header": "Toon als koptekst",
"Single": "Enkele",
"Size": "Grootte",
"Skip": "",
"Skip": "Overslaan",
"Social_Authentication": "Authenticeren met sociale media-account",
"Sort_by_new": "Sorteer op nieuw",
"Source": "Bron",
"SourceImportHelp": "Importeer JSON in schema.org/recipe-formaat of html-paginas met json+ld-recepten of microdata.",
"SourceImportSubtitle": "Importeer handmatig JSON of HTML.",
"Space": "",
"SpaceHelp": "",
"Space": "Ruimte",
"SpaceHelp": "Al je gegevens maken deel uit van je ruimte en kunnen alleen worden bekeken door gebruikers van de ruimte. ",
"SpaceLimitExceeded": "Je ruimte heeft een limiet overschreden, sommige functies zijn mogelijk beperkt.",
"SpaceLimitReached": "Deze ruimte heeft een limiet bereikt. Er kunnen geen objecten van dit type meer worden aangemaakt.",
"SpaceMemberHelp": "Voeg gebruikers toe aan je ruimte door een uitnodigingslink aan te maken en naar de persoon te sturen die je wilt toevoegen.",
"SpaceMembers": "Gebruikers van de ruimte",
"SpaceMembersHelp": "",
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"SpaceMembersHelp": "Gebruikers en hun rechten in een ruimte. Voeg extra gebruikers toe via uitnodigingslinks.",
"SpaceName": "Ruimtenaam",
"SpacePrivateObjectsHelp": " Sommige zaken zijn standaard privé en kunnen gedeeld worden met gebruikers van je ruimte.",
"SpaceSettings": "Ruimte-instellingen",
"Space_Cosmetic_Settings": "Sommige weergave instellingen kunnen worden geforceerd door de administrator van de 'Ruimte' en zullen de persoonlijke instellingen voor die 'Ruimte' overschrijven.",
"Space_Cosmetic_Settings": "Sommige weergave-instellingen kunnen worden geforceerd door de administrator van de ruimte en zullen de persoonlijke instellingen voor die ruimte overschrijven.",
"Split": "Splitsen",
"Split_All_Steps": "Splits alle rijen in aparte stappen.",
"Start": "",
"StartDate": "Startdatum",
"Starting_Day": "Eerste dag van de week",
"StartsWith": "Begint met",
@@ -555,10 +554,12 @@
"Storage": "Externe opslag",
"StorageHelp": "Extern opgeslagen locaties waar receptenbestanden (afbeelding/pdf) kunnen worden opgeslagen en gesynchroniseerd met Tandoor.",
"StoragePasswordTokenHelp": "Het opgeslagen wachtwoord/token wordt nooit weergegeven. Dit wordt alleen gewijzigd als er iets nieuws in het veld wordt ingevoerd. ",
"Structured": "Gestructureerd",
"SubstituteOnHand": "Je hebt een alternatief op voorraad.",
"Substitutes": "Alternatieven",
"Success": "Succes",
"SuccessClipboard": "Boodschappenlijst is gekopieerd naar klembord",
"Summary": "Samenvatting",
"Sunday": "Zondag",
"Supermarket": "Supermarkt",
"SupermarketCategoriesOnly": "Alleen supermarkt categorieën",
@@ -590,7 +591,7 @@
"TrigramThresholdHelp": "Bepaalt hoeveel spelfouten worden genegeerd bij het gebruiken van fuzzy search. Lagere waarden negeren meer verschillen en geven meer resultaten.",
"Tuesday": "Dinsdag",
"Type": "Type",
"UPDATE_ERROR": "",
"UPDATE_ERROR": "Fout bij bijwerken",
"Unchanged": "Ongewijzigd",
"Undefined": "Ongedefinieerd",
"Undo": "Ongedaan maken",
@@ -632,7 +633,7 @@
"ViewLogHelp": "Geschiedenis van bekeken recepten. ",
"View_Recipes": "Bekijk Recepten",
"Viewed": "Bekeken",
"Visibility": "",
"Visibility": "Zichtbaarheid",
"Waiting": "Wachten",
"WaitingTime": "Wachttijd",
"WarnPageLeave": "Er zijn niet-opgeslagen wijzigingen die verloren zullen gaan. Pagina toch verlaten?",
@@ -644,11 +645,11 @@
"Week": "Week",
"Week_Numbers": "Weeknummers",
"Welcome": "Welkom",
"WelcomeSettingsHelp": "",
"WelcometoTandoor": "",
"WelcomeSettingsHelp": "Kies de basisinstellingen voor je Tandoor ruimte. Je kunt deze later allemaal wijzigen via de instellingen.",
"WelcometoTandoor": "Welkom bij Tandoor",
"WorkingTime": "Bereidingstijd",
"Year": "Jaar",
"Yes": "",
"Yes": "Ja",
"YourSpaces": "Jouw ruimtes",
"active": "actief",
"add_keyword": "Voeg trefwoord toe",
@@ -714,7 +715,7 @@
"expert_mode": "Expertmodus",
"explain": "Leg uit",
"fields": "Velden",
"file_upload_disabled": "Het uploaden van bestanden is niet ingeschakeld voor uw ruimte.",
"file_upload_disabled": "Het uploaden van bestanden is niet ingeschakeld voor jouw ruimte.",
"filter": "Filter",
"filter_name": "Naam filter",
"filter_to_supermarket": "Filter op supermarkt",
@@ -757,8 +758,8 @@
"merge_title": "Voeg {type} samen",
"min": "min",
"ml": "milliliter [ml] (metrisch, volume)",
"move_confirmation": "Verplaats <i>{child}</i> naar ouder <i>{parent}</i>",
"move_selection": "Selecteer een ouder {type} om {source} naar te verplaatsen.",
"move_confirmation": "Verplaats <i>{child}</i> naar hoofdcategorie <i>{parent}</i>",
"move_selection": "Selecteer een hoofdcategorie {type} om {source} naar te verplaatsen.",
"move_title": "Verplaats {type}",
"no_more_images_found": "Geen extra afbeeldingen gevonden op website.",
"no_pinned_recipes": "Je hebt geen vastgepinde recepten!",
@@ -840,7 +841,7 @@
"sort_by": "Sorteer op",
"sql_debug": "SQL Debug",
"step_time_minutes": "Stap duur in minuten",
"substitute_children": "Alternatieve afgeleiden",
"substitute_children": "Alternatieve subcategorie",
"substitute_children_help": "Alle voedingsmiddelen die afgeleiden zijn van dit voedingsmiddel worden beschouwd als alternatieven.",
"substitute_help": "Alternatieven worden overwogen bij het zoeken naar recepten die kunnen worden gemaakt met beschikbare ingrediënten.",
"substitute_siblings": "Alternatieve Varianten",
@@ -868,5 +869,5 @@
"view_recipe": "Bekijk recept",
"warning_duplicate_filter": "Waarschuwing: door technische beperkingen kan het hebben van meerdere filters of dezelfde combinatie (en/of/niet) tot onverwachte resultaten leiden.",
"warning_feature_beta": "Deze functie zit op dit moment in de BETA (test) fase. Verwacht hier bugs en toekomstige wijzigingen die tot het verlies van data kunnen leiden bij het gebruik.",
"warning_space_delete": "Je kunt jouw space verwijderen inclusief alle recepten, boodschappenlijstjes, maaltijdplannen en alles wat je verder aangemaakt hebt. Dit kan niet ongedaan worden gemaakt! Weet je het zeker?"
"warning_space_delete": "Je kunt jouw ruimte verwijderen inclusief alle recepten, boodschappenlijstjes, maaltijdplannen en alles wat je verder aangemaakt hebt. Dit kan niet ongedaan worden gemaakt! Weet je het zeker?"
}

View File

@@ -363,6 +363,7 @@
"Ratings": "Oceny",
"Recently_Viewed": "Ostatnio oglądane",
"Recipe": "Przepis",
"RecipeStructure": "",
"Recipe_Book": "Książka z przepisami",
"Recipe_Image": "Obrazek dla przepisu",
"Recipes": "Przepisy",
@@ -420,6 +421,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Administratorzy przestrzeni mogą zmienić niektóre ustawienia kosmetyczne, które zastąpią ustawienia klienta dla tej przestrzeni.",
"Split_All_Steps": "Traktuj każdy wiersz jako osobne kroki.",
"Start": "",
"StartDate": "Data początkowa",
"Starting_Day": "Dzień rozpoczęcia tygodnia",
"StartsWith": "",

View File

@@ -26,6 +26,7 @@
"Auto_Sort_Help": "Mover todos os ingredientes para o passo mais indicado.",
"Automate": "Automatizar",
"Automation": "Automação",
"BatchDeleteConfirm": "",
"Books": "Livros",
"Calculator": "Calculadora",
"Calories": "Calorias",
@@ -235,6 +236,7 @@
"Ratings": "Avaliações",
"Recently_Viewed": "Vistos Recentemente",
"Recipe": "Receita",
"RecipeStructure": "",
"Recipe_Book": "Livro de Receitas",
"Recipe_Image": "Imagem da Receita",
"Recipes": "Receitas",
@@ -270,6 +272,7 @@
"Show_as_header": "Mostrar como cabeçalho",
"Size": "Tamanho",
"Sort_by_new": "Ordenar por mais recente",
"Start": "",
"StartDate": "Data de início",
"Starting_Day": "Dia de início da semana",
"StartsWith": "",

View File

@@ -414,6 +414,7 @@
"Ratings": "Classificações",
"Recently_Viewed": "Visto recentemente",
"Recipe": "Receita",
"RecipeStructure": "",
"Recipe_Book": "Livro de Receitas",
"Recipe_Image": "Imagem da receita",
"Recipes": "Receitas",
@@ -468,6 +469,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Algumas configurações cosméticas podem ser alteradas pelos administradores do espaço e substituirão as configurações do cliente para esse espaço.",
"Split_All_Steps": "Divida todas as linhas em etapas separadas.",
"Start": "",
"StartDate": "Data Início",
"Starting_Day": "Dia de início da semana",
"Step": "Etapa",

View File

@@ -298,6 +298,7 @@
"Ratings": "Evaluări",
"Recently_Viewed": "Vizualizate recent",
"Recipe": "Rețetă",
"RecipeStructure": "",
"Recipe_Book": "Carte de rețete",
"Recipe_Image": "Imagine a rețetei",
"Recipes": "Rețete",
@@ -349,6 +350,7 @@
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"Split_All_Steps": "Împărțiți toate rândurile în pași separați.",
"Start": "",
"Starting_Day": "Ziua de început a săptămânii",
"StartsWith": "",
"StartsWithHelp": "",

View File

@@ -449,6 +449,7 @@
"RecipeBookHelp": "Кулинарные книги содержат записи рецептов или могут автоматически заполняться с помощью сохранённых фильтров поиска. ",
"RecipeHelp": "Рецепты — основа Tandoor и состоят из общей информации и шагов, включающих ингредиенты, инструкции и многое другое. ",
"RecipeStepsHelp": "Ингредиенты, инструкции и другое можно редактировать на вкладке «Шаги».",
"RecipeStructure": "",
"Recipe_Book": "Книга рецептов",
"Recipe_Image": "Изображение рецепта",
"Recipes": "Рецепты",
@@ -536,6 +537,7 @@
"Space_Cosmetic_Settings": "Администраторы пространства могут менять некоторые визуальные настройки, которые будут переопределять настройки клиента для данного пространства.",
"Split": "Разделить",
"Split_All_Steps": "Разделить все строки на отдельные шаги.",
"Start": "",
"StartDate": "Дата начала",
"Starting_Day": "Начальный день недели",
"StartsWith": "Начинается с",

View File

@@ -1,20 +1,21 @@
{
"AI": "Umetna inteligenca",
"AIImportSubtitle": "Uporabite umetno inteligenco za uvoz slik receptov.",
"AISettingsHostedHelp": "",
"AISettingsHostedHelp": "Funkcije umetne inteligence lahko omogočite ali spremenite razpoložljive kredite z upravljanjem naročnine.",
"API": "API",
"API_Browser": "",
"API_Documentation": "",
"AboutTandoor": "",
"APIKey": "API ključ",
"API_Browser": "API brskalnik",
"API_Documentation": "API dokumentacija",
"AboutTandoor": "Tandoor je odprtokodna platforma za upravljanje receptov, načrtov obrokov, nakupovalnih seznamov in še več.",
"AccessTokenHelp": "Dostopni ključi za REST API.",
"Access_Token": "Dostopni žeton",
"Account": "Račun",
"Actions": "Dejanja",
"Active": "",
"Active": "Aktivno",
"Activity": "Aktivnost",
"Add": "Dodaj",
"AddAll": "Dodaj vse",
"AddChild": "",
"AddChild": "Dodaj otroka",
"AddFilter": "Dodaj filter",
"AddFoodToShopping": "Dodaj {food} v nakupovalni listek",
"AddMany": "Dodaj veliko",
@@ -30,12 +31,12 @@
"Admin": "Skrbnik",
"Advanced": "Napredno",
"Advanced Search Settings": "",
"AiCreditsBalance": "",
"AiLog": "",
"AiLogHelp": "",
"AiModelHelp": "",
"AiProvider": "",
"AiProviderHelp": "",
"AiCreditsBalance": "Kreditno stanje",
"AiLog": "Dnevnik umetne inteligence",
"AiLogHelp": "Pregled vaših zahtev za umetno inteligenco v prostorih. ",
"AiModelHelp": "Seznam vsebuje modele, ki so uradno preizkušeni in podprti. Po želji lahko dodate še druge modele.",
"AiProvider": "Ponudnik umetne inteligence",
"AiProviderHelp": "Več ponudnikov umetne inteligence lahko konfigurirate glede na svoje nastavitve. Konfigurirate jih lahko celo za delovanje v več prostorih.",
"Alignment": "Poravnava",
"AllRecipes": "Vsi recepti",
"Amount": "Količina",
@@ -55,12 +56,12 @@
"BaseUnit": "Osnovna enota",
"BaseUnitHelp": "Standardna enota za samodejno pretvorbo enot",
"Basics": "Osnove",
"BatchDeleteConfirm": "",
"BatchDeleteHelp": "",
"BatchEdit": "",
"BatchEditUpdatingItemsCount": "",
"Blocking": "",
"BlockingHelp": "",
"BatchDeleteConfirm": "Ali želite izbrisati vse prikazane elemente? Tega ni mogoče razveljaviti! OPOZORILO: Možno je, da se s tem izbrišejo predmeti, ki se uporabljajo drugje. ",
"BatchDeleteHelp": "Če elementa ni mogoče izbrisati, se nekje uporablja. ",
"BatchEdit": "Paketno urejanje",
"BatchEditUpdatingItemsCount": "Urejanje {count} {type}",
"Blocking": "Blokiranje",
"BlockingHelp": "Naslednji objekti vam preprečujejo brisanje izbranega {type}.",
"Book": "Knjiga",
"Bookmarklet": "Zaznamek",
"BookmarkletHelp1": "Povlecite naslednji gumb v vrstico z zaznamki",
@@ -68,21 +69,21 @@
"BookmarkletHelp3": "Za uvoz kliknite na zaznamek.",
"BookmarkletImportSubtitle": "Za uvoz z zasebnih strani uporabite zaznamek.",
"Books": "Knjige",
"CREATE_ERROR": "",
"CREATE_ERROR": "Napaka pri ustvarjanju",
"Calculator": "Kalkulator",
"Calories": "Kalorije",
"Cancel": "Prekini",
"Cannot_Add_Notes_To_Shopping": "Opombe ne moreš dodati v nakupovalni listek",
"Carbohydrates": "Ogljikovi hidrati",
"Cards": "Karte",
"Cascading": "",
"CascadingHelp": "",
"Cascading": "Kaskadno",
"CascadingHelp": "Naslednji objekti bodo izbrisani, ko izbrišete izbrani {type}",
"Categories": "Kategorije",
"Category": "Kategorija",
"CategoryInstruction": "Povleci kategorije za spremembo vrstnega reda v nakupovalnem listku.",
"CategoryName": "Ime kategorije",
"Change_Password": "Spremeni geslo",
"Changing": "",
"Changing": "Spreminjanje",
"ChildInheritFields": "Otroci podedujejo polja",
"ChildInheritFields_help": "Otroci bodo privzeto podedovali ta polja.",
"Choose_Category": "Izberi kategorijo",
@@ -102,7 +103,7 @@
"Continue": "Nadaljuj",
"Conversion": "Pogovor",
"ConversionsHelp": "S pretvorbami lahko izračunate količino živila v različnih enotah. Trenutno se to uporablja le za izračun lastnosti, kasneje pa se lahko uporabi tudi v drugih delih Tandoorja. ",
"ConvertUsingAI": "",
"ConvertUsingAI": "Pretvorba z umetno inteligenco",
"CookLog": "Kuharski dnevnik",
"CookLogHelp": "Vnosi v dnevnik kuhanja za recepte. ",
"Cooked": "Kuhano",
@@ -116,9 +117,9 @@
"Create": "Ustvari",
"Create Food": "Ustvari živilo",
"Create Recipe": "Ustvari recept",
"CreateAccount": "",
"CreateFirstRecipe": "",
"CreateInvitation": "",
"CreateAccount": "Ustvari račun",
"CreateFirstRecipe": "Ustvarite svoj prvi recept z urejevalnikom receptov.",
"CreateInvitation": "Ustvari povabilo",
"Create_Meal_Plan_Entry": "Ustvari vnos za načrtovan obrok",
"Create_New_Food": "Dodaj Novo Hrano",
"Create_New_Keyword": "Dodaj novo ključno besedo",
@@ -128,7 +129,7 @@
"Create_New_Unit": "Dodaj novo enoto",
"Created": "Ustvarjeno",
"CreatedBy": "Ustvaril/a",
"Credits": "",
"Credits": "Zasluge",
"Ctrl+K": "Ctrl+K",
"Current_Period": "Trenutno obdobje",
"Custom Filter": "Filter po meri",
@@ -138,7 +139,7 @@
"CustomNavLogoHelp": "Naložite sliko, ki jo boste uporabili kot logotip navigacijske vrstice. (140 x 56 slikovnih pik)",
"CustomTheme": "Tema po meri",
"CustomThemeHelp": "Preglasite sloge izbrane teme z nalaganjem datoteke CSS po meri.",
"DELETE_ERROR": "",
"DELETE_ERROR": "Napaka pri brisanju",
"Data_Import_Info": "Izboljšajte svoj prostor z uvozom seznama živil, enot in drugega, ker je pripravila skupnost, ter s tem izboljšajte svojo zbirko receptov.",
"Database": "Baza podatkov",
"DatabaseHelp": "Tandoor uporablja veliko različnih stvari, da lahko ustvarite recepte, nakupovalne sezname, načrte obrokov in še več. Tukaj lahko upravljate vse te modele.",
@@ -155,7 +156,7 @@
"Delete": "Izbriši",
"DeleteConfirmQuestion": "Ali ste prepričani, da želite izbrisati ta objekt?",
"DeleteShoppingConfirm": "Si prepričan/a, da želiš odstraniti VSO {food} iz nakupovalnega listka?",
"DeleteSomething": "",
"DeleteSomething": "Izbriši {item}",
"Delete_All": "Izbriši vse",
"Delete_Food": "Izbriši hrano",
"Delete_Keyword": "Izbriši ključno besedo",
@@ -168,7 +169,7 @@
"Disable_Amount": "Onemogoči količino",
"Disabled": "Onemogočeno",
"Documentation": "Dokumentacija",
"DontChange": "",
"DontChange": "Ne spreminjaj",
"Down": "Navzdol",
"Download": "Prenesi",
"DragToUpload": "Povlecite in spustite ali kliknite za izbiro",
@@ -197,7 +198,7 @@
"Export_Supported": "Izvoz podprt",
"Export_To_ICal": "Izvoz.ics",
"External": "Zunanje",
"ExternalRecipe": "",
"ExternalRecipe": "Zunanji recept",
"ExternalRecipeImport": "Uvoz zunanjih receptov",
"ExternalRecipeImportHelp": "Datoteke v sinhroniziranih mapah na zunanjih shrambah se ne uvozijo neposredno, temveč se začasno shranijo kot recepti za zunanji uvoz. Tukaj si lahko hitro ogledate in uredite novo najdene datoteke, preden jih premaknete v glavno zbirko. ",
"ExternalStorage": "Zunanji pomnilnik",
@@ -205,12 +206,12 @@
"FDC_ID": "FDC ID",
"FDC_ID_help": "FDC ID v bazi",
"FDC_Search": "FDC iskanje",
"FETCH_ERROR": "",
"FETCH_ERROR": "Napaka pri pridobivanju",
"Failure": "Napaka",
"Fats": "Maščobe",
"File": "Datoteka",
"Files": "Datoteke",
"Finish": "",
"Finish": "Končaj",
"FinishedAt": "Končano ob",
"First": "Prvi",
"First_name": "Ime",
@@ -223,15 +224,15 @@
"Food_Replace": "Zamenjava živila",
"Foods": "Živila",
"Friday": "Petek",
"FromBalance": "",
"FromBalance": "Iz stanja",
"Fulltext": "Celotno besedilo",
"FulltextHelp": "Polja za iskanje po celotnem besedilu. Opomba: metode iskanja »splet«, »fraza« in »surovo« delujejo samo s polji po celotnem besedilu.",
"Fuzzy": "Nejasno",
"FuzzySearchHelp": "Uporabite mehko iskanje za iskanje vnosov, tudi če obstajajo razlike v načinu pisanja besede.",
"GettingStarted": "Začetek",
"Global": "",
"GlobalHelp": "",
"Group": "",
"Global": "Globalno",
"GlobalHelp": "Globalne ponudnike umetne inteligence lahko uporabljajo uporabniki vseh prostorov. Ustvarjajo in urejajo jih lahko le superuporabniki. ",
"Group": "Skupina",
"GroupBy": "Združi po",
"HeaderWarning": "Opozorilo: Sprememba naslova izbriše količino/enoto/hrano",
"Headline": "Glavni naslov",
@@ -242,7 +243,7 @@
"Hide_Keywords": "Skrij ključno besedo",
"Hide_Recipes": "Skrij recept",
"Hide_as_header": "Skrij kot glavo",
"Hierarchy": "",
"Hierarchy": "Hierarhija",
"History": "Zgodovina",
"HostedFreeVersion": "Uporabljate brezplačno različico Tandoorja",
"Hour": "Ura",
@@ -257,11 +258,11 @@
"Import": "Uvozi",
"Import Recipe": "Uvozi recept",
"ImportAll": "Uvozi vse",
"ImportFirstRecipe": "",
"ImportFirstRecipe": "Uvozite svoj prvi recept z enega od tisočih spletnih mest ali pa uporabite enega od drugih uvoznikov za uvoz obstoječe zbirke, dokumentov ali seznamov URL-jev.",
"ImportIntoTandoor": "Uvozi v Tandoor",
"ImportIntoTandoorHelp": "",
"ImportMealPlans": "",
"ImportShoppingList": "",
"ImportIntoTandoorHelp": "Če želite uvoziti ta recept v svojo zbirko Tandoor, sledite naslednjim korakom.",
"ImportMealPlans": "Uvozi načrte prehrane",
"ImportShoppingList": "Uvozi nakupovalne sezname",
"Import_Error": "Med uvozom je prišlo do napake. Za ogled razširite podrobnosti na dnu strani.",
"Import_Not_Yet_Supported": "Uvoz še ni podprt",
"Import_Result_Info": "Uvoženih je bilo {imported} od {total} receptov",
@@ -300,12 +301,12 @@
"Last": "Zadnji",
"Last_name": "Priimek",
"Learn_More": "Preberite Več",
"LeaveSpace": "",
"LeaveSpace": "Zapusti prostor",
"Link": "Hiperpovezava",
"Load": "Naloži",
"Load_More": "Naloži več",
"LogCredits": "",
"LogCreditsHelp": "",
"LogCredits": "Zasluge za dnevnik.",
"LogCreditsHelp": "Beleži stroške kreditov za zahteve umetne inteligence. Brez tega lahko uporabniki izvedejo poljubno število zahtev umetne inteligence. ",
"Log_Cooking": "Zgodovina kuhanja",
"Log_Recipe_Cooking": "Beleži kuharski recept",
"Logo": "Logotip",
@@ -325,18 +326,19 @@
"Meal_Types": "Tipi obroka",
"Merge": "Združi",
"MergeAutomateHelp": "Ustvarite avtomatizacijo, ki bo prihodnje objekte te vrste nadomestila z izbranim objektom.",
"MergeInsteadOfDelete": "",
"MergeInsteadOfDelete": "Namesto brisanja tega {type} ga lahko združite z drugim obstoječim {type}.",
"Merge_Keyword": "Združi ključno besedo",
"Message": "Sporočilo",
"Messages": "Sporočila",
"Miscellaneous": "Razno",
"MissingConversion": "Manjkajoča konverzija",
"MissingProperties": "Manjkajoče lastnosti",
"Model": "Model",
"ModelSelectResultsHelp": "Išči več rezultatov",
"Monday": "Ponedeljek",
"Month": "Mesec",
"MonthlyCredits": "",
"MonthlyCreditsUsed": "",
"MonthlyCredits": "Mesečni krediti",
"MonthlyCreditsUsed": "Porabljeni mesečni krediti",
"More": "Več",
"Move": "Premakni",
"MoveCategory": "Premakni v: ",
@@ -366,7 +368,7 @@
"Next": "Naprej",
"Next_Day": "Naslednji Dan",
"Next_Period": "Naslednje obdobje",
"No": "",
"No": "Ne",
"NoCategory": "Brez kategorije",
"NoMoreUndo": "Ni sprememb, ki bi jih bilo mogoče razveljaviti.",
"NoUnit": "Brez enote",
@@ -376,11 +378,11 @@
"NotFoundHelp": "Strani ali predmeta, ki ga iščete, ni bilo mogoče najti.",
"NotInShopping": "{food} ni v tvojem nakupovalnem listku.",
"Note": "Opomba",
"NullingHelp": "",
"NullingHelp": "Izbrani {type} bo ob brisanju odstranjen iz naslednjih objektov.",
"Number of Objects": "Število predmetov",
"Nutrition": "Prehrana",
"NutritionsPerServing": "",
"NutritionsPerServingHelp": "",
"NutritionsPerServing": "Hranilne vrednosti na porcijo",
"NutritionsPerServingHelp": "Nekatere aplikacije ne določajo, ali so hranilne vrednosti na recept ali na porcijo. Tandoor jih privzeto obravnava kot na recept. Označite to polje, če želite, da so obravnavane kot na porcijo. ",
"OfflineAlert": "Si v načinu brez povezave, nakupovalni listek se mogoče ne bo sinhroniziral.",
"Ok": "V redu",
"OnHand": "Trenutno imam v roki",
@@ -422,9 +424,9 @@
"Previous_Day": "Prejšnji Dan",
"Previous_Period": "Prejšnje obdobje",
"Print": "Natisni",
"Private": "",
"Private": "Zasebno",
"Private_Recipe": "Zasebni Recept",
"Private_Recipe_Help": "Recept je prikazan samo vam in osebam, s katerimi ga delite.",
"Private_Recipe_Help": "Zasebni recepti so prikazani samo vam in ljudem, s katerimi so deljeni.",
"Profile": "Profil",
"Properties": "Lastnosti",
"PropertiesFoodHelp": "Lastnosti je mogoče dodati receptom in živilom. Lastnosti živil se samodejno izračunajo glede na njihovo količino v receptu.",
@@ -451,16 +453,17 @@
"RecipeBookHelp": "Knjige receptov vsebujejo vnose v knjige receptov ali pa se lahko samodejno izpolnijo z uporabo shranjenih iskalnih filtrov. ",
"RecipeHelp": "Recepti so osnova Tandoorja in so sestavljeni iz splošnih informacij in korakov, sestavljenih iz sestavin, navodil in še več. ",
"RecipeStepsHelp": "Sestavine, navodila in drugo lahko urejate v zavihku Koraki.",
"RecipeStructure": "",
"Recipe_Book": "Knjiga receptov",
"Recipe_Image": "Slika recepta",
"Recipes": "Recepti",
"Recipes_In_Import": "Recepti v vaši uvozni datoteki",
"Recipes_per_page": "Receptov na stran",
"Refresh": "",
"Refresh": "Osveži",
"Remove": "Odstrani",
"RemoveAllType": "",
"RemoveAllType": "Odstrani vse {type}",
"RemoveFoodFromShopping": "Odstrani {food} iz nakupovalnega listka",
"RemoveParent": "",
"RemoveParent": "Odstrani starša",
"Remove_nutrition_recipe": "Receptu izbriši hranilno vrednost",
"Reset": "Ponastavi",
"ResetHelp": "Pomoč pri ponastavitvi",
@@ -490,12 +493,12 @@
"Select_File": "Izberi datoteko",
"Selected": "Izbrano",
"SelectedCategories": "Izbrane kategorije",
"SelfHosted": "",
"SelfHosted": "Samostojno gostovanje",
"Serving": "Serviranje",
"Servings": "Porcije",
"ServingsText": "Besedilo o porcijah",
"Settings": "Nastavitve",
"SettingsOnlySuperuser": "",
"SettingsOnlySuperuser": "Nekatere nastavitve lahko spremeni le skrbnik strežnika.",
"Share": "Deli",
"ShopLater": "Nakupujte pozneje",
"ShopNow": "Nakupujte zdaj",
@@ -519,25 +522,26 @@
"Show_as_header": "Prikaži kot glavo",
"Single": "Ena",
"Size": "Velikost",
"Skip": "",
"Skip": "Preskoči",
"Social_Authentication": "Socialna avtentikacija",
"Sort_by_new": "Razvrsti po novih",
"Source": "Vir",
"SourceImportHelp": "Uvozite JSON v formatu schema.org/recipe ali na straneh html z receptom json+ld ali mikropodatki.",
"SourceImportSubtitle": "Ročno uvozite JSON ali HTML.",
"Space": "",
"SpaceHelp": "",
"Space": "Prostor",
"SpaceHelp": "Vsi vaši podatki so del vašega prostora in do njih lahko dostopajo samo člani prostora. ",
"SpaceLimitExceeded": "Vaš prostor je presegel eno od svojih omejitev, nekatere funkcije so morda omejene.",
"SpaceLimitReached": "Ta prostor je dosegel omejitev. Te vrste predmetov ni mogoče ustvariti več.",
"SpaceMemberHelp": "Dodajte uporabnike v svoj prostor tako, da ustvarite povezavo za povabilo in jo pošljete osebi, ki jo želite dodati.",
"SpaceMembers": "Člani prostora",
"SpaceMembersHelp": "",
"SpaceName": "",
"SpacePrivateObjectsHelp": "",
"SpaceMembersHelp": "Uporabniki in njihova dovoljenja v prostoru. Dodajte dodatne uporabnike s povezavami za povabilo.",
"SpaceName": "Ime prostora",
"SpacePrivateObjectsHelp": " Nekatere stvari so privzeto zasebne in jih je mogoče deliti s člani vašega prostora.",
"SpaceSettings": "Nastavitve prostora",
"Space_Cosmetic_Settings": "Nekatere kozmetične nastavitve lahko spremenijo skrbniki prostora in bodo preglasile nastavitve odjemalca za ta prostor.",
"Split": "Razdelitev",
"Split_All_Steps": "Vse vrstice razdelite na ločene korake.",
"Start": "",
"StartDate": "Začetni datum",
"Starting_Day": "Začetni dan v tednu",
"StartsWith": "Začne se s/z",
@@ -554,10 +558,12 @@
"Storage": "Zunanji pomnilnik",
"StorageHelp": "Zunanje lokacije za shranjevanje, kjer je mogoče shraniti datoteke z recepti (slike/pdf) in sinhronizirati s Tandoorjem.",
"StoragePasswordTokenHelp": "Shranjeno geslo/žeton ne bo nikoli prikazano. Spremeni se le, če v polje vnesete nekaj novega. ",
"Structured": "Strukturirano",
"SubstituteOnHand": "Pri roki imate nadomestek.",
"Substitutes": "Nadomestki",
"Success": "Uspešno",
"SuccessClipboard": "Nakupovalni listek je kopiran v odložišče",
"Summary": "Povzetek",
"Sunday": "Nedelja",
"Supermarket": "Trgovina",
"SupermarketCategoriesOnly": "Prikaži samo trgovinske kategorije",
@@ -589,7 +595,7 @@
"TrigramThresholdHelp": "Določa, koliko črkovalnih napak se prezre pri uporabi mehkega iskanja. Nižje vrednosti prezrejo več razlik/prinesejo več rezultatov.",
"Tuesday": "Torek",
"Type": "Tip",
"UPDATE_ERROR": "",
"UPDATE_ERROR": "Napaka pri posodabljanju",
"Unchanged": "Nespremenjeno",
"Undefined": "Nedefiniran",
"Undo": "Razveljavi",
@@ -631,7 +637,7 @@
"ViewLogHelp": "Zgodovina ogledanih receptov. ",
"View_Recipes": "Preglej recepte",
"Viewed": "Ogledano",
"Visibility": "",
"Visibility": "Vidljivost",
"Waiting": "Čakanje",
"WaitingTime": "Čakalni čas",
"WarnPageLeave": "Nekatere spremembe niso shranjene in bodo izgubljene. Želite vseeno zapustiti stran?",
@@ -643,11 +649,11 @@
"Week": "Teden",
"Week_Numbers": "Števila tednov",
"Welcome": "Dobrodošli",
"WelcomeSettingsHelp": "",
"WelcometoTandoor": "",
"WelcomeSettingsHelp": "Izberite osnovne nastavitve za vaš Tandoor prostor. Vse to lahko kasneje spremenite v nastavitvah.",
"WelcometoTandoor": "Dobrodošli v Tandoorju",
"WorkingTime": "Delovni čas",
"Year": "Leto",
"Yes": "",
"Yes": "Da",
"YourSpaces": "Vaši prostori",
"active": "aktiven",
"add_keyword": "Dodaj ključno besedo",

File diff suppressed because it is too large Load Diff

View File

@@ -337,6 +337,7 @@
"Ratings": "Derecelendirmeler",
"Recently_Viewed": "Son Görüntülenen",
"Recipe": "Tarif",
"RecipeStructure": "",
"Recipe_Book": "Yemek Tarifi Kitabı",
"Recipe_Image": "Tarif Resmi",
"Recipes": "Tarifler",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "Bazı kozmetik ayarlar alan yöneticileri tarafından değiştirilebilir ve o alanın istemci ayarlarını geçersiz kılar.",
"Split_All_Steps": "Tüm satırları ayrı adımlara bölün.",
"Start": "",
"StartDate": "Başlangıç Tarihi",
"Starting_Day": "Haftanın başlangıç günü",
"StartsWith": "",

File diff suppressed because it is too large Load Diff

View File

@@ -337,6 +337,7 @@
"Ratings": "等级",
"Recently_Viewed": "最近浏览",
"Recipe": "食谱",
"RecipeStructure": "",
"Recipe_Book": "食谱书",
"Recipe_Image": "食谱图像",
"Recipes": "食谱",
@@ -394,6 +395,7 @@
"SpacePrivateObjectsHelp": "",
"Space_Cosmetic_Settings": "空间管理员可以更改某些装饰设置,并将覆盖该空间的客户端设置。",
"Split_All_Steps": "将所有行拆分为单独的步骤。",
"Start": "",
"StartDate": "开始日期",
"Starting_Day": "一周中的第一天",
"StartsWith": "",

View File

@@ -450,6 +450,7 @@
"RecipeBookHelp": "食譜書包含食譜書條目,或可以透過使用已儲存的搜尋篩選器自動填充。 ",
"RecipeHelp": "食譜是 Tandoor 的基礎,由一般資訊和步驟組成,步驟由食材、指示等組成。 ",
"RecipeStepsHelp": "食材、指示等可以在步驟標籤中編輯。",
"RecipeStructure": "",
"Recipe_Book": "食譜書",
"Recipe_Image": "食譜圖片",
"Recipes": "食譜",
@@ -537,6 +538,7 @@
"Space_Cosmetic_Settings": "空間管理員可以更改某些裝飾設置,並將覆蓋該空間的客戶端設置。",
"Split": "分割",
"Split_All_Steps": "將所有行拆分為單獨的步驟。",
"Start": "",
"StartDate": "開始日期",
"Starting_Day": "開始日",
"StartsWith": "開頭為",

View File

@@ -49,10 +49,10 @@
<td>
{{ ingredient.food.name }}
<!-- TODO weird mixture of using ingredients but not in the correct relation to the recipe not good, properly sort out and add easy unitconversion/food edit features -->
<!-- <v-btn variant="outlined" block>-->
<!-- {{ ingredient.food.name }}-->
<!-- <model-edit-dialog model="Food" :item="ingredient.food!" @save="args => ingredient.food = args"></model-edit-dialog>-->
<!-- </v-btn>-->
<!-- <v-btn variant="outlined" block>-->
<!-- {{ ingredient.food.name }}-->
<!-- <model-edit-dialog model="Food" :item="ingredient.food!" @save="args => ingredient.food = args"></model-edit-dialog>-->
<!-- </v-btn>-->
<!-- <v-chip v-if="ingredient.unit && ingredient.food.propertiesFoodUnit && ingredient.unit.id == ingredient.food.propertiesFoodUnit.id" color="success"-->
<!-- size="small">{{ ingredient.unit.name }}-->
<!-- </v-chip>-->
@@ -73,7 +73,8 @@
@click="fdcSelectedIngredient = ingredient; fdcDialog = true"></v-btn>
<v-btn @click="updateFoodFdcData(ingredient)" icon="fa-solid fa-arrows-rotate" size="small" density="compact" variant="plain"
v-if="ingredient.food.fdcId"></v-btn>
<v-btn @click="openFdcPage(ingredient.food.fdcId)" :href="`https://fdc.nal.usda.gov/food-details/${ingredient.food.fdcId}/nutrients`" target="_blank"
<v-btn @click="openFdcPage(ingredient.food.fdcId)" :href="`https://fdc.nal.usda.gov/food-details/${ingredient.food.fdcId}/nutrients`"
target="_blank"
icon="fa-solid fa-arrow-up-right-from-square"
size="small" variant="plain" v-if="ingredient.food.fdcId"></v-btn>
</template>
@@ -81,7 +82,7 @@
</td>
<td>
<v-number-input v-model="ingredient.food.propertiesFoodAmount" density="compact" hide-details @change="updateFood(ingredient)"
:loading="ingredient.loading" style="min-width: 100px" control-variant="hidden" :precision="2">
:loading="ingredient.loading" style="min-width: 100px" control-variant="hidden" :precision="2">
</v-number-input>
</td>
@@ -90,8 +91,10 @@
:loading="ingredient.loading"></model-select>
</td>
<td v-for="p in ingredient.food.properties" v-bind:key="`${ingredient.food.id}_${p.propertyType.id}`">
<v-number-input v-model="p.propertyAmount" density="compact" hide-details v-if="p.propertyAmount != null" @change="updateFood(ingredient)" :precision="2"
:loading="ingredient.loading" @click:clear="deleteFoodProperty(p, ingredient)" style="min-width: 120px" control-variant="hidden" clearable>
<v-number-input v-model="p.propertyAmount" density="compact" hide-details v-if="p.propertyAmount != null" @change="updateFood(ingredient)"
:precision="2"
:loading="ingredient.loading" @click:clear="deleteFoodProperty(p, ingredient)" style="min-width: 120px" control-variant="hidden"
clearable>
</v-number-input>
@@ -104,11 +107,10 @@
</td>
</tr>
</tbody>
<!-- TODO remove once append to body for model select is working properly -->
<v-spacer style="margin-top: 120px;"></v-spacer>
</v-table>
</v-col>
</v-row>
<v-row>
<v-col>
<v-card prepend-icon="fa-solid fa-calculator" :title="$t('Calculator')">
<v-card-text>
<v-row dense>

View File

@@ -606,7 +606,7 @@ function importFromUrlList() {
setTimeout(importFromUrlList, 500)
})
}).catch(err => {
setTimeout(importFromUrlList, 500)
}).finally(() => {
loading.value = false
})

View File

@@ -1,11 +1,14 @@
<template>
<v-container :class="{'ps-0 pe-0 pt-0': mobile}">
<recipe-view v-model="recipe"></recipe-view>
<v-defaults-provider :defaults="(useUserPreferenceStore().isPrintMode ? {VCard: {variant: 'flat'}} : {})">
<div class="mt-2" v-if="isShared && Object.keys(recipe).length > 0">
<import-tandoor-dialog></import-tandoor-dialog>
</div>
<recipe-view v-model="recipe" :servings="servings"></recipe-view>
<div class="mt-2" v-if="isShared && Object.keys(recipe).length > 0">
<import-tandoor-dialog></import-tandoor-dialog>
</div>
</v-defaults-provider>
</v-container>
@@ -33,6 +36,13 @@ const isShared = computed(() => {
return params.share && typeof params.share == "string"
})
const servings = computed(() => {
const value = params.servings
if (!value) return undefined
const parsed = parseInt(value as string, 10)
return parsed > 0 ? parsed : undefined
})
const recipe = ref({} as Recipe)
watch(() => props.id, () => {
@@ -56,6 +66,12 @@ function refreshData(recipeId: string) {
recipe.value = r
title.value = recipe.value.name
setTimeout(() => {
if (useUserPreferenceStore().isPrintMode) {
window.print()
}
}, 500)
if (useUserPreferenceStore().isAuthenticated) {
api.apiViewLogCreate({viewLog: {recipe: Number(recipeId)} as ViewLog})
}

View File

@@ -184,7 +184,7 @@ import RecipeCard from "@/components/display/RecipeCard.vue";
import {useDisplay} from "vuetify";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {useRouteQuery} from "@vueuse/router";
import {routeQueryDateTransformer, stringToBool, toNumberArray} from "@/utils/utils";
import {numberOrUndefinedTransformer, routeQueryDateTransformer, stringToBool, toNumberArray} from "@/utils/utils";
import RandomIcon from "@/components/display/RandomIcon.vue";
import {VSelect, VTextField, VNumberInput} from "vuetify/components";
import RatingField from "@/components/inputs/RatingField.vue";
@@ -759,27 +759,30 @@ const filters = ref({
label: `${t('Rating')} (${t('exact')})`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: RatingField,
modelValue: useRouteQuery('rating', undefined, {transform: Number}),
modelValue: useRouteQuery('rating', undefined, {transform: numberOrUndefinedTransformer}),
},
ratingGte: {
id: 'ratingGte',
label: `${t('Rating')} (>=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: RatingField,
modelValue: useRouteQuery('ratingGte', undefined, {transform: Number}),
modelValue: useRouteQuery('ratingGte', undefined, {transform: numberOrUndefinedTransformer}),
},
ratingLte: {
id: 'ratingLte',
label: `${t('Rating')} (<=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: RatingField,
modelValue: useRouteQuery('ratingLte', undefined, {transform: Number}),
modelValue: useRouteQuery('ratingLte', undefined, {transform: numberOrUndefinedTransformer}),
},
timescooked: {
id: 'timescooked',
@@ -787,26 +790,29 @@ const filters = ref({
hint: 'Recipes that were cooked at least X times',
enabled: false,
default: undefined,
clearable: true,
is: VNumberInput,
modelValue: useRouteQuery('timescooked', undefined, {transform: Number}),
modelValue: useRouteQuery('timescooked', undefined, {transform: numberOrUndefinedTransformer}),
},
timescookedGte: {
id: 'timescookedGte',
label: `${t('times_cooked')} (>=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: VNumberInput,
modelValue: useRouteQuery('timescookedGte', undefined, {transform: Number}),
modelValue: useRouteQuery('timescookedGte', undefined, {transform: numberOrUndefinedTransformer}),
},
timescookedLte: {
id: 'timescookedLte',
label: `${t('times_cooked')} (<=)`,
hint: '',
enabled: false,
clearable: true,
default: undefined,
is: VNumberInput,
modelValue: useRouteQuery('timescookedLte', undefined, {transform: Number}),
modelValue: useRouteQuery('timescookedLte', undefined, {transform: numberOrUndefinedTransformer}),
},
makenow: {
id: 'makenow',

View File

@@ -34,13 +34,13 @@
</v-card-text>
</v-card>
<template v-if="totalRecipes > 0">
<horizontal-recipe-scroller :skeletons="4" mode="recent" v-if="totalRecipes > 5"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="new" v-if="totalRecipes > 1"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="recent" v-if="totalRecipes > 10"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="new" v-if="totalRecipes > 10"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="keyword" v-if="totalRecipes > 10"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="random" v-if="totalRecipes > 1"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="created_by" v-if="totalRecipes > 5"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="2" mode="rating" v-if="totalRecipes > 5"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="keyword" v-if="totalRecipes > 5"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="random" v-if="totalRecipes > 0"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="created_by" v-if="totalRecipes > 10"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="2" mode="rating" v-if="totalRecipes > 10"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="keyword" v-if="totalRecipes > 25"></horizontal-recipe-scroller>
<horizontal-recipe-scroller :skeletons="4" mode="random" v-if="totalRecipes > 25"></horizontal-recipe-scroller>
<v-row>

View File

@@ -7,6 +7,7 @@ import {computed, ComputedRef, ref} from "vue";
import {DeviceSettings} from "@/types/settings";
import {useTheme} from "vuetify";
import {useRouter} from "vue-router";
import {useRouteQuery} from "@vueuse/router";
const DEVICE_SETTINGS_KEY = 'TANDOOR_DEVICE_SETTINGS'
const USER_PREFERENCE_KEY = 'TANDOOR_USER_PREFERENCE'
@@ -55,6 +56,11 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
*/
const defaultUnitObj = ref<Unit | null>(null)
/**
* detect if print mode is activated by checking for "print" query parameter
*/
const isPrintMode = useRouteQuery('print', false, {transform: Boolean})
const theme = useTheme()
const router = useRouter()
@@ -250,10 +256,10 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
* applies user settings regarding themes/styling
*/
function updateTheme() {
if (userSettings.value.theme == 'TANDOOR') {
theme.change('light')
} else if (userSettings.value.theme == 'TANDOOR_DARK') {
if (userSettings.value.theme == 'TANDOOR_DARK' && !isPrintMode.value) {
theme.change('dark')
} else {
theme.change('light')
}
}
@@ -281,6 +287,7 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
spaces,
activeUserSpace,
isAuthenticated,
isPrintMode,
initCompleted,
defaultUnitObj,
loadUserSettings,

View File

@@ -6,6 +6,9 @@ import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
*/
export function roundDecimals(num: number) {
let decimals = useUserPreferenceStore().userSettings.ingredientDecimals
if (decimals === undefined) {
decimals = 2
}
return Number(num.toFixed(decimals))
}

View File

@@ -79,4 +79,20 @@ export function stringToBool(param: string): boolean | undefined {
export const routeQueryDateTransformer = {
get: (value: string | null | Date) => ((value == null) ? null : (new Date(value))),
set: (value: string | null | Date) => ((value == null) ? null : (DateTime.fromJSDate(new Date(value)).toISODate()))
}
}
/**
* routeQueryParam transformer for boolean fields converting string bools to real bools
*/
export const boolOrUndefinedTransformer = {
get: (value: string | null | undefined) => ((value == null) ? undefined : value == 'true'),
set: (value: boolean | null | undefined) => ((value == null) ? undefined : value.toString())
}
/**
* routeQueryParam transformer for number fields converting string numbers to real numbers and allowing undefined for resettable parameters
*/
export const numberOrUndefinedTransformer = {
get: (value: string | null | undefined) => ((value == null) ? undefined : Number(value)),
set: (value: string | null | undefined) => ((value == null) ? undefined : value.toString())
}

View File

@@ -5,6 +5,7 @@ import {aliases, fa} from 'vuetify/iconsets/fa'
// Composables
import {createVuetify} from 'vuetify'
import {DateTime} from "luxon";
import {af, ar, az, bg, ca, ckb, cs, da, de, el, en, es, et, fi, fr, he, hr, hu, id, it, ja, km, ko, lt, lv, nl, no, pl, pt, ro, ru, sk, sl, srCyrl, srLatn, sv, th, tr, uk, vi, zhHans, zhHant} from "vuetify/locale";
// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
export default createVuetify({
@@ -22,17 +23,23 @@ export default createVuetify({
maxWidth: '1400px'
},
// always localize the date display of DateInputs
VDateInput: {
displayFormat : (date: Date) => DateTime.fromJSDate(date).toLocaleString()
},
// VDateInput: {
// displayFormat: (date: Date) => DateTime.fromJSDate(date).toLocaleString()
// },
// always use color for switches to properly see if enabled or not
VSwitch: {
color: 'primary'
},
// globally set the correct decimal seperator
VNumberInput: {
decimalSeparator: 0.1.toLocaleString().replace(/\d/g, '')
}
// VNumberInput: {
// decimalSeparator: 0.1.toLocaleString().replace(/\d/g, '')
// }
},
locale: {
locale: 'en',
fallback: 'en',
messages: {af, ar, az, bg, ca, ckb, cs, da, de, el, en, es, et, fi, fr, he, hr, hu, id, it, ja, km, ko, lt, lv, nl, no, pl, pt, ro, ru, sk, sl, srCyrl, srLatn, sv, th, tr, uk, vi, zhHans, zhHant},
decimalSeparator: 0.1.toLocaleString().replace(/\d/g, '')
},
theme: {
defaultTheme: 'light',

View File

@@ -1417,10 +1417,10 @@
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.17.tgz#e8b3a41f0be76499882a89e8ed40d86a70fa4b70"
integrity sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==
"@vue/tsconfig@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@vue/tsconfig/-/tsconfig-0.7.0.tgz#67044c847b7a137b8cbfd6b23104c36dbaf80d1d"
integrity sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==
"@vue/tsconfig@^0.8.1":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@vue/tsconfig/-/tsconfig-0.8.1.tgz#4732251fa58945024424385cf3be0b1708fad5fe"
integrity sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g==
"@vueform/multiselect@^2.6.11":
version "2.6.11"
@@ -1448,18 +1448,23 @@
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-13.6.0.tgz#49196025c96c7daeb591c20a54b61cc336af99b6"
integrity sha512-rnIH7JvU7NjrpexTsl2Iwv0V0yAx9cw7+clymjKuLSXG0QMcLD0LDgdNmXic+qL0SGvgSVPEpM9IDO/wqo1vkQ==
"@vueuse/router@^13.6.0":
version "13.6.0"
resolved "https://registry.yarnpkg.com/@vueuse/router/-/router-13.6.0.tgz#29456dab42eb75a0dc5fe4c62f59dd3f7c21a6ab"
integrity sha512-iXRwR4K7nz4PReW0QudhnM9NtYGvN4KrskFgF9G7NouM43big3bpSNRRocJKFWK7iu97ww5y82B3QA2zz3S/vw==
"@vueuse/router@^13.9.0":
version "13.9.0"
resolved "https://registry.yarnpkg.com/@vueuse/router/-/router-13.9.0.tgz#44235e6732a30b53d1c8e2ef13ce783fdd189ca6"
integrity sha512-7AYay8Pv/0fC4D0eygbIyZuLyVs+9D7dsnO5D8aqat9qcOz91v/XFWR667WE1+p+OkU0ib+FjQUdnTVBNoIw8g==
dependencies:
"@vueuse/shared" "13.6.0"
"@vueuse/shared" "13.9.0"
"@vueuse/shared@13.6.0":
version "13.6.0"
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-13.6.0.tgz#872fdbd725fb4e3a12bd5aab85af9a5db0b1e481"
integrity sha512-pDykCSoS2T3fsQrYqf9SyF0QXWHmcGPQ+qiOVjlYSzlWd9dgppB2bFSM1GgKKkt7uzn0BBMV3IbJsUfHG2+BCg==
"@vueuse/shared@13.9.0":
version "13.9.0"
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-13.9.0.tgz#7168b4ed647e625b05eb4e7e80fe8aabd00e3923"
integrity sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==
acorn@^8.14.0:
version "8.15.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816"
@@ -3343,10 +3348,10 @@ vite-plugin-vuetify@^2.1.1:
debug "^4.3.3"
upath "^2.0.1"
vite@7.1.5:
version "7.1.5"
resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.5.tgz#4dbcb48c6313116689be540466fc80faa377be38"
integrity sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==
vite@7.1.11:
version "7.1.11"
resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.11.tgz#4d006746112fee056df64985191e846ebfb6007e"
integrity sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==
dependencies:
esbuild "^0.25.0"
fdir "^6.5.0"
@@ -3418,10 +3423,10 @@ vuedraggable@^4.1.0:
dependencies:
sortablejs "1.14.0"
vuetify@^3.9.7:
version "3.9.7"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.9.7.tgz#aea996f35111f25dd7e31ab956fbb40911841c24"
integrity sha512-Ib8PB3ItcguCol8f0DXLpoGyy7FvoOYW23SEWqXX+in1CSItJZHxUXXGSus94m5JWqYqQrFiwCykbHm7UWPi4Q==
vuetify@^3.10.3:
version "3.10.3"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.10.3.tgz#f04e507bb5efee6b52f11b2fd60a20dced1a8831"
integrity sha512-psc7oZfjz3LwH96ZRzSm4iGcOKKoeoVZIyO5Q5xO4vcUfWYxobL7TvMQv53jv1PnNvaMIXWeVIrQmiyce5dpTg==
w3c-xmlserializer@^5.0.0:
version "5.0.0"