Compare commits

...

768 Commits

Author SHA1 Message Date
vabene1111
0c94cf1c2e Merge pull request #2870 from TandoorRecipes/dependabot/npm_and_yarn/vue/follow-redirects-1.15.4
Bump follow-redirects from 1.15.2 to 1.15.4 in /vue
2024-01-19 16:44:06 +08:00
vabene1111
1673254934 Merge pull request #2873 from TandoorRecipes/dependabot/pip/jinja2-3.1.3
Bump jinja2 from 3.1.2 to 3.1.3
2024-01-19 16:43:50 +08:00
vabene1111
0493ef7e3a Merge pull request #2872 from FaySmash/patch-1
Improved the understandability of the postgres upgrade steps
2024-01-19 16:13:28 +08:00
Tomasz Klimczak
1fd6a47e9c Translated using Weblate (Polish)
Currently translated at 100.0% (554 of 554 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2024-01-18 00:19:56 +00:00
vabene1111
bb52f8902d added max spaces per user + added custom app name + fixed theming tests 2024-01-15 07:41:51 +08:00
vabene1111
35eff630ff updated theming tests 2024-01-14 15:39:02 +08:00
vabene1111
8d90fada1d fixed theming breaking for users without space 2024-01-14 15:33:14 +08:00
vabene1111
2ba2b97f9c moved manifest to use main theming function 2024-01-14 08:40:05 +08:00
vabene1111
26408c33f4 removed debug code 2024-01-13 07:42:54 +08:00
Cilantro4858
72b0bd7f1e Translated using Weblate (German)
Currently translated at 100.0% (554 of 554 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2024-01-12 22:40:47 +00:00
dependabot[bot]
45f0413fb9 Bump jinja2 from 3.1.2 to 3.1.3
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.3)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-11 19:51:57 +00:00
FaySmash
38c464ebae Improved the understandability of the postgres upgrade steps
I improved the understandability some parts in the psql examples for someone not familiar with the psql syntax.
2024-01-11 17:56:45 +01:00
Jan Kubošek
b4f158b913 Translated using Weblate (Czech)
Currently translated at 100.0% (554 of 554 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2024-01-11 02:19:55 +00:00
dependabot[bot]
da49b6bda0 Bump follow-redirects from 1.15.2 to 1.15.4 in /vue
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.2 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-10 08:50:00 +00:00
Jan Kubošek
e7d9d7b7b3 Translated using Weblate (Czech)
Currently translated at 100.0% (554 of 554 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2024-01-09 21:53:32 +00:00
Mára Štěpánek
5f7a57a258 Translated using Weblate (Czech)
Currently translated at 92.0% (510 of 554 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2024-01-09 18:40:00 +00:00
Jan Kubošek
4b1a80a0ed Translated using Weblate (Czech)
Currently translated at 92.0% (510 of 554 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2024-01-09 18:40:00 +00:00
Mára Štěpánek
8efc3de11f Translated using Weblate (Czech)
Currently translated at 90.5% (491 of 542 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2024-01-09 12:07:20 +00:00
Jan Kubošek
1f3cd11964 Translated using Weblate (Czech)
Currently translated at 90.5% (491 of 542 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2024-01-09 12:07:20 +00:00
Jan Kubošek
94cfc36ed5 Translated using Weblate (Czech)
Currently translated at 100.0% (362 of 362 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/cs/
2024-01-09 12:07:20 +00:00
vabene1111
d493ba72a1 fixed mealplan to date set wrongly when open multiple times 2024-01-08 20:24:23 +08:00
vabene1111
71e5484f0c test for theming function + sticky nav 2024-01-07 22:34:59 +08:00
vabene1111
761e423bde fixed markdown info 2024-01-07 18:17:31 +08:00
vabene1111
c8e674da16 all themes in one function 2024-01-07 18:07:47 +08:00
vabene1111
6f3d4491ed implemented user settings 2024-01-07 17:51:33 +08:00
vabene1111
54e2615c86 cleaned up into single flow 2024-01-07 17:24:20 +08:00
vabene1111
77942a7144 Merge branch 'develop' into beta 2024-01-07 17:17:22 +08:00
vabene1111
5a5ce4d736 moved theming functions to main tag 2024-01-07 17:17:14 +08:00
vabene1111
0d966b5e59 Merge branch 'develop' into beta 2024-01-07 16:55:22 +08:00
vabene1111
1dda4126c1 fxied theming tags 2024-01-07 16:55:12 +08:00
vabene1111
5ffe821407 Merge branch 'develop' into beta 2024-01-07 08:13:36 +08:00
vabene1111
f9bfb8e258 added custom logo to space manage view 2024-01-07 08:12:20 +08:00
vabene1111
c6fa635af2 basics of custom icons 2024-01-06 23:23:17 +08:00
vabene1111
50e1eaf645 fixed bg color for unauthenticated nav 2024-01-06 22:35:22 +08:00
vabene1111
953dc75a8d added ability to change unauthenticated theme 2024-01-06 21:43:40 +08:00
vabene1111
ac5333d0e7 cleaned .env template and created dedicated docs page for environment configuration 2024-01-06 15:34:55 +08:00
vabene1111
ecf985f5e3 change gunicorn media default 2024-01-06 14:38:27 +08:00
vabene1111
b6d4c4c3b8 Merge branch 'develop' into beta 2024-01-03 15:13:51 +01:00
vabene1111
30f3a697f0 fixed space theme defaults in model 2024-01-03 15:13:39 +01:00
vabene1111
42ced25e10 improved settings override message 2024-01-03 15:05:44 +01:00
vabene1111
6011cf359f Merge pull request #2853 from AquaticLava/Auto-Planner
Auto planner bug fix
2024-01-03 14:37:37 +01:00
AquaticLava
f57acc412b Merge remote-tracking branch 'origin/Auto-Planner' into Auto-Planner 2024-01-02 18:44:39 -07:00
AquaticLava
200cacb9ac changed keywords to be index based. 2024-01-02 18:44:23 -07:00
AquaticLava
5c89173373 changed random recipe to be index based. 2024-01-02 18:43:22 -07:00
AquaticLava
61b67cd37a Merge remote-tracking branch 'origin/Auto-Planner' into Auto-Planner 2024-01-02 15:38:47 -07:00
vabene1111
12c2f2f7aa Merge branch 'develop' into beta 2024-01-01 22:14:27 +01:00
vabene1111
3d8b1d6ccb lots of theming related changes
- upload a custom logo for your space
    - space settings can override user settings for theming
    - spaces can upload custom CSS overrides
    - allow users to disable showing the tandoor/space logo
    - allow changing navigation background color to any color desired
    - allow switching navigation text color between dark/light (different effects depending on theme)
2024-01-01 22:14:01 +01:00
Arnon Meshoulam
aa0d6b5a6b Translated using Weblate (Hebrew)
Currently translated at 95.3% (517 of 542 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/he/
2024-01-01 20:19:56 +00:00
Murphy
64ed75156c Translated using Weblate (German)
Currently translated at 98.7% (535 of 542 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2024-01-01 20:19:56 +00:00
vabene1111
c6d41e8810 fixed migrations 200 and 204 2024-01-01 19:11:37 +01:00
vabene1111
2a10843101 compiled translations 2024-01-01 15:06:58 +01:00
vabene1111
f861b39d05 Merge pull request #2833 from luc-ass/develop
Fix truenas_portainer compose example/documentation
2024-01-01 14:55:28 +01:00
vabene1111
5c18c09944 Merge branch 'develop' into develop 2024-01-01 14:55:21 +01:00
vabene1111
1bd5f96029 Merge pull request #2792 from Sriyukthika26/my-contribution
Update truenas_portainer.md
2024-01-01 14:53:47 +01:00
vabene1111
988df4eb00 Merge pull request #2823 from smilerz/admin_updates
Admin updates
2024-01-01 14:53:01 +01:00
vabene1111
bf61b6474e fixed ingredient note field to high 2024-01-01 14:51:20 +01:00
AquaticLava
be177cf258 Merge remote-tracking branch 'origin/Auto-Planner' into Auto-Planner 2023-12-31 11:20:06 -07:00
Jaan
5059abc232 Translated using Weblate (Russian)
Currently translated at 63.4% (344 of 542 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ru/
2023-12-30 15:19:57 +00:00
smilerz
cb63bb2615 avoid recursion in ingredient.__str__ 2023-12-28 10:44:51 -06:00
smilerz
7ca5a34b28 fixed recursion in Step.__str__() 2023-12-28 10:00:15 -06:00
Lucas Gasenzer
a7ea7a8987 fix code block and replace tab with spaces 2023-12-27 10:43:56 +01:00
vabene1111
8d7b4f614c improved mobile shopping entry adding layout 2023-12-22 09:25:30 +01:00
vabene1111
df67d3ce7b improved shopping context dark theme 2023-12-22 09:25:18 +01:00
vabene1111
54119ed1ec Merge branch 'develop' into beta 2023-12-22 08:38:25 +01:00
smilerz
26f694576a update __str__() on Step and Ingredient models 2023-12-20 15:55:02 -06:00
smilerz
7a5b744ff0 order recipes in admin 2023-12-20 15:49:54 -06:00
smilerz
4058c997de updates to admin pages 2023-12-20 15:46:28 -06:00
vabene1111
4de9be5c89 Merge pull request #2808 from smilerz/add_mealtype_filter
add ability to filter meal plans based on type
2023-12-20 15:55:09 +01:00
vabene1111
34ee03b720 Merge pull request #2818 from smilerz/modal_updates
Modal updates
2023-12-20 15:51:24 +01:00
smilerz
48dacf46c3 updated RecipeSwitcher with new MealPlan API format 2023-12-19 16:50:32 -06:00
smilerz
181c270b34 added substitute children to food edit modal 2023-12-19 15:22:26 -06:00
smilerz
e89c3887ec remove reference to facets on Space page 2023-12-19 15:09:18 -06:00
smilerz
99cd9bfb5b update meal_type filter on MealPlan to be a list 2023-12-19 12:59:24 -06:00
smilerz
8bbccad7a9 updated API correclty this time 2023-12-19 12:59:24 -06:00
smilerz
a59a78f44c update meal-plan API on MealPlanStore 2023-12-19 12:59:24 -06:00
smilerz
205bf5253d add ability to filter meal plans based on type 2023-12-19 12:59:19 -06:00
vabene1111
0fed6b9fb3 added migration status to system page 2023-12-16 14:03:32 +01:00
vabene1111
dd3e91e10d added ability to set rate limiting for url import 2023-12-16 09:19:12 +01:00
vabene1111
76b84898f6 lmit ingredient parser to 512 characters to prevent too complex computations 2023-12-16 09:08:50 +01:00
vabene1111
05d971835f autoamtically keep meal plan to date relative to from date 2023-12-16 08:40:20 +01:00
vabene1111
0a814fa896 dont hide ingredients in edit when hiding them in view 2023-12-16 08:18:05 +01:00
vabene1111
05ba11a48e Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2023-12-16 08:09:22 +01:00
vabene1111
6a7a22626e use commit hash as version number if not on a tagged release 2023-12-16 08:09:18 +01:00
vabene1111
1635a3a335 Merge pull request #2794 from TyreceDJ/mobileCalender/sort
Sorted by current day in meal plan
2023-12-16 07:57:18 +01:00
vabene1111
1d84e7851b Merge pull request #2706 from ambroisie/bump-allauth
Bump django-allauth from 0.54.0 to 0.58.1
2023-12-16 07:54:08 +01:00
vabene1111
44d1cc3a30 Merge pull request #2802 from smilerz/automation_fixes
kw automation not applying during url import
2023-12-16 07:48:49 +01:00
vabene1111
04b4f552f8 comment out orphaned files 2023-12-16 07:40:09 +01:00
vabene1111
6214176fe5 Merge pull request #2730 from smilerz/orphan_file_cleanup
view and delete orphaned files
2023-12-16 07:36:08 +01:00
vabene1111
205dc11125 changed raspi docs 2023-12-16 07:30:39 +01:00
smilerz
ba5112e138 kw automation not applying during url import 2023-12-12 13:49:23 -06:00
Khuslen Misheel
0e34cc72d5 Proper fix for Calendar 2023-12-10 13:46:55 -05:00
Khuslen Misheel
31c6defc93 Only fixed current day in meal plan 2023-12-10 13:44:01 -05:00
vabene1111
d4c544bb4b partially working replace logic 2023-12-10 16:32:12 +01:00
vabene1111
2b05efeff6 Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2023-12-10 16:03:18 +01:00
vabene1111
d7ddcd3214 playing around with codemirror 2023-12-10 16:03:14 +01:00
Robin Wilmet
29133f4236 Translated using Weblate (French)
Currently translated at 96.1% (521 of 542 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2023-12-10 14:19:57 +00:00
Robin Wilmet
b440b09be5 Translated using Weblate (French)
Currently translated at 93.0% (456 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/
2023-12-10 14:19:57 +00:00
smilerz
ed1f656167 fix version information on system page 2023-12-10 07:54:44 -06:00
smilerz
4f3e6d3765 added Postgres version to system page.
Added warnings for out of date Postgres versions
2023-12-10 07:54:43 -06:00
smilerz
46a50d7835 view and delete orphaned files
miscelaneous bug fixes discovered during testing
2023-12-10 07:54:37 -06:00
Khuslen Misheel
65513a8f60 Sorted by current day in meal plan 2023-12-09 15:19:40 -05:00
Sriyukthika
044ed1ec18 Update truenas_portainer.md Spelling Error 2023-12-10 00:44:15 +05:30
Sriyukthika
8f53b399c6 Update truenas_portainer.md 2023-12-09 23:58:26 +05:30
Bruno BELANYI
702c1d67d3 Bump django-allauth from 0.54.0 to 0.58.1
See the backwards incompatible changes [1].

[1]: https://docs.allauth.org/en/latest/release-notes/recent.html#id10
2023-12-06 21:59:20 +00:00
smilerz
c654cc469a Update RecipeEditView.vue
fixes #2781
2023-12-05 07:53:33 -06:00
Ferenc
8df846c9c2 Translated using Weblate (Hungarian)
Currently translated at 85.3% (460 of 539 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-12-05 09:15:12 +00:00
Ferenc
7070f6c964 Translated using Weblate (Hungarian)
Currently translated at 98.7% (484 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2023-12-05 09:15:12 +00:00
vabene1111
b454960676 some playing around 2023-12-03 15:48:37 +01:00
vabene1111
abf8f79136 Merge branch 'develop'
# Conflicts:
#	docs/faq.md
2023-12-03 14:10:28 +01:00
vabene1111
fd028047d6 clean test view 2023-12-03 14:09:58 +01:00
vabene1111
bd0e1bcefe Merge branch 'develop' into beta 2023-12-02 21:32:24 +01:00
vabene1111
a2aa0dc3b9 automatically open ingredient editor in new tab 2023-12-02 21:26:54 +01:00
vabene1111
1758aebb73 choice input datatype detection 2023-12-02 21:13:14 +01:00
vabene1111
ecffe30062 dont show property warning for 0 values any more 2023-12-02 21:07:11 +01:00
vabene1111
21653465e0 show order and add property types from property editor 2023-12-02 20:37:23 +01:00
vabene1111
f3e11e6358 fixed and improvements to property editor 2023-12-02 20:14:12 +01:00
vabene1111
0c381ed46c fixed recipe card description overlay 2023-12-02 19:28:34 +01:00
vabene1111
fd978f9c19 fixed copying recipes with properties 2023-12-02 18:58:44 +01:00
vabene1111
b069a49954 Merge pull request #2771 from tourn/bugfix/database-url-with-port
Fix parsing DATABASE_URL with port number
2023-12-02 18:48:41 +01:00
vabene1111
11c8422fbb fixed youtube import and handle resize without ingredients 2023-12-02 18:45:34 +01:00
vabene1111
2cb010c8b4 Merge pull request #2763 from smilerz/fix_long_description
truncated long description
2023-12-02 18:11:59 +01:00
vabene1111
8f96c7f0a3 Merge pull request #2768 from TandoorRecipes/dependabot/pip/pytest-7.4.3
Bump pytest from 7.3.1 to 7.4.3
2023-12-02 18:11:34 +01:00
vabene1111
3054297357 improved error handling and fixed meal plan api 2023-12-02 18:11:09 +01:00
vabene1111
3e083e2168 fully integrated property editor 2023-12-02 18:02:22 +01:00
vabene1111
d1174ea50d fixed api comment 2023-12-02 17:42:04 +01:00
vabene1111
fe11b88fd0 pretty nice property editor 2023-12-02 17:41:02 +01:00
vabene1111
a3a2433d2a made to_date field optional in meal plan api 2023-12-02 16:29:37 +01:00
vabene1111
92be2db9fd mostly working property editor 2023-12-02 15:35:33 +01:00
vabene1111
be2f759048 add disabled capabilities to generic multiselect 2023-12-02 15:22:27 +01:00
Marco Agostino
52e88ddfd3 Translated using Weblate (Italian)
Currently translated at 86.4% (466 of 539 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2023-12-02 11:19:56 +00:00
Daniel Latzer
fe208e9844 Fix parsing DATABASE_URL with port number 2023-12-02 09:42:29 +01:00
dependabot[bot]
15e7f32001 Bump pytest from 7.3.1 to 7.4.3
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.1 to 7.4.3.
- [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/7.3.1...7.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-01 00:59:26 +00:00
smilerz
745c045f06 truncated long description 2023-11-30 16:24:24 -06:00
Anders Obro
4b5abec458 Translated using Weblate (Danish)
Currently translated at 99.8% (535 of 536 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/da/
2023-11-30 13:19:57 +00:00
vabene1111
f6ed49b5c4 property editor 2023-11-29 22:04:23 +01:00
vabene1111
0a0e3a48c3 first working property editor prototype 2023-11-29 21:20:10 +01:00
vabene1111
cce2407bc0 Merge pull request #2758 from smilerz/updated_documentation
Updated documentation
2023-11-29 19:28:46 +01:00
vabene1111
9b18cab145 Update settings.py 2023-11-29 19:28:19 +01:00
smilerz
8b9a09b268 Update settings.py 2023-11-29 10:56:33 -06:00
vabene1111
db1709cef7 recipe context add to meal plan default to_date 2023-11-29 17:50:01 +01:00
vabene1111
4844e5cbc8 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-11-29 17:48:35 +01:00
vabene1111
e90781983f fixed meal plan multi period arrow breaking view #2678 2023-11-29 17:48:25 +01:00
vabene1111
86496069b3 Merge pull request #2728 from jrester/improve-import-error-msg
Improve import error messages
2023-11-29 17:24:06 +01:00
vabene1111
e1aee23c54 Merge pull request #2759 from TandoorRecipes/dependabot/pip/cryptography-41.0.6
Bump cryptography from 41.0.4 to 41.0.6
2023-11-29 17:20:22 +01:00
Jan-Niklas Weghorn
1000badd2f remove venv from .dockerignore 2023-11-29 11:41:19 +01:00
dependabot[bot]
9ae0b50558 Bump cryptography from 41.0.4 to 41.0.6
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.4 to 41.0.6.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.4...41.0.6)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-29 00:16:22 +00:00
smilerz
f69813f729 added installing extensions if necessary 2023-11-28 16:22:17 -06:00
smilerz
fcb2c07acd Update updating.md 2023-11-28 15:52:21 -06:00
smilerz
a076d20cba Update updating.md 2023-11-28 15:51:51 -06:00
smilerz
bae777bc69 Update updating.md 2023-11-28 15:51:06 -06:00
smilerz
49781bfa7f Update updating.md 2023-11-28 15:50:35 -06:00
smilerz
72d3ace0f9 Update updating.md 2023-11-28 15:49:20 -06:00
smilerz
7f44a6f187 Update updating.md 2023-11-28 15:48:33 -06:00
smilerz
92b8799d26 Update faq.md 2023-11-28 15:47:14 -06:00
smilerz
7f1eecddc4 updated documentation for postgres upgrade
installing pgbackup container
installing with DockSTARTer
2023-11-28 15:45:27 -06:00
vabene1111
4723a7ecbd added pg upgrade faq 2023-11-28 20:38:45 +01:00
smilerz
6af28e6fe5 alpine uses TZ to set OS timezone, to stay consistent
changed TIMEZONE env variable to TZ
added deprecated warning to TIMEZONE
2023-11-28 11:47:23 -06:00
vabene1111
ad1e64fb9a Merge pull request #2753 from smilerz/patch_custom_icon
Patch custom icon
2023-11-28 17:34:28 +01:00
smilerz
add600f3ca safely get icon from request.space in tag logo_url 2023-11-28 08:55:27 -06:00
Mahmoud Aljouhari
ad036d7e6c Translated using Weblate (Arabic)
Currently translated at 20.6% (109 of 528 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ar/
2023-11-28 11:03:17 +00:00
vabene1111
d7017902ab Merge branch 'develop' 2023-11-27 22:56:13 +01:00
vabene1111
35743e8be9 fixed constraint 2023-11-27 22:47:56 +01:00
vabene1111
75523c06f6 Merge branch 'develop' 2023-11-27 22:34:02 +01:00
vabene1111
7e2aee53db fixed import ingredient edit modal cleanup 2023-11-27 22:33:48 +01:00
vabene1111
9c74730461 added first draft of property editor 2023-11-27 22:20:09 +01:00
vabene1111
977d2822bc added ability to set custom logo in navbar 2023-11-27 20:29:01 +01:00
vabene1111
31f93285d8 Merge branch 'feature/space-icon' into develop 2023-11-27 20:23:45 +01:00
vabene1111
da9002a7fd Revert "WIP"
This reverts commit 58e70c982e.
2023-11-27 20:23:36 +01:00
vabene1111
899a9955fb Merge branch 'develop' into beta 2023-11-27 20:21:37 +01:00
vabene1111
1bf7af7027 hide properties if none are present in recipe 2023-11-27 20:21:18 +01:00
vabene1111
1145a8cf26 fixed PR 2693 2023-11-27 20:15:41 +01:00
vabene1111
5e918297f8 Merge pull request #2693 from blowk/develop
Update to import tags on mealie and chowdown recipes
2023-11-27 20:07:09 +01:00
vabene1111
69adad70c8 Merge pull request #2727 from jrester/dark-theme-fixes
Improve dark theme
2023-11-27 20:05:30 +01:00
vabene1111
d3905f1e80 Merge pull request #2709 from TandoorRecipes/dependabot/pip/markdown-3.5.1
Bump markdown from 3.4.3 to 3.5.1
2023-11-27 20:01:49 +01:00
vabene1111
1a1ff52725 Merge pull request #2707 from TandoorRecipes/dependabot/pip/boto3-1.28.75
Bump boto3 from 1.28.57 to 1.28.75
2023-11-27 20:01:24 +01:00
vabene1111
731958fdaa Merge pull request #2708 from TandoorRecipes/dependabot/pip/recipe-scrapers-14.52.0
Bump recipe-scrapers from 14.36.1 to 14.52.0
2023-11-27 20:01:07 +01:00
vabene1111
8a19c8eeb0 Merge pull request #2711 from TandoorRecipes/dependabot/pip/whitenoise-6.6.0
Bump whitenoise from 6.5.0 to 6.6.0
2023-11-27 20:00:53 +01:00
vabene1111
4e7368f7b6 Merge pull request #2710 from TandoorRecipes/dependabot/pip/pytest-django-4.6.0
Bump pytest-django from 4.5.2 to 4.6.0
2023-11-27 20:00:46 +01:00
vabene1111
b00f1009a6 Merge pull request #2731 from TandoorRecipes/dependabot/npm_and_yarn/vue/axios-1.6.0
Bump axios from 1.5.0 to 1.6.0 in /vue
2023-11-27 20:00:00 +01:00
vabene1111
2d3ecaaf3c Merge pull request #2700 from TandoorRecipes/dependabot/npm_and_yarn/vue/browserify-sign-4.2.2
Bump browserify-sign from 4.2.1 to 4.2.2 in /vue
2023-11-27 19:59:44 +01:00
vabene1111
339049c785 Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2023-11-27 19:59:14 +01:00
vabene1111
d0481ed18c fixed recipe card description overlay 2023-11-27 19:59:06 +01:00
vabene1111
bcee66c7a4 fixed mela recipes importer 2023-11-27 19:58:56 +01:00
vabene1111
7e993ca50e Merge pull request #2686 from TandoorRecipes/dependabot/npm_and_yarn/vue/babel/traverse-7.23.2
Bump @babel/traverse from 7.22.17 to 7.23.2 in /vue
2023-11-27 19:58:35 +01:00
vabene1111
638dc845c0 Merge pull request #2682 from djstini/fix-import
open-data-import further duplicate handling
2023-11-27 19:56:19 +01:00
vabene1111
4aea0fea8c Merge pull request #2685 from harry48225/delete-confirmation
Increase specificity of the delete confirmation dialog
2023-11-27 19:50:26 +01:00
vabene1111
2ba94df9a8 Merge pull request #2691 from gorrilla10101/patch-1
Update authentication.md
2023-11-27 19:45:25 +01:00
Spreez
5723d87768 Translated using Weblate (German)
Currently translated at 100.0% (534 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-11-22 18:19:57 +00:00
Thomas
24b1f4028f Translated using Weblate (German)
Currently translated at 100.0% (534 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-11-22 18:19:57 +00:00
Spreez
984c863ff6 Translated using Weblate (German)
Currently translated at 100.0% (490 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2023-11-22 18:19:57 +00:00
vabene1111
0f207c2fa7 Merge pull request #2718 from TandoorRecipes/dependabot/pip/django-4.2.7
Bump django from 4.2.5 to 4.2.7
2023-11-22 09:15:55 +01:00
vabene1111
58e70c982e WIP 2023-11-21 22:34:17 +01:00
blowk
4cb94a1759 Update chowdown.py 2023-11-17 19:34:36 +01:00
blowk
3e568f7bb5 Merge branch 'TandoorRecipes:develop' into develop 2023-11-17 16:16:51 +01:00
Jan-Niklas Weghorn
b69c6bc97a fix placeholder text 2023-11-15 09:52:16 +01:00
avi meyer
9132ab8f33 Translated using Weblate (Hebrew)
Currently translated at 0.9% (5 of 508 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/he/
2023-11-15 08:20:01 +00:00
avi meyer
45858d5107 Translated using Weblate (Hebrew)
Currently translated at 93.2% (498 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/he/
2023-11-15 08:19:56 +00:00
avi meyer
1e332977c5 Added translation using Weblate (Hebrew) 2023-11-14 07:56:00 +00:00
dependabot[bot]
7b70ffab5f Bump axios from 1.5.0 to 1.6.0 in /vue
Bumps [axios](https://github.com/axios/axios) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-11 15:26:26 +00:00
Jan-Niklas Weghorn
9b367e5d08 fix bottom navigation bar 2023-11-10 14:09:24 +01:00
Jan-Niklas Weghorn
3c08e3a3f1 Improve import error messages 2023-11-10 13:28:20 +01:00
Jan-Niklas Weghorn
243cac0389 cleanup 2023-11-10 12:16:43 +01:00
Jan-Niklas Weghorn
8205812c84 fix markdown editor and sidebar 2023-11-10 11:52:26 +01:00
Jan-Niklas Weghorn
94279b74c9 improve dark theme 2023-11-10 11:17:20 +01:00
noobdog
8a588db429 Translated using Weblate (Lithuanian)
Currently translated at 13.4% (72 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/lt/
2023-11-06 08:03:51 +00:00
dependabot[bot]
5150807ab7 Bump django from 4.2.5 to 4.2.7
Bumps [django](https://github.com/django/django) from 4.2.5 to 4.2.7.
- [Commits](https://github.com/django/django/compare/4.2.5...4.2.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-02 21:55:41 +00:00
smilerz
225ddc8eeb Update boot.sh
updated to handle postgres defined in database_url
2023-11-01 07:49:07 -05:00
dependabot[bot]
a6965fb3c4 Bump whitenoise from 6.5.0 to 6.6.0
Bumps [whitenoise](https://github.com/evansd/whitenoise) from 6.5.0 to 6.6.0.
- [Changelog](https://github.com/evansd/whitenoise/blob/main/docs/changelog.rst)
- [Commits](https://github.com/evansd/whitenoise/compare/6.5.0...6.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 00:16:11 +00:00
dependabot[bot]
90354305c4 Bump pytest-django from 4.5.2 to 4.6.0
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.5.2 to 4.6.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.5.2...v4.6.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 00:16:09 +00:00
dependabot[bot]
220d98a85c Bump markdown from 3.4.3 to 3.5.1
Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.4.3 to 3.5.1.
- [Release notes](https://github.com/Python-Markdown/markdown/releases)
- [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md)
- [Commits](https://github.com/Python-Markdown/markdown/compare/3.4.3...3.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 00:16:05 +00:00
dependabot[bot]
7fb4155ebe Bump recipe-scrapers from 14.36.1 to 14.52.0
Bumps [recipe-scrapers](https://github.com/hhursev/recipe-scrapers) from 14.36.1 to 14.52.0.
- [Release notes](https://github.com/hhursev/recipe-scrapers/releases)
- [Commits](https://github.com/hhursev/recipe-scrapers/compare/14.36.1...14.52.0)

---
updated-dependencies:
- dependency-name: recipe-scrapers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 00:16:01 +00:00
dependabot[bot]
a39e6e8a6a Bump boto3 from 1.28.57 to 1.28.75
Bumps [boto3](https://github.com/boto/boto3) from 1.28.57 to 1.28.75.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.28.57...1.28.75)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 00:15:57 +00:00
smilerz
97fc15ded3 Merge pull request #2705 from smilerz/move_sqlite
better support for sqlite
2023-10-30 22:12:55 -05:00
smilerz
8bee2e3976 allow arbitrary path for sqlite using DATABASE_URL 2023-10-30 21:54:25 -05:00
smilerz
e89c1742fb remove deprecated django.db.backends.postgresql_psycopg2 2023-10-30 21:42:57 -05:00
smilerz
6680fbb644 changes to enable sqlite3 in docker container 2023-10-30 21:37:45 -05:00
smilerz
4cec643e08 Update ExportResponseView.vue 2023-10-29 16:33:22 -05:00
dependabot[bot]
03bd51893e Bump browserify-sign from 4.2.1 to 4.2.2 in /vue
Bumps [browserify-sign](https://github.com/crypto-browserify/browserify-sign) from 4.2.1 to 4.2.2.
- [Changelog](https://github.com/browserify/browserify-sign/blob/main/CHANGELOG.md)
- [Commits](https://github.com/crypto-browserify/browserify-sign/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: browserify-sign
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-27 22:30:06 +00:00
smilerz
66b0e381ec Merge pull request #2699 from smilerz/fix_export
fixes recipe export
2023-10-27 14:45:03 -05:00
smilerz
fd70adf19d fixes recipe export 2023-10-27 14:43:48 -05:00
blowk
eb8422cb51 Import tags on mealie recipes 2023-10-22 20:09:27 +02:00
gorrilla10101
1008d880c9 Update authentication.md
Changed provider list url because existing one doesn't work anymore.
2023-10-21 06:07:37 -05:00
Ferenc
9cb1c21cd8 Translated using Weblate (Hungarian)
Currently translated at 81.4% (435 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-20 14:05:55 +00:00
Boris Holowka
5149cb0609 Translated using Weblate (German)
Currently translated at 96.6% (516 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-10-20 14:05:55 +00:00
Ferenc
08adf4eb6f Translated using Weblate (Hungarian)
Currently translated at 97.7% (479 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2023-10-20 14:05:55 +00:00
dependabot[bot]
62f38d00f3 Bump @babel/traverse from 7.22.17 to 7.23.2 in /vue
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.17 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-19 06:30:23 +00:00
harry
43a55c8c82 Fix bug when ingredients have no name 2023-10-18 21:46:07 +01:00
harry
d09eb64a41 Change step deletion confirmation 2023-10-18 21:30:17 +01:00
harry
8bbbc1b9ef Change remove ingredient confirmation 2023-10-18 21:09:33 +01:00
Jonas
cc367bfed2 Translated using Weblate (Lithuanian)
Currently translated at 4.6% (25 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/lt/
2023-10-15 14:19:56 +00:00
Ferenc
b18aa831ac Translated using Weblate (Hungarian)
Currently translated at 81.2% (434 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-15 14:19:55 +00:00
Ferenc
6205fbe1c4 Translated using Weblate (Hungarian)
Currently translated at 97.7% (479 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2023-10-15 14:19:55 +00:00
Jonas
879a54524c Added translation using Weblate (Lithuanian) 2023-10-14 21:14:27 +00:00
Ferenc
36678692be Translated using Weblate (Hungarian)
Currently translated at 73.7% (394 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-14 12:14:48 +00:00
Tomasz Klimczak
de6285e5f8 Translated using Weblate (Polish)
Currently translated at 100.0% (534 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2023-10-14 12:14:48 +00:00
Guilherme Roda
7ff7409f56 Translated using Weblate (Portuguese (Brazil))
Currently translated at 89.8% (480 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt_BR/
2023-10-13 14:18:58 +00:00
Ferenc
50b3636c86 Translated using Weblate (Hungarian)
Currently translated at 63.8% (341 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-13 11:43:22 +00:00
dennisstinauer
1f72a3f62f open-data-import further duplicate handling 2023-10-13 12:50:59 +02:00
Ferenc
aea796bd6d Translated using Weblate (Hungarian)
Currently translated at 51.4% (275 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-12 22:10:32 +00:00
Ferenc
edcddc3183 Translated using Weblate (Hungarian)
Currently translated at 41.0% (219 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-12 20:19:57 +00:00
pharok
45a24a4720 Translated using Weblate (French)
Currently translated at 91.0% (486 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2023-10-12 20:19:57 +00:00
Charles Pare
bed95105f3 Translated using Weblate (French)
Currently translated at 91.0% (486 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2023-10-12 20:19:57 +00:00
pharok
a39fdb4226 Translated using Weblate (French)
Currently translated at 92.8% (455 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/
2023-10-12 20:19:57 +00:00
smilerz
9d629b03b3 Update __init__.py 2023-10-12 10:44:59 -05:00
Ferenc
4eeb87cb95 Translated using Weblate (Hungarian)
Currently translated at 37.0% (198 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-11 18:33:38 +00:00
Ferenc
3ce7e43b46 Translated using Weblate (Hungarian)
Currently translated at 29.0% (155 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-10 11:19:55 +00:00
Ferenc
a3a995ef77 Translated using Weblate (Hungarian)
Currently translated at 97.5% (478 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2023-10-10 11:19:55 +00:00
Ferenc
a386b45a03 Translated using Weblate (Hungarian)
Currently translated at 2.6% (14 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/hu/
2023-10-09 01:54:03 +00:00
Guilherme Roda
74bd2ba2c0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 59.6% (335 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/pt_BR/
2023-10-09 01:54:03 +00:00
Guilherme Roda
695f467126 Translated using Weblate (Portuguese (Brazil))
Currently translated at 89.3% (477 of 534 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt_BR/
2023-10-09 01:54:03 +00:00
Ferenc
6270b46951 Translated using Weblate (Hungarian)
Currently translated at 89.5% (439 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/hu/
2023-10-09 01:54:03 +00:00
vabene1111
a3ad131e6a Merge pull request #2672 from harry48225/Improve-App-Import-Layout
Make import list layout responsive
2023-10-08 11:55:02 +02:00
Guilherme Roda
e2d5287cc6 Translated using Weblate (Portuguese (Brazil))
Currently translated at 51.0% (287 of 562 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/pt_BR/
2023-10-07 18:02:02 +00:00
Guilherme Roda
1c39d8089c Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.0% (464 of 533 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt_BR/
2023-10-07 18:02:02 +00:00
Guilherme Roda
2230b9e9ab Translated using Weblate (Portuguese)
Currently translated at 35.7% (175 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/pt/
2023-10-07 18:02:02 +00:00
harry
339d7b1c96 Make import list layout responsive 2023-10-07 17:09:53 +01:00
vabene1111
4e8c955555 fixed width recipe card skeleton 2023-10-07 08:37:53 +02:00
vabene1111
221c466c18 fixed recipe sage import and image procssing with pillow 10 2023-10-07 08:11:50 +02:00
vabene1111
2c8e029811 Merge pull request #2656 from TandoorRecipes/dependabot/github_actions/docker/metadata-action-5
Bump docker/metadata-action from 4 to 5
2023-10-05 21:14:24 +02:00
vabene1111
019825bfcb Merge pull request #2655 from TandoorRecipes/dependabot/github_actions/docker/login-action-3
Bump docker/login-action from 2 to 3
2023-10-05 21:14:13 +02:00
vabene1111
8e5ea47d5e Merge pull request #2654 from TandoorRecipes/dependabot/github_actions/docker/setup-qemu-action-3
Bump docker/setup-qemu-action from 2 to 3
2023-10-05 21:14:04 +02:00
vabene1111
425ac7f379 Merge pull request #2653 from TandoorRecipes/dependabot/github_actions/docker/setup-buildx-action-3
Bump docker/setup-buildx-action from 2 to 3
2023-10-05 21:13:57 +02:00
vabene1111
f0caef4759 Merge pull request #2652 from TandoorRecipes/dependabot/github_actions/docker/build-push-action-5
Bump docker/build-push-action from 4 to 5
2023-10-05 21:13:40 +02:00
vabene1111
3cabe85091 Merge branch 'develop' into beta 2023-10-05 19:05:09 +02:00
vabene1111
c56a76f264 Merge pull request #2404 from ignas2526/feature/2402-make-now-count
Add ability to set maximum missing ingredient count
2023-10-05 19:01:48 +02:00
vabene1111
429886e6a6 Merge branch 'develop' into feature/2402-make-now-count 2023-10-05 19:01:33 +02:00
vabene1111
339ab57df7 Merge pull request #2647 from JohnTheNerd/develop
Added support for keeping SECRET_KEY and POSTGRES_PASSWORD in a file
2023-10-05 18:59:24 +02:00
vabene1111
cb6d98a357 fixed system page permission 2023-10-05 18:58:38 +02:00
vabene1111
e746b44f3b Merge pull request #2632 from smilerz/unique_name
updates to multiple models uniqueness capabilities
2023-10-05 18:57:08 +02:00
vabene1111
bc63ba6713 Merge pull request #2630 from smilerz/imports_cleanup
Imports cleanup
2023-10-05 18:55:32 +02:00
vabene1111
ea8661ab03 fixed property view roundign 2023-10-05 18:50:47 +02:00
vabene1111
bc9a5c9435 Merge pull request #2651 from TandoorRecipes/dependabot/pip/beautifulsoup4-4.12.2
Bump beautifulsoup4 from 4.11.1 to 4.12.2
2023-10-05 18:35:47 +02:00
vabene1111
365ffa29fa Merge pull request #2650 from TandoorRecipes/dependabot/pip/django-cors-headers-4.2.0
Bump django-cors-headers from 3.13.0 to 4.2.0
2023-10-05 18:35:41 +02:00
vabene1111
b3aeee6a63 Merge pull request #2648 from TandoorRecipes/dependabot/pip/boto3-1.28.57
Bump boto3 from 1.26.41 to 1.28.57
2023-10-05 18:35:32 +02:00
vabene1111
d503dc77c3 Merge pull request #2649 from TandoorRecipes/dependabot/pip/python-dotenv-1.0.0
Bump python-dotenv from 0.21.0 to 1.0.0
2023-10-05 18:35:04 +02:00
dependabot[bot]
fee364ee4a Bump python-dotenv from 0.21.0 to 1.0.0
Bumps [python-dotenv](https://github.com/theskumar/python-dotenv) from 0.21.0 to 1.0.0.
- [Release notes](https://github.com/theskumar/python-dotenv/releases)
- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/theskumar/python-dotenv/compare/v0.21.0...v1.0.0)

---
updated-dependencies:
- dependency-name: python-dotenv
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-05 16:32:22 +00:00
vabene1111
680a8d0fce Merge pull request #2639 from TandoorRecipes/dependabot/pip/cryptography-41.0.4
Bump cryptography from 41.0.3 to 41.0.4
2023-10-05 18:31:55 +02:00
vabene1111
0944d72e32 Merge pull request #2664 from TandoorRecipes/dependabot/pip/pillow-10.0.1
Bump pillow from 9.4.0 to 10.0.1
2023-10-05 18:31:32 +02:00
vabene1111
6809ded468 Merge pull request #2659 from nabim777/add-step-on-docs-for-manually-installation
add step on docs for manual installation
2023-10-05 18:30:13 +02:00
dependabot[bot]
64d07a65dc Bump pillow from 9.4.0 to 10.0.1
Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.4.0 to 10.0.1.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/9.4.0...10.0.1)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-04 01:12:50 +00:00
Samuel
745abb57a8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 36.9% (197 of 533 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt_BR/
2023-10-02 20:19:56 +00:00
nabim777
dfe5083451 add step on docs for manual installation 2023-10-01 10:18:43 +05:45
dependabot[bot]
9377e208e8 Bump docker/metadata-action from 4 to 5
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4 to 5.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md)
- [Commits](https://github.com/docker/metadata-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:40:41 +00:00
dependabot[bot]
40f38e6c6d Bump docker/login-action from 2 to 3
Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:40:37 +00:00
dependabot[bot]
3ee0717d84 Bump docker/setup-qemu-action from 2 to 3
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:40:33 +00:00
dependabot[bot]
47155ce338 Bump docker/setup-buildx-action from 2 to 3
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:40:28 +00:00
dependabot[bot]
611080b739 Bump docker/build-push-action from 4 to 5
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:40:24 +00:00
dependabot[bot]
416d1badda Bump beautifulsoup4 from 4.11.1 to 4.12.2
Bumps [beautifulsoup4](https://www.crummy.com/software/BeautifulSoup/bs4/) from 4.11.1 to 4.12.2.

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:20:58 +00:00
dependabot[bot]
0ef5d3ad92 Bump django-cors-headers from 3.13.0 to 4.2.0
Bumps [django-cors-headers](https://github.com/adamchainz/django-cors-headers) from 3.13.0 to 4.2.0.
- [Changelog](https://github.com/adamchainz/django-cors-headers/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/adamchainz/django-cors-headers/compare/3.13.0...4.2.0)

---
updated-dependencies:
- dependency-name: django-cors-headers
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:20:55 +00:00
dependabot[bot]
efb8784b91 Bump boto3 from 1.26.41 to 1.28.57
Bumps [boto3](https://github.com/boto/boto3) from 1.26.41 to 1.28.57.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.26.41...1.28.57)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 00:20:46 +00:00
Tomasz Klimczak
a1a6f476e0 Translated using Weblate (Polish)
Currently translated at 100.0% (533 of 533 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2023-09-30 22:19:56 +00:00
John Karabudak
ccd0667f04 Added support for keeping SECRET_KEY and POSTGRES_PASSWORD in a file
This commit adds two optional environment variables:

- SECRET_KEY_FILE
- POSTGRES_PASSWORD_FILE

This change allows mounting secret data when running this in Docker Swarm, instead of having to hard-code it in our docker-compose file or provide it alongside all other environment variables.
2023-09-30 01:12:30 -02:30
Henrique Nepomuceno
38cf825816 Translated using Weblate (Portuguese (Brazil))
Currently translated at 32.2% (172 of 533 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pt_BR/
2023-09-29 20:19:56 +00:00
Leo Mu
a8dc8e7190 Translated using Weblate (Italian)
Currently translated at 87.2% (465 of 533 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2023-09-29 20:19:56 +00:00
Luis Cacho
76aca6cf38 Translated using Weblate (Spanish)
Currently translated at 68.2% (361 of 529 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/es/
2023-09-25 09:59:47 +00:00
Matias Laporte
89c31a018f Translated using Weblate (Spanish)
Currently translated at 68.2% (361 of 529 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/es/
2023-09-25 09:59:47 +00:00
Leo Mu
e54f55b6d0 Translated using Weblate (Italian)
Currently translated at 88.0% (466 of 529 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2023-09-25 09:59:47 +00:00
Matias Laporte
fff7cb607c Translated using Weblate (Spanish)
Currently translated at 61.4% (301 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/es/
2023-09-25 09:59:47 +00:00
dependabot[bot]
54c2478869 Bump cryptography from 41.0.3 to 41.0.4
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.3 to 41.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.3...41.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-21 21:06:20 +00:00
smilerz
a7795092b3 make 'name' unique in space for MealType
make MealType, Unit, Supermarket, Supermarket Category, PropoertyType
case insenstive for get_or_create
convert unit conversion create serializer to get_or_create behavior
enable create duplicate tests for unitconversion and mealtype api
2023-09-14 14:46:37 -05:00
smilerz
538fb8b42e remove unused imports, vairables and commented code
from views, and base cookbook and recipes modules
2023-09-13 13:31:53 -05:00
smilerz
1f0cd58d7d remove unused imports, variables and commented code
from tests
2023-09-13 13:08:26 -05:00
smilerz
78b1386a1c remove unused imports, variables and commented code
from integrations and templatetags
2023-09-13 09:35:22 -05:00
smilerz
aba7f8db5c remove unused imports, variables and commented code in helpers 2023-09-13 09:29:48 -05:00
vabene1111
d7fadffbfd date format in meal plan simple grid 2023-09-13 16:17:02 +02:00
vabene1111
22c7f5d85d changed date label format 2023-09-13 16:16:38 +02:00
vabene1111
c18d8daece fixed meal plan simple grid on search view after merge 2023-09-13 16:08:56 +02:00
smilerz
d91c4b33f3 Merge pull request #2609 from smilerz/automation_tests
Automation Refactor and Tests
2023-09-12 15:07:18 -05:00
smilerz
2ad6f21b9c Merge pull request #2611 from smilerz/export_fix
fix custom_filter exports and errors on Download link
2023-09-12 15:06:31 -05:00
smilerz
554170a84e Merge pull request #2615 from smilerz/clear_food_after_add
clears search on food in shopping form
2023-09-12 15:06:23 -05:00
smilerz
d43a6e551d Merge pull request #2617 from smilerz/ignore_shopping_fix
respect ignore_shopping flag
2023-09-12 15:06:13 -05:00
smilerz
02cb6d1be7 Merge pull request #2619 from smilerz/meal_plan_date
update Meal Plan grid to respect localization on date format
2023-09-12 15:05:58 -05:00
smilerz
45b1eca48b Merge pull request #2621 from smilerz/fix_recipe_count
fix recipe counting issue on extended mixin
2023-09-12 15:05:30 -05:00
smilerz
6dacd44f1f regenerate openapi 2023-09-12 09:53:59 -05:00
smilerz
1b97472368 Squashed commit of the following:
commit 52909e8117
Author: smilerz <smilerz@gmail.com>
Date:   Wed Sep 6 15:54:23 2023 -0500

    fix recipe counting issue on extended mixin
2023-09-12 09:48:41 -05:00
smilerz
d467352029 Squashed commit of the following:
commit c8fc6b5237
Author: smilerz <smilerz@gmail.com>
Date:   Wed Sep 6 14:01:27 2023 -0500

    update Meal Plan grid to respect localization on date format
2023-09-12 09:48:22 -05:00
smilerz
a0256b607e Squashed commit of the following:
commit f8f08ae337
Author: smilerz <smilerz@gmail.com>
Date:   Wed Sep 6 10:27:43 2023 -0500

    respect ignore_shopping flag
2023-09-12 09:47:55 -05:00
smilerz
847fceaf10 Squashed commit of the following:
commit 4aa3e04df0
Author: smilerz <smilerz@gmail.com>
Date:   Wed Sep 6 09:01:07 2023 -0500

    clears search on food in shopping form
2023-09-12 09:47:07 -05:00
smilerz
9e831a22df Squashed commit of the following:
commit bcfe6ca707
Author: smilerz <smilerz@gmail.com>
Date:   Fri Sep 1 11:36:10 2023 -0500

    fix custom_filter exports and errors on Download link
2023-09-12 09:46:42 -05:00
smilerz
768a5ea237 Squashed commit of the following:
commit 36403ecbae
Author: smilerz <smilerz@gmail.com>
Date:   Fri Sep 1 12:04:04 2023 -0500

    update migration for new Automation Types

commit 4620ebaf30
Author: smilerz <smilerz@gmail.com>
Date:   Fri Sep 1 07:49:10 2023 -0500

    add Name and Instruction automation to YouTube importer

commit c907da84c1
Author: smilerz <smilerz@gmail.com>
Date:   Fri Sep 1 07:45:32 2023 -0500

    remove old commented automation code

commit 9b5e39415e
Author: smilerz <smilerz@gmail.com>
Date:   Fri Sep 1 07:37:36 2023 -0500

    test for automations applied during url import
    renamed TITLE_REPLACE to NAME_REPLACE

commit 2679a22464
Author: smilerz <smilerz@gmail.com>
Date:   Thu Aug 31 15:29:59 2023 -0500

    added tests for regex_replace

commit 8bae21025b
Author: smilerz <smilerz@gmail.com>
Date:   Thu Aug 31 13:51:46 2023 -0500

    updated Automation Modal and translations

commit 4120adc546
Author: smilerz <smilerz@gmail.com>
Date:   Thu Aug 31 13:12:41 2023 -0500

    applied regex_replace automation to food and unit automations
    updated automation documentation

commit 30c891abfc
Author: smilerz <smilerz@gmail.com>
Date:   Thu Aug 31 12:46:34 2023 -0500

    migrate regex_replace functions to AutomationEngine
    create TITLE_REPLACE, UNIT_REPLACE and FOOD REPLACE automation types
    create migration for new types

commit b8317c2c29
Author: smilerz <smilerz@gmail.com>
Date:   Wed Aug 30 20:44:40 2023 -0500

    move transpose words to AutomationEngine
    create tests for transpose words

commit 39253cfd02
Author: smilerz <smilerz@gmail.com>
Date:   Wed Aug 30 17:03:29 2023 -0500

    refactor never_unit automation to AutomationEngine
    create tests for never_unit

commit 7c0b8b151c
Author: smilerz <smilerz@gmail.com>
Date:   Wed Aug 30 11:21:06 2023 -0500

    update ingredient parser to use AutomationEngine for unt, keyword, food
    update test_ingredient_parser tests to accomodate changes

commit 8e1b8923af
Author: smilerz <smilerz@gmail.com>
Date:   Mon Aug 28 16:44:35 2023 -0500

    keyword and unit Automtations refactored to Automation Engine
    keyword and unit automation tests added

commit 52eb876a08
Author: smilerz <smilerz@gmail.com>
Date:   Mon Aug 28 15:03:19 2023 -0500

    food_alias tests added

commit a820b9c09e
Author: smilerz <smilerz@gmail.com>
Date:   Sat Aug 26 12:37:16 2023 -0500

    create AutomationEngine class
    create food_automation method
    refactor food automations to use AutomationEngine
2023-09-12 09:46:08 -05:00
smilerz
36403ecbae update migration for new Automation Types 2023-09-12 09:42:09 -05:00
smilerz
4620ebaf30 add Name and Instruction automation to YouTube importer 2023-09-12 09:42:09 -05:00
smilerz
c907da84c1 remove old commented automation code 2023-09-12 09:42:08 -05:00
smilerz
9b5e39415e test for automations applied during url import
renamed TITLE_REPLACE to NAME_REPLACE
2023-09-12 09:42:08 -05:00
smilerz
2679a22464 added tests for regex_replace 2023-09-12 09:42:07 -05:00
smilerz
8bae21025b updated Automation Modal and translations 2023-09-12 09:42:07 -05:00
smilerz
4120adc546 applied regex_replace automation to food and unit automations
updated automation documentation
2023-09-12 09:41:49 -05:00
smilerz
30c891abfc migrate regex_replace functions to AutomationEngine
create TITLE_REPLACE, UNIT_REPLACE and FOOD REPLACE automation types
create migration for new types
2023-09-12 09:41:49 -05:00
smilerz
b8317c2c29 move transpose words to AutomationEngine
create tests for transpose words
2023-09-12 09:40:17 -05:00
smilerz
39253cfd02 refactor never_unit automation to AutomationEngine
create tests for never_unit
2023-09-12 09:40:17 -05:00
smilerz
7c0b8b151c update ingredient parser to use AutomationEngine for unt, keyword, food
update test_ingredient_parser tests to accomodate changes
2023-09-12 09:40:17 -05:00
smilerz
8e1b8923af keyword and unit Automtations refactored to Automation Engine
keyword and unit automation tests added
2023-09-12 09:40:16 -05:00
smilerz
52eb876a08 food_alias tests added 2023-09-12 09:39:45 -05:00
smilerz
a820b9c09e create AutomationEngine class
create food_automation method
refactor food automations to use AutomationEngine
2023-09-12 09:39:45 -05:00
smilerz
bcfe6ca707 fix custom_filter exports and errors on Download link 2023-09-12 09:36:44 -05:00
smilerz
4aa3e04df0 clears search on food in shopping form 2023-09-12 09:30:47 -05:00
smilerz
f8f08ae337 respect ignore_shopping flag 2023-09-12 09:29:11 -05:00
smilerz
c8fc6b5237 update Meal Plan grid to respect localization on date format 2023-09-12 09:25:42 -05:00
smilerz
52909e8117 fix recipe counting issue on extended mixin 2023-09-12 09:21:18 -05:00
vabene1111
c72bf57ccb Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-09-12 16:08:33 +02:00
vabene1111
d3c21cf97f updated django 2023-09-12 16:08:28 +02:00
vabene1111
942edd9336 Merge pull request #2604 from TandoorRecipes/dependabot/pip/icalendar-5.0.7
Bump icalendar from 5.0.4 to 5.0.7
2023-09-12 16:07:35 +02:00
vabene1111
8fa6c98254 updated crispy forms 2023-09-12 16:07:16 +02:00
vabene1111
73c6bfce44 Merge pull request #2595 from djstini/develop
#2514 Importing a community curated list leads to an error
2023-09-12 16:00:25 +02:00
vabene1111
c105909933 Merge pull request #2603 from TandoorRecipes/dependabot/pip/django-oauth-toolkit-2.3.0
Bump django-oauth-toolkit from 2.2.0 to 2.3.0
2023-09-12 15:57:57 +02:00
vabene1111
13baf4f30a Merge pull request #2605 from TandoorRecipes/dependabot/pip/django-scopes-2.0.0
Bump django-scopes from 1.2.0.post1 to 2.0.0
2023-09-12 15:56:52 +02:00
vabene1111
da5fd16338 fixed lockfile 2023-09-12 15:56:28 +02:00
vabene1111
83a52bd204 Merge pull request #2593 from BrainWart/issue-2261
allow signup for social accounts when the provider is set up
2023-09-12 15:50:32 +02:00
vabene1111
fe4bd6a127 Merge pull request #2624 from WoosterInitiative/Update-settings
Update and add settings
2023-09-12 15:43:41 +02:00
vabene1111
d193d91e6a fixed migration 2023-09-12 15:41:38 +02:00
vabene1111
a2f9ef2e74 Merge pull request #2623 from smilerz/remove_facets
remove facets and treeselect
2023-09-12 15:36:24 +02:00
vabene1111
3f63eab68c Merge branch 'develop' into remove_facets 2023-09-12 15:36:14 +02:00
Karl
9b6ed7a63a Update .env.template
Add option for CSRF_TRUSTED_ORIGINS for better discoverability.

Add options for newly added CORS_ALLOW_ALL_ORIGINS for discoverability as well as flexibility.
2023-09-08 12:31:46 -07:00
Karl
e2f8efb521 Update settings.py
Add deprecation notice for `CORS_ORIGIN_ALLOW_ALL` and auto switch to `CORS_ALLOW_ALL_ORIGINS`
2023-09-08 12:29:06 -07:00
vabene1111
ce29283a52 fixed auto meal plan 2023-09-08 17:05:35 +02:00
vabene1111
dcf9d59b06 add more height to meal plan 2023-09-08 16:59:52 +02:00
vabene1111
794f9cf5b9 fixed meal plan factory 2023-09-08 16:38:38 +02:00
vabene1111
9954bb9410 fixed test and added meal plan client settings load save 2023-09-08 16:27:39 +02:00
vabene1111
e57be4a704 fixed lockfile 2023-09-08 15:47:08 +02:00
vabene1111
ffaecc066f improved search page meal plan style 2023-09-08 15:36:59 +02:00
vabene1111
94f398a7f6 added multi day meal planning 2023-09-08 15:31:42 +02:00
vabene1111
65d670a995 improved meal plan UI 2023-09-08 14:13:27 +02:00
dao cat
15ed040533 Translated using Weblate (Chinese (Simplified))
Currently translated at 90.5% (479 of 529 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/zh_Hans/
2023-09-08 05:19:56 +00:00
smilerz
5d3f44ffee missing caches import 2023-09-07 13:53:30 -05:00
smilerz
9ee4be621b remove facets and treeselect 2023-09-07 13:20:51 -05:00
vabene1111
d33b0d2254 added meal type settings to meal plan settings component 2023-09-06 16:27:36 +02:00
vabene1111
1a20c4bef5 fixed syntax server 2023-09-05 16:48:59 +02:00
AJ
b350ab1b59 Translated using Weblate (French)
Currently translated at 91.6% (449 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/
2023-09-02 20:25:29 +00:00
dependabot[bot]
687e8a1f6a Bump django-scopes from 1.2.0.post1 to 2.0.0
Bumps [django-scopes](https://github.com/raphaelm/django-scopes) from 1.2.0.post1 to 2.0.0.
- [Commits](https://github.com/raphaelm/django-scopes/commits/2.0.0)

---
updated-dependencies:
- dependency-name: django-scopes
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-01 00:48:41 +00:00
dependabot[bot]
64b9605871 Bump icalendar from 5.0.4 to 5.0.7
Bumps [icalendar](https://github.com/collective/icalendar) from 5.0.4 to 5.0.7.
- [Changelog](https://github.com/collective/icalendar/blob/master/CHANGES.rst)
- [Commits](https://github.com/collective/icalendar/compare/v5.0.4...v5.0.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-01 00:48:38 +00:00
dependabot[bot]
8320473606 Bump django-oauth-toolkit from 2.2.0 to 2.3.0
Bumps [django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/jazzband/django-oauth-toolkit/releases)
- [Changelog](https://github.com/jazzband/django-oauth-toolkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jazzband/django-oauth-toolkit/compare/2.2.0...2.3.0)

---
updated-dependencies:
- dependency-name: django-oauth-toolkit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-01 00:48:33 +00:00
NeoID
88228ab853 Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.5% (373 of 529 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nb_NO/
2023-08-31 11:37:04 +00:00
vabene1111
dcfb269909 meal plan stuff 2023-08-30 10:30:12 +02:00
vabene1111
4a1ec5adf7 fixed icon issues 2023-08-30 09:05:24 +02:00
Cody McGinnis
56cdc14cc1 docs: explain social authentication auto sign up
Attempt to explain to the user that social auth with automatically allow
users to sign up for social accounts. `ALLOW_SIGNUP` now applies to
local account sign up only.
2023-08-29 20:28:30 -04:00
Cody McGinnis
b8959036bf allow signup for social accounts when the provider is set up
When a social provider is set up, the social account signup view is enabled. This seems to cover issue #2261, but it needs further testing.
2023-08-29 20:28:30 -04:00
djstini
ab24177c89 Merge branch 'TandoorRecipes:develop' into develop 2023-08-29 19:26:40 +02:00
vabene1111
4ffc9cc72f removed icons 2023-08-29 15:58:57 +02:00
vabene1111
7f62ec28e3 WIP meal plan and icon stuff 2023-08-29 14:36:57 +02:00
vabene1111
d42d784aeb Merge branch 'develop' 2023-08-29 13:09:38 +02:00
vabene1111
ce84b3b385 updated translations 2023-08-29 13:09:32 +02:00
vabene1111
74fbcb03a1 Merge pull request #2592 from WoosterInitiative/develop
Update en.json
2023-08-29 13:05:54 +02:00
dennisstinauer
b1aa70787c #2514 Importing a community curated list leads to an error 2023-08-28 22:06:49 +02:00
Karl
8675143cc1 Update en.json
Correct "loosing" to "losing."
2023-08-27 14:22:26 -07:00
Étienne
75e23106fc Translated using Weblate (French)
Currently translated at 88.6% (461 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2023-08-27 11:20:01 +00:00
Matias Laporte
2ad89b5b22 Translated using Weblate (Spanish)
Currently translated at 61.4% (301 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/es/
2023-08-27 11:20:01 +00:00
vabene1111
36074c9c35 added apple header 2023-08-27 08:42:11 +02:00
vabene1111
05560c5730 improved user agent for url image import 2023-08-26 07:54:19 +02:00
vabene1111
6ba4db6ff9 Merge pull request #2432 from smilerz/new_automations
add NEVER_UNIT automation
2023-08-26 07:41:27 +02:00
smilerz
6353885f9c update migrations after rebase 2023-08-25 08:10:21 -05:00
smilerz
833ebf8c0c Merge branch 'new_automations' of github.com:smilerz/recipes into new_automations 2023-08-25 08:04:30 -05:00
smilerz
0662255b27 update migrations 2023-08-25 08:03:07 -05:00
smilerz
fde4ea8c4c filtered automations to tokens present 2023-08-25 08:01:56 -05:00
smilerz
132815496c create Transpose Words automation 2023-08-25 08:01:26 -05:00
smilerz
a7a6abe3d2 add NEVER_UNIT automation 2023-08-25 07:57:56 -05:00
smilerz
2f617aa40f fix incorrect variable in apply_transpose_words_automations 2023-08-25 07:54:07 -05:00
smilerz
9b50ea4c22 make automation parameters case insensitive on search 2023-08-25 07:54:06 -05:00
smilerz
cde8dd8b53 fixed defect in NEVER_UNIT automation 2023-08-25 07:54:06 -05:00
smilerz
8411537f87 filtered automations to tokens present 2023-08-25 07:54:05 -05:00
smilerz
479cf1a042 create Transpose Words automation 2023-08-25 07:54:05 -05:00
smilerz
8fa00972bd add NEVER_UNIT automation 2023-08-25 07:53:53 -05:00
vabene1111
5d5eb45b5a also accept text as a parameter for import url 2023-08-25 12:15:58 +02:00
vabene1111
87beed48c9 testing share targets 2023-08-25 11:05:51 +02:00
vabene1111
cf7cc6c637 only url on share target 2023-08-25 10:56:15 +02:00
vabene1111
3d45a068e4 added share target to web manifest 2023-08-25 09:45:31 +02:00
vabene1111
01ce658883 fixed step factory 2023-08-25 09:12:58 +02:00
vabene1111
92d648c3a3 added ability to order property types 2023-08-24 12:50:17 +02:00
vabene1111
17fa3c8d7c fixed serving property calculation 2023-08-24 11:20:43 +02:00
vabene1111
c1ae4e3905 added migration for step ingredient showing 2023-08-24 11:20:31 +02:00
vabene1111
d819cbc20e Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-08-24 10:34:31 +02:00
vabene1111
f255397bbd added translation 2023-08-24 10:34:30 +02:00
vabene1111
2f0929e90e Merge pull request #2539 from srwareham/hide-step-ingredients
Added option: Hide step ingredients
2023-08-24 10:33:57 +02:00
srwareham
6785033a21 Add step-level configuration whether an ingredients table should be shown. User-level default added to settings 2023-08-23 21:46:09 -07:00
vabene1111
0345b7720c Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-08-23 13:17:48 +02:00
vabene1111
7163c33b2a fixed food edit merge/move/automate not working 2023-08-23 13:05:07 +02:00
vabene1111
934df3c5f7 Merge pull request from GHSA-66qh-qh47-9w6p
Changed remote auth var-name in env, info in docs and processing in settings
2023-08-23 11:24:29 +02:00
Theodoros Grammenos
2888b18819 Translated using Weblate (Greek)
Currently translated at 100.0% (520 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/el/
2023-08-22 21:19:55 +00:00
Theodoros Grammenos
c01081255b Translated using Weblate (Greek)
Currently translated at 62.5% (325 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/el/
2023-08-21 09:19:56 +00:00
Theodoros Grammenos
2e606dc166 Translated using Weblate (Greek)
Currently translated at 54.9% (288 of 524 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/el/
2023-08-21 09:19:55 +00:00
Theodoros Grammenos
835c5a1d3a Translated using Weblate (Greek)
Currently translated at 13.4% (70 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/el/
2023-08-19 21:36:10 +00:00
NeoID
8580aea43f Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.4% (265 of 371 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nb_NO/
2023-08-19 21:36:10 +00:00
Alexandre Braure
db4f2db236 Translated using Weblate (French)
Currently translated at 88.6% (461 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2023-08-16 21:19:58 +00:00
Bastian
7e9cef6075 Translated using Weblate (German)
Currently translated at 98.0% (510 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-08-16 21:19:58 +00:00
Alexandre Braure
75612781da Translated using Weblate (French)
Currently translated at 90.6% (444 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/fr/
2023-08-16 21:19:58 +00:00
Henning Bopp
f5fb4e563d Changed var-name in env, info in docs and processing in settings
Also added a deprecation warning and changed the structure of the authentication.md

Signed-off-by: Henning Bopp <henning.bopp@gmail.com>
2023-08-16 21:19:38 +02:00
vabene1111
1ecb57e795 removed dependency and upgraded bleach clean 2023-08-16 07:22:09 +02:00
vabene1111
c4a0df26fc Merge pull request #2446 from TandoorRecipes/dependabot/pip/bleach-6.0.0
Bump bleach from 5.0.1 to 6.0.0
2023-08-16 07:14:36 +02:00
vabene1111
8ff5142149 auto meal plan tweaks and improvements 2023-08-16 07:10:24 +02:00
vabene1111
716976453a fixed pycharm file 2023-08-16 06:20:43 +02:00
vabene1111
f07dec6062 Merge pull request #2468 from AquaticLava/Auto-Planner
Auto meal plan
2023-08-16 06:18:43 +02:00
vabene1111
ffc96890ac Delete recipes.iml 2023-08-16 06:18:02 +02:00
vabene1111
a8fd703d1d Merge pull request #2529 from TandoorRecipes/dependabot/npm_and_yarn/vue/typescript-5.1.6
Bump typescript from 4.9.5 to 5.1.6 in /vue
2023-08-16 06:06:28 +02:00
vabene1111
4592cc85a5 Merge pull request #2566 from TandoorRecipes/dependabot/npm_and_yarn/vue/eslint-8.46.0
Bump eslint from 7.32.0 to 8.46.0 in /vue
2023-08-16 06:06:17 +02:00
vabene1111
4a835c38d8 Merge pull request #2567 from TandoorRecipes/dependabot/pip/django-cleanup-8.0.0
Bump django-cleanup from 7.0.0 to 8.0.0
2023-08-16 06:06:03 +02:00
vabene1111
ef72a07acb Merge pull request #2568 from TandoorRecipes/dependabot/pip/lxml-4.9.3
Bump lxml from 4.9.2 to 4.9.3
2023-08-16 06:05:50 +02:00
vabene1111
246b9c4a02 Merge pull request #2569 from TandoorRecipes/dependabot/pip/django-auth-ldap-4.4.0
Bump django-auth-ldap from 4.2.0 to 4.4.0
2023-08-16 06:05:35 +02:00
Jochum van der Heide
c18a77bc9b Translated using Weblate (Dutch)
Currently translated at 99.8% (519 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nl/
2023-08-15 19:19:56 +00:00
Jochum van der Heide
3d7e2b1aa5 Translated using Weblate (Dutch)
Currently translated at 100.0% (490 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nl/
2023-08-15 19:19:55 +00:00
vabene1111
28f18fbc42 Merge branch 'develop' 2023-08-14 06:26:25 +02:00
Miha Perpar
ba361a8a27 Translated using Weblate (Slovenian)
Currently translated at 59.0% (307 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sl/
2023-08-13 08:19:59 +00:00
Miha Perpar
fc2ce6e488 Translated using Weblate (Slovenian)
Currently translated at 15.9% (81 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sl/
2023-08-13 08:19:59 +00:00
Tomasz Klimczak
d7f77a572a Translated using Weblate (Polish)
Currently translated at 100.0% (520 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2023-08-13 08:19:58 +00:00
Fabian Flodman
64e28fd01a Translated using Weblate (German)
Currently translated at 97.3% (506 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-08-13 08:19:58 +00:00
Thomas
714d5e5184 Translated using Weblate (German)
Currently translated at 97.3% (506 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-08-13 08:19:58 +00:00
Fabian Flodman
640500c82d Translated using Weblate (German)
Currently translated at 100.0% (490 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2023-08-13 08:19:58 +00:00
smilerz
8bf661c1ab update migrations 2023-08-10 09:06:41 -05:00
smilerz
1d29e435d5 Merge branch 'new_automations' of github.com:smilerz/recipes into new_automations 2023-08-10 08:55:14 -05:00
smilerz
6eac48633b fix incorrect variable in apply_transpose_words_automations 2023-08-10 08:54:44 -05:00
smilerz
743fae1ba7 make automation parameters case insensitive on search 2023-08-10 08:54:44 -05:00
smilerz
b3565451ff fixed defect in NEVER_UNIT automation 2023-08-10 08:54:44 -05:00
smilerz
4a93681870 filtered automations to tokens present 2023-08-10 08:54:43 -05:00
smilerz
d83b0484d8 create Transpose Words automation 2023-08-10 08:54:43 -05:00
smilerz
c0d67dbc58 add NEVER_UNIT automation 2023-08-10 08:54:33 -05:00
smilerz
3a8ea4b4c9 fix incorrect variable in apply_transpose_words_automations 2023-08-10 08:33:02 -05:00
vabene1111
4b14a099df better logging 2023-08-05 12:00:03 +02:00
vabene1111
dae7cbfb85 version script updates and system page fix 2023-08-05 10:56:27 +02:00
vabene1111
0c62b80e3a Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2023-08-05 10:28:44 +02:00
vabene1111
678963e6dd more debug in version script 2023-08-05 10:28:39 +02:00
dependabot[bot]
6d84c718fd Bump django-cleanup from 7.0.0 to 8.0.0
Bumps [django-cleanup](https://github.com/un1t/django-cleanup) from 7.0.0 to 8.0.0.
- [Changelog](https://github.com/un1t/django-cleanup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/un1t/django-cleanup/compare/7.0.0...8.0.0)

---
updated-dependencies:
- dependency-name: django-cleanup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-05 07:46:02 +00:00
vabene1111
b8e1ed8967 Merge pull request #2570 from TandoorRecipes/dependabot/pip/cryptography-41.0.3
Bump cryptography from 41.0.2 to 41.0.3
2023-08-05 09:45:13 +02:00
Chen
d87633433a Translated using Weblate (Hebrew)
Currently translated at 90.5% (471 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/he/
2023-08-03 22:19:55 +00:00
Chen
fe33adbba0 Translated using Weblate (Hebrew)
Currently translated at 25.7% (134 of 520 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/he/
2023-08-02 15:51:50 +00:00
Chen
baa84cf481 Added translation using Weblate (Hebrew) 2023-08-02 15:26:57 +00:00
AquaticLava
ecd828008e added auto shopping functionality. fixed bug when there are no matching recipes 2023-08-01 21:52:59 -06:00
dependabot[bot]
2b8c607b78 Bump cryptography from 41.0.2 to 41.0.3
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.3.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.3)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-02 02:23:22 +00:00
AquaticLava
df684f591a added share functionality. changed random recipe selection to prevent repeating duplicate choices. 2023-08-01 17:02:05 -06:00
dependabot[bot]
cb5b51bde3 Bump django-auth-ldap from 4.2.0 to 4.4.0
Bumps [django-auth-ldap](https://github.com/django-auth-ldap/django-auth-ldap) from 4.2.0 to 4.4.0.
- [Release notes](https://github.com/django-auth-ldap/django-auth-ldap/releases)
- [Changelog](https://github.com/django-auth-ldap/django-auth-ldap/blob/master/docs/changes.rst)
- [Commits](https://github.com/django-auth-ldap/django-auth-ldap/compare/4.2.0...4.4.0)

---
updated-dependencies:
- dependency-name: django-auth-ldap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 00:28:49 +00:00
dependabot[bot]
7f27419215 Bump lxml from 4.9.2 to 4.9.3
Bumps [lxml](https://github.com/lxml/lxml) from 4.9.2 to 4.9.3.
- [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-4.9.2...lxml-4.9.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 00:28:28 +00:00
dependabot[bot]
312cd077d0 Bump eslint from 7.32.0 to 8.46.0 in /vue
Bumps [eslint](https://github.com/eslint/eslint) from 7.32.0 to 8.46.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.32.0...v8.46.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 00:15:02 +00:00
Mára Štěpánek
eac059ca85 Translated using Weblate (Czech)
Currently translated at 100.0% (362 of 362 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/cs/
2023-07-31 14:19:56 +00:00
vabene1111
782dd4cb17 build stuff 2023-07-29 11:24:11 +02:00
vabene1111
f7b60f2c52 version script improvements 2023-07-29 10:55:18 +02:00
vabene1111
ca28e52698 keep git installed 2023-07-29 10:06:51 +02:00
vabene1111
0c2c12d536 improved version script 2023-07-29 08:43:17 +02:00
vabene1111
113c40c243 changed version command order 2023-07-29 08:38:13 +02:00
vabene1111
0688f46d8b new version script 2023-07-29 08:32:10 +02:00
vabene1111
2fdcdba889 base pasth pdf viewer 2023-07-29 07:48:27 +02:00
vabene1111
6a39148e5f fixed try catch and added git to permanent dependency 2023-07-28 15:59:48 +02:00
vabene1111
22dfb40fd5 improved system info even more 2023-07-27 20:48:51 +02:00
vabene1111
2b5a86ce53 improved system page 2023-07-27 20:40:25 +02:00
vabene1111
e77016ea9b playing around 2023-07-27 18:49:39 +02:00
vabene1111
9988a61da7 added version number to system screen 2023-07-27 18:39:21 +02:00
vabene1111
f34fb8eec3 Merge pull request #2563 from smilerz/test_fixes
fixed rating sort order and updated tests
2023-07-26 06:21:54 +02:00
smilerz
7853357065 fix error when filtering on rating in saved filters 2023-07-25 17:48:19 -05:00
smilerz
6f1befc43c fixed rating sort order and updated tests 2023-07-25 11:37:48 -05:00
AquaticLava
530d6b0cb6 changed random recipe to be index based. 2023-07-23 11:51:07 -06:00
vabene1111
c18386b9b5 fixed copied ingredients being linked together 2023-07-22 12:59:31 +02:00
vabene1111
d5ba2e6716 improved multi url import 2023-07-22 11:18:06 +02:00
vabene1111
b30f8c245e added option to set URL on food 2023-07-22 09:12:45 +02:00
vabene1111
74c86f1b6b Merge pull request #2541 from titilambert/patch-1
Expose food description in food form
2023-07-22 08:28:39 +02:00
smilerz
cf9d599536 fixed sort by rating so that unrated are always last 2023-07-20 15:39:35 -05:00
vabene1111
14a67fd6c2 improved spinner rendering 2023-07-20 16:24:25 +02:00
smilerz
19f1225249 make automation parameters case insensitive on search 2023-07-19 16:43:39 -05:00
smilerz
7f33f82b60 fixed defect in NEVER_UNIT automation 2023-07-19 16:42:37 -05:00
smilerz
6880c0a967 filtered automations to tokens present 2023-07-19 16:42:37 -05:00
smilerz
814f4157db create Transpose Words automation 2023-07-19 16:42:36 -05:00
smilerz
0f5e53526e add NEVER_UNIT automation 2023-07-19 16:42:04 -05:00
vabene1111
413da01c5c Merge pull request #2554 from TandoorRecipes/dependabot/npm_and_yarn/vue/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /vue
2023-07-19 09:05:55 +02:00
dependabot[bot]
a73d231bd4 Bump word-wrap from 1.2.3 to 1.2.4 in /vue
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 07:05:07 +00:00
vabene1111
4f2392faac updated pyyaml to be compatible with cython 3 2023-07-19 09:04:01 +02:00
vabene1111
2321dcec6c Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-07-18 16:40:42 +02:00
vabene1111
c2cf7ba758 fixed test 2023-07-18 16:40:38 +02:00
vabene1111
239dd4aa60 Merge pull request #2481 from TandoorRecipes/dependabot/pip/pytube-15.0.0
Bump pytube from 12.1.0 to 15.0.0
2023-07-18 15:35:04 +02:00
vabene1111
a653b2e777 Merge pull request #2525 from TandoorRecipes/dependabot/pip/whitenoise-6.5.0
Bump whitenoise from 6.2.0 to 6.5.0
2023-07-18 15:34:52 +02:00
vabene1111
d8faee7e93 Merge pull request #2545 from TandoorRecipes/dependabot/pip/cryptography-41.0.2
Bump cryptography from 41.0.0 to 41.0.2
2023-07-18 15:32:29 +02:00
vabene1111
69417425e9 Merge branch 'develop' into dependabot/pip/cryptography-41.0.2 2023-07-18 15:32:23 +02:00
vabene1111
e8574a49a7 Merge pull request #2544 from TandoorRecipes/dependabot/npm_and_yarn/vue/semver-5.7.2
Bump semver from 5.7.1 to 5.7.2 in /vue
2023-07-18 15:31:59 +02:00
vabene1111
fe624cd218 Merge pull request #2536 from TandoorRecipes/dependabot/pip/django-4.1.10
Bump django from 4.1.9 to 4.1.10
2023-07-18 15:31:34 +02:00
vabene1111
1f10a66c74 added base unit to unit editor 2023-07-18 13:54:35 +02:00
vabene1111
a8f1cd26cd change guest recipe permission 2023-07-18 10:54:20 +02:00
vabene1111
a497a6b7f5 space api read for all users in space 2023-07-15 13:57:25 +02:00
dependabot[bot]
9dc144f2b5 Bump cryptography from 41.0.0 to 41.0.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.0 to 41.0.2.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.0...41.0.2)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-15 01:23:46 +00:00
Eirik Skarding
7d50f3cf21 Translated using Weblate (Norwegian Bokmål)
Currently translated at 68.9% (344 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nb_NO/
2023-07-12 21:19:57 +00:00
dependabot[bot]
315af4911c Bump semver from 5.7.1 to 5.7.2 in /vue
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 17:57:36 +00:00
vabene1111
35704c69c7 added option to pass recipe to recipe view 2023-07-11 17:50:48 +02:00
vabene1111
a24628c771 fixed userspace tetsts 2023-07-11 17:25:43 +02:00
vabene1111
e9748a160a addded paginated user space endpoint 2023-07-11 17:01:56 +02:00
Thibault Cohen
7bc78e104f Expose food description in food form 2023-07-10 21:26:26 -04:00
Mára Štěpánek
6f0dccfec9 Translated using Weblate (Czech)
Currently translated at 97.5% (487 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2023-07-06 21:19:59 +00:00
Rubens
76d6981dab Translated using Weblate (Catalan)
Currently translated at 85.1% (417 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ca/
2023-07-06 21:19:59 +00:00
dependabot[bot]
5df37c52dd Bump django from 4.1.9 to 4.1.10
Bumps [django](https://github.com/django/django) from 4.1.9 to 4.1.10.
- [Commits](https://github.com/django/django/compare/4.1.9...4.1.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-06 00:10:14 +00:00
vabene1111
c78b7a6928 Merge branch 'develop' 2023-07-05 16:33:51 +02:00
vabene1111
7a2ccc075c improved shopping entry api endpoint performance 2023-07-04 16:49:56 +02:00
vabene1111
237054c23e improved commonly used administrative admin fields 2023-07-03 22:30:27 +02:00
vabene1111
ac1d641bd5 added RO DRF permission and internal_note filters for invite/userspace 2023-07-03 21:59:15 +02:00
vabene1111
3545b6e98a plugin loader improvements 2023-07-03 17:56:05 +02:00
vabene1111
d3a56e00ea allow disabling plugins 2023-07-03 07:41:56 +02:00
vabene1111
e9f8578c25 re added path to plugin check 2023-07-03 07:02:56 +02:00
vabene1111
dccfc436be Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-07-03 05:55:17 +02:00
vabene1111
1e85c8587b fixed plugin error message 2023-07-03 05:55:12 +02:00
vabene1111
b8f92ab054 Merge pull request #2531 from michael-genson/feature/add-source-url-to-recipe-export
Add source URL to recipe export
2023-07-03 05:47:31 +02:00
Mára Štěpánek
766ed31f8e Translated using Weblate (Czech)
Currently translated at 79.7% (398 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2023-07-02 21:19:57 +00:00
Michael Genson
cad78e115d added source url to recipe export 2023-07-02 10:42:41 -05:00
dependabot[bot]
c2def3eb9d Bump typescript from 4.9.5 to 5.1.6 in /vue
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.9.5 to 5.1.6.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-01 00:09:18 +00:00
dependabot[bot]
ad7ebf1cd5 Bump whitenoise from 6.2.0 to 6.5.0
Bumps [whitenoise](https://github.com/evansd/whitenoise) from 6.2.0 to 6.5.0.
- [Changelog](https://github.com/evansd/whitenoise/blob/main/docs/changelog.rst)
- [Commits](https://github.com/evansd/whitenoise/compare/6.2.0...6.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-01 00:03:23 +00:00
vabene1111
b599c4f6a9 added internal notes and improved invite link form 2023-06-30 23:09:22 +02:00
vabene1111
439539f56d show optional fields in generic forms 2023-06-30 23:09:01 +02:00
vabene1111
9da66c9f6c Merge branch 'develop' into beta 2023-06-29 17:26:54 +02:00
vabene1111
237bcb92c9 fixed food editor default properties unit 2023-06-29 17:26:49 +02:00
vabene1111
ce02a23dbb fixed quick ingredient import in recipe editor 2023-06-29 17:13:53 +02:00
vabene1111
8e81512735 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-06-29 17:05:37 +02:00
vabene1111
c69f0394a8 possibly fixed bug with food editor ingredient delete page reload 2023-06-29 17:05:32 +02:00
vabene1111
d7ca9e05de Merge pull request #2521 from gloriousDan/improve-docs
add note to docker-compose files and update postgres tag
2023-06-29 17:04:31 +02:00
vabene1111
64534ff810 fixed navbar color for non logged in users 2023-06-29 17:03:05 +02:00
vabene1111
124211a2f4 Merge branch 'develop' into beta 2023-06-27 16:11:45 +02:00
vabene1111
d0164a6c28 Merge pull request #2522 from gloriousDan/fix-raspi
Fix Raspi build and consolidate with normal build and image
2023-06-27 16:10:39 +02:00
Daniel Schulz
0f898ddf4a unify raspi and normal build again 2023-06-27 00:51:55 +02:00
Daniel Schulz
e903382034 update alpine to v3.18 2023-06-27 00:51:22 +02:00
Daniel Schulz
0d225450da add note to docker-compose files and update postgres tag 2023-06-27 00:33:29 +02:00
vabene1111
71555fee28 Merge branch 'develop' into beta 2023-06-26 21:06:56 +02:00
vabene1111
c077a64484 further improvements 2023-06-26 20:57:51 +02:00
vabene1111
6c16094b42 added initial version of tandoor dark theme 2023-06-26 20:43:50 +02:00
vabene1111
5aa80746f9 Merge branch 'develop' 2023-06-26 20:25:58 +02:00
vabene1111
cc64717818 auto add schema attrs in json importer 2023-06-26 20:22:59 +02:00
vabene1111
6acd892116 fixed broken image would fail default importer 2023-06-26 20:18:36 +02:00
vabene1111
3955408aa4 dont show properties view if no properties are present in DB 2023-06-26 20:03:25 +02:00
vabene1111
3de2468df3 fixed to light nav color in some themes 2023-06-26 19:57:38 +02:00
vabene1111
b1d983fbc3 fixed required field in food 2023-06-26 17:08:45 +02:00
vabene1111
5f443d2593 fixed issue when creating food with properties 2023-06-26 16:48:50 +02:00
vabene1111
436158f596 fixed allow decimals in food property amount 2023-06-26 15:47:44 +02:00
vabene1111
dcc56fc138 added new docs entry to nav 2023-06-26 15:21:05 +02:00
vabene1111
0eef10079b Merge pull request #2517 from 16cdlogan/patch-1
Create Truenas-Portainer
2023-06-26 15:19:03 +02:00
16cdlogan
2b839dfb19 Create Truenas-Portainer
Install Tandoor Recipes on TrueNAS Core and Portainer
2023-06-25 21:32:54 -04:00
sweeney
491b678d6e Translated using Weblate (Greek)
Currently translated at 1.4% (7 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/el/
2023-06-25 14:19:55 +00:00
sweeney
151dce006d Translated using Weblate (Greek)
Currently translated at 54.7% (287 of 524 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/el/
2023-06-25 14:19:55 +00:00
sweeney
d4f538b4aa Translated using Weblate (Greek)
Currently translated at 35.4% (186 of 524 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/el/
2023-06-24 13:32:57 +00:00
sweeney
a727439c57 Added translation using Weblate (Greek) 2023-06-24 13:32:57 +00:00
vabene1111
f779107749 Merge branch 'develop' 2023-06-24 12:17:48 +02:00
vabene1111
4a5c8f41fa fixed open data slug uniqueness check 2023-06-24 12:15:47 +02:00
vabene1111
bf458e22e8 fixed merging deleting food properties 2023-06-24 11:52:42 +02:00
sweeney
9b8088fca2 Translated using Weblate (Greek)
Currently translated at 25.5% (134 of 524 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/el/
2023-06-23 09:19:56 +00:00
Thomas
68435aa335 Translated using Weblate (German)
Currently translated at 99.7% (498 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-06-23 09:19:56 +00:00
vabene1111
afe5465044 added styling options to several components 2023-06-22 15:58:32 +02:00
vabene1111
9decf3cf14 Merge branch 'develop' 2023-06-22 11:30:19 +02:00
vabene1111
b31c3cfd2f updated CI node version 2023-06-22 10:15:45 +02:00
vabene1111
1306c7381c fixed keyword import error 2023-06-22 10:11:00 +02:00
vabene1111
dbd2025e71 updated lock file 2023-06-22 08:55:31 +02:00
AquaticLava
ac17b84a7a updated auto meal plan to start at the current day, and exclude a meal plan if it has no keywords. Added debug buttons to help with testing. 2023-06-21 19:35:48 -06:00
AquaticLava
9756b7b653 regenerated open api file 2023-06-21 19:32:54 -06:00
AquaticLava
ee38d93e3b Created auto meal plan api endpoint. 2023-06-21 19:31:49 -06:00
AquaticLava
ee5c7d0ef4 Merge branch 'TandoorRecipes:develop' into Auto-Planner 2023-06-21 19:16:49 -06:00
vabene1111
f19f4abe0c fixed yarn lock? 2023-06-21 21:41:27 +02:00
vabene1111
7c4a854bfd update lock file
might still be broken because the stupid build does not work
2023-06-21 21:21:15 +02:00
vabene1111
04322b56a4 fixed recipe view component 2023-06-21 21:12:14 +02:00
vabene1111
45b4ac3e9e fixed broken mealplan 2023-06-21 21:06:19 +02:00
vabene1111
362ed9b088 Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-06-21 17:06:06 +02:00
vabene1111
8bf347dd09 moved recipe view to component (currently broken) 2023-06-21 17:05:59 +02:00
John Doe
d449f0c2fc Translated using Weblate (Czech)
Currently translated at 10.8% (54 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2023-06-21 14:20:01 +00:00
Tobias Huppertz
6dab514817 Translated using Weblate (German)
Currently translated at 99.5% (497 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-06-21 14:20:01 +00:00
Tobias Huppertz
8ce0d416c2 Translated using Weblate (German)
Currently translated at 100.0% (490 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2023-06-21 14:20:01 +00:00
vabene1111
dd88641763 improved plugin nav capabilities 2023-06-21 16:07:32 +02:00
vabene1111
fb52f34ef9 Merge branch 'master' into develop 2023-06-21 14:52:39 +02:00
vabene1111
561c2f2d1f Merge branch 'develop' 2023-06-21 14:48:11 +02:00
vabene1111
05a99c9b64 Merge branch 'develop' into beta 2023-06-20 16:49:07 +02:00
vabene1111
4b48c1046e rezeptsuite enhancements 2023-06-20 16:49:00 +02:00
vabene1111
3e0f2fbddc fixed recipesage servings and time 2023-06-20 16:31:40 +02:00
vabene1111
c5eb025186 fixed nextcloud import how to step 2023-06-20 16:22:02 +02:00
vabene1111
32690f04b2 Merge branch 'develop' into beta 2023-06-20 15:46:51 +02:00
vabene1111
23bfc3c3b0 re-added property imports for open data importer 2023-06-20 15:42:25 +02:00
vabene1111
813c7a46f1 added additonal verification of imported images 2023-06-20 13:35:34 +02:00
vabene1111
6b475468fc added some more validation 2023-06-20 13:22:44 +02:00
vabene1111
053ff9506a fixed open data import store error 2023-06-20 13:03:18 +02:00
John Doe
11a699ed47 Translated using Weblate (Czech)
Currently translated at 7.0% (35 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/cs/
2023-06-19 10:16:11 +00:00
vabene1111
b3c6cacdad added better edge case handling to recipe card 2023-06-13 17:33:12 +02:00
vabene1111
29b74557a6 Merge branch 'develop' into beta 2023-06-13 13:24:05 +02:00
vabene1111
4875b158fd fixed open data importer 2023-06-13 13:23:57 +02:00
vabene1111
6bb04dc56d improved property functions 2023-06-12 17:20:00 +02:00
vabene1111
2dc038edc7 fixed url import array in name 2023-06-12 16:18:24 +02:00
vabene1111
8597c3e95d Merge pull request #2489 from TandoorRecipes/dependabot/pip/cryptography-41.0.0
Bump cryptography from 39.0.1 to 41.0.0
2023-06-08 16:30:20 +02:00
vabene1111
5c0094fd43 Merge pull request #2478 from jwr1/develop
Fix bottom navigation not hiding in print mode
2023-06-08 14:43:51 +02:00
vabene1111
23d67a5bd3 compile messages and added norwegian to language option 2023-06-08 14:40:55 +02:00
vabene1111
3a26f09307 Merge pull request #2488 from smilerz/delete_empty
add admin command to delete unattached ingredients and steps
2023-06-08 14:38:34 +02:00
Eirik Skarding
2592e606cc Translated using Weblate (Norwegian Bokmål)
Currently translated at 44.0% (220 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nb_NO/
2023-06-08 00:19:55 +00:00
Eirik Skarding
11f2b95b4d Translated using Weblate (Norwegian Bokmål)
Currently translated at 35.8% (179 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nb_NO/
2023-06-06 12:19:55 +00:00
Eirik Skarding
c171a01b7d Translated using Weblate (Norwegian Bokmål)
Currently translated at 33.8% (169 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nb_NO/
2023-06-03 14:19:56 +00:00
dependabot[bot]
2671519386 Bump cryptography from 39.0.1 to 41.0.0
Bumps [cryptography](https://github.com/pyca/cryptography) from 39.0.1 to 41.0.0.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/39.0.1...41.0.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-02 20:15:48 +00:00
smilerz
19750cf499 add admin command to delete unattached ingredients and steps 2023-06-02 08:58:08 -05:00
vabene1111
711f80b1fb Merge branch 'develop' of https://github.com/TandoorRecipes/recipes into develop 2023-06-01 21:44:48 +02:00
vabene1111
1ffa0f396a fixed fuzzy filter mixing not working without login 2023-06-01 21:44:44 +02:00
dependabot[bot]
991a51d55e Bump pytube from 12.1.0 to 15.0.0
Bumps [pytube](https://github.com/pytube/pytube) from 12.1.0 to 15.0.0.
- [Release notes](https://github.com/pytube/pytube/releases)
- [Commits](https://github.com/pytube/pytube/compare/v12.1.0...v15.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-01 00:57:43 +00:00
sweeney
e052a7869d Translated using Weblate (Greek)
Currently translated at 11.0% (58 of 524 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/el/
2023-05-31 17:19:57 +00:00
Tomasz Klimczak
d57f35e4e8 Translated using Weblate (Polish)
Currently translated at 100.0% (499 of 499 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/pl/
2023-05-31 17:19:57 +00:00
vabene1111
c43e7e0331 Merge branch 'develop' into beta 2023-05-29 17:51:17 +02:00
John Wesley
2cb7030b04 Fix bottom navigation not hiding in print mode 2023-05-29 11:46:07 -04:00
vabene1111
a53f17c1b9 default properties food unit 2023-05-29 17:37:09 +02:00
vabene1111
326549568f added unit conversion editor to food editor 2023-05-29 17:16:22 +02:00
vabene1111
c0577abb89 fixed generic modal form error (merge conflict) 2023-05-29 15:40:25 +02:00
vabene1111
fe7fd7700d Merge branch 'develop' into beta 2023-05-29 12:44:12 +02:00
vabene1111
a65e93a9b3 fixed property helper bug with non food ingredients 2023-05-29 12:43:14 +02:00
Luis Cacho
cadf14c338 Translated using Weblate (Spanish)
Currently translated at 74.3% (357 of 480 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/es/
2023-05-26 16:19:57 +00:00
Luis Cacho
7b49f1f437 Translated using Weblate (Spanish)
Currently translated at 56.1% (275 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/es/
2023-05-26 16:19:57 +00:00
vabene1111
c6ef0e0087 Merge branch 'develop' into beta 2023-05-26 16:11:30 +02:00
vabene1111
2214540a51 Merge branch 'feature/unit-conversion' into develop 2023-05-26 16:11:20 +02:00
vabene1111
256b7b1543 Merge branch 'develop' into feature/unit-conversion
# Conflicts:
#	cookbook/helper/recipe_url_import.py
2023-05-26 16:11:11 +02:00
vabene1111
ebc213395d added property api test 2023-05-26 16:06:49 +02:00
vabene1111
7af581f0ff allow users to choose between food and recipe properties 2023-05-26 15:59:49 +02:00
vabene1111
aeb944b281 dont show properties if no reference amout is given 2023-05-26 15:32:55 +02:00
vabene1111
43105ddd2f fixed onhand test (cache) and fixed shared recipe properties 2023-05-26 10:57:08 +02:00
vabene1111
f2b3cfb8f0 Merge branch 'develop' 2023-05-26 09:56:17 +02:00
vabene1111
3302dacdc3 properties structure imporioved 2023-05-25 16:13:16 +02:00
sardigital
5f07ef04d2 Translated using Weblate (Russian)
Currently translated at 71.6% (344 of 480 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ru/
2023-05-25 06:19:56 +00:00
vabene1111
4c69a0b721 fixed json import missing source url attribute 2023-05-24 20:32:47 +02:00
vabene1111
2a538abf80 test work 2023-05-24 15:59:25 +02:00
vabene1111
3236b65d9e food editor and property view improvements 2023-05-24 13:49:29 +02:00
vabene1111
79cd17a5ba Merge branch 'develop' into feature/unit-conversion
# Conflicts:
#	vue/src/components/Modals/GenericModalForm.vue
2023-05-24 08:53:49 +02:00
vabene1111
06a08dcf6e allow plugins to add navs 2023-05-23 16:05:12 +02:00
vabene1111
de29b44c0d Merge branch 'develop' 2023-05-23 15:32:57 +02:00
vabene1111
dc4ca81270 updated generic modal form to always show errors 2023-05-23 15:32:53 +02:00
vabene1111
dd3dc0a058 Merge branch 'develop' 2023-05-23 14:49:06 +02:00
vabene1111
30c6389382 added force show error parameter to standard toast 2023-05-23 14:18:59 +02:00
vabene1111
45effbbcde Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2023-05-23 13:35:11 +02:00
vabene1111
ffa06ca75e emit additonal hidden event from generic modal form 2023-05-23 13:35:06 +02:00
vabene1111
903a4c93eb Merge pull request #2470 from gloriousDan/enable_gunicorn_debug_log
Enable gunicorn debug log
2023-05-23 13:13:21 +02:00
vabene1111
a8ae6c86e2 Merge pull request #2474 from TandoorRecipes/dependabot/pip/requests-2.31.0
Bump requests from 2.28.2 to 2.31.0
2023-05-23 13:12:25 +02:00
vabene1111
976445c1f0 Merge pull request #2435 from screendriver/noindex
Prevent indexing content by search engines
2023-05-23 13:11:12 +02:00
dependabot[bot]
9cf1141794 Bump requests from 2.28.2 to 2.31.0
Bumps [requests](https://github.com/psf/requests) from 2.28.2 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.2...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-23 06:26:41 +00:00
vabene1111
b095bee229 added FDA key .env (temporarily) and plugin loader catch block 2023-05-22 17:47:13 +02:00
vabene1111
3c3ecc5342 comonent in generic form trial
# Conflicts:
#	vue/src/components/FoodEditor.vue
#	vue/src/components/Modals/GenericModalForm.vue
#	vue/src/utils/models.js
2023-05-21 20:26:00 +02:00
Daniel Schulz
8b50b99977 make gunicorn log level setting available 2023-05-21 14:06:54 +02:00
vabene1111
f369b74c94 fixed plugin bundle path 2023-05-21 12:00:20 +02:00
vabene1111
7b11f276a8 added - before prefix 2023-05-21 11:39:04 +02:00
vabene1111
fe35173ab5 open data tag suffix 2023-05-21 11:05:59 +02:00
vabene1111
4bd879c787 added link creation to open data workflow 2023-05-21 10:57:47 +02:00
vabene1111
fcbc5ed5d0 changed sub repo path 2023-05-21 10:55:07 +02:00
vabene1111
2bdc541183 fixed repo install 2023-05-21 10:52:12 +02:00
vabene1111
4b08eea39d test plugin container release 2023-05-21 10:47:42 +02:00
vabene1111
c777cfe5b9 improved plugin functionality
- added abiulity to extend default api router from plugion
- added dability to pass custom model definition to generic model/api functions
- added ability to pass custom API clients to generic API function
2023-05-20 12:53:14 +02:00
AquaticLava
6c9227faac fixed formatting and minor bug causeing the start of the period to always be the current day. 2023-05-18 11:14:59 -06:00
vabene1111
e860d0aa83 Merge branch 'develop' into feature/unit-conversion 2023-05-18 14:29:39 +02:00
vabene1111
b5681a0255 Merge branch 'develop' 2023-05-18 14:29:31 +02:00
vabene1111
ddd2f96b85 updated translations 2023-05-18 14:29:19 +02:00
vabene1111
b56b778573 Merge pull request #2458 from ambroisie/fix-multiple-files-field
Fix multiple file field
2023-05-18 14:26:41 +02:00
vabene1111
cf7fc906bb Merge pull request #2463 from TandoorRecipes/dependabot/pip/django-4.1.9
Bump django from 4.1.7 to 4.1.9
2023-05-18 14:26:25 +02:00
AquaticLava
693b43af2e Merge remote-tracking branch 'origin/develop' into Auto-Planner
# Conflicts:
#	vue/src/apps/MealPlanView/MealPlanView.vue
2023-05-17 21:22:26 -06:00
vabene1111
0539e1ea15 food edit modal done 2023-05-11 17:13:35 +02:00
dependabot[bot]
c5c37296e9 Bump django from 4.1.7 to 4.1.9
Bumps [django](https://github.com/django/django) from 4.1.7 to 4.1.9.
- [Commits](https://github.com/django/django/compare/4.1.7...4.1.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-09 22:47:01 +00:00
vabene1111
6030fa1d68 property scaling and ui 2023-05-08 12:09:55 +02:00
vabene1111
2a5cba0178 improvements to property calculation 2023-05-07 00:30:32 +02:00
vabene1111
9a77089c6d improved unit conversion and tests 2023-05-06 23:57:45 +02:00
vabene1111
5f79895a97 added migration for existing nutrition information 2023-05-06 23:21:09 +02:00
vabene1111
19f5da77b2 cleanup migrations, remove pint to speed up base conversion and calculate properties on converted ingredients 2023-05-06 22:21:27 +02:00
vabene1111
2cc7278865 extremly innefficent WIP 2023-05-06 20:54:36 +02:00
vabene1111
60f31608b9 added recipe properties 2023-05-06 19:14:25 +02:00
vabene1111
763f71a05c cleanup views 2023-05-06 17:40:39 +02:00
vabene1111
e3921cd6a8 Merge branch 'develop' into feature/unit-conversion 2023-05-06 17:01:06 +02:00
vabene1111
54a5c145cc comonent in generic form trial 2023-05-05 17:04:20 +02:00
vabene1111
86fd0dcab1 made the open data importer its own component 2023-05-05 16:33:30 +02:00
Bruno BELANYI
6b04c92297 Fix multiple file field
Due to [1], the previous solution does not work on recent Django releases.

See [2] for the documented work-around, as applied in this commit.

Closes #2457.

[1]: https://docs.djangoproject.com/en/4.2/releases/4.2.1/
[2]: https://docs.djangoproject.com/en/4.2/topics/http/file-uploads/#uploading-multiple-files
2023-05-04 22:41:19 +01:00
vabene1111
12da77f037 beser response and stuff 2023-05-04 17:12:49 +02:00
vabene1111
071926aada improved importer merging behavior 2023-05-04 15:29:06 +02:00
vabene1111
33d048e623 improve importer 2023-05-04 08:43:36 +02:00
vabene1111
135640dd58 Merge pull request #2454 from smilerz/pytest_fixes
reload food objects to resolve inconsistent behavior
2023-05-03 19:24:46 +02:00
smilerz
d8ddf66921 reload food objects to resolve inconsistent behavior 2023-05-03 10:17:59 -05:00
vabene1111
274fce5236 fixed importer 2023-05-02 16:27:03 +02:00
vabene1111
1046065f46 fixed load bulk 2023-05-01 22:36:39 +02:00
vabene1111
60243ad901 load bulk 2023-05-01 13:39:09 +02:00
vabene1111
d62c49eb2f not yet fully working food import 2023-05-01 13:29:14 +02:00
vabene1111
7e3313f48c added automation to docs TOC 2023-05-01 12:59:55 +02:00
axeron2036
ea4c16cc2a Translated using Weblate (Russian)
Currently translated at 9.6% (48 of 496 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ru/
2023-05-01 07:55:47 +00:00
dependabot[bot]
4fb5ce550e Bump bleach from 5.0.1 to 6.0.0
Bumps [bleach](https://github.com/mozilla/bleach) from 5.0.1 to 6.0.0.
- [Release notes](https://github.com/mozilla/bleach/releases)
- [Changelog](https://github.com/mozilla/bleach/blob/main/CHANGES)
- [Commits](https://github.com/mozilla/bleach/compare/v5.0.1...v6.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 00:58:35 +00:00
vabene1111
1bb6eb7141 import open data content 2023-04-30 22:30:56 +02:00
vabene1111
89e3e85d1e Merge branch 'develop' into feature/unit-conversion
# Conflicts:
#	requirements.txt
2023-04-30 21:51:56 +02:00
vabene1111
dfde340447 basic import working 2023-04-30 21:51:28 +02:00
Oliver Cervera
e7239c7c68 Translated using Weblate (Italian)
Currently translated at 91.4% (448 of 490 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/it/
2023-04-29 07:55:49 +00:00
vabene1111
f7ef2ed4f5 Merge pull request #2437 from gabe565/ci-fix-stable-notify
Fix stable release Discord notification
2023-04-27 13:18:59 +02:00
noxonad
56f6de3510 Translated using Weblate (Romanian)
Currently translated at 100.0% (480 of 480 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ro/
2023-04-27 08:55:57 +00:00
noxonad
cf86af7a23 Translated using Weblate (Romanian)
Currently translated at 100.0% (509 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/ro/
2023-04-27 08:55:57 +00:00
Mike Miller
fe32a743db Translated using Weblate (German)
Currently translated at 100.0% (480 of 480 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-04-27 08:55:57 +00:00
Sebastian Krug
93b750dbf1 Translated using Weblate (German)
Currently translated at 100.0% (480 of 480 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2023-04-27 08:55:57 +00:00
Sebastian Krug
4337f594f6 Translated using Weblate (German)
Currently translated at 100.0% (489 of 489 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2023-04-27 08:55:57 +00:00
Gabe Cook
17fc24fc1b Fix stable release Discord notification 2023-04-26 11:19:38 -05:00
Christian Rackerseder
44771bde71 Prevent indexing content by search engines 2023-04-26 12:19:30 +02:00
vabene1111
6149f693ab Merge branch 'develop' into beta 2023-04-26 07:46:56 +02:00
vabene1111
3ec02db2f6 working food property editor 2023-04-15 11:19:20 +02:00
vabene1111
b275c53e5a first ideas of property editor 2023-04-11 17:27:10 +02:00
vabene1111
7d9fcac0c7 basic food property viewer in recipe view 2023-04-11 16:48:38 +02:00
vabene1111
ec083214ef Merge branch 'develop' into feature/unit-conversion 2023-04-11 14:46:58 +02:00
Ignas Poklad
497321799c Add ability to set maximum missing ingredient count 2023-04-04 18:35:32 +02:00
vabene1111
2a6fc723d0 first food property UI prototype 2023-04-04 13:13:51 +02:00
vabene1111
25c914606e improved converters and helpers 2023-04-02 10:54:57 +02:00
vabene1111
44cb2d9807 improved tests and limited conversion to existing units 2023-04-02 10:05:28 +02:00
vabene1111
f90a66af1e Merge branch 'develop' into feature/unit-conversion 2023-04-02 09:17:38 +02:00
Ignas Poklad
78f1ee175b Add ability to set maximum missing ingredient count 2023-03-30 00:47:21 +02:00
vabene1111
b8cbda10f1 disable space creation for demo user on hosted instance 2023-03-28 23:21:57 +02:00
vabene1111
daef57823f Merge branch 'develop' into beta 2023-03-28 15:43:44 +02:00
vabene1111
7e350b2f90 improved property calculator 2023-03-25 07:59:07 +01:00
vabene1111
6d5592c1be basic food property calculation 2023-03-25 07:46:06 +01:00
vabene1111
9241638686 Merge branch 'develop' into feature/unit-conversion 2023-03-25 06:23:56 +01:00
vabene1111
cb518a0cca many more unit conversions 2023-03-16 17:07:46 +01:00
vabene1111
6efe4ab08d base unit conversions 2023-03-15 17:30:23 +01:00
vabene1111
27c5749b21 Merge branch 'develop' into feature/unit-conversion 2023-03-15 14:57:00 +01:00
vabene1111
5c7b9a93ae Merge branch 'master' into beta 2023-03-14 23:10:44 +01:00
vabene1111
b681364f95 Merge branch 'develop' into beta 2023-02-27 17:26:27 +01:00
vabene1111
b10be8d321 playing around with pint 2023-02-26 11:56:48 +01:00
vabene1111
8a648a5e41 unit conversion cleanups 2023-02-26 09:12:16 +01:00
vabene1111
fcf861f5eb cleaner caching function 2023-02-26 08:49:44 +01:00
vabene1111
1efcf386e2 ingredient related recipes performance 2023-02-26 08:27:20 +01:00
vabene1111
38010117e5 optimized unit conversion queries
using filter breaks prefetch related
2023-02-26 08:22:07 +01:00
vabene1111
c217bf2445 improved recipe detail API performance
by properly using prefetch related
from 600 queries in 280ms to 290 in ~100 ms
2023-02-25 23:34:35 +01:00
vabene1111
671269dca7 Merge branch 'develop' into feature/unit-conversion 2023-02-25 22:15:42 +01:00
vabene1111
40d14eeb9f Merge branch 'develop' into beta 2023-02-24 23:32:45 +01:00
vabene1111
2e013e7b43 add api endpoints and genereic views 2023-02-24 23:17:12 +01:00
vabene1111
ff6c8d5822 added unique constraints 2023-02-24 22:27:35 +01:00
vabene1111
a2b987352f user nutrition types + ingredient nutrtion calculation 2023-02-24 22:12:52 +01:00
vabene1111
5651beffb2 Merge branch 'develop' into feature/unit-conversion
# Conflicts:
#	vue/yarn.lock
2023-02-24 20:41:01 +01:00
vabene1111
46b09f11b6 Merge branch 'develop' into beta 2023-02-24 20:40:41 +01:00
vabene1111
900291dc5f Merge branch 'develop' into beta 2023-02-12 13:30:40 +01:00
vabene1111
e9f9134e2e Merge branch 'develop' into beta 2023-02-11 17:57:48 +01:00
vabene1111
8fe11b12f8 Merge branch 'develop' into beta 2023-01-27 15:52:54 +01:00
vabene1111
a1cfb7ad9f Merge branch 'develop' into beta 2023-01-20 14:58:31 +01:00
vabene1111
2bddf21175 Merge branch 'develop' into beta 2023-01-19 19:14:47 +01:00
vabene1111
29bb391bfe Merge branch 'develop' into feature/unit-conversion 2023-01-15 17:44:46 +01:00
vabene1111
3ced8c7a1e first conversions working 2023-01-09 17:42:53 +01:00
AquaticLava
4a390b5824 removed logging 2023-01-08 12:01:59 -07:00
vabene1111
aa5490adb3 Merge branch 'develop' into beta 2023-01-07 10:32:48 +01:00
AquaticLava
785dc15cd9 Merge branch 'TandoorRecipes:develop' into Auto-Planner 2023-01-05 16:27:27 -07:00
AquaticLava
31f3425354 Menu for auto planner, menu sets auto planner settings. delete method no longer deletes all records for testing the auto planner. 2023-01-05 16:25:42 -07:00
vabene1111
bea089dd5e Merge branch 'develop' into beta 2022-11-09 13:23:48 +01:00
vabene1111
2c7237adaa Merge branch 'develop' into beta 2022-09-21 16:32:53 +02:00
vabene1111
98af1e1e4c Merge branch 'develop' into beta 2022-09-15 19:05:57 +02:00
AquaticLava
689eb426ea method for asynchronous generation of meals. start of menu for auto planner. delete method deletes all records for testing the auto planner. 2022-09-04 16:31:28 -06:00
vabene1111
4a1aee38a3 Merge branch 'develop' into beta 2022-08-05 18:02:48 +02:00
vabene1111
92c21bc382 Merge branch 'develop' into beta 2022-08-05 16:55:00 +02:00
vabene1111
ba748cc5fe Merge branch 'develop' into beta 2022-07-11 23:42:31 +02:00
vabene1111
22b1a9634a Merge branch 'develop' into beta 2022-07-07 19:17:21 +02:00
vabene1111
eeb5395efc Merge branch 'develop' into beta 2022-07-01 11:58:40 +02:00
vabene1111
6ea259596a Merge branch 'develop' into beta 2022-06-26 12:54:24 +02:00
vabene1111
49275a96fe Merge branch 'develop' into beta 2022-06-20 16:53:31 +02:00
309 changed files with 39404 additions and 11841 deletions

View File

@@ -3,7 +3,6 @@ npm-debug.log
Dockerfile*
docker-compose*
.dockerignore
.git
.gitignore
README.md
LICENSE

View File

@@ -1,169 +1,15 @@
# only set this to true when testing/debugging
# when unset: 1 (true) - dont unset this, just for development
DEBUG=0
SQL_DEBUG=0
DEBUG_TOOLBAR=0
# HTTP port to bind to
# TANDOOR_PORT=8080
# hosts the application can run under e.g. recipes.mydomain.com,cooking.mydomain.com,...
ALLOWED_HOSTS=*
# ---------------------------------------------------------------------------
# This template contains only required options.
# Visit the docs to find more https://docs.tandoor.dev/system/configuration/
# ---------------------------------------------------------------------------
# random secret key, use for example `base64 /dev/urandom | head -c50` to generate one
# ---------------------------- REQUIRED -------------------------
SECRET_KEY=
# ---------------------------------------------------------------
# your default timezone See https://timezonedb.com/time-zones for a list of timezones
TIMEZONE=Europe/Berlin
# add only a database password if you want to run with the default postgres, otherwise change settings accordingly
DB_ENGINE=django.db.backends.postgresql
# DB_OPTIONS= {} # e.g. {"sslmode":"require"} to enable ssl
POSTGRES_HOST=db_recipes
POSTGRES_DB=djangodb
POSTGRES_PORT=5432
POSTGRES_USER=djangouser
# ---------------------------- REQUIRED -------------------------
POSTGRES_PASSWORD=
# ---------------------------------------------------------------
POSTGRES_DB=djangodb
# database connection string, when used overrides other database settings.
# format might vary depending on backend
# DATABASE_URL = engine://username:password@host:port/dbname
# the default value for the user preference 'fractions' (enable/disable fraction support)
# default: disabled=0
FRACTION_PREF_DEFAULT=0
# the default value for the user preference 'comments' (enable/disable commenting system)
# default comments enabled=1
COMMENT_PREF_DEFAULT=1
# Users can set a amount of time after which the shopping list is refreshed when they are in viewing mode
# This is the minimum interval users can set. Setting this to low will allow users to refresh very frequently which
# might cause high load on the server. (Technically they can obviously refresh as often as they want with their own scripts)
SHOPPING_MIN_AUTOSYNC_INTERVAL=5
# Default for user setting sticky navbar
# STICKY_NAV_PREF_DEFAULT=1
# If base URL is something other than just / (you are serving a subfolder in your proxy for instance http://recipe_app/recipes/)
# Be sure to not have a trailing slash: e.g. '/recipes' instead of '/recipes/'
# SCRIPT_NAME=/recipes
# If staticfiles are stored at a different location uncomment and change accordingly, MUST END IN /
# this is not required if you are just using a subfolder
# This can either be a relative path from the applications base path or the url of an external host
# STATIC_URL=/static/
# If mediafiles are stored at a different location uncomment and change accordingly, MUST END IN /
# this is not required if you are just using a subfolder
# This can either be a relative path from the applications base path or the url of an external host
# MEDIA_URL=/media/
# Serve mediafiles directly using gunicorn. Basically everyone recommends not doing this. Please use any of the examples
# provided that include an additional nxginx container to handle media file serving.
# If you know what you are doing turn this back on (1) to serve media files using djangos serve() method.
# when unset: 1 (true) - this is temporary until an appropriate amount of time has passed for everyone to migrate
GUNICORN_MEDIA=0
# GUNICORN SERVER RELATED SETTINGS (see https://docs.gunicorn.org/en/stable/design.html#how-many-workers for recommended settings)
# GUNICORN_WORKERS=1
# GUNICORN_THREADS=1
# S3 Media settings: store mediafiles in s3 or any compatible storage backend (e.g. minio)
# as long as S3_ACCESS_KEY is not set S3 features are disabled
# S3_ACCESS_KEY=
# S3_SECRET_ACCESS_KEY=
# S3_BUCKET_NAME=
# S3_REGION_NAME= # default none, set your region might be required
# S3_QUERYSTRING_AUTH=1 # default true, set to 0 to serve media from a public bucket without signed urls
# S3_QUERYSTRING_EXPIRE=3600 # number of seconds querystring are valid for
# S3_ENDPOINT_URL= # when using a custom endpoint like minio
# S3_CUSTOM_DOMAIN= # when using a CDN/proxy to S3 (see https://github.com/TandoorRecipes/recipes/issues/1943)
# Email Settings, see https://docs.djangoproject.com/en/3.2/ref/settings/#email-host
# Required for email confirmation and password reset (automatically activates if host is set)
# EMAIL_HOST=
# EMAIL_PORT=
# EMAIL_HOST_USER=
# EMAIL_HOST_PASSWORD=
# EMAIL_USE_TLS=0
# EMAIL_USE_SSL=0
# email sender address (default 'webmaster@localhost')
# DEFAULT_FROM_EMAIL=
# prefix used for account related emails (default "[Tandoor Recipes] ")
# ACCOUNT_EMAIL_SUBJECT_PREFIX=
# allow authentication via reverse proxy (e.g. authelia), leave off if you dont know what you are doing
# see docs for more information https://docs.tandoor.dev/features/authentication/
# when unset: 0 (false)
REVERSE_PROXY_AUTH=0
# Default settings for spaces, apply per space and can be changed in the admin view
# SPACE_DEFAULT_MAX_RECIPES=0 # 0=unlimited recipes
# SPACE_DEFAULT_MAX_USERS=0 # 0=unlimited users per space
# SPACE_DEFAULT_MAX_FILES=0 # Maximum file storage for space in MB. 0 for unlimited, -1 to disable file upload.
# SPACE_DEFAULT_ALLOW_SHARING=1 # Allow users to share recipes with public links
# allow people to create accounts on your application instance (without an invite link)
# when unset: 0 (false)
# ENABLE_SIGNUP=0
# If signup is enabled you might want to add a captcha to it to prevent spam
# HCAPTCHA_SITEKEY=
# HCAPTCHA_SECRET=
# if signup is enabled you might want to provide urls to data protection policies or terms and conditions
# TERMS_URL=
# PRIVACY_URL=
# IMPRINT_URL=
# enable serving of prometheus metrics under the /metrics path
# ATTENTION: view is not secured (as per the prometheus default way) so make sure to secure it
# trough your web server (or leave it open of you dont care if the stats are exposed)
# ENABLE_METRICS=0
# allows you to setup OAuth providers
# see docs for more information https://docs.tandoor.dev/features/authentication/
# SOCIAL_PROVIDERS = allauth.socialaccount.providers.github, allauth.socialaccount.providers.nextcloud,
# Should a newly created user from a social provider get assigned to the default space and given permission by default ?
# ATTENTION: This feature might be deprecated in favor of a space join and public viewing system in the future
# default 0 (false), when 1 (true) users will be assigned space and group
# SOCIAL_DEFAULT_ACCESS = 1
# if SOCIAL_DEFAULT_ACCESS is used, which group should be added
# SOCIAL_DEFAULT_GROUP=guest
# Django session cookie settings. Can be changed to allow a single django application to authenticate several applications
# when running under the same database
# SESSION_COOKIE_DOMAIN=.example.com
# SESSION_COOKIE_NAME=sessionid # use this only to not interfere with non unified django applications under the same top level domain
# by default SORT_TREE_BY_NAME is disabled this will store all Keywords and Food in the order they are created
# enabling this setting makes saving new keywords and foods very slow, which doesn't matter in most usecases.
# however, when doing large imports of recipes that will create new objects, can increase total run time by 10-15x
# Keywords and Food can be manually sorted by name in Admin
# This value can also be temporarily changed in Admin, it will revert the next time the application is started
# This will be fixed/changed in the future by changing the implementation or finding a better workaround for sorting
# SORT_TREE_BY_NAME=0
# LDAP authentication
# default 0 (false), when 1 (true) list of allowed users will be fetched from LDAP server
#LDAP_AUTH=
#AUTH_LDAP_SERVER_URI=
#AUTH_LDAP_BIND_DN=
#AUTH_LDAP_BIND_PASSWORD=
#AUTH_LDAP_USER_SEARCH_BASE_DN=
#AUTH_LDAP_TLS_CACERTFILE=
#AUTH_LDAP_START_TLS=
# Enables exporting PDF (see export docs)
# Disabled by default, uncomment to enable
# ENABLE_PDF_EXPORT=1
# Recipe exports are cached for a certain time by default, adjust time if needed
# EXPORT_FILE_CACHE_DURATION=600

View File

@@ -0,0 +1,110 @@
name: Build Docker Container with open data plugin installed
on: push
jobs:
build-container:
name: Build ${{ matrix.name }} Container
runs-on: ubuntu-latest
if: github.repository_owner == 'TandoorRecipes'
continue-on-error: ${{ matrix.continue-on-error }}
permissions:
contents: read
packages: write
strategy:
matrix:
include:
# Standard build config
- name: Standard
dockerfile: Dockerfile
platforms: linux/amd64,linux/arm64
suffix: ""
continue-on-error: false
steps:
- uses: actions/checkout@v3
- name: Get version number
id: get_version
run: |
if [[ "$GITHUB_REF" = refs/tags/* ]]; then
echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
elif [[ "$GITHUB_REF" = refs/heads/beta ]]; then
echo VERSION=beta >> $GITHUB_OUTPUT
else
echo VERSION=develop >> $GITHUB_OUTPUT
fi
# clone open data plugin
- name: clone open data plugin repo
uses: actions/checkout@master
with:
repository: TandoorRecipes/open_data_plugin
ref: master
path: ./recipes/plugins/open_data_plugin
# Build Vue frontend
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: yarn
cache-dependency-path: vue/yarn.lock
- name: Install dependencies
working-directory: ./vue
run: yarn install --frozen-lockfile
- name: Build dependencies
working-directory: ./vue
run: yarn build
- name: Setup Open Data Plugin Links
working-directory: ./recipes/plugins/open_data_plugin
run: python setup_repo.py
- name: Build Open Data Frontend
working-directory: ./recipes/plugins/open_data_plugin/vue
run: yarn build
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
if: github.secret_source == 'Actions'
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
if: github.secret_source == 'Actions'
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
vabene1111/recipes
ghcr.io/TandoorRecipes/recipes
flavor: |
latest=false
suffix=${{ matrix.suffix }}
tags: |
type=raw,value=latest,suffix=-open-data-plugin,enable=${{ startsWith(github.ref, 'refs/tags/') }}
type=semver,suffix=-open-data-plugin,pattern={{version}}
type=semver,suffix=-open-data-plugin,pattern={{major}}.{{minor}}
type=semver,suffix=-open-data-plugin,pattern={{major}}
type=ref,suffix=-open-data-plugin,event=branch
- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.dockerfile }}
pull: true
push: ${{ github.secret_source == 'Actions' }}
platforms: ${{ matrix.platforms }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@@ -17,15 +17,9 @@ jobs:
# Standard build config
- name: Standard
dockerfile: Dockerfile
platforms: linux/amd64,linux/arm64
platforms: linux/amd64,linux/arm64,linux/arm/v7
suffix: ""
continue-on-error: false
# Raspi build config
- name: Raspi
dockerfile: Dockerfile-raspi
platforms: linux/arm/v7
suffix: "-raspi"
continue-on-error: true
steps:
- uses: actions/checkout@v3
@@ -40,20 +34,10 @@ jobs:
echo VERSION=develop >> $GITHUB_OUTPUT
fi
# Update Version number
- name: Update version file
uses: DamianReeves/write-file-action@v1.2
with:
path: recipes/version.py
contents: |
VERSION_NUMBER = '${{ steps.get_version.outputs.VERSION }}'
BUILD_REF = '${{ github.sha }}'
write-mode: overwrite
# Build Vue frontend
- uses: actions/setup-node@v3
with:
node-version: '14'
node-version: '18'
cache: yarn
cache-dependency-path: vue/yarn.lock
- name: Install dependencies
@@ -64,17 +48,17 @@ jobs:
run: yarn build
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
if: github.secret_source == 'Actions'
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
if: github.secret_source == 'Actions'
with:
registry: ghcr.io
@@ -82,7 +66,7 @@ jobs:
password: ${{ github.token }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: |
vabene1111/recipes
@@ -97,7 +81,7 @@ jobs:
type=semver,pattern={{major}}
type=ref,event=branch
- name: Build and Push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.dockerfile }}
@@ -115,13 +99,17 @@ jobs:
needs: build-container
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Set tag name
run: |
# Strip "refs/tags/" prefix
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
# Send stable discord notification
- name: Discord notification
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
uses: Ilshidur/action-discord@0.3.2
with:
args: '🚀 Version {{ EVENT_PAYLOAD.release.tag_name }} of tandoor has been released 🥳 Check it out https://github.com/vabene1111/recipes/releases/tag/{{ EVENT_PAYLOAD.release.tag_name }}'
args: '🚀 Version {{ VERSION }} of tandoor has been released 🥳 Check it out https://github.com/vabene1111/recipes/releases/tag/{{ VERSION }}'
notify-beta:
name: Notify Beta

View File

@@ -20,7 +20,7 @@ jobs:
# Build Vue frontend
- uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'
- name: Install Vue dependencies
working-directory: ./vue
run: yarn install

1
.gitignore vendored
View File

@@ -74,6 +74,7 @@ mediafiles/
\.env
staticfiles/
postgresql/
data/
/docker-compose.override.yml

View File

@@ -3,6 +3,7 @@
<words>
<w>pinia</w>
<w>selfhosted</w>
<w>unapplied</w>
</words>
</dictionary>
</component>

View File

@@ -1,5 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Default" />
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>

2
.idea/vcs.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -1,7 +1,7 @@
FROM python:3.10-alpine3.15
FROM python:3.10-alpine3.18
#Install all dependencies.
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography openldap
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev openldap git
#Print all logs without buffering it.
ENV PYTHONUNBUFFERED 1
@@ -15,7 +15,11 @@ WORKDIR /opt/recipes
COPY requirements.txt ./
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev git && \
RUN \
if [ `apk --print-arch` = "armv7" ]; then \
printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \
fi
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev && \
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
python -m venv venv && \
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
@@ -26,5 +30,11 @@ RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-de
#Copy project and execute it.
COPY . ./
# collect information from git repositories
RUN /opt/recipes/venv/bin/python version.py
# delete git repositories to reduce image size
RUN find . -type d -name ".git" | xargs rm -rf
RUN chmod +x boot.sh
ENTRYPOINT ["/opt/recipes/boot.sh"]

View File

@@ -1,33 +0,0 @@
# builds of cryptography for raspberry pi (or better arm v7) fail for some
FROM python:3.9-alpine3.15
#Install all dependencies.
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev py-cryptography openldap gcompat
#Print all logs without buffering it.
ENV PYTHONUNBUFFERED 1
#This port will be used by gunicorn.
EXPOSE 8080
#Create app dir and install requirements.
RUN mkdir /opt/recipes
WORKDIR /opt/recipes
COPY requirements.txt ./
RUN \
if [ `apk --print-arch` = "armv7" ]; then \
printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \
fi
RUN apk add --no-cache --virtual .build-deps gcc musl-dev zlib-dev jpeg-dev libwebp-dev python3-dev git && \
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
python -m venv venv && \
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
venv/bin/pip install wheel==0.37.1 && \
venv/bin/pip install -r requirements.txt --no-cache-dir --no-binary=Pillow && \
apk --purge del .build-deps
#Copy project and execute it.
COPY . ./
RUN chmod +x boot.sh
ENTRYPOINT ["/opt/recipes/boot.sh"]

23
boot.sh
View File

@@ -4,6 +4,7 @@ source venv/bin/activate
TANDOOR_PORT="${TANDOOR_PORT:-8080}"
GUNICORN_WORKERS="${GUNICORN_WORKERS:-3}"
GUNICORN_THREADS="${GUNICORN_THREADS:-2}"
GUNICORN_LOG_LEVEL="${GUNICORN_LOG_LEVEL:-'info'}"
NGINX_CONF_FILE=/opt/recipes/nginx/conf.d/Recipes.conf
display_warning() {
@@ -18,9 +19,14 @@ if [ ! -f "$NGINX_CONF_FILE" ] && [ $GUNICORN_MEDIA -eq 0 ]; then
display_warning "Nginx configuration file could not be found at the default location!\nPath: ${NGINX_CONF_FILE}"
fi
# SECRET_KEY must be set in .env file
# SECRET_KEY (or a valid file at SECRET_KEY_FILE) must be set in .env file
if [ -f "${SECRET_KEY_FILE}" ]; then
export SECRET_KEY=$(cat "$SECRET_KEY_FILE")
fi
if [ -z "${SECRET_KEY}" ]; then
display_warning "The environment variable 'SECRET_KEY' is not set but REQUIRED for running Tandoor!"
display_warning "The environment variable 'SECRET_KEY' (or 'SECRET_KEY_FILE' that points to an existing file) is not set but REQUIRED for running Tandoor!"
fi
@@ -29,11 +35,16 @@ echo "Waiting for database to be ready..."
attempt=0
max_attempts=20
if [ "${DB_ENGINE}" != 'django.db.backends.sqlite3' ]; then
if [ "${DB_ENGINE}" == 'django.db.backends.postgresql' ] || [ "${DATABASE_URL}" == 'postgres'* ]; then
# POSTGRES_PASSWORD (or a valid file at POSTGRES_PASSWORD_FILE) must be set in .env file
if [ -f "${POSTGRES_PASSWORD_FILE}" ]; then
export POSTGRES_PASSWORD=$(cat "$POSTGRES_PASSWORD_FILE")
fi
# POSTGRES_PASSWORD must be set in .env file
if [ -z "${POSTGRES_PASSWORD}" ]; then
display_warning "The environment variable 'POSTGRES_PASSWORD' is not set but REQUIRED for running Tandoor!"
display_warning "The environment variable 'POSTGRES_PASSWORD' (or 'POSTGRES_PASSWORD_FILE' that points to an existing file) is not set but REQUIRED for running Tandoor!"
fi
while pg_isready --host=${POSTGRES_HOST} --port=${POSTGRES_PORT} --user=${POSTGRES_USER} -q; status=$?; attempt=$((attempt+1)); [ $status -ne 0 ] && [ $attempt -le $max_attempts ]; do
@@ -65,4 +76,4 @@ echo "Done"
chmod -R 755 /opt/recipes/mediafiles
exec gunicorn -b :$TANDOOR_PORT --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level INFO recipes.wsgi
exec gunicorn -b :$TANDOOR_PORT --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi

View File

@@ -10,12 +10,13 @@ from treebeard.forms import movenodeform_factory
from cookbook.managers import DICTIONARY
from .models import (BookmarkletImport, Comment, CookLog, Food, FoodInheritField, ImportLog,
Ingredient, InviteLink, Keyword, MealPlan, MealType, NutritionInformation,
from .models import (BookmarkletImport, Comment, CookLog, Food, ImportLog, Ingredient, InviteLink,
Keyword, MealPlan, MealType, NutritionInformation, Property, PropertyType,
Recipe, RecipeBook, RecipeBookEntry, RecipeImport, SearchPreference, ShareLink,
ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage,
Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog,
TelegramBot, Unit, UserFile, UserPreference, ViewLog, Automation, UserSpace)
TelegramBot, Unit, UnitConversion, UserFile, UserPreference, UserSpace,
ViewLog)
class CustomUserAdmin(UserAdmin):
@@ -38,6 +39,8 @@ def delete_space_action(modeladmin, request, queryset):
class SpaceAdmin(admin.ModelAdmin):
list_display = ('name', 'created_by', 'max_recipes', 'max_users', 'max_file_storage_mb', 'allow_sharing')
search_fields = ('name', 'created_by__username')
autocomplete_fields = ('created_by',)
filter_horizontal = ('food_inherit',)
list_filter = ('max_recipes', 'max_users', 'max_file_storage_mb', 'allow_sharing')
date_hierarchy = 'created_at'
actions = [delete_space_action]
@@ -49,16 +52,19 @@ admin.site.register(Space, SpaceAdmin)
class UserSpaceAdmin(admin.ModelAdmin):
list_display = ('user', 'space',)
search_fields = ('user__username', 'space__name',)
filter_horizontal = ('groups',)
autocomplete_fields = ('user', 'space',)
admin.site.register(UserSpace, UserSpaceAdmin)
class UserPreferenceAdmin(admin.ModelAdmin):
list_display = ('name', 'theme', 'nav_color', 'default_page',)
list_display = ('name', 'theme', 'default_page')
search_fields = ('user__username',)
list_filter = ('theme', 'nav_color', 'default_page',)
list_filter = ('theme', 'default_page',)
date_hierarchy = 'created_at'
filter_horizontal = ('plan_share', 'shopping_share',)
@staticmethod
def name(obj):
@@ -102,11 +108,16 @@ class SupermarketCategoryInline(admin.TabularInline):
class SupermarketAdmin(admin.ModelAdmin):
list_display = ('name', 'space',)
inlines = (SupermarketCategoryInline,)
class SupermarketCategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'space',)
admin.site.register(Supermarket, SupermarketAdmin)
admin.site.register(SupermarketCategory)
admin.site.register(SupermarketCategory, SupermarketCategoryAdmin)
class SyncLogAdmin(admin.ModelAdmin):
@@ -150,9 +161,24 @@ class KeywordAdmin(TreeAdmin):
admin.site.register(Keyword, KeywordAdmin)
@admin.action(description='Delete Steps not part of a Recipe.')
def delete_unattached_steps(modeladmin, request, queryset):
with scopes_disabled():
Step.objects.filter(recipe=None).delete()
class StepAdmin(admin.ModelAdmin):
list_display = ('name', 'order',)
search_fields = ('name',)
list_display = ('recipe_and_name', 'order', 'space')
ordering = ('recipe__name', 'name', 'space',)
search_fields = ('name', 'recipe__name')
actions = [delete_unattached_steps]
@staticmethod
@admin.display(description="Name")
def recipe_and_name(obj):
if not obj.recipe_set.exists():
return f"Orphaned Step{'':s if not obj.name else f': {obj.name}'}"
return f"{obj.recipe_set.first().name}: {obj.name}" if obj.name else obj.recipe_set.first().name
admin.site.register(Step, StepAdmin)
@@ -170,8 +196,9 @@ def rebuild_index(modeladmin, request, queryset):
class RecipeAdmin(admin.ModelAdmin):
list_display = ('name', 'internal', 'created_by', 'storage')
list_display = ('name', 'internal', 'created_by', 'storage', 'space')
search_fields = ('name', 'created_by__username')
ordering = ('name', 'created_by__username',)
list_filter = ('internal',)
date_hierarchy = 'created_at'
@@ -179,13 +206,20 @@ class RecipeAdmin(admin.ModelAdmin):
def created_by(obj):
return obj.created_by.get_user_display_name()
if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']:
if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql':
actions = [rebuild_index]
admin.site.register(Recipe, RecipeAdmin)
admin.site.register(Unit)
class UnitAdmin(admin.ModelAdmin):
list_display = ('name', 'space')
ordering = ('name', 'space',)
search_fields = ('name',)
admin.site.register(Unit, UnitAdmin)
# admin.site.register(FoodInheritField)
@@ -201,11 +235,32 @@ class FoodAdmin(TreeAdmin):
admin.site.register(Food, FoodAdmin)
class IngredientAdmin(admin.ModelAdmin):
list_display = ('food', 'amount', 'unit')
class UnitConversionAdmin(admin.ModelAdmin):
list_display = ('base_amount', 'base_unit', 'food', 'converted_amount', 'converted_unit')
search_fields = ('food__name', 'unit__name')
admin.site.register(UnitConversion, UnitConversionAdmin)
@admin.action(description='Delete Ingredients not part of a Recipe.')
def delete_unattached_ingredients(modeladmin, request, queryset):
with scopes_disabled():
Ingredient.objects.filter(step__recipe=None).delete()
class IngredientAdmin(admin.ModelAdmin):
list_display = ('recipe_name', 'amount', 'unit', 'food', 'space')
search_fields = ('food__name', 'unit__name', 'step__recipe__name')
actions = [delete_unattached_ingredients]
@staticmethod
@admin.display(description="Recipe")
def recipe_name(obj):
recipes = obj.step_set.first().recipe_set.all() if obj.step_set.exists() else None
return recipes.first().name if recipes else 'Orphaned Ingredient'
admin.site.register(Ingredient, IngredientAdmin)
@@ -230,7 +285,7 @@ admin.site.register(RecipeImport, RecipeImportAdmin)
class RecipeBookAdmin(admin.ModelAdmin):
list_display = ('name', 'user_name')
list_display = ('name', 'user_name', 'space')
search_fields = ('name', 'created_by__username')
@staticmethod
@@ -249,7 +304,7 @@ admin.site.register(RecipeBookEntry, RecipeBookEntryAdmin)
class MealPlanAdmin(admin.ModelAdmin):
list_display = ('user', 'recipe', 'meal_type', 'date')
list_display = ('user', 'recipe', 'meal_type', 'from_date', 'to_date')
@staticmethod
def user(obj):
@@ -286,6 +341,7 @@ admin.site.register(InviteLink, InviteLinkAdmin)
class CookLogAdmin(admin.ModelAdmin):
list_display = ('recipe', 'created_by', 'created_at', 'rating', 'servings')
search_fields = ('recipe__name', 'space__name',)
admin.site.register(CookLog, CookLogAdmin)
@@ -305,11 +361,11 @@ class ShoppingListEntryAdmin(admin.ModelAdmin):
admin.site.register(ShoppingListEntry, ShoppingListEntryAdmin)
class ShoppingListAdmin(admin.ModelAdmin):
list_display = ('id', 'created_by', 'created_at')
# class ShoppingListAdmin(admin.ModelAdmin):
# list_display = ('id', 'created_by', 'created_at')
admin.site.register(ShoppingList, ShoppingListAdmin)
# admin.site.register(ShoppingList, ShoppingListAdmin)
class ShareLinkAdmin(admin.ModelAdmin):
@@ -319,6 +375,22 @@ class ShareLinkAdmin(admin.ModelAdmin):
admin.site.register(ShareLink, ShareLinkAdmin)
class PropertyTypeAdmin(admin.ModelAdmin):
search_fields = ('space',)
list_display = ('id', 'space', 'name', 'fdc_id')
admin.site.register(PropertyType, PropertyTypeAdmin)
class PropertyAdmin(admin.ModelAdmin):
list_display = ('property_amount', 'property_type')
admin.site.register(Property, PropertyAdmin)
class NutritionInformationAdmin(admin.ModelAdmin):
list_display = ('id',)

View File

@@ -9,8 +9,8 @@ from django_scopes import scopes_disabled
from django_scopes.forms import SafeModelChoiceField, SafeModelMultipleChoiceField
from hcaptcha.fields import hCaptchaField
from .models import (Comment, Food, InviteLink, Keyword, MealPlan, MealType, Recipe, RecipeBook,
RecipeBookEntry, SearchPreference, Space, Storage, Sync, User, UserPreference)
from .models import (Comment, Food, InviteLink, Keyword, Recipe, RecipeBook, RecipeBookEntry,
SearchPreference, Space, Storage, Sync, User, UserPreference)
class SelectWidget(widgets.Select):
@@ -33,64 +33,6 @@ class DateWidget(forms.DateInput):
super().__init__(**kwargs)
class UserPreferenceForm(forms.ModelForm):
prefix = 'preference'
def __init__(self, *args, **kwargs):
space = kwargs.pop('space')
super().__init__(*args, **kwargs)
self.fields['plan_share'].queryset = User.objects.filter(userspace__space=space).all()
class Meta:
model = UserPreference
fields = (
'default_unit', 'use_fractions', 'use_kj', 'theme', 'nav_color',
'sticky_navbar', 'default_page', 'plan_share', 'ingredient_decimals', 'comments', 'left_handed',
)
labels = {
'default_unit': _('Default unit'),
'use_fractions': _('Use fractions'),
'use_kj': _('Use KJ'),
'theme': _('Theme'),
'nav_color': _('Navbar color'),
'sticky_navbar': _('Sticky navbar'),
'default_page': _('Default page'),
'plan_share': _('Plan sharing'),
'ingredient_decimals': _('Ingredient decimal places'),
'shopping_auto_sync': _('Shopping list auto sync period'),
'comments': _('Comments'),
'left_handed': _('Left-handed mode')
}
help_texts = {
'nav_color': _('Color of the top navigation bar. Not all colors work with all themes, just try them out!'),
'default_unit': _('Default Unit to be used when inserting a new ingredient into a recipe.'),
'use_fractions': _(
'Enables support for fractions in ingredient amounts (e.g. convert decimals to fractions automatically)'),
'use_kj': _('Display nutritional energy amounts in joules instead of calories'),
'plan_share': _('Users with whom newly created meal plans should be shared by default.'),
'shopping_share': _('Users with whom to share shopping lists.'),
'ingredient_decimals': _('Number of decimals to round ingredients.'),
'comments': _('If you want to be able to create and see comments underneath recipes.'),
'shopping_auto_sync': _(
'Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but might use a little bit '
'of mobile data. If lower than instance limit it is reset when saving.'
),
'sticky_navbar': _('Makes the navbar stick to the top of the page.'),
'mealplan_autoadd_shopping': _('Automatically add meal plan ingredients to shopping list.'),
'mealplan_autoexclude_onhand': _('Exclude ingredients that are on hand.'),
'left_handed': _('Will optimize the UI for use with your left hand.')
}
widgets = {
'plan_share': MultiSelectWidget,
'shopping_share': MultiSelectWidget,
}
class UserNameForm(forms.ModelForm):
prefix = 'name'
@@ -167,8 +109,26 @@ class ImportExportBase(forms.Form):
))
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleFileField(forms.FileField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", MultipleFileInput())
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
single_file_clean = super().clean
if isinstance(data, (list, tuple)):
result = [single_file_clean(d, initial) for d in data]
else:
result = single_file_clean(data, initial)
return result
class ImportForm(ImportExportBase):
files = forms.FileField(required=True, widget=forms.ClearableFileInput(attrs={'multiple': True}))
files = MultipleFileField(required=True)
duplicates = forms.BooleanField(help_text=_(
'To prevent duplicates recipes with the same name as existing ones are ignored. Check this box to import everything.'),
required=False)
@@ -305,50 +265,6 @@ class ImportRecipeForm(forms.ModelForm):
}
# TODO deprecate
class MealPlanForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
space = kwargs.pop('space')
super().__init__(*args, **kwargs)
self.fields['recipe'].queryset = Recipe.objects.filter(space=space).all()
self.fields['meal_type'].queryset = MealType.objects.filter(space=space).all()
self.fields['shared'].queryset = User.objects.filter(userpreference__space=space).all()
def clean(self):
cleaned_data = super(MealPlanForm, self).clean()
if cleaned_data['title'] == '' and cleaned_data['recipe'] is None:
raise forms.ValidationError(
_('You must provide at least a recipe or a title.')
)
return cleaned_data
class Meta:
model = MealPlan
fields = (
'recipe', 'title', 'meal_type', 'note',
'servings', 'date', 'shared'
)
help_texts = {
'shared': _('You can list default users to share recipes with in the settings.'),
'note': _('You can use markdown to format this field. See the <a href="/docs/markdown/">docs here</a>')
}
widgets = {
'recipe': SelectWidget,
'date': DateWidget,
'shared': MultiSelectWidget
}
field_classes = {
'recipe': SafeModelChoiceField,
'meal_type': SafeModelChoiceField,
'shared': SafeModelMultipleChoiceField,
}
class InviteLinkForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
@@ -489,8 +405,8 @@ class ShoppingPreferenceForm(forms.ModelForm):
help_texts = {
'shopping_share': _('Users will see all items you add to your shopping list. They must add you to see items on their list.'),
'shopping_auto_sync': _(
'Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but might use a little bit '
'of mobile data. If lower than instance limit it is reset when saving.'
'Setting to 0 will disable auto sync. When viewing a shopping list the list is updated every set seconds to sync changes someone else might have made. Useful when shopping with multiple people but might use a little bit '
'of mobile data. If lower than instance limit it is reset when saving.'
),
'mealplan_autoadd_shopping': _('Automatically add meal plan ingredients to shopping list.'),
'mealplan_autoinclude_related': _('When adding a meal plan to the shopping list (manually or automatically), include all related recipes.'),
@@ -534,11 +450,10 @@ class SpacePreferenceForm(forms.ModelForm):
class Meta:
model = Space
fields = ('food_inherit', 'reset_food_inherit', 'show_facet_count', 'use_plural')
fields = ('food_inherit', 'reset_food_inherit', 'use_plural')
help_texts = {
'food_inherit': _('Fields on food that should be inherited by default.'),
'show_facet_count': _('Show recipe counts on search filters'),
'use_plural': _('Use the plural form for units and food inside this space.'),
}

View File

@@ -1,11 +1,10 @@
import datetime
from django.conf import settings
from gettext import gettext as _
from allauth.account.adapter import DefaultAccountAdapter
from django.conf import settings
from django.contrib import messages
from django.core.cache import caches
from gettext import gettext as _
from cookbook.models import InviteLink
@@ -17,10 +16,13 @@ class AllAuthCustomAdapter(DefaultAccountAdapter):
Whether to allow sign-ups.
"""
signup_token = False
if 'signup_token' in request.session and InviteLink.objects.filter(valid_until__gte=datetime.datetime.today(), used_by=None, uuid=request.session['signup_token']).exists():
if 'signup_token' in request.session and InviteLink.objects.filter(
valid_until__gte=datetime.datetime.today(), used_by=None, uuid=request.session['signup_token']).exists():
signup_token = True
if (request.resolver_match.view_name == 'account_signup' or request.resolver_match.view_name == 'socialaccount_signup') and not settings.ENABLE_SIGNUP and not signup_token:
if request.resolver_match.view_name == 'account_signup' and not settings.ENABLE_SIGNUP and not signup_token:
return False
elif request.resolver_match.view_name == 'socialaccount_signup' and len(settings.SOCIAL_PROVIDERS) < 1:
return False
else:
return super(AllAuthCustomAdapter, self).is_open_for_signup(request)
@@ -33,7 +35,7 @@ class AllAuthCustomAdapter(DefaultAccountAdapter):
if c == default:
try:
super(AllAuthCustomAdapter, self).send_mail(template_prefix, email, context)
except Exception: # dont fail signup just because confirmation mail could not be send
except Exception: # dont fail signup just because confirmation mail could not be send
pass
else:
messages.add_message(self.request, messages.ERROR, _('In order to prevent spam, the requested email was not send. Please wait a few minutes and try again.'))

View File

@@ -7,7 +7,7 @@ class Round(Func):
def str2bool(v):
if type(v) == bool or v is None:
if isinstance(v, bool) or v is None:
return v
else:
return v.lower() in ("yes", "true", "1")

View File

@@ -0,0 +1,227 @@
import re
from django.core.cache import caches
from django.db.models.functions import Lower
from cookbook.models import Automation
class AutomationEngine:
request = None
source = None
use_cache = None
food_aliases = None
keyword_aliases = None
unit_aliases = None
never_unit = None
transpose_words = None
regex_replace = {
Automation.DESCRIPTION_REPLACE: None,
Automation.INSTRUCTION_REPLACE: None,
Automation.FOOD_REPLACE: None,
Automation.UNIT_REPLACE: None,
Automation.NAME_REPLACE: None,
}
def __init__(self, request, use_cache=True, source=None):
self.request = request
self.use_cache = use_cache
if not source:
self.source = "default_string_to_avoid_false_regex_match"
else:
self.source = source
def apply_keyword_automation(self, keyword):
keyword = keyword.strip()
if self.use_cache and self.keyword_aliases is None:
self.keyword_aliases = {}
KEYWORD_CACHE_KEY = f'automation_keyword_alias_{self.request.space.pk}'
if c := caches['default'].get(KEYWORD_CACHE_KEY, None):
self.keyword_aliases = c
caches['default'].touch(KEYWORD_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.KEYWORD_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.keyword_aliases[a.param_1.lower()] = a.param_2
caches['default'].set(KEYWORD_CACHE_KEY, self.keyword_aliases, 30)
else:
self.keyword_aliases = {}
if self.keyword_aliases:
try:
keyword = self.keyword_aliases[keyword.lower()]
except KeyError:
pass
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.KEYWORD_ALIAS, param_1__iexact=keyword, disabled=False).order_by('order').first():
return automation.param_2
return keyword
def apply_unit_automation(self, unit):
unit = unit.strip()
if self.use_cache and self.unit_aliases is None:
self.unit_aliases = {}
UNIT_CACHE_KEY = f'automation_unit_alias_{self.request.space.pk}'
if c := caches['default'].get(UNIT_CACHE_KEY, None):
self.unit_aliases = c
caches['default'].touch(UNIT_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.UNIT_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.unit_aliases[a.param_1.lower()] = a.param_2
caches['default'].set(UNIT_CACHE_KEY, self.unit_aliases, 30)
else:
self.unit_aliases = {}
if self.unit_aliases:
try:
unit = self.unit_aliases[unit.lower()]
except KeyError:
pass
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.UNIT_ALIAS, param_1__iexact=unit, disabled=False).order_by('order').first():
return automation.param_2
return self.apply_regex_replace_automation(unit, Automation.UNIT_REPLACE)
def apply_food_automation(self, food):
food = food.strip()
if self.use_cache and self.food_aliases is None:
self.food_aliases = {}
FOOD_CACHE_KEY = f'automation_food_alias_{self.request.space.pk}'
if c := caches['default'].get(FOOD_CACHE_KEY, None):
self.food_aliases = c
caches['default'].touch(FOOD_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.FOOD_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.food_aliases[a.param_1.lower()] = a.param_2
caches['default'].set(FOOD_CACHE_KEY, self.food_aliases, 30)
else:
self.food_aliases = {}
if self.food_aliases:
try:
return self.food_aliases[food.lower()]
except KeyError:
return food
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.FOOD_ALIAS, param_1__iexact=food, disabled=False).order_by('order').first():
return automation.param_2
return self.apply_regex_replace_automation(food, Automation.FOOD_REPLACE)
def apply_never_unit_automation(self, tokens):
"""
Moves a string that should never be treated as a unit to next token and optionally replaced with default unit
e.g. NEVER_UNIT: param1: egg, param2: None would modify ['1', 'egg', 'white'] to ['1', '', 'egg', 'white']
or NEVER_UNIT: param1: egg, param2: pcs would modify ['1', 'egg', 'yolk'] to ['1', 'pcs', 'egg', 'yolk']
:param1 string: string that should never be considered a unit, will be moved to token[2]
:param2 (optional) unit as string: will insert unit string into token[1]
:return: unit as string (possibly changed by automation)
"""
if self.use_cache and self.never_unit is None:
self.never_unit = {}
NEVER_UNIT_CACHE_KEY = f'automation_never_unit_{self.request.space.pk}'
if c := caches['default'].get(NEVER_UNIT_CACHE_KEY, None):
self.never_unit = c
caches['default'].touch(NEVER_UNIT_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.NEVER_UNIT).only('param_1', 'param_2').order_by('order').all():
self.never_unit[a.param_1.lower()] = a.param_2
caches['default'].set(NEVER_UNIT_CACHE_KEY, self.never_unit, 30)
else:
self.never_unit = {}
new_unit = None
alt_unit = self.apply_unit_automation(tokens[1])
never_unit = False
if self.never_unit:
try:
new_unit = self.never_unit[tokens[1].lower()]
never_unit = True
except KeyError:
return tokens
else:
if a := Automation.objects.annotate(param_1_lower=Lower('param_1')).filter(space=self.request.space, type=Automation.NEVER_UNIT, param_1_lower__in=[
tokens[1].lower(), alt_unit.lower()], disabled=False).order_by('order').first():
new_unit = a.param_2
never_unit = True
if never_unit:
tokens.insert(1, new_unit)
return tokens
def apply_transpose_automation(self, string):
"""
If two words (param_1 & param_2) are detected in sequence, swap their position in the ingredient string
:param 1: first word to detect
:param 2: second word to detect
return: new ingredient string
"""
if self.use_cache and self.transpose_words is None:
self.transpose_words = {}
TRANSPOSE_WORDS_CACHE_KEY = f'automation_transpose_words_{self.request.space.pk}'
if c := caches['default'].get(TRANSPOSE_WORDS_CACHE_KEY, None):
self.transpose_words = c
caches['default'].touch(TRANSPOSE_WORDS_CACHE_KEY, 30)
else:
i = 0
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.TRANSPOSE_WORDS).only(
'param_1', 'param_2').order_by('order').all()[:512]:
self.transpose_words[i] = [a.param_1.lower(), a.param_2.lower()]
i += 1
caches['default'].set(TRANSPOSE_WORDS_CACHE_KEY, self.transpose_words, 30)
else:
self.transpose_words = {}
tokens = [x.lower() for x in string.replace(',', ' ').split()]
if self.transpose_words:
for key, value in self.transpose_words.items():
if value[0] in tokens and value[1] in tokens:
string = re.sub(rf"\b({value[0]})\W*({value[1]})\b", r"\2 \1", string, flags=re.IGNORECASE)
else:
for rule in Automation.objects.filter(space=self.request.space, type=Automation.TRANSPOSE_WORDS, disabled=False) \
.annotate(param_1_lower=Lower('param_1'), param_2_lower=Lower('param_2')) \
.filter(param_1_lower__in=tokens, param_2_lower__in=tokens).order_by('order')[:512]:
if rule.param_1 in tokens and rule.param_2 in tokens:
string = re.sub(rf"\b({rule.param_1})\W*({rule.param_2})\b", r"\2 \1", string, flags=re.IGNORECASE)
return string
def apply_regex_replace_automation(self, string, automation_type):
# TODO add warning - maybe on SPACE page? when a max of 512 automations of a specific type is exceeded (ALIAS types excluded?)
"""
Replaces strings in a recipe field that are from a matched source
field_type are Automation.type that apply regex replacements
Automation.DESCRIPTION_REPLACE
Automation.INSTRUCTION_REPLACE
Automation.FOOD_REPLACE
Automation.UNIT_REPLACE
Automation.NAME_REPLACE
regex replacment utilized the following fields from the Automation model
:param 1: source that should apply the automation in regex format ('.*' for all)
:param 2: regex pattern to match ()
:param 3: replacement string (leave blank to delete)
return: new string
"""
if self.use_cache and self.regex_replace[automation_type] is None:
self.regex_replace[automation_type] = {}
REGEX_REPLACE_CACHE_KEY = f'automation_regex_replace_{self.request.space.pk}'
if c := caches['default'].get(REGEX_REPLACE_CACHE_KEY, None):
self.regex_replace[automation_type] = c[automation_type]
caches['default'].touch(REGEX_REPLACE_CACHE_KEY, 30)
else:
i = 0
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=automation_type).only(
'param_1', 'param_2', 'param_3').order_by('order').all()[:512]:
self.regex_replace[automation_type][i] = [a.param_1, a.param_2, a.param_3]
i += 1
caches['default'].set(REGEX_REPLACE_CACHE_KEY, self.regex_replace, 30)
else:
self.regex_replace[automation_type] = {}
if self.regex_replace[automation_type]:
for rule in self.regex_replace[automation_type].values():
if re.match(rule[0], (self.source)[:512]):
string = re.sub(rule[1], rule[2], string, flags=re.IGNORECASE)
else:
for rule in Automation.objects.filter(space=self.request.space, disabled=False, type=automation_type).only(
'param_1', 'param_2', 'param_3').order_by('order').all()[:512]:
if re.match(rule.param_1, (self.source)[:512]):
string = re.sub(rule.param_2, rule.param_3, string, flags=re.IGNORECASE)
return string

View File

@@ -0,0 +1,11 @@
class CacheHelper:
space = None
BASE_UNITS_CACHE_KEY = None
PROPERTY_TYPE_CACHE_KEY = None
def __init__(self, space):
self.space = space
self.BASE_UNITS_CACHE_KEY = f'SPACE_{space.id}_BASE_UNITS'
self.PROPERTY_TYPE_CACHE_KEY = f'SPACE_{space.id}_PROPERTY_TYPES'

View File

@@ -0,0 +1,19 @@
import json
def get_all_nutrient_types():
f = open('') # <--- download the foundation food or any other dataset and retrieve all nutrition ID's from it https://fdc.nal.usda.gov/download-datasets.html
json_data = json.loads(f.read())
nutrients = {}
for food in json_data['FoundationFoods']:
for entry in food['foodNutrients']:
nutrients[entry['nutrient']['id']] = {'name': entry['nutrient']['name'], 'unit': entry['nutrient']['unitName']}
nutrient_ids = list(nutrients.keys())
nutrient_ids.sort()
for nid in nutrient_ids:
print('{', f'value: {nid}, text: "{nutrients[nid]["name"]} [{nutrients[nid]["unit"]}] ({nid})"', '},')
get_all_nutrient_types()

View File

@@ -1,8 +1,7 @@
import os
import sys
from io import BytesIO
from PIL import Image
from io import BytesIO
def rescale_image_jpeg(image_object, base_width=1020):
@@ -11,7 +10,7 @@ def rescale_image_jpeg(image_object, base_width=1020):
width_percent = (base_width / float(img.size[0]))
height = int((float(img.size[1]) * float(width_percent)))
img = img.resize((base_width, height), Image.ANTIALIAS)
img = img.resize((base_width, height), Image.LANCZOS)
img_bytes = BytesIO()
img.save(img_bytes, 'JPEG', quality=90, optimize=True, icc_profile=icc_profile)
@@ -22,7 +21,7 @@ def rescale_image_png(image_object, base_width=1020):
image_object = Image.open(image_object)
wpercent = (base_width / float(image_object.size[0]))
hsize = int((float(image_object.size[1]) * float(wpercent)))
img = image_object.resize((base_width, hsize), Image.ANTIALIAS)
img = image_object.resize((base_width, hsize), Image.LANCZOS)
im_io = BytesIO()
img.save(im_io, 'PNG', quality=90)
@@ -40,7 +39,12 @@ def get_filetype(name):
# TODO also add env variable to define which images sizes should be compressed
# filetype argument can not be optional, otherwise this function will treat all images as if they were a jpeg
# Because it's no longer optional, no reason to return it
def handle_image(request, image_object, filetype):
def handle_image(request, image_object, filetype):
try:
Image.open(image_object).verify()
except Exception:
return None
if (image_object.size / 1000) > 500: # if larger than 500 kb compress
if filetype == '.jpeg' or filetype == '.jpg':
return rescale_image_jpeg(image_object)

View File

@@ -2,18 +2,16 @@ import re
import string
import unicodedata
from django.core.cache import caches
from cookbook.models import Unit, Food, Automation, Ingredient
from cookbook.helper.automation_helper import AutomationEngine
from cookbook.models import Food, Ingredient, Unit
class IngredientParser:
request = None
ignore_rules = False
food_aliases = {}
unit_aliases = {}
automation = None
def __init__(self, request, cache_mode, ignore_automations=False):
def __init__(self, request, cache_mode=True, ignore_automations=False):
"""
Initialize ingredient parser
:param request: request context (to control caching, rule ownership, etc.)
@@ -22,65 +20,8 @@ class IngredientParser:
"""
self.request = request
self.ignore_rules = ignore_automations
if cache_mode:
FOOD_CACHE_KEY = f'automation_food_alias_{self.request.space.pk}'
if c := caches['default'].get(FOOD_CACHE_KEY, None):
self.food_aliases = c
caches['default'].touch(FOOD_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.FOOD_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.food_aliases[a.param_1] = a.param_2
caches['default'].set(FOOD_CACHE_KEY, self.food_aliases, 30)
UNIT_CACHE_KEY = f'automation_unit_alias_{self.request.space.pk}'
if c := caches['default'].get(UNIT_CACHE_KEY, None):
self.unit_aliases = c
caches['default'].touch(UNIT_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.UNIT_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.unit_aliases[a.param_1] = a.param_2
caches['default'].set(UNIT_CACHE_KEY, self.unit_aliases, 30)
else:
self.food_aliases = {}
self.unit_aliases = {}
def apply_food_automation(self, food):
"""
Apply food alias automations to passed food
:param food: unit as string
:return: food as string (possibly changed by automation)
"""
if self.ignore_rules:
return food
else:
if self.food_aliases:
try:
return self.food_aliases[food]
except KeyError:
return food
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.FOOD_ALIAS, param_1=food, disabled=False).order_by('order').first():
return automation.param_2
return food
def apply_unit_automation(self, unit):
"""
Apply unit alias automations to passed unit
:param unit: unit as string
:return: unit as string (possibly changed by automation)
"""
if self.ignore_rules:
return unit
else:
if self.unit_aliases:
try:
return self.unit_aliases[unit]
except KeyError:
return unit
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.UNIT_ALIAS, param_1=unit, disabled=False).order_by('order').first():
return automation.param_2
return unit
if not self.ignore_rules:
self.automation = AutomationEngine(self.request, use_cache=cache_mode)
def get_unit(self, unit):
"""
@@ -91,7 +32,10 @@ class IngredientParser:
if not unit:
return None
if len(unit) > 0:
u, created = Unit.objects.get_or_create(name=self.apply_unit_automation(unit), space=self.request.space)
if self.ignore_rules:
u, created = Unit.objects.get_or_create(name=unit.strip(), space=self.request.space)
else:
u, created = Unit.objects.get_or_create(name=self.automation.apply_unit_automation(unit), space=self.request.space)
return u
return None
@@ -104,7 +48,10 @@ class IngredientParser:
if not food:
return None
if len(food) > 0:
f, created = Food.objects.get_or_create(name=self.apply_food_automation(food), space=self.request.space)
if self.ignore_rules:
f, created = Food.objects.get_or_create(name=food.strip(), space=self.request.space)
else:
f, created = Food.objects.get_or_create(name=self.automation.apply_food_automation(food), space=self.request.space)
return f
return None
@@ -133,10 +80,10 @@ class IngredientParser:
end = 0
while (end < len(x) and (x[end] in string.digits
or (
(x[end] == '.' or x[end] == ',' or x[end] == '/')
and end + 1 < len(x)
and x[end + 1] in string.digits
))):
(x[end] == '.' or x[end] == ',' or x[end] == '/')
and end + 1 < len(x)
and x[end + 1] in string.digits
))):
end += 1
if end > 0:
if "/" in x[:end]:
@@ -160,7 +107,8 @@ class IngredientParser:
if unit is not None and unit.strip() == '':
unit = None
if unit is not None and (unit.startswith('(') or unit.startswith('-')): # i dont know any unit that starts with ( or - so its likely an alternative like 1L (500ml) Water or 2-3
if unit is not None and (unit.startswith('(') or unit.startswith(
'-')): # i dont know any unit that starts with ( or - so its likely an alternative like 1L (500ml) Water or 2-3
unit = None
note = x
return amount, unit, note
@@ -221,6 +169,9 @@ class IngredientParser:
if len(ingredient) == 0:
raise ValueError('string to parse cannot be empty')
if len(ingredient) > 512:
raise ValueError('cannot parse ingredients with more than 512 characters')
# some people/languages put amount and unit at the end of the ingredient string
# if something like this is detected move it to the beginning so the parser can handle it
if len(ingredient) < 1000 and re.search(r'^([^\W\d_])+(.)*[1-9](\d)*\s*([^\W\d_])+', ingredient):
@@ -230,8 +181,8 @@ class IngredientParser:
# if the string contains parenthesis early on remove it and place it at the end
# because its likely some kind of note
if re.match('(.){1,6}\s\((.[^\(\)])+\)\s', ingredient):
match = re.search('\((.[^\(])+\)', ingredient)
if re.match('(.){1,6}\\s\\((.[^\\(\\)])+\\)\\s', ingredient):
match = re.search('\\((.[^\\(])+\\)', ingredient)
ingredient = ingredient[:match.start()] + ingredient[match.end():] + ' ' + ingredient[match.start():match.end()]
# leading spaces before commas result in extra tokens, clean them out
@@ -239,12 +190,15 @@ class IngredientParser:
# handle "(from) - (to)" amounts by using the minimum amount and adding the range to the description
# "10.5 - 200 g XYZ" => "100 g XYZ (10.5 - 200)"
ingredient = re.sub("^(\d+|\d+[\\.,]\d+) - (\d+|\d+[\\.,]\d+) (.*)", "\\1 \\3 (\\1 - \\2)", ingredient)
ingredient = re.sub("^(\\d+|\\d+[\\.,]\\d+) - (\\d+|\\d+[\\.,]\\d+) (.*)", "\\1 \\3 (\\1 - \\2)", ingredient)
# if amount and unit are connected add space in between
if re.match('([0-9])+([A-z])+\s', ingredient):
if re.match('([0-9])+([A-z])+\\s', ingredient):
ingredient = re.sub(r'(?<=([a-z])|\d)(?=(?(1)\d|[a-z]))', ' ', ingredient)
if not self.ignore_rules:
ingredient = self.automation.apply_transpose_automation(ingredient)
tokens = ingredient.split() # split at each space into tokens
if len(tokens) == 1:
# there only is one argument, that must be the food
@@ -257,6 +211,8 @@ class IngredientParser:
# three arguments if it already has a unit there can't be
# a fraction for the amount
if len(tokens) > 2:
if not self.ignore_rules:
tokens = self.automation.apply_never_unit_automation(tokens)
try:
if unit is not None:
# a unit is already found, no need to try the second argument for a fraction
@@ -303,10 +259,11 @@ class IngredientParser:
if unit_note not in note:
note += ' ' + unit_note
if unit:
unit = self.apply_unit_automation(unit.strip())
if unit and not self.ignore_rules:
unit = self.automation.apply_unit_automation(unit)
food = self.apply_food_automation(food.strip())
if food and not self.ignore_rules:
food = self.automation.apply_food_automation(food)
if len(food) > Food._meta.get_field('name').max_length: # test if food name is to long
# try splitting it at a space and taking only the first arg
if len(food.split()) > 1 and len(food.split()[0]) < Food._meta.get_field('name').max_length:

View File

@@ -0,0 +1,210 @@
from cookbook.models import (Food, FoodProperty, Property, PropertyType, Supermarket,
SupermarketCategory, SupermarketCategoryRelation, Unit, UnitConversion)
class OpenDataImporter:
request = None
data = {}
slug_id_cache = {}
update_existing = False
use_metric = True
def __init__(self, request, data, update_existing=False, use_metric=True):
self.request = request
self.data = data
self.update_existing = update_existing
self.use_metric = use_metric
def _update_slug_cache(self, object_class, datatype):
self.slug_id_cache[datatype] = dict(object_class.objects.filter(space=self.request.space, open_data_slug__isnull=False).values_list('open_data_slug', 'id', ))
def import_units(self):
datatype = 'unit'
insert_list = []
for u in list(self.data[datatype].keys()):
insert_list.append(Unit(
name=self.data[datatype][u]['name'],
plural_name=self.data[datatype][u]['plural_name'],
base_unit=self.data[datatype][u]['base_unit'] if self.data[datatype][u]['base_unit'] != '' else None,
open_data_slug=u,
space=self.request.space
))
if self.update_existing:
return Unit.objects.bulk_create(insert_list, update_conflicts=True, update_fields=(
'name', 'plural_name', 'base_unit', 'open_data_slug'), unique_fields=('space', 'name',))
else:
return Unit.objects.bulk_create(insert_list, update_conflicts=True, update_fields=('open_data_slug',), unique_fields=('space', 'name',))
def import_category(self):
datatype = 'category'
insert_list = []
for k in list(self.data[datatype].keys()):
insert_list.append(SupermarketCategory(
name=self.data[datatype][k]['name'],
open_data_slug=k,
space=self.request.space
))
return SupermarketCategory.objects.bulk_create(insert_list, update_conflicts=True, update_fields=('open_data_slug',), unique_fields=('space', 'name',))
def import_property(self):
datatype = 'property'
insert_list = []
for k in list(self.data[datatype].keys()):
insert_list.append(PropertyType(
name=self.data[datatype][k]['name'],
unit=self.data[datatype][k]['unit'],
open_data_slug=k,
space=self.request.space
))
return PropertyType.objects.bulk_create(insert_list, update_conflicts=True, update_fields=('open_data_slug',), unique_fields=('space', 'name',))
def import_supermarket(self):
datatype = 'store'
self._update_slug_cache(SupermarketCategory, 'category')
insert_list = []
for k in list(self.data[datatype].keys()):
insert_list.append(Supermarket(
name=self.data[datatype][k]['name'],
open_data_slug=k,
space=self.request.space
))
# always add open data slug if matching supermarket is found, otherwise relation might fail
supermarkets = Supermarket.objects.bulk_create(insert_list, unique_fields=('space', 'name',), update_conflicts=True, update_fields=('open_data_slug',))
self._update_slug_cache(Supermarket, 'store')
insert_list = []
for k in list(self.data[datatype].keys()):
relations = []
order = 0
for c in self.data[datatype][k]['categories']:
relations.append(
SupermarketCategoryRelation(
supermarket_id=self.slug_id_cache[datatype][k],
category_id=self.slug_id_cache['category'][c],
order=order,
)
)
order += 1
SupermarketCategoryRelation.objects.bulk_create(relations, ignore_conflicts=True, unique_fields=('supermarket', 'category',))
return supermarkets
def import_food(self):
identifier_list = []
datatype = 'food'
for k in list(self.data[datatype].keys()):
identifier_list.append(self.data[datatype][k]['name'])
identifier_list.append(self.data[datatype][k]['plural_name'])
existing_objects_flat = []
existing_objects = {}
for f in Food.objects.filter(space=self.request.space).filter(name__in=identifier_list).values_list('id', 'name', 'plural_name'):
existing_objects_flat.append(f[1])
existing_objects_flat.append(f[2])
existing_objects[f[1]] = f
existing_objects[f[2]] = f
self._update_slug_cache(Unit, 'unit')
self._update_slug_cache(PropertyType, 'property')
insert_list = []
insert_list_flat = []
update_list = []
update_field_list = []
for k in list(self.data[datatype].keys()):
if not (self.data[datatype][k]['name'] in existing_objects_flat or self.data[datatype][k]['plural_name'] in existing_objects_flat):
if not (self.data[datatype][k]['name'] in insert_list_flat or self.data[datatype][k]['plural_name'] in insert_list_flat):
insert_list.append({'data': {
'name': self.data[datatype][k]['name'],
'plural_name': self.data[datatype][k]['plural_name'] if self.data[datatype][k]['plural_name'] != '' else None,
'supermarket_category_id': self.slug_id_cache['category'][self.data[datatype][k]['store_category']],
'fdc_id': self.data[datatype][k]['fdc_id'] if self.data[datatype][k]['fdc_id'] != '' else None,
'open_data_slug': k,
'space': self.request.space.id,
}})
# build a fake second flat array to prevent duplicate foods from being inserted.
# trying to insert a duplicate would throw a db error :(
insert_list_flat.append(self.data[datatype][k]['name'])
insert_list_flat.append(self.data[datatype][k]['plural_name'])
else:
if self.data[datatype][k]['name'] in existing_objects:
existing_food_id = existing_objects[self.data[datatype][k]['name']][0]
else:
existing_food_id = existing_objects[self.data[datatype][k]['plural_name']][0]
if self.update_existing:
update_field_list = ['name', 'plural_name', 'preferred_unit_id', 'preferred_shopping_unit_id', 'supermarket_category_id', 'fdc_id', 'open_data_slug', ]
update_list.append(Food(
id=existing_food_id,
name=self.data[datatype][k]['name'],
plural_name=self.data[datatype][k]['plural_name'] if self.data[datatype][k]['plural_name'] != '' else None,
supermarket_category_id=self.slug_id_cache['category'][self.data[datatype][k]['store_category']],
fdc_id=self.data[datatype][k]['fdc_id'] if self.data[datatype][k]['fdc_id'] != '' else None,
open_data_slug=k,
))
else:
update_field_list = ['open_data_slug', ]
update_list.append(Food(id=existing_food_id, open_data_slug=k, ))
Food.load_bulk(insert_list, None)
if len(update_list) > 0:
Food.objects.bulk_update(update_list, update_field_list)
self._update_slug_cache(Food, 'food')
food_property_list = []
# alias_list = []
for k in list(self.data[datatype].keys()):
for fp in self.data[datatype][k]['properties']['type_values']:
# try catch here because somettimes key "k" is not set for he food cache
try:
food_property_list.append(Property(
property_type_id=self.slug_id_cache['property'][fp['property_type']],
property_amount=fp['property_value'],
import_food_id=self.slug_id_cache['food'][k],
space=self.request.space,
))
except KeyError:
print(str(k) + ' is not in self.slug_id_cache["food"]')
Property.objects.bulk_create(food_property_list, ignore_conflicts=True, unique_fields=('space', 'import_food_id', 'property_type',))
property_food_relation_list = []
for p in Property.objects.filter(space=self.request.space, import_food_id__isnull=False).values_list('import_food_id', 'id', ):
property_food_relation_list.append(Food.properties.through(food_id=p[0], property_id=p[1]))
FoodProperty.objects.bulk_create(property_food_relation_list, ignore_conflicts=True, unique_fields=('food_id', 'property_id',))
return insert_list + update_list
def import_conversion(self):
datatype = 'conversion'
insert_list = []
for k in list(self.data[datatype].keys()):
# try catch here because sometimes key "k" is not set for he food cache
try:
insert_list.append(UnitConversion(
base_amount=self.data[datatype][k]['base_amount'],
base_unit_id=self.slug_id_cache['unit'][self.data[datatype][k]['base_unit']],
converted_amount=self.data[datatype][k]['converted_amount'],
converted_unit_id=self.slug_id_cache['unit'][self.data[datatype][k]['converted_unit']],
food_id=self.slug_id_cache['food'][self.data[datatype][k]['food']],
open_data_slug=k,
space=self.request.space,
created_by=self.request.user,
))
except KeyError:
print(str(k) + ' is not in self.slug_id_cache["food"]')
return UnitConversion.objects.bulk_create(insert_list, ignore_conflicts=True, unique_fields=('space', 'base_unit', 'converted_unit', 'food', 'open_data_slug'))

View File

@@ -4,16 +4,16 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import user_passes_test
from django.core.cache import cache
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.http import HttpResponseRedirect
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext as _
from oauth2_provider.contrib.rest_framework import TokenHasScope, TokenHasReadWriteScope
from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope
from oauth2_provider.models import AccessToken
from rest_framework import permissions
from rest_framework.permissions import SAFE_METHODS
from cookbook.models import ShareLink, Recipe, UserSpace
from cookbook.models import Recipe, ShareLink, UserSpace
def get_allowed_groups(groups_required):
@@ -255,9 +255,6 @@ class CustomIsShared(permissions.BasePermission):
return request.user.is_authenticated
def has_object_permission(self, request, view, obj):
# # temporary hack to make old shopping list work with new shopping list
# if obj.__class__.__name__ in ['ShoppingList', 'ShoppingListEntry']:
# return is_object_shared(request.user, obj) or obj.created_by in list(request.user.get_shopping_share())
return is_object_shared(request.user, obj)
@@ -322,7 +319,8 @@ class CustomRecipePermission(permissions.BasePermission):
def has_permission(self, request, view): # user is either at least a guest or a share link is given and the request is safe
share = request.query_params.get('share', None)
return has_group_permission(request.user, ['guest']) or (share and request.method in SAFE_METHODS and 'pk' in view.kwargs)
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS) or has_group_permission(
request.user, ['user'])) or (share and request.method in SAFE_METHODS and 'pk' in view.kwargs)
def has_object_permission(self, request, view, obj):
share = request.query_params.get('share', None)
@@ -332,7 +330,8 @@ class CustomRecipePermission(permissions.BasePermission):
if obj.private:
return ((obj.created_by == request.user) or (request.user in obj.shared.all())) and obj.space == request.space
else:
return has_group_permission(request.user, ['guest']) and obj.space == request.space
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS)
or has_group_permission(request.user, ['user'])) and obj.space == request.space
class CustomUserPermission(permissions.BasePermission):
@@ -361,7 +360,7 @@ class CustomTokenHasScope(TokenHasScope):
"""
def has_permission(self, request, view):
if type(request.auth) == AccessToken:
if isinstance(request.auth, AccessToken):
return super().has_permission(request, view)
else:
return request.user.is_authenticated
@@ -375,7 +374,7 @@ class CustomTokenHasReadWriteScope(TokenHasReadWriteScope):
"""
def has_permission(self, request, view):
if type(request.auth) == AccessToken:
if isinstance(request.auth, AccessToken):
return super().has_permission(request, view)
else:
return True
@@ -434,3 +433,10 @@ def switch_user_active_space(user, space):
return us
except ObjectDoesNotExist:
return None
class IsReadOnlyDRF(permissions.BasePermission):
message = 'You cannot interact with this object as it is not owned by you!'
def has_permission(self, request, view):
return request.method in SAFE_METHODS

View File

@@ -0,0 +1,74 @@
from django.core.cache import caches
from cookbook.helper.cache_helper import CacheHelper
from cookbook.helper.unit_conversion_helper import UnitConversionHelper
from cookbook.models import PropertyType
class FoodPropertyHelper:
space = None
def __init__(self, space):
"""
Helper to perform food property calculations
:param space: space to limit scope to
"""
self.space = space
def calculate_recipe_properties(self, recipe):
"""
Calculate all food properties for a given recipe.
:param recipe: recipe to calculate properties for
:return: dict of with property keys and total/food values for each property available
"""
ingredients = []
computed_properties = {}
for s in recipe.steps.all():
ingredients += s.ingredients.all()
property_types = caches['default'].get(CacheHelper(self.space).PROPERTY_TYPE_CACHE_KEY, None)
if not property_types:
property_types = PropertyType.objects.filter(space=self.space).all()
# cache is cleared on property type save signal so long duration is fine
caches['default'].set(CacheHelper(self.space).PROPERTY_TYPE_CACHE_KEY, property_types, 60 * 60)
for fpt in property_types:
computed_properties[fpt.id] = {'id': fpt.id, 'name': fpt.name, 'description': fpt.description,
'unit': fpt.unit, 'order': fpt.order, 'food_values': {}, 'total_value': 0, 'missing_value': False}
uch = UnitConversionHelper(self.space)
for i in ingredients:
if i.food is not None:
conversions = uch.get_conversions(i)
for pt in property_types:
found_property = False
if i.food.properties_food_amount == 0 or i.food.properties_food_unit is None:
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': 0}
computed_properties[pt.id]['missing_value'] = i.food.properties_food_unit is None
else:
for p in i.food.properties.all():
if p.property_type == pt:
for c in conversions:
if c.unit == i.food.properties_food_unit:
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:
computed_properties[pt.id]['missing_value'] = True
computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': 0}
return computed_properties
# small dict helper to add to existing key or create new, probably a better way of doing this
# TODO move to central helper ?
@staticmethod
def add_or_create(d, key, value, food):
if key in d:
d[key]['value'] += value
else:
d[key] = {'id': food.id, 'food': food.name, 'value': value}
return d

View File

@@ -1,191 +0,0 @@
# import json
# import re
# from json import JSONDecodeError
# from urllib.parse import unquote
# from bs4 import BeautifulSoup
# from bs4.element import Tag
# from recipe_scrapers import scrape_html, scrape_me
# from recipe_scrapers._exceptions import NoSchemaFoundInWildMode
# from recipe_scrapers._utils import get_host_name, normalize_string
# from cookbook.helper import recipe_url_import as helper
# from cookbook.helper.scrapers.scrapers import text_scraper
# def get_recipe_from_source(text, url, request):
# def build_node(k, v):
# if isinstance(v, dict):
# node = {
# 'name': k,
# 'value': k,
# 'children': get_children_dict(v)
# }
# elif isinstance(v, list):
# node = {
# 'name': k,
# 'value': k,
# 'children': get_children_list(v)
# }
# else:
# node = {
# 'name': k + ": " + normalize_string(str(v)),
# 'value': normalize_string(str(v))
# }
# return node
# def get_children_dict(children):
# kid_list = []
# for k, v in children.items():
# kid_list.append(build_node(k, v))
# return kid_list
# def get_children_list(children):
# kid_list = []
# for kid in children:
# if type(kid) == list:
# node = {
# 'name': "unknown list",
# 'value': "unknown list",
# 'children': get_children_list(kid)
# }
# kid_list.append(node)
# elif type(kid) == dict:
# for k, v in kid.items():
# kid_list.append(build_node(k, v))
# else:
# kid_list.append({
# 'name': normalize_string(str(kid)),
# 'value': normalize_string(str(kid))
# })
# return kid_list
# recipe_tree = []
# parse_list = []
# soup = BeautifulSoup(text, "html.parser")
# html_data = get_from_html(soup)
# images = get_images_from_source(soup, url)
# text = unquote(text)
# scrape = None
# if url and not text:
# try:
# scrape = scrape_me(url_path=url, wild_mode=True)
# except(NoSchemaFoundInWildMode):
# pass
# if not scrape:
# try:
# parse_list.append(remove_graph(json.loads(text)))
# if not url and 'url' in parse_list[0]:
# url = parse_list[0]['url']
# scrape = text_scraper("<script type='application/ld+json'>" + text + "</script>", url=url)
# except JSONDecodeError:
# for el in soup.find_all('script', type='application/ld+json'):
# el = remove_graph(el)
# if not url and 'url' in el:
# url = el['url']
# if type(el) == list:
# for le in el:
# parse_list.append(le)
# elif type(el) == dict:
# parse_list.append(el)
# for el in soup.find_all(type='application/json'):
# el = remove_graph(el)
# if type(el) == list:
# for le in el:
# parse_list.append(le)
# elif type(el) == dict:
# parse_list.append(el)
# scrape = text_scraper(text, url=url)
# recipe_json = helper.get_from_scraper(scrape, request)
# # TODO: DEPRECATE recipe_tree & html_data. first validate it isn't used anywhere
# for el in parse_list:
# temp_tree = []
# if isinstance(el, Tag):
# try:
# el = json.loads(el.string)
# except TypeError:
# continue
# for k, v in el.items():
# if isinstance(v, dict):
# node = {
# 'name': k,
# 'value': k,
# 'children': get_children_dict(v)
# }
# elif isinstance(v, list):
# node = {
# 'name': k,
# 'value': k,
# 'children': get_children_list(v)
# }
# else:
# node = {
# 'name': k + ": " + normalize_string(str(v)),
# 'value': normalize_string(str(v))
# }
# temp_tree.append(node)
# if '@type' in el and el['@type'] == 'Recipe':
# recipe_tree += [{'name': 'ld+json', 'children': temp_tree}]
# else:
# recipe_tree += [{'name': 'json', 'children': temp_tree}]
# return recipe_json, recipe_tree, html_data, images
# def get_from_html(soup):
# INVISIBLE_ELEMS = ('style', 'script', 'head', 'title')
# html = []
# for s in soup.strings:
# if ((s.parent.name not in INVISIBLE_ELEMS) and (len(s.strip()) > 0)):
# html.append(s)
# return html
# def get_images_from_source(soup, url):
# sources = ['src', 'srcset', 'data-src']
# images = []
# img_tags = soup.find_all('img')
# if url:
# site = get_host_name(url)
# prot = url.split(':')[0]
# urls = []
# for img in img_tags:
# for src in sources:
# try:
# urls.append(img[src])
# except KeyError:
# pass
# for u in urls:
# u = u.split('?')[0]
# filename = re.search(r'/([\w_-]+[.](jpg|jpeg|gif|png))$', u)
# if filename:
# if (('http' not in u) and (url)):
# # sometimes an image source can be relative
# # if it is provide the base url
# u = '{}://{}{}'.format(prot, site, u)
# if 'http' in u:
# images.append(u)
# return images
# def remove_graph(el):
# # recipes type might be wrapped in @graph type
# if isinstance(el, Tag):
# try:
# el = json.loads(el.string)
# if '@graph' in el:
# for x in el['@graph']:
# if '@type' in x and x['@type'] == 'Recipe':
# el = x
# except (TypeError, JSONDecodeError):
# pass
# return el

View File

@@ -1,14 +1,11 @@
import json
from collections import Counter
from datetime import date, timedelta
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector, TrigramSimilarity
from django.core.cache import cache, caches
from django.db.models import (Avg, Case, Count, Exists, F, Func, Max, OuterRef, Q, Subquery, Value,
When)
from django.core.cache import cache
from django.db.models import Avg, Case, Count, Exists, F, Max, OuterRef, Q, Subquery, Value, When
from django.db.models.functions import Coalesce, Lower, Substr
from django.utils import timezone, translation
from django.utils.translation import gettext as _
from cookbook.helper.HelperFunctions import Round, str2bool
from cookbook.managers import DICTIONARY
@@ -17,21 +14,25 @@ from cookbook.models import (CookLog, CustomFilter, Food, Keyword, Recipe, Searc
from recipes import settings
# TODO create extensive tests to make sure ORs ANDs and various filters, sorting, etc work as expected
# TODO consider creating a simpleListRecipe API that only includes minimum of recipe info and minimal filtering
class RecipeSearch():
_postgres = settings.DATABASES['default']['ENGINE'] in [
'django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']
_postgres = settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql'
def __init__(self, request, **params):
self._request = request
self._queryset = None
if f := params.get('filter', None):
custom_filter = CustomFilter.objects.filter(id=f, space=self._request.space).filter(Q(created_by=self._request.user) |
Q(shared=self._request.user) | Q(recipebook__shared=self._request.user)).first()
custom_filter = (
CustomFilter.objects.filter(id=f, space=self._request.space)
.filter(Q(created_by=self._request.user) | Q(shared=self._request.user) | Q(recipebook__shared=self._request.user))
.first()
)
if custom_filter:
self._params = {**json.loads(custom_filter.search)}
self._original_params = {**(params or {})}
# json.loads casts rating as an integer, expecting string
if isinstance(self._params.get('rating', None), int):
self._params['rating'] = str(self._params['rating'])
else:
self._params = {**(params or {})}
else:
@@ -85,9 +86,9 @@ class RecipeSearch():
self._viewedon = self._params.get('viewedon', None)
self._makenow = self._params.get('makenow', None)
# this supports hidden feature to find recipes missing X ingredients
if type(self._makenow) == bool and self._makenow == True:
if isinstance(self._makenow, bool) and self._makenow == True:
self._makenow = 0
elif type(self._makenow) == str and self._makenow in ["yes", "true"]:
elif isinstance(self._makenow, str) and self._makenow in ["yes", "true"]:
self._makenow = 0
else:
try:
@@ -98,24 +99,18 @@ class RecipeSearch():
self._search_type = self._search_prefs.search or 'plain'
if self._string:
if self._postgres:
self._unaccent_include = self._search_prefs.unaccent.values_list(
'field', flat=True)
self._unaccent_include = self._search_prefs.unaccent.values_list('field', flat=True)
else:
self._unaccent_include = []
self._icontains_include = [
x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.icontains.values_list('field', flat=True)]
self._istartswith_include = [
x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.istartswith.values_list('field', flat=True)]
self._icontains_include = [x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.icontains.values_list('field', flat=True)]
self._istartswith_include = [x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.istartswith.values_list('field', flat=True)]
self._trigram_include = None
self._fulltext_include = None
self._trigram = False
if self._postgres and self._string:
self._language = DICTIONARY.get(
translation.get_language(), 'simple')
self._trigram_include = [
x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.trigram.values_list('field', flat=True)]
self._fulltext_include = self._search_prefs.fulltext.values_list(
'field', flat=True) or None
self._language = DICTIONARY.get(translation.get_language(), 'simple')
self._trigram_include = [x + '__unaccent' if x in self._unaccent_include else x for x in self._search_prefs.trigram.values_list('field', flat=True)]
self._fulltext_include = self._search_prefs.fulltext.values_list('field', flat=True) or None
if self._search_type not in ['websearch', 'raw'] and self._trigram_include:
self._trigram = True
@@ -150,7 +145,7 @@ class RecipeSearch():
self.unit_filters(units=self._units)
self._makenow_filter(missing=self._makenow)
self.string_filters(string=self._string)
return self._queryset.filter(space=self._request.space).distinct().order_by(*self.orderby)
return self._queryset.filter(space=self._request.space).order_by(*self.orderby)
def _sort_includes(self, *args):
for x in args:
@@ -166,7 +161,7 @@ class RecipeSearch():
else:
order = []
# TODO add userpreference for default sort order and replace '-favorite'
default_order = ['-name']
default_order = ['name']
# recent and new_recipe are always first; they float a few recipes to the top
if self._num_recent:
order += ['-recent']
@@ -175,7 +170,6 @@ class RecipeSearch():
# if a sort order is provided by user - use that order
if self._sort_order:
if not isinstance(self._sort_order, list):
order += [self._sort_order]
else:
@@ -215,24 +209,18 @@ class RecipeSearch():
self._queryset = self._queryset.filter(query_filter).distinct()
if self._fulltext_include:
if self._fuzzy_match is None:
self._queryset = self._queryset.annotate(
score=Coalesce(Max(self.search_rank), 0.0))
self._queryset = self._queryset.annotate(score=Coalesce(Max(self.search_rank), 0.0))
else:
self._queryset = self._queryset.annotate(
rank=Coalesce(Max(self.search_rank), 0.0))
self._queryset = self._queryset.annotate(rank=Coalesce(Max(self.search_rank), 0.0))
if self._fuzzy_match is not None:
simularity = self._fuzzy_match.filter(
pk=OuterRef('pk')).values('simularity')
simularity = self._fuzzy_match.filter(pk=OuterRef('pk')).values('simularity')
if not self._fulltext_include:
self._queryset = self._queryset.annotate(
score=Coalesce(Subquery(simularity), 0.0))
self._queryset = self._queryset.annotate(score=Coalesce(Subquery(simularity), 0.0))
else:
self._queryset = self._queryset.annotate(
simularity=Coalesce(Subquery(simularity), 0.0))
self._queryset = self._queryset.annotate(simularity=Coalesce(Subquery(simularity), 0.0))
if self._sort_includes('score') and self._fulltext_include and self._fuzzy_match is not None:
self._queryset = self._queryset.annotate(
score=F('rank') + F('simularity'))
self._queryset = self._queryset.annotate(score=F('rank') + F('simularity'))
else:
query_filter = Q()
for f in [x + '__unaccent__iexact' if x in self._unaccent_include else x + '__iexact' for x in SearchFields.objects.all().values_list('field', flat=True)]:
@@ -241,78 +229,69 @@ class RecipeSearch():
def _cooked_on_filter(self, cooked_date=None):
if self._sort_includes('lastcooked') or cooked_date:
lessthan = self._sort_includes(
'-lastcooked') or '-' in (cooked_date or [])[:1]
lessthan = self._sort_includes('-lastcooked') or '-' in (cooked_date or [])[:1]
if lessthan:
default = timezone.now() - timedelta(days=100000)
else:
default = timezone.now()
self._queryset = self._queryset.annotate(lastcooked=Coalesce(
Max(Case(When(cooklog__created_by=self._request.user, cooklog__space=self._request.space, then='cooklog__created_at'))), Value(default)))
self._queryset = self._queryset.annotate(
lastcooked=Coalesce(Max(Case(When(cooklog__created_by=self._request.user, cooklog__space=self._request.space, then='cooklog__created_at'))), Value(default))
)
if cooked_date is None:
return
cooked_date = date(*[int(x)
for x in cooked_date.split('-') if x != ''])
cooked_date = date(*[int(x)for x in cooked_date.split('-') if x != ''])
if lessthan:
self._queryset = self._queryset.filter(
lastcooked__date__lte=cooked_date).exclude(lastcooked=default)
self._queryset = self._queryset.filter(lastcooked__date__lte=cooked_date).exclude(lastcooked=default)
else:
self._queryset = self._queryset.filter(
lastcooked__date__gte=cooked_date).exclude(lastcooked=default)
self._queryset = self._queryset.filter(lastcooked__date__gte=cooked_date).exclude(lastcooked=default)
def _created_on_filter(self, created_date=None):
if created_date is None:
return
lessthan = '-' in created_date[:1]
created_date = date(*[int(x)
for x in created_date.split('-') if x != ''])
created_date = date(*[int(x) for x in created_date.split('-') if x != ''])
if lessthan:
self._queryset = self._queryset.filter(
created_at__date__lte=created_date)
self._queryset = self._queryset.filter(created_at__date__lte=created_date)
else:
self._queryset = self._queryset.filter(
created_at__date__gte=created_date)
self._queryset = self._queryset.filter(created_at__date__gte=created_date)
def _updated_on_filter(self, updated_date=None):
if updated_date is None:
return
lessthan = '-' in updated_date[:1]
updated_date = date(*[int(x)
for x in updated_date.split('-') if x != ''])
updated_date = date(*[int(x)for x in updated_date.split('-') if x != ''])
if lessthan:
self._queryset = self._queryset.filter(
updated_at__date__lte=updated_date)
self._queryset = self._queryset.filter(updated_at__date__lte=updated_date)
else:
self._queryset = self._queryset.filter(
updated_at__date__gte=updated_date)
self._queryset = self._queryset.filter(updated_at__date__gte=updated_date)
def _viewed_on_filter(self, viewed_date=None):
if self._sort_includes('lastviewed') or viewed_date:
longTimeAgo = timezone.now() - timedelta(days=100000)
self._queryset = self._queryset.annotate(lastviewed=Coalesce(
Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__created_at'))), Value(longTimeAgo)))
self._queryset = self._queryset.annotate(
lastviewed=Coalesce(Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__created_at'))), Value(longTimeAgo))
)
if viewed_date is None:
return
lessthan = '-' in viewed_date[:1]
viewed_date = date(*[int(x)
for x in viewed_date.split('-') if x != ''])
viewed_date = date(*[int(x)for x in viewed_date.split('-') if x != ''])
if lessthan:
self._queryset = self._queryset.filter(
lastviewed__date__lte=viewed_date).exclude(lastviewed=longTimeAgo)
self._queryset = self._queryset.filter(lastviewed__date__lte=viewed_date).exclude(lastviewed=longTimeAgo)
else:
self._queryset = self._queryset.filter(
lastviewed__date__gte=viewed_date).exclude(lastviewed=longTimeAgo)
self._queryset = self._queryset.filter(lastviewed__date__gte=viewed_date).exclude(lastviewed=longTimeAgo)
def _new_recipes(self, new_days=7):
# TODO make new days a user-setting
if not self._new:
return
self._queryset = (
self._queryset.annotate(new_recipe=Case(
When(created_at__gte=(timezone.now() - timedelta(days=new_days)), then=('pk')), default=Value(0), ))
self._queryset = self._queryset.annotate(
new_recipe=Case(
When(created_at__gte=(timezone.now() - timedelta(days=new_days)), then=('pk')),
default=Value(0),
)
)
def _recently_viewed(self, num_recent=None):
@@ -322,34 +301,35 @@ class RecipeSearch():
Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__pk'))), Value(0)))
return
num_recent_recipes = ViewLog.objects.filter(created_by=self._request.user, space=self._request.space).values(
'recipe').annotate(recent=Max('created_at')).order_by('-recent')[:num_recent]
self._queryset = self._queryset.annotate(recent=Coalesce(Max(Case(When(
pk__in=num_recent_recipes.values('recipe'), then='viewlog__pk'))), Value(0)))
num_recent_recipes = (
ViewLog.objects.filter(created_by=self._request.user, space=self._request.space)
.values('recipe').annotate(recent=Max('created_at')).order_by('-recent')[:num_recent]
)
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, times_cooked=None):
if self._sort_includes('favorite') or times_cooked:
less_than = '-' in (times_cooked or []
) and not self._sort_includes('-favorite')
less_than = '-' in (str(times_cooked) or []) and not self._sort_includes('-favorite')
if less_than:
default = 1000
else:
default = 0
favorite_recipes = CookLog.objects.filter(created_by=self._request.user, space=self._request.space, recipe=OuterRef('pk')
).values('recipe').annotate(count=Count('pk', distinct=True)).values('count')
self._queryset = self._queryset.annotate(
favorite=Coalesce(Subquery(favorite_recipes), default))
favorite_recipes = (
CookLog.objects.filter(created_by=self._request.user, space=self._request.space, recipe=OuterRef('pk'))
.values('recipe')
.annotate(count=Count('pk', distinct=True))
.values('count')
)
self._queryset = self._queryset.annotate(favorite=Coalesce(Subquery(favorite_recipes), default))
if times_cooked is None:
return
if times_cooked == '0':
self._queryset = self._queryset.filter(favorite=0)
elif less_than:
self._queryset = self._queryset.filter(favorite__lte=int(
times_cooked.replace('-', ''))).exclude(favorite=0)
self._queryset = self._queryset.filter(favorite__lte=int(times_cooked.replace('-', ''))).exclude(favorite=0)
else:
self._queryset = self._queryset.filter(
favorite__gte=int(times_cooked))
self._queryset = self._queryset.filter(favorite__gte=int(times_cooked))
def keyword_filters(self, **kwargs):
if all([kwargs[x] is None for x in kwargs]):
@@ -382,8 +362,7 @@ class RecipeSearch():
else:
self._queryset = self._queryset.filter(f_and)
if 'not' in kw_filter:
self._queryset = self._queryset.exclude(
id__in=recipes.values('id'))
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
def food_filters(self, **kwargs):
if all([kwargs[x] is None for x in kwargs]):
@@ -397,8 +376,7 @@ class RecipeSearch():
foods = Food.objects.filter(pk__in=kwargs[fd_filter])
if 'or' in fd_filter:
if self._include_children:
f_or = Q(
steps__ingredients__food__in=Food.include_descendants(foods))
f_or = Q(steps__ingredients__food__in=Food.include_descendants(foods))
else:
f_or = Q(steps__ingredients__food__in=foods)
@@ -410,8 +388,7 @@ class RecipeSearch():
recipes = Recipe.objects.all()
for food in foods:
if self._include_children:
f_and = Q(
steps__ingredients__food__in=food.get_descendants_and_self())
f_and = Q(steps__ingredients__food__in=food.get_descendants_and_self())
else:
f_and = Q(steps__ingredients__food=food)
if 'not' in fd_filter:
@@ -419,8 +396,7 @@ class RecipeSearch():
else:
self._queryset = self._queryset.filter(f_and)
if 'not' in fd_filter:
self._queryset = self._queryset.exclude(
id__in=recipes.values('id'))
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
def unit_filters(self, units=None, operator=True):
if operator != True:
@@ -429,27 +405,25 @@ class RecipeSearch():
return
if not isinstance(units, list):
units = [units]
self._queryset = self._queryset.filter(
steps__ingredients__unit__in=units)
self._queryset = self._queryset.filter(steps__ingredients__unit__in=units)
def rating_filter(self, rating=None):
if rating or self._sort_includes('rating'):
lessthan = self._sort_includes('-rating') or '-' in (rating or [])
if lessthan:
lessthan = '-' in (rating or [])
reverse = 'rating' in (self._sort_order or []) and '-rating' not in (self._sort_order or [])
if lessthan or reverse:
default = 100
else:
default = 0
# TODO make ratings a settings user-only vs all-users
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(
cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
if rating is None:
return
if rating == '0':
self._queryset = self._queryset.filter(rating=0)
elif lessthan:
self._queryset = self._queryset.filter(
rating__lte=int(rating[1:])).exclude(rating=0)
self._queryset = self._queryset.filter(rating__lte=int(rating[1:])).exclude(rating=0)
else:
self._queryset = self._queryset.filter(rating__gte=int(rating))
@@ -477,14 +451,11 @@ class RecipeSearch():
recipes = Recipe.objects.all()
for book in kwargs[bk_filter]:
if 'not' in bk_filter:
recipes = recipes.filter(
recipebookentry__book__id=book)
recipes = recipes.filter(recipebookentry__book__id=book)
else:
self._queryset = self._queryset.filter(
recipebookentry__book__id=book)
self._queryset = self._queryset.filter(recipebookentry__book__id=book)
if 'not' in bk_filter:
self._queryset = self._queryset.exclude(
id__in=recipes.values('id'))
self._queryset = self._queryset.exclude(id__in=recipes.values('id'))
def step_filters(self, steps=None, operator=True):
if operator != True:
@@ -503,25 +474,20 @@ class RecipeSearch():
rank = []
if 'name' in self._fulltext_include:
vectors.append('name_search_vector')
rank.append(SearchRank('name_search_vector',
self.search_query, cover_density=True))
rank.append(SearchRank('name_search_vector', self.search_query, cover_density=True))
if 'description' in self._fulltext_include:
vectors.append('desc_search_vector')
rank.append(SearchRank('desc_search_vector',
self.search_query, cover_density=True))
rank.append(SearchRank('desc_search_vector', self.search_query, cover_density=True))
if 'steps__instruction' in self._fulltext_include:
vectors.append('steps__search_vector')
rank.append(SearchRank('steps__search_vector',
self.search_query, cover_density=True))
rank.append(SearchRank('steps__search_vector', self.search_query, cover_density=True))
if 'keywords__name' in self._fulltext_include:
# explicitly settings unaccent on keywords and foods so that they behave the same as search_vector fields
vectors.append('keywords__name__unaccent')
rank.append(SearchRank('keywords__name__unaccent',
self.search_query, cover_density=True))
rank.append(SearchRank('keywords__name__unaccent', self.search_query, cover_density=True))
if 'steps__ingredients__food__name' in self._fulltext_include:
vectors.append('steps__ingredients__food__name__unaccent')
rank.append(SearchRank('steps__ingredients__food__name',
self.search_query, cover_density=True))
rank.append(SearchRank('steps__ingredients__food__name', self.search_query, cover_density=True))
for r in rank:
if self.search_rank is None:
@@ -529,8 +495,7 @@ class RecipeSearch():
else:
self.search_rank += r
# modifying queryset will annotation creates duplicate results
self._filters.append(Q(id__in=Recipe.objects.annotate(
vector=SearchVector(*vectors)).filter(Q(vector=self.search_query))))
self._filters.append(Q(id__in=Recipe.objects.annotate(vector=SearchVector(*vectors)).filter(Q(vector=self.search_query))))
def build_text_filters(self, string=None):
if not string:
@@ -555,15 +520,19 @@ class RecipeSearch():
trigram += TrigramSimilarity(f, self._string)
else:
trigram = TrigramSimilarity(f, self._string)
self._fuzzy_match = Recipe.objects.annotate(trigram=trigram).distinct(
).annotate(simularity=Max('trigram')).values('id', 'simularity').filter(simularity__gt=self._search_prefs.trigram_threshold)
self._fuzzy_match = (
Recipe.objects.annotate(trigram=trigram)
.distinct()
.annotate(simularity=Max('trigram'))
.values('id', 'simularity')
.filter(simularity__gt=self._search_prefs.trigram_threshold)
)
self._filters += [Q(pk__in=self._fuzzy_match.values('pk'))]
def _makenow_filter(self, missing=None):
if missing is None or (type(missing) == bool and missing == False):
if missing is None or (isinstance(missing, bool) and missing == False):
return
shopping_users = [
*self._request.user.get_shopping_share(), self._request.user]
shopping_users = [*self._request.user.get_shopping_share(), self._request.user]
onhand_filter = (
Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand
@@ -573,264 +542,40 @@ class RecipeSearch():
| Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users))
)
makenow_recipes = Recipe.objects.annotate(
count_food=Count('steps__ingredients__food__pk', filter=Q(
steps__ingredients__food__isnull=False), distinct=True),
count_onhand=Count('steps__ingredients__food__pk',
filter=onhand_filter, distinct=True),
count_ignore_shopping=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__ignore_shopping=True,
steps__ingredients__food__recipe__isnull=True), distinct=True),
has_child_sub=Case(When(steps__ingredients__food__in=self.__children_substitute_filter(
shopping_users), then=Value(1)), default=Value(0)),
has_sibling_sub=Case(When(steps__ingredients__food__in=self.__sibling_substitute_filter(
shopping_users), then=Value(1)), default=Value(0))
).annotate(missingfood=F('count_food') - F('count_onhand') - F('count_ignore_shopping')).filter(missingfood=missing)
self._queryset = self._queryset.distinct().filter(
id__in=makenow_recipes.values('id'))
count_food=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__isnull=False), distinct=True),
count_onhand=Count('steps__ingredients__food__pk', filter=onhand_filter, distinct=True),
count_ignore_shopping=Count(
'steps__ingredients__food__pk', filter=Q(steps__ingredients__food__ignore_shopping=True, steps__ingredients__food__recipe__isnull=True), distinct=True
),
has_child_sub=Case(When(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users), then=Value(1)), default=Value(0)),
has_sibling_sub=Case(When(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users), then=Value(1)), default=Value(0))
).annotate(missingfood=F('count_food') - F('count_onhand') - F('count_ignore_shopping')).filter(missingfood__lte=missing)
self._queryset = self._queryset.distinct().filter(id__in=makenow_recipes.values('id'))
@staticmethod
def __children_substitute_filter(shopping_users=None):
children_onhand_subquery = Food.objects.filter(
path__startswith=OuterRef('path'),
depth__gt=OuterRef('depth'),
onhand_users__in=shopping_users
children_onhand_subquery = Food.objects.filter(path__startswith=OuterRef('path'), depth__gt=OuterRef('depth'), onhand_users__in=shopping_users)
return (
Food.objects.exclude( # list of foods that are onhand and children of: foods that are not onhand and are set to use children as substitutes
Q(onhand_users__in=shopping_users) | Q(ignore_shopping=True, recipe__isnull=True) | Q(substitute__onhand_users__in=shopping_users)
)
.exclude(depth=1, numchild=0)
.filter(substitute_children=True)
.annotate(child_onhand_count=Exists(children_onhand_subquery))
.filter(child_onhand_count=True)
)
return Food.objects.exclude( # list of foods that are onhand and children of: foods that are not onhand and are set to use children as substitutes
Q(onhand_users__in=shopping_users)
| Q(ignore_shopping=True, recipe__isnull=True)
| Q(substitute__onhand_users__in=shopping_users)
).exclude(depth=1, numchild=0
).filter(substitute_children=True
).annotate(child_onhand_count=Exists(children_onhand_subquery)
).filter(child_onhand_count=True)
@staticmethod
def __sibling_substitute_filter(shopping_users=None):
sibling_onhand_subquery = Food.objects.filter(
path__startswith=Substr(
OuterRef('path'), 1, Food.steplen * (OuterRef('depth') - 1)),
depth=OuterRef('depth'),
onhand_users__in=shopping_users
path__startswith=Substr(OuterRef('path'), 1, Food.steplen * (OuterRef('depth') - 1)), depth=OuterRef('depth'), onhand_users__in=shopping_users
)
return Food.objects.exclude( # list of foods that are onhand and siblings of: foods that are not onhand and are set to use siblings as substitutes
Q(onhand_users__in=shopping_users)
| Q(ignore_shopping=True, recipe__isnull=True)
| Q(substitute__onhand_users__in=shopping_users)
).exclude(depth=1, numchild=0
).filter(substitute_siblings=True
).annotate(sibling_onhand=Exists(sibling_onhand_subquery)
).filter(sibling_onhand=True)
class RecipeFacet():
class CacheEmpty(Exception):
pass
def __init__(self, request, queryset=None, hash_key=None, cache_timeout=3600):
if hash_key is None and queryset is None:
raise ValueError(_("One of queryset or hash_key must be provided"))
self._request = request
self._queryset = queryset
self.hash_key = hash_key or str(hash(self._queryset.query))
self._SEARCH_CACHE_KEY = f"recipes_filter_{self.hash_key}"
self._cache_timeout = cache_timeout
self._cache = caches['default'].get(self._SEARCH_CACHE_KEY, {})
if self._cache is None and self._queryset is None:
raise self.CacheEmpty("No queryset provided and cache empty")
self.Keywords = self._cache.get('Keywords', None)
self.Foods = self._cache.get('Foods', None)
self.Books = self._cache.get('Books', None)
self.Ratings = self._cache.get('Ratings', None)
# TODO Move Recent to recipe annotation/serializer: requrires change in RecipeSearch(), RecipeSearchView.vue and serializer
self.Recent = self._cache.get('Recent', None)
if self._queryset is not None:
self._recipe_list = list(
self._queryset.values_list('id', flat=True))
self._search_params = {
'keyword_list': self._request.query_params.getlist('keywords', []),
'food_list': self._request.query_params.getlist('foods', []),
'book_list': self._request.query_params.getlist('book', []),
'search_keywords_or': str2bool(self._request.query_params.get('keywords_or', True)),
'search_foods_or': str2bool(self._request.query_params.get('foods_or', True)),
'search_books_or': str2bool(self._request.query_params.get('books_or', True)),
'space': self._request.space,
}
elif self.hash_key is not None:
self._recipe_list = self._cache.get('recipe_list', [])
self._search_params = {
'keyword_list': self._cache.get('keyword_list', None),
'food_list': self._cache.get('food_list', None),
'book_list': self._cache.get('book_list', None),
'search_keywords_or': self._cache.get('search_keywords_or', None),
'search_foods_or': self._cache.get('search_foods_or', None),
'search_books_or': self._cache.get('search_books_or', None),
'space': self._cache.get('space', None),
}
self._cache = {
**self._search_params,
'recipe_list': self._recipe_list,
'Ratings': self.Ratings,
'Recent': self.Recent,
'Keywords': self.Keywords,
'Foods': self.Foods,
'Books': self.Books
}
caches['default'].set(self._SEARCH_CACHE_KEY,
self._cache, self._cache_timeout)
def get_facets(self, from_cache=False):
if from_cache:
return {
'cache_key': self.hash_key or '',
'Ratings': self.Ratings or {},
'Recent': self.Recent or [],
'Keywords': self.Keywords or [],
'Foods': self.Foods or [],
'Books': self.Books or []
}
return {
'cache_key': self.hash_key,
'Ratings': self.get_ratings(),
'Recent': self.get_recent(),
'Keywords': self.get_keywords(),
'Foods': self.get_foods(),
'Books': self.get_books()
}
def set_cache(self, key, value):
self._cache = {**self._cache, key: value}
caches['default'].set(
self._SEARCH_CACHE_KEY,
self._cache,
self._cache_timeout
return (
Food.objects.exclude( # list of foods that are onhand and siblings of: foods that are not onhand and are set to use siblings as substitutes
Q(onhand_users__in=shopping_users) | Q(ignore_shopping=True, recipe__isnull=True) | Q(substitute__onhand_users__in=shopping_users)
)
.exclude(depth=1, numchild=0)
.filter(substitute_siblings=True)
.annotate(sibling_onhand=Exists(sibling_onhand_subquery))
.filter(sibling_onhand=True)
)
def get_books(self):
if self.Books is None:
self.Books = []
return self.Books
def get_keywords(self):
if self.Keywords is None:
if self._search_params['search_keywords_or']:
keywords = Keyword.objects.filter(
space=self._request.space).distinct()
else:
keywords = Keyword.objects.filter(Q(recipe__in=self._recipe_list) | Q(
depth=1)).filter(space=self._request.space).distinct()
# set keywords to root objects only
keywords = self._keyword_queryset(keywords)
self.Keywords = [{**x, 'children': None}
if x['numchild'] > 0 else x for x in list(keywords)]
self.set_cache('Keywords', self.Keywords)
return self.Keywords
def get_foods(self):
if self.Foods is None:
# # if using an OR search, will annotate all keywords, otherwise, just those that appear in results
if self._search_params['search_foods_or']:
foods = Food.objects.filter(
space=self._request.space).distinct()
else:
foods = Food.objects.filter(Q(ingredient__step__recipe__in=self._recipe_list) | Q(
depth=1)).filter(space=self._request.space).distinct()
# set keywords to root objects only
foods = self._food_queryset(foods)
self.Foods = [{**x, 'children': None}
if x['numchild'] > 0 else x for x in list(foods)]
self.set_cache('Foods', self.Foods)
return self.Foods
def get_ratings(self):
if self.Ratings is None:
if not self._request.space.demo and self._request.space.show_facet_count:
if self._queryset is None:
self._queryset = Recipe.objects.filter(
id__in=self._recipe_list)
rating_qs = self._queryset.annotate(rating=Round(Avg(Case(When(
cooklog__created_by=self._request.user, then='cooklog__rating'), default=Value(0)))))
self.Ratings = dict(Counter(r.rating for r in rating_qs))
else:
self.Rating = {}
self.set_cache('Ratings', self.Ratings)
return self.Ratings
def get_recent(self):
if self.Recent is None:
# TODO make days of recent recipe a setting
recent_recipes = ViewLog.objects.filter(created_by=self._request.user, space=self._request.space, created_at__gte=timezone.now() - timedelta(days=14)
).values_list('recipe__pk', flat=True)
self.Recent = list(recent_recipes)
self.set_cache('Recent', self.Recent)
return self.Recent
def add_food_children(self, id):
try:
food = Food.objects.get(id=id)
nodes = food.get_ancestors()
except Food.DoesNotExist:
return self.get_facets()
foods = self._food_queryset(food.get_children(), food)
deep_search = self.Foods
for node in nodes:
index = next((i for i, x in enumerate(
deep_search) if x["id"] == node.id), None)
deep_search = deep_search[index]['children']
index = next((i for i, x in enumerate(
deep_search) if x["id"] == food.id), None)
deep_search[index]['children'] = [
{**x, 'children': None} if x['numchild'] > 0 else x for x in list(foods)]
self.set_cache('Foods', self.Foods)
return self.get_facets()
def add_keyword_children(self, id):
try:
keyword = Keyword.objects.get(id=id)
nodes = keyword.get_ancestors()
except Keyword.DoesNotExist:
return self.get_facets()
keywords = self._keyword_queryset(keyword.get_children(), keyword)
deep_search = self.Keywords
for node in nodes:
index = next((i for i, x in enumerate(
deep_search) if x["id"] == node.id), None)
deep_search = deep_search[index]['children']
index = next((i for i, x in enumerate(deep_search)
if x["id"] == keyword.id), None)
deep_search[index]['children'] = [
{**x, 'children': None} if x['numchild'] > 0 else x for x in list(keywords)]
self.set_cache('Keywords', self.Keywords)
return self.get_facets()
def _recipe_count_queryset(self, field, depth=1, steplen=4):
return Recipe.objects.filter(**{f'{field}__path__startswith': OuterRef('path'), f'{field}__depth__gte': depth}, id__in=self._recipe_list, space=self._request.space
).annotate(count=Coalesce(Func('pk', function='Count'), 0)).values('count')
def _keyword_queryset(self, queryset, keyword=None):
depth = getattr(keyword, 'depth', 0) + 1
steplen = depth * Keyword.steplen
if not self._request.space.demo and self._request.space.show_facet_count:
return queryset.annotate(count=Coalesce(Subquery(self._recipe_count_queryset('keywords', depth, steplen)), 0)
).filter(depth=depth, count__gt=0
).values('id', 'name', 'count', 'numchild').order_by(Lower('name').asc())[:200]
else:
return queryset.filter(depth=depth).values('id', 'name', 'numchild').order_by(Lower('name').asc())
def _food_queryset(self, queryset, food=None):
depth = getattr(food, 'depth', 0) + 1
steplen = depth * Food.steplen
if not self._request.space.demo and self._request.space.show_facet_count:
return queryset.annotate(count=Coalesce(Subquery(self._recipe_count_queryset('steps__ingredients__food', depth, steplen)), 0)
).filter(depth__lte=depth, count__gt=0
).values('id', 'name', 'count', 'numchild').order_by(Lower('name').asc())[:200]
else:
return queryset.filter(depth__lte=depth).values('id', 'name', 'numchild').order_by(Lower('name').asc())

View File

@@ -1,8 +1,7 @@
# import random
import re
import traceback
from html import unescape
from django.core.cache import caches
from django.utils.dateparse import parse_duration
from django.utils.translation import gettext as _
from isodate import parse_duration as iso_parse_duration
@@ -10,19 +9,37 @@ from isodate.isoerror import ISO8601Error
from pytube import YouTube
from recipe_scrapers._utils import get_host_name, get_minutes
# from cookbook.helper import recipe_url_import as helper
from cookbook.helper.automation_helper import AutomationEngine
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.models import Automation, Keyword
# from unicodedata import decomposition
# from recipe_scrapers._utils import get_minutes ## temporary until/unless upstream incorporates get_minutes() PR
from cookbook.models import Automation, Keyword, PropertyType
def get_from_scraper(scrape, request):
# converting the scrape_me object to the existing json format based on ld+json
recipe_json = {}
recipe_json = {
'steps': [],
'internal': True
}
keywords = []
# assign source URL
try:
source_url = scrape.canonical_url()
except Exception:
try:
source_url = scrape.url
except Exception:
pass
if source_url:
recipe_json['source_url'] = source_url
try:
keywords.append(source_url.replace('http://', '').replace('https://', '').split('/')[0])
except Exception:
recipe_json['source_url'] = ''
automation_engine = AutomationEngine(request, source=recipe_json.get('source_url'))
# assign recipe name
try:
recipe_json['name'] = parse_name(scrape.title()[:128] or None)
except Exception:
@@ -33,6 +50,13 @@ def get_from_scraper(scrape, request):
except Exception:
recipe_json['name'] = ''
if isinstance(recipe_json['name'], list) and len(recipe_json['name']) > 0:
recipe_json['name'] = recipe_json['name'][0]
recipe_json['name'] = automation_engine.apply_regex_replace_automation(recipe_json['name'], Automation.NAME_REPLACE)
# assign recipe description
# TODO notify user about limit if reached - >256 description will be truncated
try:
description = scrape.description() or None
except Exception:
@@ -43,16 +67,20 @@ def get_from_scraper(scrape, request):
except Exception:
description = ''
recipe_json['internal'] = True
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:
servings = scrape.schema.data.get('recipeYield') or 1 # dont use scrape.yields() as this will always return "x servings" or "x items", should be improved in scrapers directly
# 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)
# assign time attributes
try:
recipe_json['working_time'] = get_minutes(scrape.prep_time()) or 0
except Exception:
@@ -77,6 +105,7 @@ def get_from_scraper(scrape, request):
except Exception:
pass
# assign image
try:
recipe_json['image'] = parse_image(scrape.image()) or None
except Exception:
@@ -87,7 +116,7 @@ def get_from_scraper(scrape, request):
except Exception:
recipe_json['image'] = ''
keywords = []
# assign keywords
try:
if scrape.schema.data.get("keywords"):
keywords += listify_keywords(scrape.schema.data.get("keywords"))
@@ -112,20 +141,6 @@ def get_from_scraper(scrape, request):
except Exception:
pass
try:
source_url = scrape.canonical_url()
except Exception:
try:
source_url = scrape.url
except Exception:
pass
if source_url:
recipe_json['source_url'] = source_url
try:
keywords.append(source_url.replace('http://', '').replace('https://', '').split('/')[0])
except Exception:
recipe_json['source_url'] = ''
try:
if scrape.author():
keywords.append(scrape.author())
@@ -133,33 +148,24 @@ def get_from_scraper(scrape, request):
pass
try:
recipe_json['keywords'] = parse_keywords(list(set(map(str.casefold, keywords))), request.space)
recipe_json['keywords'] = parse_keywords(list(set(map(str.casefold, keywords))), request)
except AttributeError:
recipe_json['keywords'] = keywords
ingredient_parser = IngredientParser(request, True)
recipe_json['steps'] = []
# assign steps
try:
for i in parse_instructions(scrape.instructions()):
recipe_json['steps'].append({'instruction': i, 'ingredients': [], })
recipe_json['steps'].append({'instruction': i, 'ingredients': [], 'show_ingredients_table': request.user.userpreference.show_step_ingredients, })
except Exception:
pass
if len(recipe_json['steps']) == 0:
recipe_json['steps'].append({'instruction': '', 'ingredients': [], })
parsed_description = parse_description(description)
# TODO notify user about limit if reached
# limits exist to limit the attack surface for dos style attacks
automations = Automation.objects.filter(type=Automation.DESCRIPTION_REPLACE, space=request.space, disabled=False).only('param_1', 'param_2', 'param_3').all().order_by('order')[:512]
for a in automations:
if re.match(a.param_1, (recipe_json['source_url'])[:512]):
parsed_description = re.sub(a.param_2, a.param_3, parsed_description, count=1)
if len(parsed_description) > 256: # split at 256 as long descriptions don't look good on recipe cards
recipe_json['steps'][0]['instruction'] = f'*{parsed_description}* \n\n' + recipe_json['steps'][0]['instruction']
else:
recipe_json['description'] = parsed_description[:512]
recipe_json['description'] = recipe_json['description'][:512]
if len(recipe_json['description']) > 256: # split at 256 as long descriptions don't look good on recipe cards
recipe_json['steps'][0]['instruction'] = f"*{recipe_json['description']}* \n\n" + recipe_json['steps'][0]['instruction']
try:
for x in scrape.ingredients():
@@ -193,16 +199,44 @@ def get_from_scraper(scrape, request):
except Exception:
pass
if recipe_json['source_url']:
automations = Automation.objects.filter(type=Automation.INSTRUCTION_REPLACE, space=request.space, disabled=False).only('param_1', 'param_2', 'param_3').order_by('order').all()[:512]
for a in automations:
if re.match(a.param_1, (recipe_json['source_url'])[:512]):
for s in recipe_json['steps']:
s['instruction'] = re.sub(a.param_2, a.param_3, s['instruction'])
try:
recipe_json['properties'] = get_recipe_properties(request.space, scrape.schema.nutrients())
print(recipe_json['properties'])
except Exception:
traceback.print_exc()
pass
for s in recipe_json['steps']:
s['instruction'] = automation_engine.apply_regex_replace_automation(s['instruction'], Automation.INSTRUCTION_REPLACE)
# re.sub(a.param_2, a.param_3, s['instruction'])
return recipe_json
def get_recipe_properties(space, property_data):
# {'servingSize': '1', 'calories': '302 kcal', 'proteinContent': '7,66g', 'fatContent': '11,56g', 'carbohydrateContent': '41,33g'}
properties = {
"property-calories": "calories",
"property-carbohydrates": "carbohydrateContent",
"property-proteins": "proteinContent",
"property-fats": "fatContent",
}
recipe_properties = []
for pt in PropertyType.objects.filter(space=space, open_data_slug__in=list(properties.keys())).all():
for p in list(properties.keys()):
if pt.open_data_slug == p:
if properties[p] in property_data:
recipe_properties.append({
'property_type': {
'id': pt.id,
'name': pt.name,
},
'property_amount': parse_servings(property_data[properties[p]]) / float(property_data['servingSize']),
})
return recipe_properties
def get_from_youtube_scraper(url, request):
"""A YouTube Information Scraper."""
kw, created = Keyword.objects.get_or_create(name='YouTube', space=request.space)
@@ -225,10 +259,14 @@ def get_from_youtube_scraper(url, request):
}
try:
video = YouTube(url=url)
default_recipe_json['name'] = video.title
automation_engine = AutomationEngine(request, source=url)
video = YouTube(url)
video.streams.first() # this is required to execute some kind of generator/web request that fetches the description
default_recipe_json['name'] = automation_engine.apply_regex_replace_automation(video.title, Automation.NAME_REPLACE)
default_recipe_json['image'] = video.thumbnail_url
default_recipe_json['steps'][0]['instruction'] = video.description
if video.description:
default_recipe_json['steps'][0]['instruction'] = automation_engine.apply_regex_replace_automation(video.description, Automation.INSTRUCTION_REPLACE)
except Exception:
pass
@@ -236,7 +274,7 @@ def get_from_youtube_scraper(url, request):
def parse_name(name):
if type(name) == list:
if isinstance(name, list):
try:
name = name[0]
except Exception:
@@ -280,16 +318,16 @@ def parse_instructions(instructions):
"""
instruction_list = []
if type(instructions) == list:
if isinstance(instructions, list):
for i in instructions:
if type(i) == str:
if isinstance(i, str):
instruction_list.append(clean_instruction_string(i))
else:
if 'text' in i:
instruction_list.append(clean_instruction_string(i['text']))
elif 'itemListElement' in i:
for ile in i['itemListElement']:
if type(ile) == str:
if isinstance(ile, str):
instruction_list.append(clean_instruction_string(ile))
elif 'text' in ile:
instruction_list.append(clean_instruction_string(ile['text']))
@@ -305,13 +343,13 @@ def parse_image(image):
# check if list of images is returned, take first if so
if not image:
return None
if type(image) == list:
if isinstance(image, list):
for pic in image:
if (type(pic) == str) and (pic[:4] == 'http'):
if (isinstance(pic, str)) and (pic[:4] == 'http'):
image = pic
elif 'url' in pic:
image = pic['url']
elif type(image) == dict:
elif isinstance(image, dict):
if 'url' in image:
image = image['url']
@@ -322,12 +360,12 @@ def parse_image(image):
def parse_servings(servings):
if type(servings) == str:
if isinstance(servings, str):
try:
servings = int(re.search(r'\d+', servings).group())
except AttributeError:
servings = 1
elif type(servings) == list:
elif isinstance(servings, list):
try:
servings = int(re.findall(r'\b\d+\b', servings[0])[0])
except KeyError:
@@ -336,12 +374,12 @@ def parse_servings(servings):
def parse_servings_text(servings):
if type(servings) == str:
if isinstance(servings, str):
try:
servings = re.sub("\d+", '', servings).strip()
servings = re.sub("\\d+", '', servings).strip()
except Exception:
servings = ''
if type(servings) == list:
if isinstance(servings, list):
try:
servings = parse_servings_text(servings[1])
except Exception:
@@ -358,7 +396,7 @@ def parse_time(recipe_time):
recipe_time = round(iso_parse_duration(recipe_time).seconds / 60)
except ISO8601Error:
try:
if (type(recipe_time) == list and len(recipe_time) > 0):
if (isinstance(recipe_time, list) and len(recipe_time) > 0):
recipe_time = recipe_time[0]
recipe_time = round(parse_duration(recipe_time).seconds / 60)
except AttributeError:
@@ -367,18 +405,9 @@ def parse_time(recipe_time):
return recipe_time
def parse_keywords(keyword_json, space):
def parse_keywords(keyword_json, request):
keywords = []
keyword_aliases = {}
# retrieve keyword automation cache if it exists, otherwise build from database
KEYWORD_CACHE_KEY = f'automation_keyword_alias_{space.pk}'
if c := caches['default'].get(KEYWORD_CACHE_KEY, None):
self.food_aliases = c
caches['default'].touch(KEYWORD_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=space, disabled=False, type=Automation.KEYWORD_ALIAS).only('param_1', 'param_2').order_by('order').all():
keyword_aliases[a.param_1] = a.param_2
caches['default'].set(KEYWORD_CACHE_KEY, keyword_aliases, 30)
automation_engine = AutomationEngine(request)
# keywords as list
for kw in keyword_json:
@@ -386,12 +415,8 @@ def parse_keywords(keyword_json, space):
# if alias exists use that instead
if len(kw) != 0:
if keyword_aliases:
try:
kw = keyword_aliases[kw]
except KeyError:
pass
if k := Keyword.objects.filter(name=kw, space=space).first():
kw = automation_engine.apply_keyword_automation(kw)
if k := Keyword.objects.filter(name__iexact=kw, space=request.space).first():
keywords.append({'label': str(k), 'name': k.name, 'id': k.id})
else:
keywords.append({'label': kw, 'name': kw})
@@ -402,15 +427,15 @@ def parse_keywords(keyword_json, space):
def listify_keywords(keyword_list):
# keywords as string
try:
if type(keyword_list[0]) == dict:
if isinstance(keyword_list[0], dict):
return keyword_list
except (KeyError, IndexError):
pass
if type(keyword_list) == str:
if isinstance(keyword_list, str):
keyword_list = keyword_list.split(',')
# keywords as string in list
if (type(keyword_list) == list and len(keyword_list) == 1 and ',' in keyword_list[0]):
if (isinstance(keyword_list, list) and len(keyword_list) == 1 and ',' in keyword_list[0]):
keyword_list = keyword_list[0].split(',')
return [x.strip() for x in keyword_list]
@@ -464,13 +489,13 @@ def get_images_from_soup(soup, url):
def clean_dict(input_dict, key):
if type(input_dict) == dict:
if isinstance(input_dict, dict):
for x in list(input_dict):
if x == key:
del input_dict[x]
elif type(input_dict[x]) == dict:
elif isinstance(input_dict[x], dict):
input_dict[x] = clean_dict(input_dict[x], key)
elif type(input_dict[x]) == list:
elif isinstance(input_dict[x], list):
temp_list = []
for e in input_dict[x]:
temp_list.append(clean_dict(e, key))

View File

@@ -1,8 +1,6 @@
from django.urls import reverse
from django_scopes import scope, scopes_disabled
from oauth2_provider.contrib.rest_framework import OAuth2Authentication
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.exceptions import AuthenticationFailed
from cookbook.views import views
@@ -50,7 +48,6 @@ class ScopeMiddleware:
return views.no_groups(request)
request.space = user_space.space
# with scopes_disabled():
with scope(space=request.space):
return self.get_response(request)
else:

View File

@@ -1,16 +1,13 @@
from datetime import timedelta
from decimal import Decimal
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import F, OuterRef, Q, Subquery, Value
from django.db.models.functions import Coalesce
from django.utils import timezone
from django.utils.translation import gettext as _
from cookbook.helper.HelperFunctions import Round, str2bool
from cookbook.models import (Ingredient, MealPlan, Recipe, ShoppingListEntry, ShoppingListRecipe,
SupermarketCategoryRelation)
from recipes import settings
def shopping_helper(qs, request):
@@ -47,7 +44,7 @@ class RecipeShoppingEditor():
self.mealplan = self._kwargs.get('mealplan', None)
if type(self.mealplan) in [int, float]:
self.mealplan = MealPlan.objects.filter(id=self.mealplan, space=self.space)
if type(self.mealplan) == dict:
if isinstance(self.mealplan, dict):
self.mealplan = MealPlan.objects.filter(id=self.mealplan['id'], space=self.space).first()
self.id = self._kwargs.get('id', None)
@@ -69,11 +66,12 @@ class RecipeShoppingEditor():
@property
def _recipe_servings(self):
return getattr(self.recipe, 'servings', None) or getattr(getattr(self.mealplan, 'recipe', None), 'servings', None) or getattr(getattr(self._shopping_list_recipe, 'recipe', None), 'servings', None)
return getattr(self.recipe, 'servings', None) or getattr(getattr(self.mealplan, 'recipe', None), 'servings',
None) or getattr(getattr(self._shopping_list_recipe, 'recipe', None), 'servings', None)
@property
def _servings_factor(self):
return Decimal(self.servings)/Decimal(self._recipe_servings)
return Decimal(self.servings) / Decimal(self._recipe_servings)
@property
def _shared_users(self):
@@ -90,9 +88,10 @@ class RecipeShoppingEditor():
def get_recipe_ingredients(self, id, exclude_onhand=False):
if exclude_onhand:
return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space).exclude(food__onhand_users__id__in=[x.id for x in self._shared_users])
return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space).exclude(
food__onhand_users__id__in=[x.id for x in self._shared_users])
else:
return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space)
return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space)
@property
def _include_related(self):
@@ -109,7 +108,7 @@ class RecipeShoppingEditor():
self.servings = float(servings)
if mealplan := kwargs.get('mealplan', None):
if type(mealplan) == dict:
if isinstance(mealplan, dict):
self.mealplan = MealPlan.objects.filter(id=mealplan['id'], space=self.space).first()
else:
self.mealplan = mealplan
@@ -170,14 +169,14 @@ class RecipeShoppingEditor():
try:
self._shopping_list_recipe.delete()
return True
except:
except BaseException:
return False
def _add_ingredients(self, ingredients=None):
if not ingredients:
return
elif type(ingredients) == list:
ingredients = Ingredient.objects.filter(id__in=ingredients)
elif isinstance(ingredients, list):
ingredients = Ingredient.objects.filter(id__in=ingredients, food__ignore_shopping=False)
existing = self._shopping_list_recipe.entries.filter(ingredient__in=ingredients).values_list('ingredient__pk', flat=True)
add_ingredients = ingredients.exclude(id__in=existing)
@@ -199,120 +198,3 @@ class RecipeShoppingEditor():
to_delete = self._shopping_list_recipe.entries.exclude(ingredient__in=ingredients)
ShoppingListEntry.objects.filter(id__in=to_delete).delete()
self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space)
# # TODO refactor as class
# def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None, ingredients=None, created_by=None, space=None, append=False):
# """
# Creates ShoppingListRecipe and associated ShoppingListEntrys from a recipe or a meal plan with a recipe
# :param list_recipe: Modify an existing ShoppingListRecipe
# :param recipe: Recipe to use as list of ingredients. One of [recipe, mealplan] are required
# :param mealplan: alternatively use a mealplan recipe as source of ingredients
# :param servings: Optional: Number of servings to use to scale shoppinglist. If servings = 0 an existing recipe list will be deleted
# :param ingredients: Ingredients, list of ingredient IDs to include on the shopping list. When not provided all ingredients will be used
# :param append: If False will remove any entries not included with ingredients, when True will append ingredients to the shopping list
# """
# r = recipe or getattr(mealplan, 'recipe', None) or getattr(list_recipe, 'recipe', None)
# if not r:
# raise ValueError(_("You must supply a recipe or mealplan"))
# created_by = created_by or getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', None)
# if not created_by:
# raise ValueError(_("You must supply a created_by"))
# try:
# servings = float(servings)
# except (ValueError, TypeError):
# servings = getattr(mealplan, 'servings', 1.0)
# servings_factor = servings / r.servings
# shared_users = list(created_by.get_shopping_share())
# shared_users.append(created_by)
# if list_recipe:
# created = False
# else:
# list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings)
# created = True
# related_step_ing = []
# if servings == 0 and not created:
# list_recipe.delete()
# return []
# elif ingredients:
# ingredients = Ingredient.objects.filter(pk__in=ingredients, space=space)
# else:
# ingredients = Ingredient.objects.filter(step__recipe=r, food__ignore_shopping=False, space=space)
# if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
# ingredients = ingredients.exclude(food__onhand_users__id__in=[x.id for x in shared_users])
# if related := created_by.userpreference.mealplan_autoinclude_related:
# # TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans
# related_recipes = r.get_related_recipes()
# for x in related_recipes:
# # related recipe is a Step serving size is driven by recipe serving size
# # TODO once/if Steps can have a serving size this needs to be refactored
# if exclude_onhand:
# # if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior
# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]).values_list('id', flat=True)
# else:
# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True)
# x_ing = []
# if ingredients.filter(food__recipe=x).exists():
# for ing in ingredients.filter(food__recipe=x):
# if exclude_onhand:
# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users])
# else:
# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__ignore_shopping=True)
# for i in [x for x in x_ing]:
# ShoppingListEntry.objects.create(
# list_recipe=list_recipe,
# food=i.food,
# unit=i.unit,
# ingredient=i,
# amount=i.amount * Decimal(servings_factor),
# created_by=created_by,
# space=space,
# )
# # dont' add food to the shopping list that are actually recipes that will be added as ingredients
# ingredients = ingredients.exclude(food__recipe=x)
# add_ingredients = list(ingredients.values_list('id', flat=True)) + related_step_ing
# if not append:
# existing_list = ShoppingListEntry.objects.filter(list_recipe=list_recipe)
# # delete shopping list entries not included in ingredients
# existing_list.exclude(ingredient__in=ingredients).delete()
# # add shopping list entries that did not previously exist
# add_ingredients = set(add_ingredients) - set(existing_list.values_list('ingredient__id', flat=True))
# add_ingredients = Ingredient.objects.filter(id__in=add_ingredients, space=space)
# # if servings have changed, update the ShoppingListRecipe and existing Entries
# if servings <= 0:
# servings = 1
# if not created and list_recipe.servings != servings:
# update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True))
# list_recipe.servings = servings
# list_recipe.save()
# for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients):
# sle.amount = sle.ingredient.amount * Decimal(servings_factor)
# sle.save()
# # add any missing Entries
# for i in [x for x in add_ingredients if x.food]:
# ShoppingListEntry.objects.create(
# list_recipe=list_recipe,
# food=i.food,
# unit=i.unit,
# ingredient=i,
# amount=i.amount * Decimal(servings_factor),
# created_by=created_by,
# space=space,
# )
# # return all shopping list items
# return list_recipe

View File

@@ -2,7 +2,6 @@ from gettext import gettext as _
import bleach
import markdown as md
from bleach_allowlist import markdown_attrs, markdown_tags
from jinja2 import Template, TemplateSyntaxError, UndefinedError
from markdown.extensions.tables import TableExtension
@@ -53,9 +52,17 @@ class IngredientObject(object):
def render_instructions(step): # TODO deduplicate markdown cleanup code
instructions = step.instruction
tags = markdown_tags + [
'pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead', 'img'
]
tags = {
"h1", "h2", "h3", "h4", "h5", "h6",
"b", "i", "strong", "em", "tt",
"p", "br",
"span", "div", "blockquote", "code", "pre", "hr",
"ul", "ol", "li", "dd", "dt",
"img",
"a",
"sub", "sup",
'pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead'
}
parsed_md = md.markdown(
instructions,
extensions=[
@@ -63,7 +70,11 @@ def render_instructions(step): # TODO deduplicate markdown cleanup code
UrlizeExtension(), MarkdownFormatExtension()
]
)
markdown_attrs['*'] = markdown_attrs['*'] + ['class', 'width', 'height']
markdown_attrs = {
"*": ["id", "class", 'width', 'height'],
"img": ["src", "alt", "title"],
"a": ["href", "alt", "title"],
}
instructions = bleach.clean(parsed_md, tags, markdown_attrs)

View File

@@ -0,0 +1,141 @@
from django.core.cache import caches
from decimal import Decimal
from cookbook.helper.cache_helper import CacheHelper
from cookbook.models import Ingredient, Unit
CONVERSION_TABLE = {
'weight': {
'g': 1000,
'kg': 1,
'ounce': 35.274,
'pound': 2.20462
},
'volume': {
'ml': 1000,
'l': 1,
'fluid_ounce': 33.814,
'pint': 2.11338,
'quart': 1.05669,
'gallon': 0.264172,
'tbsp': 67.628,
'tsp': 202.884,
'imperial_fluid_ounce': 35.1951,
'imperial_pint': 1.75975,
'imperial_quart': 0.879877,
'imperial_gallon': 0.219969,
'imperial_tbsp': 56.3121,
'imperial_tsp': 168.936,
},
}
BASE_UNITS_WEIGHT = list(CONVERSION_TABLE['weight'].keys())
BASE_UNITS_VOLUME = list(CONVERSION_TABLE['volume'].keys())
class ConversionException(Exception):
pass
class UnitConversionHelper:
space = None
def __init__(self, space):
"""
Initializes unit conversion helper
:param space: space to perform conversions on
"""
self.space = space
@staticmethod
def convert_from_to(from_unit, to_unit, amount):
"""
Convert from one base unit to another. Throws ConversionException if trying to convert between different systems (weight/volume) or if units are not supported.
:param from_unit: str unit to convert from
:param to_unit: str unit to convert to
:param amount: amount to convert
:return: Decimal converted amount
"""
system = None
if from_unit in BASE_UNITS_WEIGHT and to_unit in BASE_UNITS_WEIGHT:
system = 'weight'
if from_unit in BASE_UNITS_VOLUME and to_unit in BASE_UNITS_VOLUME:
system = 'volume'
if not system:
raise ConversionException('Trying to convert units not existing or not in one unit system (weight/volume)')
return Decimal(amount / Decimal(CONVERSION_TABLE[system][from_unit] / CONVERSION_TABLE[system][to_unit]))
def base_conversions(self, ingredient_list):
"""
Calculates all possible base unit conversions for each ingredient give.
Converts to all common base units IF they exist in the unit database of the space.
For useful results all ingredients passed should be of the same food, otherwise filtering afterwards might be required.
:param ingredient_list: list of ingredients to convert
:return: ingredient list with appended conversions
"""
base_conversion_ingredient_list = ingredient_list.copy()
for i in ingredient_list:
try:
conversion_unit = i.unit.name
if i.unit.base_unit:
conversion_unit = i.unit.base_unit
# TODO allow setting which units to convert to? possibly only once conversions become visible
units = caches['default'].get(CacheHelper(self.space).BASE_UNITS_CACHE_KEY, None)
if not units:
units = Unit.objects.filter(space=self.space, base_unit__in=(BASE_UNITS_VOLUME + BASE_UNITS_WEIGHT)).all()
caches['default'].set(CacheHelper(self.space).BASE_UNITS_CACHE_KEY, units, 60 * 60) # cache is cleared on unit save signal so long duration is fine
for u in units:
try:
ingredient = Ingredient(amount=self.convert_from_to(conversion_unit, u.base_unit, i.amount), unit=u, food=ingredient_list[0].food, )
if not any((x.unit.name == ingredient.unit.name or x.unit.base_unit == ingredient.unit.name) for x in base_conversion_ingredient_list):
base_conversion_ingredient_list.append(ingredient)
except ConversionException:
pass
except Exception:
pass
return base_conversion_ingredient_list
def get_conversions(self, ingredient):
"""
Converts an ingredient to all possible conversions based on the custom unit conversion database.
After that passes conversion to UnitConversionHelper.base_conversions() to get all base conversions possible.
:param ingredient: Ingredient object
:return: list of ingredients with all possible custom and base conversions
"""
conversions = [ingredient]
if ingredient.unit:
for c in ingredient.unit.unit_conversion_base_relation.all():
if c.space == self.space:
r = self._uc_convert(c, ingredient.amount, ingredient.unit, ingredient.food)
if r and r not in conversions:
conversions.append(r)
for c in ingredient.unit.unit_conversion_converted_relation.all():
if c.space == self.space:
r = self._uc_convert(c, ingredient.amount, ingredient.unit, ingredient.food)
if r and r not in conversions:
conversions.append(r)
conversions = self.base_conversions(conversions)
return conversions
def _uc_convert(self, uc, amount, unit, food):
"""
Helper to calculate values for custom unit conversions.
Converts given base values using the passed UnitConversion object into a converted Ingredient
:param uc: UnitConversion object
:param amount: base amount
:param unit: base unit
:param food: base food
:return: converted ingredient object from base amount/unit/food
"""
if uc.food is None or uc.food == food:
if unit == uc.base_unit:
return Ingredient(amount=amount * (uc.converted_amount / uc.base_amount), unit=uc.converted_unit, food=food, space=self.space)
else:
return Ingredient(amount=amount * (uc.base_amount / uc.converted_amount), unit=uc.base_unit, food=food, space=self.space)

View File

@@ -36,7 +36,7 @@ class ChefTap(Integration):
recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True, space=self.request.space, )
step = Step.objects.create(instruction='\n'.join(directions), space=self.request.space,)
step = Step.objects.create(instruction='\n'.join(directions), space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,)
if source_url != '':
step.instruction += '\n' + source_url

View File

@@ -4,6 +4,7 @@ from zipfile import ZipFile
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text, parse_time
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Keyword, Recipe, Step
@@ -19,6 +20,10 @@ class Chowdown(Integration):
direction_mode = False
description_mode = False
description = None
prep_time = None
serving = None
ingredients = []
directions = []
descriptions = []
@@ -26,6 +31,12 @@ class Chowdown(Integration):
line = fl.decode("utf-8")
if 'title:' in line:
title = line.replace('title:', '').replace('"', '').strip()
if 'description:' in line:
description = line.replace('description:', '').replace('"', '').strip()
if 'prep_time:' in line:
prep_time = line.replace('prep_time:', '').replace('"', '').strip()
if 'yield:' in line:
serving = line.replace('yield:', '').replace('"', '').strip()
if 'image:' in line:
image = line.replace('image:', '').strip()
if 'tags:' in line:
@@ -48,15 +59,43 @@ class Chowdown(Integration):
descriptions.append(line)
recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True, space=self.request.space)
if description:
recipe.description = description
for k in tags.split(','):
print(f'adding keyword {k.strip()}')
keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
recipe.keywords.add(keyword)
step = Step.objects.create(
instruction='\n'.join(directions) + '\n\n' + '\n'.join(descriptions), space=self.request.space,
)
ingredients_added = False
for direction in directions:
if len(direction.strip()) > 0:
step = Step.objects.create(
instruction=direction, name='', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
else:
step = Step.objects.create(
instruction=direction, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
if not ingredients_added:
ingredients_added = True
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
if len(ingredient.strip()) > 0:
amount, unit, food, note = ingredient_parser.parse(ingredient)
f = ingredient_parser.get_food(food)
u = ingredient_parser.get_unit(unit)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
))
recipe.steps.add(step)
if serving:
recipe.servings = parse_servings(serving)
recipe.servings_text = 'servings'
if prep_time:
recipe.working_time = parse_time(prep_time)
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
@@ -76,6 +115,7 @@ class Chowdown(Integration):
if re.match(f'^images/{image}$', z.filename):
self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename)), filetype=get_filetype(z.filename))
recipe.save()
return recipe
def get_file_from_recipe(self, recipe):

View File

@@ -1,20 +1,15 @@
import base64
import gzip
import json
import re
from gettext import gettext as _
from io import BytesIO
import requests
import validators
import yaml
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import (get_from_scraper, get_images_from_soup,
iso_duration_to_minutes)
from cookbook.helper.scrapers.scrapers import text_scraper
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Keyword, Recipe, Step
from cookbook.models import Ingredient, Recipe, Step
class CookBookApp(Integration):
@@ -25,7 +20,6 @@ class CookBookApp(Integration):
def get_recipe_from_file(self, file):
recipe_html = file.getvalue().decode("utf-8")
# recipe_json, recipe_tree, html_data, images = get_recipe_from_source(recipe_html, 'CookBookApp', self.request)
scrape = text_scraper(text=recipe_html)
recipe_json = get_from_scraper(scrape, self.request)
images = list(dict.fromkeys(get_images_from_soup(scrape.soup, None)))
@@ -37,7 +31,7 @@ class CookBookApp(Integration):
try:
recipe.servings = re.findall('([0-9])+', recipe_json['recipeYield'])[0]
except Exception as e:
except Exception:
pass
try:
@@ -47,7 +41,8 @@ class CookBookApp(Integration):
pass
# assuming import files only contain single step
step = Step.objects.create(instruction=recipe_json['steps'][0]['instruction'], space=self.request.space, )
step = Step.objects.create(instruction=recipe_json['steps'][0]['instruction'], space=self.request.space,
show_ingredients_table=self.request.user.userpreference.show_step_ingredients, )
if 'nutrition' in recipe_json:
step.instruction = step.instruction + '\n\n' + recipe_json['nutrition']
@@ -62,7 +57,7 @@ class CookBookApp(Integration):
if unit := ingredient.get('unit', None):
u = ingredient_parser.get_unit(unit.get('name', None))
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=ingredient.get('amount', None), note=ingredient.get('note', None), original_text=ingredient.get('original_text', None), space=self.request.space,
food=f, unit=u, amount=ingredient.get('amount', None), note=ingredient.get('note', None), original_text=ingredient.get('original_text', None), space=self.request.space,
))
if len(images) > 0:

View File

@@ -1,17 +1,12 @@
import base64
import json
from io import BytesIO
from gettext import gettext as _
import requests
import validators
from lxml import etree
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_time, parse_servings_text
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text, parse_time
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Keyword, Recipe, Step
from cookbook.models import Ingredient, Recipe, Step
class Cookmate(Integration):
@@ -50,7 +45,7 @@ class Cookmate(Integration):
for step in recipe_text.getchildren():
if step.text:
step = Step.objects.create(
instruction=step.text.strip(), space=self.request.space,
instruction=step.text.strip(), space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
recipe.steps.add(step)

View File

@@ -1,4 +1,3 @@
import re
from io import BytesIO
from zipfile import ZipFile
@@ -26,12 +25,13 @@ class CopyMeThat(Integration):
except AttributeError:
source = None
recipe = Recipe.objects.create(name=file.find("div", {"id": "name"}).text.strip()[:128], source_url=source, created_by=self.request.user, internal=True, space=self.request.space, )
recipe = Recipe.objects.create(name=file.find("div", {"id": "name"}).text.strip(
)[:128], source_url=source, created_by=self.request.user, internal=True, space=self.request.space, )
for category in file.find_all("span", {"class": "recipeCategory"}):
keyword, created = Keyword.objects.get_or_create(name=category.text, space=self.request.space)
recipe.keywords.add(keyword)
try:
recipe.servings = parse_servings(file.find("a", {"id": "recipeYield"}).text.strip())
recipe.working_time = iso_duration_to_minutes(file.find("span", {"meta": "prepTime"}).text.strip())
@@ -51,7 +51,7 @@ class CopyMeThat(Integration):
except AttributeError:
pass
step = Step.objects.create(instruction='', space=self.request.space, )
step = Step.objects.create(instruction='', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, )
ingredient_parser = IngredientParser(self.request, True)
@@ -61,7 +61,14 @@ class CopyMeThat(Integration):
if not isinstance(ingredient, Tag) or not ingredient.text.strip() or "recipeIngredient_spacer" in ingredient['class']:
continue
if any(x in ingredient['class'] for x in ["recipeIngredient_subheader", "recipeIngredient_note"]):
step.ingredients.add(Ingredient.objects.create(is_header=True, note=ingredient.text.strip()[:256], original_text=ingredient.text.strip(), space=self.request.space, ))
step.ingredients.add(
Ingredient.objects.create(
is_header=True,
note=ingredient.text.strip()[
:256],
original_text=ingredient.text.strip(),
space=self.request.space,
))
else:
amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
f = ingredient_parser.get_food(food)
@@ -78,7 +85,7 @@ class CopyMeThat(Integration):
step.save()
recipe.steps.add(step)
step = Step.objects.create(instruction='', space=self.request.space, )
step.name = instruction.text.strip()[:128]
else:
step.instruction += instruction.text.strip() + ' \n\n'

View File

@@ -1,4 +1,5 @@
import json
import traceback
from io import BytesIO, StringIO
from re import match
from zipfile import ZipFile
@@ -19,7 +20,10 @@ class Default(Integration):
recipe = self.decode_recipe(recipe_string)
images = list(filter(lambda v: match('image.*', v), recipe_zip.namelist()))
if images:
self.import_recipe_image(recipe, BytesIO(recipe_zip.read(images[0])), filetype=get_filetype(images[0]))
try:
self.import_recipe_image(recipe, BytesIO(recipe_zip.read(images[0])), filetype=get_filetype(images[0]))
except AttributeError:
traceback.print_exc()
return recipe
def decode_recipe(self, string):
@@ -54,7 +58,7 @@ class Default(Integration):
try:
recipe_zip_obj.writestr(f'image{get_filetype(r.image.file.name)}', r.image.file.read())
except ValueError:
except (ValueError, FileNotFoundError):
pass
recipe_zip_obj.close()
@@ -67,4 +71,4 @@ class Default(Integration):
export_zip_obj.close()
return [[ self.get_export_file_name(), export_zip_stream.getvalue() ]]
return [[self.get_export_file_name(), export_zip_stream.getvalue()]]

View File

@@ -28,7 +28,7 @@ class Domestica(Integration):
recipe.save()
step = Step.objects.create(
instruction=file['directions'], space=self.request.space,
instruction=file['directions'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
if file['source'] != '':

View File

@@ -1,4 +1,3 @@
import traceback
import datetime
import traceback
import uuid
@@ -18,8 +17,7 @@ from lxml import etree
from cookbook.helper.image_processing import handle_image
from cookbook.models import Keyword, Recipe
from recipes.settings import DEBUG
from recipes.settings import EXPORT_FILE_CACHE_DURATION
from recipes.settings import DEBUG, EXPORT_FILE_CACHE_DURATION
class Integration:
@@ -39,7 +37,6 @@ class Integration:
self.ignored_recipes = []
description = f'Imported by {request.user.get_user_display_name()} at {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}. Type: {export_type}'
icon = '📥'
try:
last_kw = Keyword.objects.filter(name__regex=r'^(Import [0-9]+)', space=request.space).latest('created_at')
@@ -52,23 +49,19 @@ class Integration:
self.keyword = parent.add_child(
name=name,
description=description,
icon=icon,
space=request.space
)
except (IntegrityError, ValueError): # in case, for whatever reason, the name does exist append UUID to it. Not nice but works for now.
self.keyword = parent.add_child(
name=f'{name} {str(uuid.uuid4())[0:8]}',
description=description,
icon=icon,
space=request.space
)
def do_export(self, recipes, el):
with scope(space=self.request.space):
el.total_recipes = len(recipes)
el.total_recipes = len(recipes)
el.cache_duration = EXPORT_FILE_CACHE_DURATION
el.save()
@@ -80,7 +73,7 @@ class Integration:
export_file = file
else:
#zip the files if there is more then one file
# zip the files if there is more then one file
export_filename = self.get_export_file_name()
export_stream = BytesIO()
export_obj = ZipFile(export_stream, 'w')
@@ -91,8 +84,7 @@ class Integration:
export_obj.close()
export_file = export_stream.getvalue()
cache.set('export_file_'+str(el.pk), {'filename': export_filename, 'file': export_file}, EXPORT_FILE_CACHE_DURATION)
cache.set('export_file_' + str(el.pk), {'filename': export_filename, 'file': export_file}, EXPORT_FILE_CACHE_DURATION)
el.running = False
el.save()
@@ -100,7 +92,6 @@ class Integration:
response['Content-Disposition'] = 'attachment; filename="' + export_filename + '"'
return response
def import_file_name_filter(self, zip_info_object):
"""
Since zipfile.namelist() returns all files in all subdirectories this function allows filtering of files
@@ -164,7 +155,7 @@ class Integration:
for z in file_list:
try:
if not hasattr(z, 'filename') or type(z) == Tag:
if not hasattr(z, 'filename') or isinstance(z, Tag):
recipe = self.get_recipe_from_file(z)
else:
recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename)))
@@ -298,7 +289,6 @@ class Integration:
if DEBUG:
traceback.print_exc()
def get_export_file_name(self, format='zip'):
return "export_{}.{}".format(datetime.datetime.now().strftime("%Y-%m-%d"), format)

View File

@@ -7,7 +7,7 @@ from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text, parse_time
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step
from cookbook.models import Ingredient, Keyword, Recipe, Step
class Mealie(Integration):
@@ -25,7 +25,7 @@ class Mealie(Integration):
created_by=self.request.user, internal=True, space=self.request.space)
for s in recipe_json['recipe_instructions']:
step = Step.objects.create(instruction=s['text'], space=self.request.space, )
step = Step.objects.create(instruction=s['text'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, )
recipe.steps.add(step)
step = recipe.steps.first()
@@ -56,6 +56,12 @@ class Mealie(Integration):
except Exception:
pass
if 'tags' in recipe_json and len(recipe_json['tags']) > 0:
for k in recipe_json['tags']:
if 'name' in k:
keyword, created = Keyword.objects.get_or_create(name=k['name'].strip(), space=self.request.space)
recipe.keywords.add(keyword)
if 'notes' in recipe_json and len(recipe_json['notes']) > 0:
notes_text = "#### Notes \n\n"
for n in recipe_json['notes']:

View File

@@ -39,7 +39,7 @@ class MealMaster(Integration):
recipe.keywords.add(keyword)
step = Step.objects.create(
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
instruction='\n'.join(directions) + '\n\n', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
ingredient_parser = IngredientParser(self.request, True)

View File

@@ -57,7 +57,7 @@ class MelaRecipes(Integration):
recipe.source_url = recipe_json['link']
step = Step.objects.create(
instruction=instruction, space=self.request.space,
instruction=instruction, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients
)
ingredient_parser = IngredientParser(self.request, True)

View File

@@ -2,13 +2,14 @@ import json
import re
from io import BytesIO, StringIO
from zipfile import ZipFile
from PIL import Image
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import iso_duration_to_minutes
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Keyword, Recipe, Step, NutritionInformation
from cookbook.models import Ingredient, Keyword, NutritionInformation, Recipe, Step
class NextcloudCookbook(Integration):
@@ -51,9 +52,14 @@ class NextcloudCookbook(Integration):
ingredients_added = False
for s in recipe_json['recipeInstructions']:
step = Step.objects.create(
instruction=s, space=self.request.space,
)
if 'text' in s:
step = Step.objects.create(
instruction=s['text'], name=s['name'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
else:
step = Step.objects.create(
instruction=s, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
if not ingredients_added:
if len(recipe_json['description'].strip()) > 500:
step.instruction = recipe_json['description'].strip() + '\n\n' + step.instruction
@@ -85,7 +91,7 @@ class NextcloudCookbook(Integration):
if nutrition != {}:
recipe.nutrition = NutritionInformation.objects.create(**nutrition, space=self.request.space)
recipe.save()
except Exception as e:
except Exception:
pass
for f in self.files:
@@ -98,11 +104,10 @@ class NextcloudCookbook(Integration):
return recipe
def formatTime(self, min):
h = min//60
h = min // 60
m = min % 60
return f'PT{h}H{m}M0S'
def get_file_from_recipe(self, recipe):
export = {}
@@ -111,7 +116,7 @@ class NextcloudCookbook(Integration):
export['url'] = recipe.source_url
export['prepTime'] = self.formatTime(recipe.working_time)
export['cookTime'] = self.formatTime(recipe.waiting_time)
export['totalTime'] = self.formatTime(recipe.working_time+recipe.waiting_time)
export['totalTime'] = self.formatTime(recipe.working_time + recipe.waiting_time)
export['recipeYield'] = recipe.servings
export['image'] = f'/Recipes/{recipe.name}/full.jpg'
export['imageUrl'] = f'/Recipes/{recipe.name}/full.jpg'
@@ -133,7 +138,6 @@ class NextcloudCookbook(Integration):
export['recipeIngredient'] = recipeIngredient
export['recipeInstructions'] = recipeInstructions
return "recipe.json", json.dumps(export)
def get_files_from_recipes(self, recipes, el, cookie):
@@ -163,7 +167,7 @@ class NextcloudCookbook(Integration):
export_zip_obj.close()
return [[ self.get_export_file_name(), export_zip_stream.getvalue() ]]
return [[self.get_export_file_name(), export_zip_stream.getvalue()]]
def getJPEG(self, imageByte):
image = Image.open(BytesIO(imageByte))
@@ -172,14 +176,14 @@ class NextcloudCookbook(Integration):
bytes = BytesIO()
image.save(bytes, "JPEG")
return bytes.getvalue()
def getThumb(self, size, imageByte):
image = Image.open(BytesIO(imageByte))
w, h = image.size
m = min(w, h)
m = min(w, h)
image = image.crop(((w-m)//2, (h-m)//2, (w+m)//2, (h+m)//2))
image = image.crop(((w - m) // 2, (h - m) // 2, (w + m) // 2, (h + m) // 2))
image = image.resize([size, size], Image.Resampling.LANCZOS)
image = image.convert('RGB')

View File

@@ -1,9 +1,11 @@
import json
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step, Keyword, Comment, CookLog
from django.utils.translation import gettext as _
from cookbook.models import Comment, CookLog, Ingredient, Keyword, Recipe, Step
class OpenEats(Integration):
@@ -25,16 +27,16 @@ class OpenEats(Integration):
if file["source"] != '':
instructions += '\n' + _('Recipe source:') + f'[{file["source"]}]({file["source"]})'
cuisine_keyword, created = Keyword.objects.get_or_create(name="Cuisine", space=self.request.space)
cuisine_keyword, created = Keyword.objects.get_or_create(name="Cuisine", space=self.request.space)
if file["cuisine"] != '':
keyword, created = Keyword.objects.get_or_create(name=file["cuisine"].strip(), space=self.request.space)
keyword, created = Keyword.objects.get_or_create(name=file["cuisine"].strip(), space=self.request.space)
if created:
keyword.move(cuisine_keyword, pos="last-child")
recipe.keywords.add(keyword)
course_keyword, created = Keyword.objects.get_or_create(name="Course", space=self.request.space)
course_keyword, created = Keyword.objects.get_or_create(name="Course", space=self.request.space)
if file["course"] != '':
keyword, created = Keyword.objects.get_or_create(name=file["course"].strip(), space=self.request.space)
keyword, created = Keyword.objects.get_or_create(name=file["course"].strip(), space=self.request.space)
if created:
keyword.move(course_keyword, pos="last-child")
recipe.keywords.add(keyword)
@@ -51,7 +53,7 @@ class OpenEats(Integration):
recipe.image = f'recipes/openeats-import/{file["photo"]}'
recipe.save()
step = Step.objects.create(instruction=instructions, space=self.request.space,)
step = Step.objects.create(instruction=instructions, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,)
ingredient_parser = IngredientParser(self.request, True)
for ingredient in file['ingredients']:

View File

@@ -58,7 +58,7 @@ class Paprika(Integration):
pass
step = Step.objects.create(
instruction=instructions, space=self.request.space,
instruction=instructions, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
if 'description' in recipe_json and len(recipe_json['description'].strip()) > 500:
@@ -90,7 +90,7 @@ class Paprika(Integration):
if validators.url(url, public=True):
response = requests.get(url)
self.import_recipe_image(recipe, BytesIO(response.content))
except:
except Exception:
if recipe_json.get("photo_data", None):
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_json['photo_data'])), filetype='.jpeg')

View File

@@ -1,21 +1,11 @@
import json
from io import BytesIO
from re import match
from zipfile import ZipFile
import asyncio
from pyppeteer import launch
from rest_framework.renderers import JSONRenderer
from cookbook.helper.image_processing import get_filetype
from cookbook.integration.integration import Integration
from cookbook.serializer import RecipeExportSerializer
from cookbook.models import ExportLog
from asgiref.sync import sync_to_async
import django.core.management.commands.runserver as runserver
import logging
from asgiref.sync import sync_to_async
from pyppeteer import launch
from cookbook.integration.integration import Integration
class PDFexport(Integration):
@@ -42,7 +32,6 @@ class PDFexport(Integration):
}
}
files = []
for recipe in recipes:
@@ -50,20 +39,18 @@ class PDFexport(Integration):
await page.emulateMedia('print')
await page.setCookie(cookies)
await page.goto('http://'+cmd.default_addr+':'+cmd.default_port+'/view/recipe/'+str(recipe.id), {'waitUntil': 'domcontentloaded'})
await page.waitForSelector('#printReady');
await page.goto('http://' + cmd.default_addr + ':' + cmd.default_port + '/view/recipe/' + str(recipe.id), {'waitUntil': 'domcontentloaded'})
await page.waitForSelector('#printReady')
files.append([recipe.name + '.pdf', await page.pdf(options)])
await page.close();
await page.close()
el.exported_recipes += 1
el.msg += self.get_recipe_processed_msg(recipe)
await sync_to_async(el.save, thread_sensitive=True)()
await browser.close()
return files
def get_files_from_recipes(self, recipes, el, cookie):
return asyncio.run(self.get_files_from_recipes_async(recipes, el, cookie))

View File

@@ -35,7 +35,7 @@ class Pepperplate(Integration):
recipe = Recipe.objects.create(name=title, description=description, created_by=self.request.user, internal=True, space=self.request.space)
step = Step.objects.create(
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
instruction='\n'.join(directions) + '\n\n', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
ingredient_parser = IngredientParser(self.request, True)

View File

@@ -1,6 +1,7 @@
from io import BytesIO
import requests
import validators
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.integration.integration import Integration
@@ -45,7 +46,7 @@ class Plantoeat(Integration):
recipe = Recipe.objects.create(name=title, description=description, created_by=self.request.user, internal=True, space=self.request.space)
step = Step.objects.create(
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
instruction='\n'.join(directions) + '\n\n', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
if tags:
@@ -67,8 +68,9 @@ class Plantoeat(Integration):
if image_url:
try:
response = requests.get(image_url)
self.import_recipe_image(recipe, BytesIO(response.content))
if validators.url(image_url, public=True):
response = requests.get(image_url)
self.import_recipe_image(recipe, BytesIO(response.content))
except Exception as e:
print('failed to import image ', str(e))

View File

@@ -46,7 +46,7 @@ class RecetteTek(Integration):
if not instructions:
instructions = ''
step = Step.objects.create(instruction=instructions, space=self.request.space,)
step = Step.objects.create(instruction=instructions, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,)
# Append the original import url to the step (if it exists)
try:

View File

@@ -41,7 +41,7 @@ class RecipeKeeper(Integration):
except AttributeError:
pass
step = Step.objects.create(instruction='', space=self.request.space, )
step = Step.objects.create(instruction='', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, )
ingredient_parser = IngredientParser(self.request, True)
for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):

View File

@@ -5,6 +5,7 @@ import requests
import validators
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text, parse_time
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step
@@ -18,25 +19,27 @@ class RecipeSage(Integration):
created_by=self.request.user, internal=True,
space=self.request.space)
if file['recipeYield'] != '':
recipe.servings = parse_servings(file['recipeYield'])
recipe.servings_text = parse_servings_text(file['recipeYield'])
try:
if file['recipeYield'] != '':
recipe.servings = int(file['recipeYield'])
if 'totalTime' in file and file['totalTime'] != '':
recipe.working_time = parse_time(file['totalTime'])
if file['totalTime'] != '':
recipe.waiting_time = int(file['totalTime']) - int(file['timePrep'])
if file['prepTime'] != '':
recipe.working_time = int(file['timePrep'])
recipe.save()
if 'timePrep' in file and file['prepTime'] != '':
recipe.working_time = parse_time(file['timePrep'])
recipe.waiting_time = parse_time(file['totalTime']) - parse_time(file['timePrep'])
except Exception as e:
print('failed to parse yield or time ', str(e))
print('failed to parse time ', str(e))
recipe.save()
ingredient_parser = IngredientParser(self.request, True)
ingredients_added = False
for s in file['recipeInstructions']:
step = Step.objects.create(
instruction=s['text'], space=self.request.space,
instruction=s['text'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
if not ingredients_added:
ingredients_added = True

View File

@@ -2,12 +2,10 @@ import base64
from io import BytesIO
from xml import etree
from lxml import etree
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import parse_time, parse_servings, parse_servings_text
from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text
from cookbook.integration.integration import Integration
from cookbook.models import Ingredient, Recipe, Step, Keyword
from cookbook.models import Ingredient, Keyword, Recipe, Step
class Rezeptsuitede(Integration):
@@ -22,9 +20,12 @@ class Rezeptsuitede(Integration):
name=recipe_xml.find('head').attrib['title'].strip(),
created_by=self.request.user, internal=True, space=self.request.space)
if recipe_xml.find('head').attrib['servingtype']:
recipe.servings = parse_servings(recipe_xml.find('head').attrib['servingtype'].strip())
recipe.servings_text = parse_servings_text(recipe_xml.find('head').attrib['servingtype'].strip())
try:
if recipe_xml.find('head').attrib['servingtype']:
recipe.servings = parse_servings(recipe_xml.find('head').attrib['servingtype'].strip())
recipe.servings_text = parse_servings_text(recipe_xml.find('head').attrib['servingtype'].strip())
except KeyError:
pass
if recipe_xml.find('remark') is not None: # description is a list of <li>'s with text
if recipe_xml.find('remark').find('line') is not None:
@@ -34,7 +35,7 @@ class Rezeptsuitede(Integration):
try:
if prep.find('step').text:
step = Step.objects.create(
instruction=prep.find('step').text.strip(), space=self.request.space,
instruction=prep.find('step').text.strip(), space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
recipe.steps.add(step)
except Exception:
@@ -50,20 +51,22 @@ class Rezeptsuitede(Integration):
for ingredient in recipe_xml.find('part').findall('ingredient'):
f = ingredient_parser.get_food(ingredient.attrib['item'])
u = ingredient_parser.get_unit(ingredient.attrib['unit'])
amount, unit, note = ingredient_parser.parse_amount(ingredient.attrib['qty'])
amount = 0
if ingredient.attrib['qty'].strip() != '':
amount, unit, note = ingredient_parser.parse_amount(ingredient.attrib['qty'])
ingredient_step.ingredients.add(Ingredient.objects.create(food=f, unit=u, amount=amount, space=self.request.space, ))
try:
k, created = Keyword.objects.get_or_create(name=recipe_xml.find('head').find('cat').text.strip(), space=self.request.space)
recipe.keywords.add(k)
except Exception as e:
except Exception:
pass
recipe.save()
try:
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_xml.find('head').find('picbin').text)), filetype='.jpeg')
except:
except BaseException:
pass
return recipe

View File

@@ -38,7 +38,7 @@ class RezKonv(Integration):
recipe.keywords.add(keyword)
step = Step.objects.create(
instruction=' \n'.join(directions) + '\n\n', space=self.request.space,
instruction=' \n'.join(directions) + '\n\n', space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,
)
ingredient_parser = IngredientParser(self.request, True)
@@ -60,8 +60,8 @@ class RezKonv(Integration):
def split_recipe_file(self, file):
recipe_list = []
current_recipe = ''
encoding_list = ['windows-1250',
'latin-1'] # TODO build algorithm to try trough encodings and fail if none work, use for all importers
# TODO build algorithm to try trough encodings and fail if none work, use for all importers
# encoding_list = ['windows-1250', 'latin-1']
encoding = 'windows-1250'
for fl in file.readlines():
try:

View File

@@ -43,7 +43,7 @@ class Saffron(Integration):
recipe = Recipe.objects.create(name=title, description=description, created_by=self.request.user, internal=True, space=self.request.space, )
step = Step.objects.create(instruction='\n'.join(directions), space=self.request.space, )
step = Step.objects.create(instruction='\n'.join(directions), space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, )
ingredient_parser = IngredientParser(self.request, True)
for ingredient in ingredients:
@@ -59,11 +59,11 @@ class Saffron(Integration):
def get_file_from_recipe(self, recipe):
data = "Title: "+recipe.name if recipe.name else ""+"\n"
data += "Description: "+recipe.description if recipe.description else ""+"\n"
data = "Title: " + recipe.name if recipe.name else "" + "\n"
data += "Description: " + recipe.description if recipe.description else "" + "\n"
data += "Source: \n"
data += "Original URL: \n"
data += "Yield: "+str(recipe.servings)+"\n"
data += "Yield: " + str(recipe.servings) + "\n"
data += "Cookbook: \n"
data += "Section: \n"
data += "Image: \n"
@@ -78,13 +78,13 @@ class Saffron(Integration):
data += "Ingredients: \n"
for ingredient in recipeIngredient:
data += ingredient+"\n"
data += ingredient + "\n"
data += "Instructions: \n"
for instruction in recipeInstructions:
data += instruction+"\n"
data += instruction + "\n"
return recipe.name+'.txt', data
return recipe.name + '.txt', data
def get_files_from_recipes(self, recipes, el, cookie):
files = []

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-04-29 18:42+0200\n"
"PO-Revision-Date: 2022-07-06 14:32+0000\n"
"Last-Translator: Nidhal Brniyah <n1a1b1@gmail.com>\n"
"PO-Revision-Date: 2023-11-28 11:03+0000\n"
"Last-Translator: Mahmoud Aljouhari <mapgohary@gmail.com>\n"
"Language-Team: Arabic <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/ar/>\n"
"Language: ar\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.15\n"
#: .\cookbook\filters.py:23 .\cookbook\templates\forms\ingredients.html:34
#: .\cookbook\templates\space.html:49 .\cookbook\templates\stats.html:28
@@ -2578,7 +2578,7 @@ msgstr ""
#: .\cookbook\views\views.py:262
msgid "This feature is not available in the demo version!"
msgstr ""
msgstr "هذه الميزة غير موجودة في النسخة التجريبية!"
#: .\cookbook\views\views.py:322
msgid "You must select at least one field to search!"

View File

@@ -12,9 +12,9 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-07-06 21:19+0000\n"
"Last-Translator: Rubens <rubenixnagios@gmail.com>\n"
"Language-Team: Catalan <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/ca/>\n"
"Language: ca\n"
@@ -116,7 +116,7 @@ msgstr "Nombre de decimals dels ingredients."
msgid "If you want to be able to create and see comments underneath recipes."
msgstr "Si vols poder crear i veure comentaris a sota de les receptes."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -133,7 +133,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "Barra de navegació s'enganxi a la part superior de la pàgina."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
"Afegeix automàticament els ingredients del pla d'àpats a la llista de la "
@@ -155,11 +155,11 @@ msgstr ""
"Tots dos camps són opcionals. Si no se'n dóna cap, es mostrarà el nom "
"d'usuari"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Nom"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Paraules clau"
@@ -171,7 +171,7 @@ msgstr "Temps de preparació en minuts"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Temps d'espera (cocció/fornejat) en minuts"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Ruta"
@@ -183,7 +183,7 @@ msgstr "UID Emmagatzematge"
msgid "Default"
msgstr "Per defecte"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -191,21 +191,21 @@ msgstr ""
"Per evitar duplicats, s'ignoren les receptes amb el mateix nom que les "
"existents. Marqueu aquesta casella per importar-ho tot."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Afegir el teu comentari: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
"Deixeu-lo buit per a Dropbox i introduïu la contrasenya de l'aplicació per a "
"nextcloud."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr "Deixeu-lo buit per a nextcloud i introduïu el token API per a Dropbox."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -213,33 +213,33 @@ msgstr ""
"Deixeu-lo buit per a Dropbox i introduïu només l'URL base per a Nextcloud "
"(<code>/remote.php/webdav/</code> s'afegeix automàticament)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Emmagatzematge"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Actiu"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Cerca Cadena"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "ID d'Arxiu"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Has de proporcionar com a mínim una recepta o un títol."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"Podeu llistar els usuaris predeterminats amb els quals voleu compartir "
"receptes a la configuració."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -247,15 +247,15 @@ msgstr ""
"Podeu utilitzar el marcador per donar format a aquest camp. Consulteu els <a "
"href=\"/docs/markdown/\">documents aquí </a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "Nombre màxim d'usuaris assolit per a aquest espai."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "Adreça de correu electrònic existent!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -263,15 +263,15 @@ msgstr ""
"No cal una adreça de correu electrònic, però si està present, s'enviarà "
"l'enllaç d'invitació a l'usuari."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "Nom agafat."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "Accepteu les condicions i la privadesa"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -280,7 +280,7 @@ msgstr ""
"de trigrama (p. ex., els valors baixos signifiquen que s'ignoren més errors "
"ortogràfics)."
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
@@ -288,7 +288,7 @@ msgstr ""
"Seleccioneu el tipus de mètode de cerca. Feu clic <a href=\"/docs/search/"
"\">aquí</a> per obtenir una descripció completa de les opcions."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -296,7 +296,7 @@ msgstr ""
"Utilitzeu la concordança difusa en unitats, paraules clau i ingredients quan "
"editeu i importeu receptes."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
@@ -304,7 +304,7 @@ msgstr ""
"Camps per cercar ignorant els accents. La selecció d'aquesta opció pot "
"millorar o degradar la qualitat de la cerca en funció de l'idioma"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
@@ -312,7 +312,7 @@ msgstr ""
"Camps per cercar coincidències parcials. (p. ex., en cercar \"Pastís\" "
"tornarà \"pastís\" i \"peça\" i \"sabó\")"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
@@ -320,7 +320,7 @@ msgstr ""
"Camps per cercar l'inici de les coincidències de paraula. (p. ex., en cercar "
"\"sa\" es tornarà \"amanida\" i \"entrepà\")"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -329,7 +329,7 @@ msgstr ""
"trobareu \"recepta\".) Nota: aquesta opció entrarà en conflicte amb els "
"mètodes de cerca \"web\" i \"cru\"."
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
@@ -337,35 +337,35 @@ msgstr ""
"Camps per a la cerca de text complet. Nota: els mètodes de cerca \"web\", "
"\"frase\" i \"en brut\" només funcionen amb camps de text complet."
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Mètode de cerca"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "Cerques difuses"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "Ignora Accents"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "Cerca Parcial"
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "Comença amb"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "Cerca Difusa"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Text Sencer"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -373,7 +373,7 @@ msgstr ""
"Els usuaris veuran tots els articles que afegiu a la vostra llista de la "
"compra. Us han d'afegir per veure els elements de la seva llista."
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
@@ -381,7 +381,7 @@ msgstr ""
"Quan afegiu un pla d'àpats a la llista de la compra (de manera manual o "
"automàtica), inclou totes les receptes relacionades."
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
@@ -389,95 +389,95 @@ msgstr ""
"Quan afegiu un pla d'àpats a la llista de la compra (manual o "
"automàticament), excloeu els ingredients que teniu a mà."
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
"Nombre d'hores per defecte per retardar l'entrada d'una llista de la compra."
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
"Filtreu la llista de compres per incloure només categories de supermercats."
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr "Dies de les entrades recents de la llista de la compra per mostrar."
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr "Marca el menjar com a \"A mà\" quan marqueu la llista de la compra."
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "Delimitador per a les exportacions CSV."
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr "Prefix per afegir en copiar la llista al porta-retalls."
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Compartir Llista de la Compra"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Autosync"
msgstr "Autosinc"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "Afegeix automàticament un pla d'àpats"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "Exclou a mà"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "Incloure Relacionats"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "Hores de retard per defecte"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "Filtrar a supermercat"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "Dies recents"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "Delimitador CSV"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Prefix de Llista"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "Auto a mà"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "Restablir Herència Alimentària"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr "Restableix tots els aliments per heretar els camps configurats."
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr "Camps dels aliments que s'han d'heretar per defecte."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "Mostra el recompte de receptes als filtres de cerca"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""
msgstr "Empra el plural d'aquestes unitats i menjars dins de l'espai."
#: .\cookbook\helper\AllAuthCustomAdapter.py:39
msgid ""

View File

@@ -11,8 +11,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
"PO-Revision-Date: 2023-03-25 11:32+0000\n"
"Last-Translator: Matěj Kubla <matykubla@gmail.com>\n"
"PO-Revision-Date: 2024-01-09 12:07+0000\n"
"Last-Translator: Jan Kubošek <kuboja@outlook.cz>\n"
"Language-Team: Czech <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/cs/>\n"
"Language: cs\n"
@@ -36,7 +36,7 @@ msgid ""
"try them out!"
msgstr ""
"Barva horního navigačního menu. Některé barvy neladí se všemi tématy a je "
"třeba je vyzkoušet."
"třeba je vyzkoušet!"
#: .\cookbook\forms.py:45
msgid "Default Unit to be used when inserting a new ingredient into a recipe."
@@ -50,7 +50,7 @@ msgid ""
"to fractions automatically)"
msgstr ""
"Povolit podporu zlomků u množství ingrediencí (desetinná čísla budou "
"automaticky převedena na zlomky)."
"automaticky převedena na zlomky)"
#: .\cookbook\forms.py:47
msgid ""
@@ -190,7 +190,7 @@ msgid ""
"Leave empty for dropbox and enter only base url for nextcloud "
"(<code>/remote.php/webdav/</code> is added automatically)"
msgstr ""
"Pro dropbox ponechejte nevyplňené pole. Pro nextcloud použijte pouze "
"Pro dropbox ponechejte nevyplné pole. Pro nextcloud použijte pouze "
"základní url (<code>/remote.php/webdav/</code> bude přidán automaticky)."
#: .\cookbook\forms.py:263
@@ -529,7 +529,7 @@ msgstr "Dávková úprava receptu"
#: .\cookbook\templates\batch\edit.html:20
msgid "Add the specified keywords to all recipes containing a word"
msgstr "Přidat štítek ke všem receptům, které obsahují specifické slovo."
msgstr "Přidat štítek ke všem receptům, které obsahují specifické slovo"
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:66
msgid "Sync"

View File

@@ -14,11 +14,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-02-09 13:55+0000\n"
"Last-Translator: Marion Kämpfer <marion@murphyslantech.de>\n"
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/recipes-"
"backend/de/>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-11-22 18:19+0000\n"
"Last-Translator: Spreez <tandoor@larsdev.de>\n"
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/de/>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -119,7 +119,7 @@ msgstr ""
"Wenn du in der Lage sein willst, Kommentare unter Rezepten zu erstellen und "
"zu sehen."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -135,7 +135,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "Navigationsleiste wird oben angeheftet."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr "Fügt die Zutaten des Speiseplans automatisch zur Einkaufsliste hinzu."
@@ -155,13 +155,13 @@ msgstr ""
"Beide Felder sind optional. Wenn keins von beiden gegeben ist, wird der "
"Nutzername angezeigt"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Name"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Stichwörter"
msgstr "Schlüsselwörter"
#: .\cookbook\forms.py:125
msgid "Preparation time in minutes"
@@ -171,7 +171,7 @@ msgstr "Zubereitungszeit in Minuten"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Wartezeit (kochen/backen) in Minuten"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Pfad"
@@ -183,7 +183,7 @@ msgstr "Speicher-UID"
msgid "Default"
msgstr "Standard"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -191,19 +191,19 @@ msgstr ""
"Um Duplikate zu vermeiden werden Rezepte mit dem gleichen Namen ignoriert. "
"Aktivieren Sie dieses Kontrollkästchen, um alles zu importieren."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Schreibe einen Kommentar: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr "Für Dropbox leer lassen, bei Nextcloud App-Passwort eingeben."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr "Für Nextcloud leer lassen, für Dropbox API-Token eingeben."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -211,33 +211,33 @@ msgstr ""
"Für Dropbox leer lassen, für Nextcloud Server-URL angeben (<code>/remote.php/"
"webdav/</code> wird automatisch hinzugefügt)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Speicher"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Aktiv"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Suchwort"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "Datei-ID"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Mindestens ein Rezept oder ein Titel müssen angegeben werden."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"Sie können in den Einstellungen Standardbenutzer auflisten, für die Sie "
"Rezepte freigeben möchten."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -245,15 +245,15 @@ msgstr ""
"Markdown kann genutzt werden, um dieses Feld zu formatieren. Siehe <a href="
"\"/docs/markdown/\">hier</a> für weitere Information"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "Maximale Nutzer-Anzahl wurde für diesen Space erreicht."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "Email-Adresse ist bereits vergeben!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -261,15 +261,15 @@ msgstr ""
"Eine Email-Adresse wird nicht benötigt, aber falls vorhanden, wird der "
"Einladungslink zum Benutzer geschickt."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "Name wird bereits verwendet."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "AGB und Datenschutzerklärung akzeptieren"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -277,7 +277,7 @@ msgstr ""
"Legt fest wie unscharf eine Suche ist, falls Trigramme verwendet werden (i."
"A. führen niedrigere Werte zum ignorieren von mehr Tippfehlern)."
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
@@ -285,7 +285,7 @@ msgstr ""
"Suchmethode auswählen. Klicke <a href=\"/docs/search/\">hier</a> für eine "
"vollständige Erklärung der Optionen."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -293,7 +293,7 @@ msgstr ""
"Benutze die unscharfe Suche für Einheiten, Schlüsselwörter und Zutaten beim "
"ändern und importieren von Rezepten."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
@@ -301,7 +301,7 @@ msgstr ""
"Felder bei welchen Akzente ignoriert werden. Das aktivieren dieser Option "
"kann die Suchqualität je nach Sprache verbessern oder verschlechtern"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
@@ -309,7 +309,7 @@ msgstr ""
"Felder welche auf partielle Treffer durchsucht werden. (z.B. eine Suche "
"nach 'Spa' wird 'Spaghetti', 'Spargel' und 'Grünspargel' liefern.)"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
@@ -317,7 +317,7 @@ msgstr ""
"Felder welche auf übereinstimmenden Wortbeginn durchsucht werden. (z.B. eine "
"Suche nach \"Spa\" wird \"Spaghetti\" und \"Spargel\" liefern.)"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -326,7 +326,7 @@ msgstr ""
"\"Kuhcen\" wird \"Kuchen\" liefern.) Tipp: Diese Option konfligiert mit den "
"\"web\" und \"raw\" Suchtypen."
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
@@ -334,35 +334,35 @@ msgstr ""
"Felder welche im Volltext durchsucht werden sollen. Tipp: Die Suchtypen \"web"
"\", \"raw\" und \"phrase\" funktionieren nur mit Volltext-Feldern."
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Suchmethode"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "Unscharfe Suche"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "Akzente ignorieren"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "Teilweise Übereinstimmung"
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "Beginnt mit"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "Unpräzise Suche"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Volltext"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -371,7 +371,7 @@ msgstr ""
"Benutzer müssen Sie hinzufügen, damit Sie Artikel auf der Liste der Benutzer "
"sehen können."
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
@@ -379,7 +379,7 @@ msgstr ""
"Wenn Sie einen Essensplan zur Einkaufsliste hinzufügen (manuell oder "
"automatisch), fügen Sie alle zugehörigen Rezepte hinzu."
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
@@ -387,98 +387,98 @@ msgstr ""
"Wenn Sie einen Essensplan zur Einkaufsliste hinzufügen (manuell oder "
"automatisch), schließen Sie Zutaten aus, die Sie gerade zur Hand haben."
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
"Voreingestellte Anzahl von Stunden für die Verzögerung eines "
"Einkaufslisteneintrags."
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
"Nur für den Supermarkt konfigurierte Kategorien in Einkaufsliste anzeigen."
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr ""
"Tage der letzten Einträge in der Einkaufsliste, die angezeigt werden sollen."
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
"Lebensmittel als vorrätig markieren, wenn es in der Einkaufliste abgehakt "
"wurde."
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "Separator für CSV-Export."
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr "Zusatz wird der in die Zwischenablage kopierten Liste vorangestellt."
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Einkaufsliste teilen"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Automatischer Abgleich"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "automatisch dem Menüplan hinzufügen"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "Ausgenommen Vorrätiges"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "dazugehörend"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "Standardmäßige Verzögerung in Stunden"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "Supermarkt filtern"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "Vergangene Tage"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "CSV Trennzeichen"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Listenpräfix"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "Automatisch als vorrätig markieren"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "Lebensmittelvererbung zurücksetzen"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr ""
"Alle Lebensmittel zurücksetzen, um die konfigurierten Felder zu übernehmen."
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr "Zutaten, die standardmäßig übernommen werden sollen."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "Rezeptanzahl im Suchfiltern anzeigen"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr "Pluralform für Einheiten und Essen in diesem Space verwenden."
@@ -600,10 +600,8 @@ msgid "Imported %s recipes."
msgstr "%s Rezepte importiert."
#: .\cookbook\integration\openeats.py:26
#, fuzzy
#| msgid "Recipe Home"
msgid "Recipe source:"
msgstr "Rezept-Hauptseite"
msgstr "Rezept-Quelle:"
#: .\cookbook\integration\paprika.py:49
msgid "Notes"
@@ -733,14 +731,12 @@ msgid "Keyword Alias"
msgstr "Stichwort Alias"
#: .\cookbook\models.py:1232
#, fuzzy
msgid "Description Replace"
msgstr "Beschreibung"
msgstr "Beschreibung ersetzen"
#: .\cookbook\models.py:1232
#, fuzzy
msgid "Instruction Replace"
msgstr "Anleitung"
msgstr "Anleitung ersetzen"
#: .\cookbook\models.py:1258 .\cookbook\views\delete.py:36
#: .\cookbook\views\edit.py:251 .\cookbook\views\new.py:48
@@ -1440,11 +1436,11 @@ msgid ""
" "
msgstr ""
"\n"
" <b>Password und Token</b> werden im <b>Klartext</b> in der Datenbank "
" <b>Passwort und Token</b> werden im <b>Klartext</b> in der Datenbank "
"gespeichert.\n"
" Dies ist notwendig da Passwort oder Token benötigt werden, um API-"
"Anfragen zu stellen, bringt jedoch auch ein Sicherheitsrisiko mit sich. <br/"
">\n"
"Anfragen zu stellen, bringt jedoch auch ein Sicherheitsrisiko mit sich. <br/>"
"\n"
" Um das Risiko zu minimieren sollten, wenn möglich, Tokens oder "
"Accounts mit limitiertem Zugriff verwendet werden.\n"
" "
@@ -2604,7 +2600,7 @@ msgstr "Ungültiges URL Schema."
#: .\cookbook\views\api.py:1233
msgid "No usable data could be found."
msgstr "Es konnten keine nutzbaren Daten gefunden werden."
msgstr "Es konnten keine passenden Daten gefunden werden."
#: .\cookbook\views\api.py:1326 .\cookbook\views\import_export.py:117
msgid "Importing is not implemented for this provider"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,9 +13,9 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-03-13 06:55+0000\n"
"Last-Translator: Amara Ude <apu24@drexel.edu>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-09-25 09:59+0000\n"
"Last-Translator: Matias Laporte <laportematias+weblate@gmail.com>\n"
"Language-Team: Spanish <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/es/>\n"
"Language: es\n"
@@ -117,7 +117,7 @@ msgstr "Número de decimales para redondear los ingredientes."
msgid "If you want to be able to create and see comments underneath recipes."
msgstr "Si desea poder crear y ver comentarios debajo de las recetas."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -135,7 +135,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "Hace la barra de navegación fija en la parte superior de la página."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
"Añadir de manera automática los ingredientes del plan a la lista de la "
@@ -157,11 +157,11 @@ msgstr ""
"Ambos campos son opcionales. Si no se proporciona ninguno, se mostrará el "
"nombre de usuario en su lugar"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Nombre"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Palabras clave"
@@ -173,7 +173,7 @@ msgstr "Tiempo de preparación en minutos"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Tiempo de espera (cocinar/hornear) en minutos"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Ruta"
@@ -185,7 +185,7 @@ msgstr "UID de almacenamiento"
msgid "Default"
msgstr "Por defecto"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -193,22 +193,22 @@ msgstr ""
"Para evitar duplicados, las recetas con el mismo nombre serán ignoradas. "
"Marca esta opción para importar todas las recetas."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Añada su comentario: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
"Déjelo vacío para Dropbox e ingrese la contraseña de la aplicación para "
"nextcloud."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr ""
"Déjelo en blanco para nextcloud e ingrese el token de api para dropbox."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -216,33 +216,33 @@ msgstr ""
"Dejar vació para Dropbox e introducir sólo la URL base para Nextcloud "
"(<code>/remote.php/webdav/</code> se añade automáticamente)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Almacenamiento"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Activo"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Cadena de búsqueda"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "ID de Fichero"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Debe proporcionar al menos una receta o un título."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"Puede enumerar los usuarios predeterminados con los que compartir recetas en "
"la configuración."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -250,15 +250,15 @@ msgstr ""
"Puede utilizar Markdown para formatear este campo. Vea la <a href=\"/docs/"
"markdown/\">documentación aqui</a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "Se ha alcanzado el número máximo de usuarios en este espacio."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "¡El correo electrónico ya existe!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -266,15 +266,15 @@ msgstr ""
"El correo electrónico es opcional. Si se añade uno se mandará un link de "
"invitación."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "El nombre ya existe."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "Aceptar términos y condiciones"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -283,7 +283,7 @@ msgstr ""
"similitud de trigramas(Ej. Valores más pequeños indican que más fallos se "
"van a ignorar)."
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
@@ -291,7 +291,7 @@ msgstr ""
"Selecciona el tipo de búsqueda. Haz click <a href=\"/docs/search/\">aquí</"
"a> para una descripción completa de las opciones."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -299,7 +299,7 @@ msgstr ""
"Utilizar comparación difusa en unidades, palabras clave e ingredientes al "
"editar e importar recetas."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
@@ -307,7 +307,7 @@ msgstr ""
"Campos de búsqueda ignorando acentos.  La selección de esta opción puede "
"mejorar o degradar la calidad de la búsqueda dependiendo del idioma"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
@@ -315,7 +315,7 @@ msgstr ""
"Campos de búsqueda para coincidencias parciales. (por ejemplo, buscar 'Pie' "
"devolverá 'pie' y 'piece' y 'soapie')"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
@@ -323,7 +323,7 @@ msgstr ""
"Campos de búsqueda para coincidencias al principio de la palabra. (por "
"ejemplo, buscar 'sa' devolverá 'ensalada' y 'sándwich')"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -332,7 +332,7 @@ msgstr ""
"'receta'). Nota: esta opción entrará en conflicto con los métodos de "
"búsqueda 'web' y 'raw'."
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
@@ -340,35 +340,35 @@ msgstr ""
"Campos para búsqueda de texto completo. Nota: los métodos de búsqueda 'web', "
"'phrase' y 'raw' solo funcionan con campos de texto completo."
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Método de Búsqueda"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "Búsquedas difusas"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "Ignorar Acento"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "Coincidencia Parcial"
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "Comienza Con"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "Búsqueda Difusa"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Texto Completo"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -376,7 +376,7 @@ msgstr ""
"Los usuarios verán todos los elementos que agregues a tu lista de compras. "
"Deben agregarte para ver los elementos en su lista."
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
@@ -384,7 +384,7 @@ msgstr ""
"Al agregar un plan de comidas a la lista de compras (manualmente o "
"automáticamente), incluir todas las recetas relacionadas."
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
@@ -392,96 +392,96 @@ msgstr ""
"Al agregar un plan de comidas a la lista de compras (manualmente o "
"automáticamente), excluir los ingredientes que están disponibles."
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
"Número predeterminado de horas para retrasar una entrada en la lista de "
"compras."
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
"Filtrar la lista de compras para incluir solo categorías de supermercados."
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr "Días de entradas recientes en la lista de compras a mostrar."
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
"Marcar los alimentos como 'Disponible' cuando se marca en la lista de "
"compras."
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "Delimitador a utilizar para exportaciones CSV."
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr "Prefijo a agregar al copiar la lista al portapapeles."
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Compartir Lista de la Compra"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Autosincronización"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "Agregar Plan de Comidas automáticamente"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "Excluir Disponible"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "Incluir Relacionados"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "Horas de Retraso Predeterminadas"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "Filtrar según Supermercado"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "Días Recientes"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "Delimitador CSV"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Prefijo de la lista"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "Auto en existencia"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "Restablecer la herencia de alimentos"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr "Reiniciar todos los alimentos para heredar los campos configurados."
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr "Campos en los alimentos que deben ser heredados por defecto."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "Mostrar cantidad de recetas en los filtros de búsquedas"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""
"Utilice la forma plural para las unidades y alimentos dentro de este espacio."
@@ -543,19 +543,19 @@ msgstr ""
#: .\cookbook\helper\recipe_url_import.py:268
msgid "knead"
msgstr ""
msgstr "amasar"
#: .\cookbook\helper\recipe_url_import.py:269
msgid "thicken"
msgstr ""
msgstr "espesar"
#: .\cookbook\helper\recipe_url_import.py:270
msgid "warm up"
msgstr ""
msgstr "precalentar"
#: .\cookbook\helper\recipe_url_import.py:271
msgid "ferment"
msgstr ""
msgstr "fermentar"
#: .\cookbook\helper\recipe_url_import.py:272
msgid "sous-vide"
@@ -573,11 +573,11 @@ msgstr ""
#: .\cookbook\integration\copymethat.py:44
#: .\cookbook\integration\melarecipes.py:37
msgid "Favorite"
msgstr ""
msgstr "Favorito"
#: .\cookbook\integration\copymethat.py:50
msgid "I made this"
msgstr ""
msgstr "Lo he preparado"
#: .\cookbook\integration\integration.py:218
msgid ""
@@ -603,10 +603,8 @@ msgid "Imported %s recipes."
msgstr "Se importaron %s recetas."
#: .\cookbook\integration\openeats.py:26
#, fuzzy
#| msgid "Recipe Home"
msgid "Recipe source:"
msgstr "Página de inicio"
msgstr "Fuente de la receta:"
#: .\cookbook\integration\paprika.py:49
msgid "Notes"
@@ -647,19 +645,21 @@ msgstr "Sección"
#: .\cookbook\management\commands\rebuildindex.py:14
msgid "Rebuilds full text search index on Recipe"
msgstr ""
msgstr "Reconstruye el índice de búsqueda por texto completo de la receta"
#: .\cookbook\management\commands\rebuildindex.py:18
msgid "Only Postgresql databases use full text search, no index to rebuild"
msgstr ""
"Solo las bases de datos Postgresql utilizan la búsqueda por texto completo, "
"no hay índice para reconstruir"
#: .\cookbook\management\commands\rebuildindex.py:29
msgid "Recipe index rebuild complete."
msgstr ""
msgstr "Se reconstruyó el índice de la receta."
#: .\cookbook\management\commands\rebuildindex.py:31
msgid "Recipe index rebuild failed."
msgstr ""
msgstr "No fue posible reconstruir el índice de la receta."
#: .\cookbook\migrations\0047_auto_20200602_1133.py:14
msgid "Breakfast"
@@ -701,23 +701,23 @@ msgstr "Libros"
#: .\cookbook\models.py:580
msgid " is part of a recipe step and cannot be deleted"
msgstr ""
msgstr " es parte del paso de una receta y no puede ser eliminado"
#: .\cookbook\models.py:1181 .\cookbook\templates\search_info.html:28
msgid "Simple"
msgstr ""
msgstr "Simple"
#: .\cookbook\models.py:1182 .\cookbook\templates\search_info.html:33
msgid "Phrase"
msgstr ""
msgstr "Frase"
#: .\cookbook\models.py:1183 .\cookbook\templates\search_info.html:38
msgid "Web"
msgstr ""
msgstr "Web"
#: .\cookbook\models.py:1184 .\cookbook\templates\search_info.html:47
msgid "Raw"
msgstr ""
msgstr "Crudo"
#: .\cookbook\models.py:1231
msgid "Food Alias"
@@ -764,49 +764,53 @@ msgstr "Palabra clave"
#: .\cookbook\serializer.py:198
msgid "File uploads are not enabled for this Space."
msgstr ""
msgstr "Las cargas de archivo no están habilitadas para esta Instancia."
#: .\cookbook\serializer.py:209
msgid "You have reached your file upload limit."
msgstr ""
msgstr "Has alcanzado el límite de cargas de archivo."
#: .\cookbook\serializer.py:291
msgid "Cannot modify Space owner permission."
msgstr ""
msgstr "No puedes modificar los permisos del propietario de la Instancia."
#: .\cookbook\serializer.py:1093
msgid "Hello"
msgstr ""
msgstr "Hola"
#: .\cookbook\serializer.py:1093
msgid "You have been invited by "
msgstr ""
msgstr "Has sido invitado por: "
#: .\cookbook\serializer.py:1094
msgid " to join their Tandoor Recipes space "
msgstr ""
msgstr " para unirte a su instancia de Tandoor Recipes "
#: .\cookbook\serializer.py:1095
msgid "Click the following link to activate your account: "
msgstr ""
msgstr "Haz click en el siguiente enlace para activar tu cuenta: "
#: .\cookbook\serializer.py:1096
msgid ""
"If the link does not work use the following code to manually join the space: "
msgstr ""
"Si el enlace no funciona, utiliza el siguiente código para unirte "
"manualmente a la instancia: "
#: .\cookbook\serializer.py:1097
msgid "The invitation is valid until "
msgstr ""
msgstr "La invitación es válida hasta "
#: .\cookbook\serializer.py:1098
msgid ""
"Tandoor Recipes is an Open Source recipe manager. Check it out on GitHub "
msgstr ""
"Tandoor Recipes es un administrador de recetas Open Source. Dale una ojeada "
"en GitHub "
#: .\cookbook\serializer.py:1101
msgid "Tandoor Recipes Invite"
msgstr ""
msgstr "Invitación para Tandoor Recipes"
#: .\cookbook\serializer.py:1242
msgid "Existing shopping list to update"

View File

@@ -13,11 +13,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"Language-Team: French <http://translate.tandoor.dev/projects/tandoor/recipes-"
"backend/fr/>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-12-10 14:19+0000\n"
"Last-Translator: Robin Wilmet <wilmetrobin@hotmail.com>\n"
"Language-Team: French <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/fr/>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -121,7 +121,7 @@ msgstr ""
"Si vous souhaitez pouvoir créer et consulter des commentaires en dessous des "
"recettes."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -139,7 +139,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "Épingler la barre de navigation en haut de la page."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
"Ajouter les ingrédients du menu de la semaine à la liste de courses "
@@ -161,11 +161,11 @@ msgstr ""
"Les deux champs sont facultatifs. Si aucun nest rempli, le nom "
"dutilisateur sera affiché à la place"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Nom"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Mots-clés"
@@ -177,7 +177,7 @@ msgstr "Temps de préparation en minutes"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Temps dattente (cuisson) en minutes"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Chemin"
@@ -189,7 +189,7 @@ msgstr "UID de stockage"
msgid "Default"
msgstr "Par défaut"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -197,22 +197,22 @@ msgstr ""
"Pour éviter les doublons, les recettes de même nom seront ignorées. Cocher "
"cette case pour tout importer."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Ajoutez votre commentaire : "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
"Laissez vide pour Dropbox et renseignez votre mot de passe dapplication "
"pour Nextcloud."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr ""
"Laissez vide pour Nextcloud et renseignez votre jeton dAPI pour Dropbox."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -220,33 +220,33 @@ msgstr ""
"Laisser vide pour Dropbox et saisissez seulement lURL de base pour "
"Nextcloud (<code>/remote.php/webdav/</code> est ajouté automatiquement)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Stockage"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Actif"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Texte recherché"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "ID du fichier"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Vous devez au moins fournir une recette ou un titre."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"Vous pouvez lister les utilisateurs par défaut avec qui partager des "
"recettes dans les paramètres."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -254,15 +254,15 @@ msgstr ""
"Vous pouvez utiliser du markdown pour mettre en forme ce champ. Voir la <a "
"href=\"/docs/markdown/\">documentation ici</a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "Nombre maximum dutilisateurs atteint pour ce groupe."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "Adresse mail déjà utilisée !"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -270,15 +270,15 @@ msgstr ""
"Une adresse mail nest pas requise mais si elle est renseignée, le lien "
"dinvitation sera envoyé à lutilisateur."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "Nom déjà utilisé."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "Accepter les conditions dutilisation"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -287,7 +287,7 @@ msgstr ""
"par similarité de trigrammes (par exemple, des valeurs faibles signifient "
"que davantage de fautes de frappe sont ignorées)."
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
@@ -295,7 +295,7 @@ msgstr ""
"Sélectionner la méthode de recherche. Cliquer <a href=\"/docs/search/"
"\">ici</a> pour une description complète des choix."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -303,16 +303,16 @@ msgstr ""
"Utilisez la correspondance floue sur les unités, les mots-clés et les "
"ingrédients lors de lédition et de limportation de recettes."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
msgstr ""
"Champs à rechercher en ignorant les accents. La sélection de cette option "
"peut améliorer ou dégrader la qualité de la recherche en fonction de la "
"langue."
"langue"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
@@ -320,16 +320,16 @@ msgstr ""
"Champs à rechercher pour les correspondances partielles. (par exemple, la "
"recherche de « Tarte » renverra « tarte », « tartelette » et « tartes »)"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
msgstr ""
"Champs permettant de rechercher les correspondances de début de mot (par "
"exemple, si vous recherchez « sa », vous obtiendrez « salade » et "
"« sandwich»)."
"exemple, si vous recherchez « sa », vous obtiendrez « salade » et « "
"sandwich»)"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -338,7 +338,7 @@ msgstr ""
 rectte», vous trouverez « recette ».) Remarque : cette option est "
"incompatible avec les méthodes de recherche « web » et « brute »."
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
@@ -347,35 +347,35 @@ msgstr ""
 web », « phrase » et « brute » ne fonctionnent quavec des champs en texte "
"intégral."
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Méthode de recherche"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "Recherches floues"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "Ignorer les accents"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "correspondance partielle"
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "Commence par"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "Recherche floue"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Texte intégral"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -384,7 +384,7 @@ msgstr ""
"courses. Ils doivent vous ajouter pour que vous puissiez voir les éléments "
"de leur liste."
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
@@ -392,7 +392,7 @@ msgstr ""
"Lors de lajout dun menu de la semaine à la liste de courses (manuel ou "
"automatique), inclure toutes les recettes connexes."
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
@@ -400,97 +400,97 @@ msgstr ""
"Lors de lajout dun menu de la semaine à la liste de courses (manuel ou "
"automatique), exclure les ingrédients disponibles."
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
"Nombre d'heures par défaut pour retarder l'ajoût d'un article à la liste de "
"courses."
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
"Filtrer la liste de courses pour ninclure que des catégories de "
"supermarchés."
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr "Jours des entrées récentes de la liste de courses à afficher."
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
"Marquer laliment comme disponible lorsquil est rayé de la liste de courses."
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "Caractère de séparation à utiliser pour les exportations CSV."
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr "Préfixe à ajouter lors de la copie de la liste dans le presse-papiers."
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Partager la liste de courses"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Synchronisation automatique"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "Ajouter le menu de la semaine automatiquement"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "Exclure ingrédients disponibles"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "Inclure recettes connexes"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "Heures de retard par défaut"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "Filtrer par supermarché"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "Jours récents"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "Caractère de séparation CSV"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Préfixe de la liste"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "Disponible automatique"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "Réinitialiser l'héritage alimentaire"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr "Réinitialiser tous les aliments pour hériter les champs configurés."
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr "Champs sur les aliments à hériter par défaut."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr ""
"Afficher le nombre de consultations par recette sur les filtres de recherche"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""
"Utiliser la forme plurielle pour les unités et les aliments dans ce groupe."
@@ -546,38 +546,36 @@ msgid "One of queryset or hash_key must be provided"
msgstr "Il est nécessaire de fournir soit le queryset, soit la clé de hachage"
#: .\cookbook\helper\recipe_url_import.py:266
#, fuzzy
#| msgid "Use fractions"
msgid "reverse rotation"
msgstr "Utiliser les fractions"
msgstr "sens inverse"
#: .\cookbook\helper\recipe_url_import.py:267
msgid "careful rotation"
msgstr ""
msgstr "sens horloger"
#: .\cookbook\helper\recipe_url_import.py:268
msgid "knead"
msgstr ""
msgstr "pétrir"
#: .\cookbook\helper\recipe_url_import.py:269
msgid "thicken"
msgstr ""
msgstr "épaissir"
#: .\cookbook\helper\recipe_url_import.py:270
msgid "warm up"
msgstr ""
msgstr "réchauffer"
#: .\cookbook\helper\recipe_url_import.py:271
msgid "ferment"
msgstr ""
msgstr "fermenter"
#: .\cookbook\helper\recipe_url_import.py:272
msgid "sous-vide"
msgstr ""
msgstr "sous-vide"
#: .\cookbook\helper\shopping_helper.py:157
msgid "You must supply a servings size"
msgstr "Vous devez fournir une information de portion"
msgstr "Vous devez fournir un nombre de portions"
#: .\cookbook\helper\template_helper.py:79
#: .\cookbook\helper\template_helper.py:81
@@ -590,7 +588,6 @@ msgid "Favorite"
msgstr "Favori"
#: .\cookbook\integration\copymethat.py:50
#, fuzzy
msgid "I made this"
msgstr "J'ai fait ça"
@@ -620,10 +617,8 @@ msgid "Imported %s recipes."
msgstr "%s recettes importées."
#: .\cookbook\integration\openeats.py:26
#, fuzzy
#| msgid "Recipe Home"
msgid "Recipe source:"
msgstr "Page daccueil"
msgstr "Source de la recette :"
#: .\cookbook\integration\paprika.py:49
msgid "Notes"
@@ -648,7 +643,7 @@ msgstr "Portions"
#: .\cookbook\integration\saffron.py:25
msgid "Waiting time"
msgstr "temps dattente"
msgstr "Temps dattente"
#: .\cookbook\integration\saffron.py:27
msgid "Preparation Time"
@@ -851,7 +846,6 @@ msgid "ID of unit to use for the shopping list"
msgstr "ID de lunité à utiliser pour la liste de courses"
#: .\cookbook\serializer.py:1259
#, fuzzy
msgid "When set to true will delete all food from active shopping lists."
msgstr ""
"Lorsqu'il est défini sur \"true\", tous les aliments des listes de courses "
@@ -967,8 +961,9 @@ msgid ""
" ."
msgstr ""
"Confirmez SVP que\n"
" <a href=\"mailto:%(email)s\"></a> est une adresse mail de "
"lutilisateur %(user_display)s."
" <a href=\"mailto:%(email)s\"></a> est une adresse mail de l"
"utilisateur %(user_display)s\n"
" ."
#: .\cookbook\templates\account\email_confirm.html:22
#: .\cookbook\templates\generic\delete_template.html:72
@@ -1371,9 +1366,8 @@ msgid "Are you sure you want to delete the %(title)s: <b>%(object)s</b> "
msgstr "Êtes-vous sûr(e) de vouloir supprimer %(title)s : <b>%(object)s</b> "
#: .\cookbook\templates\generic\delete_template.html:22
#, fuzzy
msgid "This cannot be undone!"
msgstr "Cela ne peut pas être annulé !"
msgstr "L'opération ne peut pas être annulée !"
#: .\cookbook\templates\generic\delete_template.html:27
msgid "Protected"
@@ -1456,12 +1450,12 @@ msgid ""
" "
msgstr ""
"\n"
" Les champs <b>Mot de passe et Token</b> sont stockés <b>en texte "
"brut</b>dans la base de données.\n"
" Les champs <b>Mot de passe et Token</b> sont stockés <b>en clair</"
"b>dans la base de données.\n"
" C'est nécessaire car ils sont utilisés pour faire des requêtes API, "
"mais cela accroît le risque que quelqu'un les vole.<br/>\n"
" Pour limiter les risques, des tokens ou comptes avec un accès limité "
"devraient être utilisés.\n"
" Pour limiter les risques, il est possible d'utiliser des tokens ou "
"des comptes avec un accès limité.\n"
" "
#: .\cookbook\templates\index.html:29
@@ -1771,15 +1765,6 @@ msgstr ""
" "
#: .\cookbook\templates\search_info.html:29
#, fuzzy
#| msgid ""
#| " \n"
#| " Simple searches ignore punctuation and common words such as "
#| "'the', 'a', 'and'. And will treat seperate words as required.\n"
#| " Searching for 'apple or flour' will return any recipe that "
#| "includes both 'apple' and 'flour' anywhere in the fields that have been "
#| "selected for a full text search.\n"
#| " "
msgid ""
" \n"
" Simple searches ignore punctuation and common words such as "
@@ -1791,7 +1776,7 @@ msgid ""
msgstr ""
" \n"
" Les recherches simples ignorent la ponctuation et les mots "
"courants tels que \"le\", \"a\", \"et\", et traiteront les mots séparés "
"courants tels que \"le\", \"et\", \"a\", et traiteront les mots séparés "
"comme il se doit.\n"
" Si vous recherchez \"pomme ou farine\", vous obtiendrez toutes "
"les recettes qui contiennent à la fois \"pomme\" et \"farine\" dans les "
@@ -2219,7 +2204,7 @@ msgstr "Gérer labonnement"
#: .\cookbook\templates\space_overview.html:13 .\cookbook\views\delete.py:216
msgid "Space"
msgstr "Groupe :"
msgstr "Groupe"
#: .\cookbook\templates\space_overview.html:17
msgid ""
@@ -2659,7 +2644,7 @@ msgstr ""
#: .\cookbook\views\api.py:1394
msgid "Sync successful!"
msgstr "Synchro réussie !"
msgstr "Synchronisation réussie !"
#: .\cookbook\views\api.py:1399
msgid "Error synchronizing with Storage"
@@ -2732,6 +2717,8 @@ msgid ""
"The PDF Exporter is not enabled on this instance as it is still in an "
"experimental state."
msgstr ""
"L'export PDF n'est pas activé sur cette instance car il est toujours au "
"statut expérimental."
#: .\cookbook\views\lists.py:24
msgid "Import Log"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -10,9 +10,9 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-12-05 09:15+0000\n"
"Last-Translator: Ferenc <ugyes@freemail.hu>\n"
"Language-Team: Hungarian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/hu/>\n"
"Language: hu_HU\n"
@@ -99,7 +99,7 @@ msgstr ""
#: .\cookbook\forms.py:74
msgid "Users with whom newly created meal plans should be shared by default."
msgstr ""
"Azok a felhasználók, akikkel az újonnan létrehozott étkezési terveket "
"Azok a felhasználók, akikkel az újonnan létrehozott menüterveket "
"alapértelmezés szerint meg kell osztani."
#: .\cookbook\forms.py:75
@@ -116,7 +116,7 @@ msgstr ""
"Ha azt szeretné, hogy hozzászólásokat tudjon létrehozni és látni a receptek "
"alatt."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -133,10 +133,9 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "A navigációs sávot az oldal tetejére rögzíti."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
"Automatikusan hozzáadja az étkezési terv hozzávalóit a bevásárlólistához."
msgstr "Automatikusan hozzáadja a menüterv hozzávalóit a bevásárlólistához."
#: .\cookbook\forms.py:84
msgid "Exclude ingredients that are on hand."
@@ -154,11 +153,11 @@ msgstr ""
"Mindkét mező opcionális. Ha egyiket sem adjuk meg, akkor a felhasználónév "
"jelenik meg helyette"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Név"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Kulcsszavak"
@@ -170,7 +169,7 @@ msgstr "Előkészítési idő percben"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Várakozási idő (sütés/főzés) percben"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Elérési útvonal"
@@ -182,7 +181,7 @@ msgstr "Tárhely UID"
msgid "Default"
msgstr "Alapértelmezett"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -191,23 +190,23 @@ msgstr ""
"recepteket a rendszer figyelmen kívül hagyja. Jelölje be ezt a négyzetet, ha "
"mindent importálni szeretne."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Add hozzá a kommented: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
"A dropbox esetében hagyja üresen, a nextcloud esetében pedig adja meg az "
"alkalmazás jelszavát."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr ""
"A nextcloud esetében hagyja üresen, a dropbox esetében pedig adja meg az api "
"tokent."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -215,33 +214,33 @@ msgstr ""
"Hagyja üresen a dropbox esetén, és csak a nextcloud alap url-jét adja meg "
"(<code>/remote.php/webdav/</code> automatikusan hozzáadódik)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Tárhely"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Aktív"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Keresési kifejezés"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "Fájl ID"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Legalább egy receptet vagy címet kell megadnia."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"A beállításokban megadhatja a receptek megosztására szolgáló alapértelmezett "
"felhasználókat."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -249,15 +248,15 @@ msgstr ""
"A mező formázásához használhatja a markdown formátumot. Lásd a <a href=\"/"
"docs/markdown/\">dokumentációt itt</a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "Elérte a felhasználók maximális számát ezen a területen."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "Az e-mail cím már foglalt!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -265,15 +264,15 @@ msgstr ""
"Az e-mail cím megadása nem kötelező, de ha van, a meghívó linket elküldi a "
"felhasználónak."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "A név már foglalt."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "Feltételek és adatvédelem elfogadása"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -282,19 +281,15 @@ msgstr ""
"párosítást használ (pl. az alacsony értékek azt jelentik, hogy több gépelési "
"hibát figyelmen kívül hagynak)."
#: .\cookbook\forms.py:444
#, fuzzy
#| msgid ""
#| "Select type method of search. Click <a href=\"/docs/search/\">here</a> "
#| "for full desciption of choices."
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
msgstr ""
"Válassza ki a keresés típusát. Kattintson <a href=\"/docs/search/\">ide</a> "
"a lehetőségek teljes leírásáért."
"Válassza ki a keresés típusát. Kattintson <a href=\"/docs/search/\">ide</"
"a> a lehetőségek teljes leírásáért."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -302,7 +297,7 @@ msgstr ""
"A receptek szerkesztése és importálása során az egységek, kulcsszavak és "
"összetevők bizonytalan megfeleltetése."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
@@ -310,7 +305,7 @@ msgstr ""
"Az ékezetek figyelmen kívül hagyásával keresendő mezők. Ennek az opciónak a "
"kiválasztása javíthatja vagy ronthatja a keresés minőségét a nyelvtől függően"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
@@ -318,7 +313,7 @@ msgstr ""
"Részleges egyezések keresésére szolgáló mezők. (pl. a 'Pie' keresése a "
"'pie' és a 'piece' és a 'soapie' kifejezéseket adja vissza.)"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
@@ -326,7 +321,7 @@ msgstr ""
"Mezők a szó eleji egyezések kereséséhez. (pl. a 'sa' keresés a 'salad' és a "
"'sandwich' kifejezéseket adja vissza)"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -335,7 +330,7 @@ msgstr ""
"'recipe' szót.) Megjegyzés: ez az opció ütközik a 'web' és a 'raw' keresési "
"módszerekkel."
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
@@ -343,37 +338,35 @@ msgstr ""
"Mezők a teljes szöveges kereséshez. Megjegyzés: A 'web', 'phrase' és 'raw' "
"keresési módszerek csak teljes szöveges mezőkkel működnek."
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Keresési módszer"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "Bizonytalan keresések"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "Ékezetek ignorálása"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "Részleges találat"
#: .\cookbook\forms.py:463
#, fuzzy
#| msgid "Starts Wtih"
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "Kezdődik a következővel"
msgstr "Ezzel kezdődik"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "Bizonytalan keresés"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Teljes szöveg"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -382,114 +375,115 @@ msgstr ""
"Ahhoz, hogy láthassák a saját listájukon szereplő tételeket, hozzá kell "
"adniuk téged."
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
msgstr ""
"Amikor étkezési tervet ad hozzá a bevásárlólistához (kézzel vagy "
"automatikusan), vegye fel az összes kapcsolódó receptet."
"Amikor menütervet ad hozzá a bevásárlólistához (kézzel vagy automatikusan), "
"vegye fel az összes kapcsolódó receptet."
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
msgstr ""
"Amikor étkezési tervet ad hozzá a bevásárlólistához (kézzel vagy "
"automatikusan), zárja ki a kéznél lévő összetevőket."
"Amikor menütervet ad hozzá a bevásárlólistához (kézzel vagy automatikusan), "
"zárja ki a kéznél lévő összetevőket."
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr "A bevásárlólista bejegyzés késleltetésének alapértelmezett ideje."
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
"Szűrje a bevásárlólistát úgy, hogy csak a szupermarket kategóriákat "
"tartalmazza."
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr "A legutóbbi bevásárlólista bejegyzések megjelenítendő napjai."
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
"Jelölje meg a \" Kéznél van\" jelölést, ha a bevásárlólistáról kipipálta az "
"élelmiszert."
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "A CSV exportáláshoz használandó elválasztójel."
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr "A lista vágólapra másolásakor hozzáadandó előtag."
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Bevásárlólista megosztása"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Automatikus szinkronizálás"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "Automatikus étkezési terv hozzáadása"
msgstr "Menüterv automatikus hozzáadása"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "Kéznél levő kihagyása"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "Tartalmazza a kapcsolódókat"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "Alapértelmezett késleltetési órák"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "Szűrő a szupermarkethez"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "Legutóbbi napok"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "CSV elválasztó"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Lista előtagja"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "Automatikus Kéznél lévő"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "Élelmiszer-öröklés visszaállítása"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr "Állítsa vissza az összes ételt, hogy örökölje a konfigurált mezőket."
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr ""
"Az élelmiszerek azon mezői, amelyeket alapértelmezés szerint örökölni kell."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "A receptek számának megjelenítése a keresési szűrőkön"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""
"Használja a többes számot az egységek és az ételek esetében ezen a helyen."
#: .\cookbook\helper\AllAuthCustomAdapter.py:39
msgid ""
@@ -538,10 +532,8 @@ msgid "One of queryset or hash_key must be provided"
msgstr "A queryset vagy a hash_key valamelyikét meg kell adni"
#: .\cookbook\helper\recipe_url_import.py:266
#, fuzzy
#| msgid "Use fractions"
msgid "reverse rotation"
msgstr "Törtek használata"
msgstr "Ellentétes irány"
#: .\cookbook\helper\recipe_url_import.py:267
msgid "careful rotation"
@@ -549,29 +541,27 @@ msgstr ""
#: .\cookbook\helper\recipe_url_import.py:268
msgid "knead"
msgstr ""
msgstr "dagasztás"
#: .\cookbook\helper\recipe_url_import.py:269
msgid "thicken"
msgstr ""
msgstr "sűrítés"
#: .\cookbook\helper\recipe_url_import.py:270
msgid "warm up"
msgstr ""
msgstr "melegítés"
#: .\cookbook\helper\recipe_url_import.py:271
msgid "ferment"
msgstr ""
msgstr "fermentálás"
#: .\cookbook\helper\recipe_url_import.py:272
msgid "sous-vide"
msgstr ""
msgstr "sous-vide"
#: .\cookbook\helper\shopping_helper.py:157
#, fuzzy
#| msgid "You must supply a created_by"
msgid "You must supply a servings size"
msgstr "Meg kell adnia egy created_by"
msgstr "Meg kell adnia az adagok nagyságát"
#: .\cookbook\helper\template_helper.py:79
#: .\cookbook\helper\template_helper.py:81
@@ -581,11 +571,11 @@ msgstr "Nem sikerült elemezni a sablon kódját."
#: .\cookbook\integration\copymethat.py:44
#: .\cookbook\integration\melarecipes.py:37
msgid "Favorite"
msgstr ""
msgstr "Kedvenc"
#: .\cookbook\integration\copymethat.py:50
msgid "I made this"
msgstr ""
msgstr "Elkészítettem"
#: .\cookbook\integration\integration.py:218
msgid ""
@@ -613,10 +603,8 @@ msgid "Imported %s recipes."
msgstr "Importálva %s recept."
#: .\cookbook\integration\openeats.py:26
#, fuzzy
#| msgid "Recipe Home"
msgid "Recipe source:"
msgstr "Recipe Home"
msgstr "Recept forrása:"
#: .\cookbook\integration\paprika.py:49
msgid "Notes"
@@ -632,10 +620,8 @@ msgstr "Forrás"
#: .\cookbook\integration\recettetek.py:54
#: .\cookbook\integration\recipekeeper.py:70
#, fuzzy
#| msgid "Import Log"
msgid "Imported from"
msgstr "Import napló"
msgstr "Importálva a"
#: .\cookbook\integration\saffron.py:23
msgid "Servings"
@@ -662,12 +648,10 @@ msgid "Rebuilds full text search index on Recipe"
msgstr "Újraépíti a teljes szöveges keresési indexet a Recept oldalon"
#: .\cookbook\management\commands\rebuildindex.py:18
#, fuzzy
#| msgid "Only Postgress databases use full text search, no index to rebuild"
msgid "Only Postgresql databases use full text search, no index to rebuild"
msgstr ""
"Csak a Postgress adatbázisok használnak teljes szöveges keresést, nincs "
"újjáépítendő index"
"Csak a Postgresql adatbázisok használják a teljes szöveges keresést, nem "
"kell indexet újjáépíteni"
#: .\cookbook\management\commands\rebuildindex.py:29
msgid "Recipe index rebuild complete."
@@ -711,7 +695,7 @@ msgstr "Keresés"
#: .\cookbook\templates\meal_plan.html:7 .\cookbook\views\delete.py:178
#: .\cookbook\views\edit.py:211 .\cookbook\views\new.py:179
msgid "Meal-Plan"
msgstr "Étkezési terv"
msgstr "Menüterv"
#: .\cookbook\models.py:367 .\cookbook\templates\base.html:118
msgid "Books"
@@ -750,16 +734,12 @@ msgid "Keyword Alias"
msgstr "Kulcsszó álneve"
#: .\cookbook\models.py:1232
#, fuzzy
#| msgid "Description"
msgid "Description Replace"
msgstr "Leírás"
msgstr "Leírás csere"
#: .\cookbook\models.py:1232
#, fuzzy
#| msgid "Instructions"
msgid "Instruction Replace"
msgstr "Elkészítés"
msgstr "Leírás cseréje"
#: .\cookbook\models.py:1258 .\cookbook\views\delete.py:36
#: .\cookbook\views\edit.py:251 .\cookbook\views\new.py:48
@@ -767,10 +747,8 @@ msgid "Recipe"
msgstr "Recept"
#: .\cookbook\models.py:1259
#, fuzzy
#| msgid "Foods"
msgid "Food"
msgstr "Ételek"
msgstr "Étel"
#: .\cookbook\models.py:1260 .\cookbook\templates\base.html:141
msgid "Keyword"
@@ -786,7 +764,7 @@ msgstr "Elérte a fájlfeltöltési limitet."
#: .\cookbook\serializer.py:291
msgid "Cannot modify Space owner permission."
msgstr ""
msgstr "A Hely tulajdonosi engedélye nem módosítható."
#: .\cookbook\serializer.py:1093
msgid "Hello"
@@ -1176,7 +1154,7 @@ msgstr "Ételek"
#: .\cookbook\templates\base.html:165 .\cookbook\views\lists.py:122
msgid "Units"
msgstr "Egységek"
msgstr "Mértékegységek"
#: .\cookbook\templates\base.html:179 .\cookbook\templates\supermarket.html:7
msgid "Supermarket"
@@ -1206,10 +1184,8 @@ msgstr "Előzmények"
#: .\cookbook\templates\base.html:255
#: .\cookbook\templates\ingredient_editor.html:7
#: .\cookbook\templates\ingredient_editor.html:13
#, fuzzy
#| msgid "Ingredients"
msgid "Ingredient Editor"
msgstr "Hozzávalók"
msgstr "Hozzávaló szerkesztő"
#: .\cookbook\templates\base.html:267
#: .\cookbook\templates\export_response.html:7
@@ -1244,15 +1220,13 @@ msgstr "Admin"
#: .\cookbook\templates\base.html:312
#: .\cookbook\templates\space_overview.html:25
#, fuzzy
#| msgid "No Space"
msgid "Your Spaces"
msgstr "Nincs hely"
msgstr "Ön Helye"
#: .\cookbook\templates\base.html:323
#: .\cookbook\templates\space_overview.html:6
msgid "Overview"
msgstr ""
msgstr "Áttekintés"
#: .\cookbook\templates\base.html:327
msgid "Markdown Guide"
@@ -1276,11 +1250,11 @@ msgstr "Kijelentkezés"
#: .\cookbook\templates\base.html:360
msgid "You are using the free version of Tandor"
msgstr ""
msgstr "Ön a Tandoor ingyenes verzióját használja"
#: .\cookbook\templates\base.html:361
msgid "Upgrade Now"
msgstr ""
msgstr "Frissítés most"
#: .\cookbook\templates\batch\edit.html:6
msgid "Batch edit Category"
@@ -1377,7 +1351,7 @@ msgstr "Biztos, hogy törölni akarod a %(title)s: <b>%(object)s</b> "
#: .\cookbook\templates\generic\delete_template.html:22
msgid "This cannot be undone!"
msgstr ""
msgstr "Ezt nem lehet visszafordítani!"
#: .\cookbook\templates\generic\delete_template.html:27
msgid "Protected"
@@ -1541,8 +1515,6 @@ msgstr "A sortörés a sor vége után két szóköz hozzáadásával történik
#: .\cookbook\templates\markdown_info.html:57
#: .\cookbook\templates\markdown_info.html:73
#, fuzzy
#| msgid "or by leaving a blank line inbetween."
msgid "or by leaving a blank line in between."
msgstr "vagy egy üres sort hagyva közöttük."
@@ -1566,10 +1538,6 @@ msgid "Lists"
msgstr "Listák"
#: .\cookbook\templates\markdown_info.html:85
#, fuzzy
#| msgid ""
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
#| "before the list!</b>"
msgid ""
"Lists can ordered or unordered. It is <b>important to leave a blank line "
"before the list!</b>"
@@ -1701,11 +1669,11 @@ msgstr ""
#: .\cookbook\templates\openid\login.html:27
#: .\cookbook\templates\socialaccount\authentication_error.html:27
msgid "Back"
msgstr ""
msgstr "Vissza"
#: .\cookbook\templates\profile.html:7
msgid "Profile"
msgstr ""
msgstr "Profil"
#: .\cookbook\templates\recipe_view.html:41
msgid "by"
@@ -1718,7 +1686,7 @@ msgstr "Megjegyzés"
#: .\cookbook\templates\rest_framework\api.html:5
msgid "Recipe Home"
msgstr "Recipe Home"
msgstr "Recept főoldal"
#: .\cookbook\templates\search_info.html:5
#: .\cookbook\templates\search_info.html:9
@@ -2104,17 +2072,15 @@ msgstr "Szuperfelhasználói fiók létrehozása"
#: .\cookbook\templates\socialaccount\authentication_error.html:7
#: .\cookbook\templates\socialaccount\authentication_error.html:23
#, fuzzy
#| msgid "Social Login"
msgid "Social Network Login Failure"
msgstr "Közösségi bejelentkezés"
msgstr "Közösségi hálózat bejelentkezési hiba"
#: .\cookbook\templates\socialaccount\authentication_error.html:25
#, fuzzy
#| msgid "An error occurred attempting to move "
msgid ""
"An error occurred while attempting to login via your social network account."
msgstr "Hiba történt az áthelyezés közben "
msgstr ""
"Hiba történt, miközben megpróbált bejelentkezni a közösségi hálózati fiókján "
"keresztül."
#: .\cookbook\templates\socialaccount\connections.html:4
#: .\cookbook\templates\socialaccount\connections.html:15
@@ -2152,17 +2118,19 @@ msgstr "Regisztráció"
#: .\cookbook\templates\socialaccount\login.html:9
#, python-format
msgid "Connect %(provider)s"
msgstr ""
msgstr "Csatlakozás %(provider)s"
#: .\cookbook\templates\socialaccount\login.html:11
#, python-format
msgid "You are about to connect a new third party account from %(provider)s."
msgstr ""
"Ön egy új, harmadik féltől származó fiókot készül csatlakoztatni "
"a%(provider)-tól/től."
#: .\cookbook\templates\socialaccount\login.html:13
#, python-format
msgid "Sign In Via %(provider)s"
msgstr ""
msgstr "Bejelentkezve %(provider)s keresztül"
#: .\cookbook\templates\socialaccount\login.html:15
#, python-format
@@ -2171,7 +2139,7 @@ msgstr ""
#: .\cookbook\templates\socialaccount\login.html:20
msgid "Continue"
msgstr ""
msgstr "Folytatás"
#: .\cookbook\templates\socialaccount\signup.html:10
#, python-format
@@ -2210,10 +2178,8 @@ msgid "Manage Subscription"
msgstr "Feliratkozás kezelése"
#: .\cookbook\templates\space_overview.html:13 .\cookbook\views\delete.py:216
#, fuzzy
#| msgid "Space:"
msgid "Space"
msgstr "Tér:"
msgstr "Tér"
#: .\cookbook\templates\space_overview.html:17
msgid ""
@@ -2230,13 +2196,11 @@ msgstr "Meghívást kaphatsz egy meglévő térbe, vagy létrehozhatod a sajáto
#: .\cookbook\templates\space_overview.html:53
msgid "Owner"
msgstr ""
msgstr "Tulajdonos"
#: .\cookbook\templates\space_overview.html:57
#, fuzzy
#| msgid "Create Space"
msgid "Leave Space"
msgstr "Tér létrehozása"
msgstr "Kilépés a Térből"
#: .\cookbook\templates\space_overview.html:78
#: .\cookbook\templates\space_overview.html:88
@@ -2485,87 +2449,111 @@ msgstr ""
"teljes szöveges keresés is."
#: .\cookbook\views\api.py:733
#, fuzzy
#| msgid "ID of keyword a recipe should have. For multiple repeat parameter."
msgid ""
"ID of keyword a recipe should have. For multiple repeat parameter. "
"Equivalent to keywords_or"
msgstr ""
"A recept kulcsszavának azonosítója. Többszörös ismétlődő paraméter esetén."
"A recept kulcsszavának azonosítója. Többszörös ismétlődő paraméter esetén. "
"Egyenértékű a keywords_or kulcsszavakkal"
#: .\cookbook\views\api.py:736
msgid ""
"Keyword IDs, repeat for multiple. Return recipes with any of the keywords"
msgstr ""
"Kulcsszó azonosítók. Többször is megadható. A megadott kulcsszavak "
"mindegyikéhez tartozó receptek listázza"
#: .\cookbook\views\api.py:739
msgid ""
"Keyword IDs, repeat for multiple. Return recipes with all of the keywords."
msgstr ""
"Kulcsszó azonosítók. Többször is megadható. Az összes megadott kulcsszót "
"tartalmazó receptek listázása."
#: .\cookbook\views\api.py:742
msgid ""
"Keyword IDs, repeat for multiple. Exclude recipes with any of the keywords."
msgstr ""
"Kulcsszó azonosító. Többször is megadható. Kizárja a recepteket a megadott "
"kulcsszavak egyikéből."
#: .\cookbook\views\api.py:745
msgid ""
"Keyword IDs, repeat for multiple. Exclude recipes with all of the keywords."
msgstr ""
"Kulcsszó azonosítók. Többször is megadható. Kizárja az összes megadott "
"kulcsszóval rendelkező receptet."
#: .\cookbook\views\api.py:747
msgid "ID of food a recipe should have. For multiple repeat parameter."
msgstr ""
"Az ételek azonosítója egy receptnek tartalmaznia kell. Többszörös ismétlődő "
"paraméter esetén."
"Annak az összetevőnek az azonosítója, amelynek receptjeit fel kell sorolni. "
"Többször is megadható."
#: .\cookbook\views\api.py:750
msgid "Food IDs, repeat for multiple. Return recipes with any of the foods"
msgstr ""
"Összetevő azonosító. Többször is megadható. Legalább egy összetevő "
"receptjeinek listája"
#: .\cookbook\views\api.py:752
msgid "Food IDs, repeat for multiple. Return recipes with all of the foods."
msgstr ""
"Összetevő azonosító. Többször is megadható. Az összes megadott összetevőt "
"tartalmazó receptek listája."
#: .\cookbook\views\api.py:754
msgid "Food IDs, repeat for multiple. Exclude recipes with any of the foods."
msgstr ""
"Összetevő azonosító. Többször is megadható. Kizárja azokat a recepteket, "
"amelyek a megadott összetevők bármelyikét tartalmazzák."
#: .\cookbook\views\api.py:756
msgid "Food IDs, repeat for multiple. Exclude recipes with all of the foods."
msgstr ""
"Összetevő azonosító. Többször is megadható. Kizárja az összes megadott "
"összetevőt tartalmazó recepteket."
#: .\cookbook\views\api.py:757
msgid "ID of unit a recipe should have."
msgstr "Az egység azonosítója, amellyel a receptnek rendelkeznie kell."
msgstr "A recepthez tartozó mértékegység azonosítója."
#: .\cookbook\views\api.py:759
msgid ""
"Rating a recipe should have or greater. [0 - 5] Negative value filters "
"rating less than."
msgstr ""
"Egy recept minimális értékelése (0-5). A negatív értékek a maximális "
"értékelés szerint szűrnek."
#: .\cookbook\views\api.py:760
msgid "ID of book a recipe should be in. For multiple repeat parameter."
msgstr ""
"A könyv azonosítója, amelyben a receptnek szerepelnie kell. Többszörös "
"ismétlés esetén paraméter."
"A könyv azonosítója, amelyben a recept található. Többször is megadható."
#: .\cookbook\views\api.py:762
msgid "Book IDs, repeat for multiple. Return recipes with any of the books"
msgstr ""
"A könyv azonosítója. Többször is megadható. A megadott könyvek összes "
"receptjének listája"
#: .\cookbook\views\api.py:764
msgid "Book IDs, repeat for multiple. Return recipes with all of the books."
msgstr ""
"A könyv azonosítója. Többször is megadható. Az összes könyvben szereplő "
"recept listája."
#: .\cookbook\views\api.py:766
msgid "Book IDs, repeat for multiple. Exclude recipes with any of the books."
msgstr ""
"A könyv azonosítói. Többször is megadható. Kizárja a megadott könyvek "
"receptjeit."
#: .\cookbook\views\api.py:768
msgid "Book IDs, repeat for multiple. Exclude recipes with all of the books."
msgstr ""
"A könyv azonosítói. Többször is megadható. Kizárja az összes megadott "
"könyvben szereplő receptet."
#: .\cookbook\views\api.py:770
msgid "If only internal recipes should be returned. [true/<b>false</b>]"
@@ -2587,36 +2575,50 @@ msgid ""
"Filter recipes cooked X times or more. Negative values returns cooked less "
"than X times"
msgstr ""
"X-szer vagy többször főzött receptek szűrése. A negatív értékek X "
"alkalomnál kevesebbet főzött recepteket jelenítik meg"
#: .\cookbook\views\api.py:778
msgid ""
"Filter recipes last cooked on or after YYYY-MM-DD. Prepending - filters on "
"or before date."
msgstr ""
"Megjeleníti azokat a recepteket, amelyeket a megadott napon (ÉÉÉÉ-HH-NN) "
"vagy később főztek meg utoljára. A - jelölve az adott dátumon vagy azt "
"megelőzően elkészítettek kerülnek be a receptek listájába."
#: .\cookbook\views\api.py:780
msgid ""
"Filter recipes created on or after YYYY-MM-DD. Prepending - filters on or "
"before date."
msgstr ""
"Megjeleníti azokat a recepteket, amelyeket a megadott napon (ÉÉÉÉ-HH-NN) "
"vagy később hoztak létre. A - jelölve az adott dátumon vagy azt megelőzően "
"hozták létre."
#: .\cookbook\views\api.py:782
msgid ""
"Filter recipes updated on or after YYYY-MM-DD. Prepending - filters on or "
"before date."
msgstr ""
"Megjeleníti azokat a recepteket, amelyeket a megadott napon (ÉÉÉÉ-HH-NN) "
"vagy később frissültek. A - jelölve az adott dátumon vagy azt megelőzően "
"frissültek."
#: .\cookbook\views\api.py:784
msgid ""
"Filter recipes lasts viewed on or after YYYY-MM-DD. Prepending - filters on "
"or before date."
msgstr ""
"Megjeleníti azokat a recepteket, amelyeket a megadott napon (ÉÉÉÉ-HH-NN) "
"vagy később néztek meg utoljára. A - jelölve az adott dátumon vagy azt "
"megelőzően néztek meg utoljára."
#: .\cookbook\views\api.py:786
#, fuzzy
#| msgid "If only internal recipes should be returned. [true/<b>false</b>]"
msgid "Filter recipes that can be made with OnHand food. [true/<b>false</b>]"
msgstr "Ha csak a belső recepteket kell visszaadni. [true/<b>false</b>]"
msgstr ""
"Felsorolja azokat a recepteket, amelyeket a rendelkezésre álló összetevőkből "
"el lehet készíteni. [true/<b>false</b>]"
#: .\cookbook\views\api.py:946
msgid ""
@@ -2647,7 +2649,7 @@ msgstr "Semmi feladat."
#: .\cookbook\views\api.py:1198
msgid "Invalid Url"
msgstr ""
msgstr "Érvénytelen URL"
#: .\cookbook\views\api.py:1205
msgid "Connection Refused."
@@ -2655,13 +2657,11 @@ msgstr "Kapcsolat megtagadva."
#: .\cookbook\views\api.py:1210
msgid "Bad URL Schema."
msgstr ""
msgstr "Rossz URL séma."
#: .\cookbook\views\api.py:1233
#, fuzzy
#| msgid "No useable data could be found."
msgid "No usable data could be found."
msgstr "Nem találtam használható adatokat."
msgstr "Nem sikerült használható adatokat találni."
#: .\cookbook\views\api.py:1326 .\cookbook\views\import_export.py:117
msgid "Importing is not implemented for this provider"
@@ -2774,10 +2774,8 @@ msgid "Shopping Categories"
msgstr "Bevásárlási kategóriák"
#: .\cookbook\views\lists.py:187
#, fuzzy
#| msgid "Filter"
msgid "Custom Filters"
msgstr "Szűrő"
msgstr "Egyedi szűrők"
#: .\cookbook\views\lists.py:224
msgid "Steps"

View File

@@ -11,9 +11,9 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-04-29 07:55+0000\n"
"Last-Translator: Oliver Cervera <olivercervera@yahoo.it>\n"
"Language-Team: Italian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/it/>\n"
"Language: it\n"
@@ -116,7 +116,7 @@ msgid "If you want to be able to create and see comments underneath recipes."
msgstr ""
"Se vuoi essere in grado di creare e vedere i commenti sotto le ricette."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -134,7 +134,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "Fissa la barra di navigazione nella parte superiore della pagina."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
"Aggiungi automaticamente gli ingredienti del piano alimentare alla lista "
@@ -156,11 +156,11 @@ msgstr ""
"Entrambi i campi sono facoltativi. Se non viene fornito, verrà visualizzato "
"il nome utente"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Nome"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Parole chiave"
@@ -172,7 +172,7 @@ msgstr "Tempo di preparazione in minuti"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Tempo di attesa (cottura) in minuti"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Percorso"
@@ -184,7 +184,7 @@ msgstr "UID di archiviazione"
msgid "Default"
msgstr "Predefinito"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -192,20 +192,20 @@ msgstr ""
"Per prevenire duplicati, vengono ignorate le ricette che hanno lo stesso "
"nome di quelle esistenti. Metti la spunta per importare tutto."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Aggiungi il tuo commento: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
"Lascia vuoto per dropbox e inserisci la password dell'app per nextcloud."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr "Lascia vuoto per nextcloud e inserisci l'api token per dropbox."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -213,33 +213,33 @@ msgstr ""
"Lascia vuoto per dropbox e inserisci solo l'url base per nextcloud (<code>/"
"remote.php/webdav/</code> è aggiunto automaticamente)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Archiviazione"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Attivo"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Stringa di Ricerca"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "ID del File"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Devi fornire almeno una ricetta o un titolo."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"È possibile visualizzare l'elenco degli utenti predefiniti con cui "
"condividere le ricette nelle impostazioni."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -247,15 +247,15 @@ msgstr ""
"Puoi usare markdown per formattare questo campo. Guarda la <a href=\"/docs/"
"markdown/\">documentazione qui</a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "È stato raggiunto il numero massimo di utenti per questa istanza."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "Questo indirizzo email è già in uso!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -263,15 +263,15 @@ msgstr ""
"Non è obbligatorio specificare l'indirizzo email, ma se presente verrà "
"utilizzato per mandare all'utente un link di invito."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "Nome già in uso."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "Accetta i Termini d'uso e Privacy"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -280,7 +280,7 @@ msgstr ""
"trigrammi (ad esempio, valori bassi significano che vengono ignorati più "
"errori di battitura)."
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
@@ -288,7 +288,7 @@ msgstr ""
"Seleziona il metodo di ricerca. Clicca <a href=\"/docs/search/\">qui</a> "
"per avere maggiori informazioni."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -296,7 +296,7 @@ msgstr ""
"Usa la corrispondenza vaga per unità, parole chiave e ingredienti durante la "
"modifica e l'importazione di ricette."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
@@ -304,7 +304,7 @@ msgstr ""
"Campi da cercare ignorando gli accenti. A seconda alla lingua utilizzata, "
"questa opzione può migliorare o peggiorare la ricerca"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
@@ -312,7 +312,7 @@ msgstr ""
"Campi da cercare con corrispondenza parziale. (ad esempio, cercando 'Torta' "
"verranno mostrati 'torta', 'tortino' e 'contorta')"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
@@ -320,7 +320,7 @@ msgstr ""
"Campi da cercare all'inizio di parole corrispondenti (es. cercando per 'ins' "
"mostrerà 'insalata' e 'insaccati')"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -329,7 +329,7 @@ msgstr ""
"verrà mostrato 'ricetta'). Nota: questa opzione non è compatibile con la "
"ricerca 'web' o 'raw'."
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
@@ -337,35 +337,35 @@ msgstr ""
"Campi per la ricerca full-text. Nota: i metodi di ricerca 'web', 'frase' e "
"'raw' funzionano solo con i campi full-text."
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Metodo di ricerca"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "Ricerche vaghe"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "Ignora accento"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "Corrispondenza parziale"
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "Inizia con"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "Ricerca vaga"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Full Text"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -373,7 +373,7 @@ msgstr ""
"Gli utenti potranno vedere tutti gli elementi che aggiungi alla tua lista "
"della spesa. Devono aggiungerti per vedere gli elementi nella loro lista."
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
@@ -381,7 +381,7 @@ msgstr ""
"Quando si aggiunge un piano alimentare alla lista della spesa (manualmente o "
"automaticamente), includi tutte le ricette correlate."
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
@@ -389,97 +389,97 @@ msgstr ""
"Quando si aggiunge un piano alimentare alla lista della spesa (manualmente o "
"automaticamente), escludi gli ingredienti già disponibili."
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
"Il numero predefinito di ore per ritardare l'inserimento di una lista della "
"spesa."
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
"Filtra la lista della spesa per includere solo categorie dei supermercati."
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr "Giorni di visualizzazione di voci recenti della lista della spesa."
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
"Contrassegna gli alimenti come 'Disponibili' quando spuntati dalla lista "
"della spesa."
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "Delimitatore usato per le esportazioni CSV."
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr "Prefisso da aggiungere quando si copia una lista negli appunti."
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Condividi lista della spesa"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Sincronizzazione automatica"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "Aggiungi automaticamente al piano alimentare"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "Escludi Disponibile"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "Includi correlati"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "Ore di ritardo predefinite"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "Filtra per supermercato"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "Giorni recenti"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "Delimitatore CSV"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Prefisso lista"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "Disponibilità automatica"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "Ripristina Eredità Alimenti"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr "Ripristina tutti gli alimenti per ereditare i campi configurati."
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr ""
"Campi su alimenti che devono essere ereditati per impostazione predefinita."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "Mostra il conteggio delle ricette nei filtri di ricerca"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""
"Usare la forma plurale per le unità e gli alimenti all'interno di questo "
@@ -531,10 +531,8 @@ msgid "One of queryset or hash_key must be provided"
msgstr "Uno tra queryset o has_key deve essere fornito"
#: .\cookbook\helper\recipe_url_import.py:266
#, fuzzy
#| msgid "Use fractions"
msgid "reverse rotation"
msgstr "Usa frazioni"
msgstr "rotazione inversa"
#: .\cookbook\helper\recipe_url_import.py:267
msgid "careful rotation"
@@ -604,10 +602,8 @@ msgid "Imported %s recipes."
msgstr "Importate %s ricette."
#: .\cookbook\integration\openeats.py:26
#, fuzzy
#| msgid "Recipe Home"
msgid "Recipe source:"
msgstr "Pagina iniziale ricette"
msgstr "Fonte ricetta:"
#: .\cookbook\integration\paprika.py:49
msgid "Notes"
@@ -1929,10 +1925,12 @@ msgid ""
"Allows fine control over search results but might not return results if too "
"many spelling mistakes are made."
msgstr ""
"Consente un controllo preciso sui risultati della ricerca, ma potrebbe non "
"mostrare risultati se vengono commessi troppi errori."
#: .\cookbook\templates\settings.html:44
msgid "Perfect for large Databases"
msgstr "Perfetto per database grandi"
msgstr "Ideale per database grandi"
#: .\cookbook\templates\setup.html:6 .\cookbook\templates\system.html:5
msgid "Cookbook Setup"
@@ -1954,10 +1952,8 @@ msgstr "Crea super utente"
#: .\cookbook\templates\socialaccount\authentication_error.html:7
#: .\cookbook\templates\socialaccount\authentication_error.html:23
#, fuzzy
#| msgid "Social Login"
msgid "Social Network Login Failure"
msgstr "Login con social network"
msgstr "Errore di login con Social Network"
#: .\cookbook\templates\socialaccount\authentication_error.html:25
msgid ""

View File

@@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-01-08 17:55+0000\n"
"Last-Translator: Joachim Weber <joachim.weber@gmx.de>\n"
"Language-Team: Latvian <http://translate.tandoor.dev/projects/tandoor/"
@@ -125,7 +125,7 @@ msgid "If you want to be able to create and see comments underneath recipes."
msgstr ""
"Ja vēlaties, lai jūs varētu izveidot un redzēt komentārus zem receptēm."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -143,7 +143,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr ""
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
@@ -163,11 +163,11 @@ msgstr ""
"Abi lauki nav obligāti. Ja neviens nav norādīts, tā vietā tiks parādīts "
"lietotājvārds"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Vārds"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Atslēgvārdi"
@@ -179,7 +179,7 @@ msgstr "Pagatavošanas laiks minūtēs"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Gaidīšanas laiks (vārīšana / cepšana) minūtēs"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Ceļš"
@@ -191,25 +191,25 @@ msgstr "Krātuves UID"
msgid "Default"
msgstr ""
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
msgstr ""
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Pievienot komentāru: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr "Atstājiet tukšu Dropbox un ievadiet lietotnes paroli Nextcloud."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr "Atstājiet tukšu Nextcloud un ievadiet API tokenu Dropbox."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -217,33 +217,33 @@ msgstr ""
"Atstājiet tukšu Dropbox un ievadiet tikai Nextcloud bāzes URL (<kods> /"
"remote.php/webdav/ </code> tiek pievienots automātiski)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Krātuve"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr ""
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Meklēšanas virkne"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "Faila ID"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Jums jānorāda vismaz recepte vai nosaukums."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"Iestatījumos varat uzskaitīt noklusējuma lietotājus, ar kuriem koplietot "
"receptes."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -251,219 +251,219 @@ msgstr ""
"Lai formatētu šo lauku, varat izmantot Markdown. Skatiet <a href=\"/docs/"
"markdown/\"> dokumentus šeit </a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr ""
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr ""
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
msgstr ""
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr ""
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr ""
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
msgstr ""
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
msgstr ""
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
msgstr ""
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
msgstr ""
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
msgstr ""
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
msgstr ""
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
msgstr ""
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
msgstr ""
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
#, fuzzy
#| msgid "Search"
msgid "Search Method"
msgstr "Meklēt"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr ""
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr ""
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr ""
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr ""
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
#, fuzzy
#| msgid "Search"
msgid "Fuzzy Search"
msgstr "Meklēt"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
#, fuzzy
#| msgid "Text"
msgid "Full Text"
msgstr "Teskts"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
msgstr ""
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
msgstr ""
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
msgstr ""
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr ""
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr ""
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr ""
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
#, fuzzy
#| msgid "Shopping List"
msgid "Share Shopping List"
msgstr "Iepirkumu saraksts"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr ""
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr ""
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr ""
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr ""
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr ""
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr ""
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr ""
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr ""
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Saraksta prefikss"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr ""
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr ""
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr ""
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
#, fuzzy
#| msgid "Food that should be replaced."
msgid "Fields on food that should be inherited by default."
msgstr "Ēdiens, kas būtu jāaizstāj."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
#, fuzzy
#| msgid "Show recently viewed recipes on search page."
msgid "Show recipe counts on search filters"
msgstr "Parādīt nesen skatītās receptes meklēšanas lapā."
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-04-11 15:09+0200\n"
"PO-Revision-Date: 2023-04-17 20:55+0000\n"
"Last-Translator: Espen Sellevåg <buskmenn.drammer03@icloud.com>\n"
"PO-Revision-Date: 2023-08-19 21:36+0000\n"
"Last-Translator: NeoID <neoid@animenord.com>\n"
"Language-Team: Norwegian Bokmål <http://translate.tandoor.dev/projects/"
"tandoor/recipes-backend/nb_NO/>\n"
"Language: nb_NO\n"
@@ -31,6 +31,8 @@ msgid ""
"Color of the top navigation bar. Not all colors work with all themes, just "
"try them out!"
msgstr ""
"Farge på toppnavigasjonslinjen. Ikke alle farger fungerer med alle temaer, "
"så bare prøv dem ut!"
#: .\cookbook\forms.py:46
msgid "Default Unit to be used when inserting a new ingredient into a recipe."
@@ -79,13 +81,15 @@ msgstr ""
#: .\cookbook\forms.py:56
msgid "Makes the navbar stick to the top of the page."
msgstr ""
msgstr "Fest navigasjonslinjen til toppen av siden."
#: .\cookbook\forms.py:72
msgid ""
"Both fields are optional. If none are given the username will be displayed "
"instead"
msgstr ""
"Begge feltene er valgfrie. Hvis ingen blir oppgitt, vil brukernavnet vises i "
"stedet"
#: .\cookbook\forms.py:93 .\cookbook\forms.py:315
#: .\cookbook\templates\forms\edit_internal_recipe.html:45
@@ -97,15 +101,15 @@ msgstr "Navn"
#: .\cookbook\templates\forms\edit_internal_recipe.html:81
#: .\cookbook\templates\stats.html:24 .\cookbook\templates\url_import.html:202
msgid "Keywords"
msgstr ""
msgstr "Nøkkelord"
#: .\cookbook\forms.py:95
msgid "Preparation time in minutes"
msgstr ""
msgstr "Forberedelsestid i minutter"
#: .\cookbook\forms.py:96
msgid "Waiting time (cooking/baking) in minutes"
msgstr ""
msgstr "Ventetid (til matlaging/baking) i minutter"
#: .\cookbook\forms.py:97 .\cookbook\forms.py:317
msgid "Path"
@@ -124,6 +128,8 @@ msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
msgstr ""
"For å unngå duplikater, blir oppskrifter med samme navn som eksisterende "
"ignorert. Merk av denne boksen for å importere alt."
#: .\cookbook\forms.py:149
msgid "New Unit"
@@ -131,7 +137,7 @@ msgstr "Ny enhet"
#: .\cookbook\forms.py:150
msgid "New unit that other gets replaced by."
msgstr ""
msgstr "Ny enhet som erstatter den gamle."
#: .\cookbook\forms.py:155
msgid "Old Unit"
@@ -143,19 +149,19 @@ msgstr "Enhet som skal erstattes."
#: .\cookbook\forms.py:172
msgid "New Food"
msgstr ""
msgstr "Ny matvare"
#: .\cookbook\forms.py:173
msgid "New food that other gets replaced by."
msgstr ""
msgstr "Ny matvare som erstatter den gamle."
#: .\cookbook\forms.py:178
msgid "Old Food"
msgstr ""
msgstr "Gammel matvare"
#: .\cookbook\forms.py:179
msgid "Food that should be replaced."
msgstr ""
msgstr "Matvare som bør erstattes."
#: .\cookbook\forms.py:197
msgid "Add your comment: "
@@ -163,17 +169,19 @@ msgstr "Legg til din kommentar: "
#: .\cookbook\forms.py:238
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
msgstr "La det stå tomt for Dropbox og skriv inn app-passordet for Nextcloud."
#: .\cookbook\forms.py:245
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr ""
msgstr "La det stå tomt for Nextcloud og skriv inn API-tokenet for Dropbox."
#: .\cookbook\forms.py:253
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
msgstr ""
"La det stå tomt for Dropbox, og skriv bare inn grunn-URLen for Nextcloud "
"(<code>/remote.php/webdav/</code> blir lagt til automatisk)"
#: .\cookbook\forms.py:291
msgid "Search String"
@@ -185,11 +193,12 @@ msgstr "Fil-ID"
#: .\cookbook\forms.py:354
msgid "You must provide at least a recipe or a title."
msgstr ""
msgstr "Du må oppgi minst en oppskrift eller en tittel."
#: .\cookbook\forms.py:367
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"Du kan liste opp standardbrukere for å dele oppskrifter innen innstillingene."
#: .\cookbook\forms.py:368
#: .\cookbook\templates\forms\edit_internal_recipe.html:377
@@ -197,10 +206,14 @@ msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
msgstr ""
"Du kan bruke Markdown for å formatere dette feltet. Se <a href=\"/docs/"
"markdown/\">dokumentasjonen her</a>"
#: .\cookbook\forms.py:393
msgid "A username is not required, if left blank the new user can choose one."
msgstr ""
"Et brukernavn er ikke påkrevd. Hvis det blir stående tomt, kan den nye "
"brukeren velge ett selv."
#: .\cookbook\helper\permission_helper.py:123
#: .\cookbook\helper\permission_helper.py:129
@@ -222,26 +235,30 @@ msgstr "Du er ikke innlogget og kan derfor ikke vise siden!"
#: .\cookbook\helper\permission_helper.py:167
#: .\cookbook\helper\permission_helper.py:182
msgid "You cannot interact with this object as it is not owned by you!"
msgstr ""
msgstr "Du kan ikke samhandle med dette objektet, da det ikke tilhører deg!"
#: .\cookbook\helper\recipe_url_import.py:40 .\cookbook\views\api.py:549
msgid "The requested site provided malformed data and cannot be read."
msgstr ""
"Nettstedet du har forespurt, har levert feilformatert data som ikke kan "
"leses."
#: .\cookbook\helper\recipe_url_import.py:54
msgid ""
"The requested site does not provide any recognized data format to import the "
"recipe from."
msgstr ""
"Det forespurte nettstedet gir ingen gjenkjennelig dataformat som kan "
"importeres oppskriften fra."
#: .\cookbook\helper\recipe_url_import.py:160
msgid "Imported from"
msgstr ""
msgstr "Importert fra"
#: .\cookbook\helper\template_helper.py:60
#: .\cookbook\helper\template_helper.py:62
msgid "Could not parse template code."
msgstr ""
msgstr "Kunne ikke analysere mal-koden."
#: .\cookbook\integration\integration.py:102
#: .\cookbook\templates\import.html:14 .\cookbook\templates\import.html:20
@@ -250,50 +267,52 @@ msgstr ""
#: .\cookbook\templates\url_import.html:233 .\cookbook\views\delete.py:60
#: .\cookbook\views\edit.py:190
msgid "Import"
msgstr ""
msgstr "Importér"
#: .\cookbook\integration\integration.py:131
msgid ""
"Importer expected a .zip file. Did you choose the correct importer type for "
"your data ?"
msgstr ""
"Importøren forventet en .zip-fil. Har du valgt riktig type importør for "
"dataene dine?"
#: .\cookbook\integration\integration.py:134
msgid "The following recipes were ignored because they already existed:"
msgstr ""
msgstr "Følgende oppskrifter ble ignorert fordi de allerede eksisterte:"
#: .\cookbook\integration\integration.py:137
#, python-format
msgid "Imported %s recipes."
msgstr ""
msgstr "Importerte %s oppskrifter."
#: .\cookbook\integration\paprika.py:44
msgid "Notes"
msgstr ""
msgstr "Notater"
#: .\cookbook\integration\paprika.py:47
msgid "Nutritional Information"
msgstr ""
msgstr "Næringsinformasjon"
#: .\cookbook\integration\paprika.py:50
msgid "Source"
msgstr ""
msgstr "Kilde"
#: .\cookbook\integration\safron.py:23
#: .\cookbook\templates\forms\edit_internal_recipe.html:75
#: .\cookbook\templates\include\log_cooking.html:16
#: .\cookbook\templates\url_import.html:84
msgid "Servings"
msgstr ""
msgstr "Porsjoner"
#: .\cookbook\integration\safron.py:25
msgid "Waiting time"
msgstr ""
msgstr "Ventetid"
#: .\cookbook\integration\safron.py:27
#: .\cookbook\templates\forms\edit_internal_recipe.html:69
msgid "Preparation Time"
msgstr ""
msgstr "Forberedelsestid"
#: .\cookbook\integration\safron.py:29 .\cookbook\templates\base.html:71
#: .\cookbook\templates\forms\ingredients.html:7
@@ -329,7 +348,7 @@ msgstr "Søk"
#: .\cookbook\templates\meal_plan.html:5 .\cookbook\views\delete.py:152
#: .\cookbook\views\edit.py:224 .\cookbook\views\new.py:188
msgid "Meal-Plan"
msgstr ""
msgstr "Måltidsplan"
#: .\cookbook\models.py:112 .\cookbook\templates\base.html:82
msgid "Books"
@@ -337,11 +356,11 @@ msgstr "Bøker"
#: .\cookbook\models.py:119
msgid "Small"
msgstr ""
msgstr "Liten"
#: .\cookbook\models.py:119
msgid "Large"
msgstr ""
msgstr "Stor"
#: .\cookbook\models.py:327
#: .\cookbook\templates\forms\edit_internal_recipe.html:198
@@ -1109,22 +1128,24 @@ msgstr ""
#: .\cookbook\templates\markdown_info.html:125
msgid "Images & Links"
msgstr ""
msgstr "Bilder og lenker"
#: .\cookbook\templates\markdown_info.html:126
msgid ""
"Links can be formatted with Markdown. This application also allows to paste "
"links directly into markdown fields without any formatting."
msgstr ""
"Lenker kan formateres med Markdown. Denne applikasjonen lar deg også lime "
"inn lenker direkte i Markdown-felt uten noen formatering."
#: .\cookbook\templates\markdown_info.html:132
#: .\cookbook\templates\markdown_info.html:145
msgid "This will become an image"
msgstr ""
msgstr "Dette vil bli til et bilde"
#: .\cookbook\templates\markdown_info.html:152
msgid "Tables"
msgstr ""
msgstr "Tabeller"
#: .\cookbook\templates\markdown_info.html:153
msgid ""
@@ -1132,124 +1153,130 @@ msgid ""
"editor like <a href=\"https://www.tablesgenerator.com/markdown_tables\" rel="
"\"noreferrer noopener\" target=\"_blank\">this one.</a>"
msgstr ""
"Markdown-tabeller er vanskelige å lage for hånd. Det anbefales å bruke en "
"tabellredigerer som <a href=\"https://www.tablesgenerator.com/"
"markdown_tables\" rel=\"noreferrer noopener\" target=\"_blank\">denne.</a>"
#: .\cookbook\templates\markdown_info.html:155
#: .\cookbook\templates\markdown_info.html:157
#: .\cookbook\templates\markdown_info.html:171
#: .\cookbook\templates\markdown_info.html:177
msgid "Table"
msgstr ""
msgstr "Tabell"
#: .\cookbook\templates\markdown_info.html:155
#: .\cookbook\templates\markdown_info.html:172
msgid "Header"
msgstr ""
msgstr "Overskrift"
#: .\cookbook\templates\markdown_info.html:157
#: .\cookbook\templates\markdown_info.html:178
msgid "Cell"
msgstr ""
msgstr "Celle"
#: .\cookbook\templates\meal_plan.html:101
msgid "New Entry"
msgstr ""
msgstr "Ny oppføring"
#: .\cookbook\templates\meal_plan.html:113
#: .\cookbook\templates\shopping_list.html:52
msgid "Search Recipe"
msgstr ""
msgstr "Søk oppskrift"
#: .\cookbook\templates\meal_plan.html:139
msgid "Title"
msgstr ""
msgstr "Tittel"
#: .\cookbook\templates\meal_plan.html:141
msgid "Note (optional)"
msgstr ""
msgstr "Merknad (valgfritt)"
#: .\cookbook\templates\meal_plan.html:143
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\" target=\"_blank\" rel=\"noopener noreferrer\">docs here</a>"
msgstr ""
"Du kan bruke Markdown for å formatere dette feltet. Se <a href=\"/docs/"
"markdown/\" target=\"_blank\" rel=\"noopener noreferrer\">dokumentasjonen "
"her</a>"
#: .\cookbook\templates\meal_plan.html:147
#: .\cookbook\templates\meal_plan.html:251
msgid "Serving Count"
msgstr ""
msgstr "Antall porsjoner"
#: .\cookbook\templates\meal_plan.html:153
msgid "Create only note"
msgstr ""
msgstr "Opprett kun en merknad"
#: .\cookbook\templates\meal_plan.html:168
#: .\cookbook\templates\shopping_list.html:7
#: .\cookbook\templates\shopping_list.html:29
#: .\cookbook\templates\shopping_list.html:705
msgid "Shopping List"
msgstr ""
msgstr "Handleliste"
#: .\cookbook\templates\meal_plan.html:172
msgid "Shopping list currently empty"
msgstr ""
msgstr "Handlelisten er for øyeblikket tom"
#: .\cookbook\templates\meal_plan.html:175
msgid "Open Shopping List"
msgstr ""
msgstr "Åpne handlelisten"
#: .\cookbook\templates\meal_plan.html:189
msgid "Plan"
msgstr ""
msgstr "Plan"
#: .\cookbook\templates\meal_plan.html:196
msgid "Number of Days"
msgstr ""
msgstr "Antall dager"
#: .\cookbook\templates\meal_plan.html:206
msgid "Weekday offset"
msgstr ""
msgstr "Ukedagsforskyvning"
#: .\cookbook\templates\meal_plan.html:209
msgid ""
"Number of days starting from the first day of the week to offset the default "
"view."
msgstr ""
msgstr "Antall dager fra den første dagen i uken for å endre standardvisningen."
#: .\cookbook\templates\meal_plan.html:217
#: .\cookbook\templates\meal_plan.html:294
msgid "Edit plan types"
msgstr ""
msgstr "Rediger plantyper"
#: .\cookbook\templates\meal_plan.html:219
msgid "Show help"
msgstr ""
msgstr "Vis hjelp"
#: .\cookbook\templates\meal_plan.html:220
msgid "Week iCal export"
msgstr ""
msgstr "Uke iCal-eksport"
#: .\cookbook\templates\meal_plan.html:264
#: .\cookbook\templates\meal_plan_entry.html:18
msgid "Created by"
msgstr ""
msgstr "Opprettet av"
#: .\cookbook\templates\meal_plan.html:270
#: .\cookbook\templates\meal_plan_entry.html:20
#: .\cookbook\templates\shopping_list.html:250
msgid "Shared with"
msgstr ""
msgstr "Delt med"
#: .\cookbook\templates\meal_plan.html:280
msgid "Add to Shopping"
msgstr ""
msgstr "Legg til i handlelisten"
#: .\cookbook\templates\meal_plan.html:323
msgid "New meal type"
msgstr ""
msgstr "Ny måltidstype"
#: .\cookbook\templates\meal_plan.html:338
msgid "Meal Plan Help"
msgstr ""
msgstr "Hjelp for måltidsplanen"
#: .\cookbook\templates\meal_plan.html:344
msgid ""
@@ -1289,7 +1316,7 @@ msgstr ""
#: .\cookbook\templates\meal_plan_entry.html:6
msgid "Meal Plan View"
msgstr ""
msgstr "Visning av måltidsplanen"
#: .\cookbook\templates\meal_plan_entry.html:50
msgid "Never cooked before."
@@ -1297,7 +1324,7 @@ msgstr ""
#: .\cookbook\templates\meal_plan_entry.html:76
msgid "Other meals on this day"
msgstr ""
msgstr "Andre måltider denne dagen"
#: .\cookbook\templates\no_groups_info.html:5
#: .\cookbook\templates\no_groups_info.html:12

View File

@@ -12,11 +12,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-02-27 13:55+0000\n"
"Last-Translator: Jesse <jesse.kamps@pm.me>\n"
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/recipes-"
"backend/nl/>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-08-15 19:19+0000\n"
"Last-Translator: Jochum van der Heide <jochum@famvanderheide.com>\n"
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/nl/>\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -116,7 +116,7 @@ msgstr "Aantal decimalen om ingrediënten op af te ronden."
msgid "If you want to be able to create and see comments underneath recipes."
msgstr "Als je opmerkingen onder recepten wil kunnen maken en zien."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -133,7 +133,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "Zet de navbar vast aan de bovenkant van de pagina."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr "Zet maaltijdplan ingrediënten automatisch op boodschappenlijst."
@@ -153,11 +153,11 @@ msgstr ""
"Beide velden zijn optioneel. Indien niks is opgegeven wordt de "
"gebruikersnaam weergegeven"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Naam"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Etiketten"
@@ -169,7 +169,7 @@ msgstr "Voorbereidingstijd in minuten"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Wacht tijd in minuten (koken en bakken)"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Pad"
@@ -181,7 +181,7 @@ msgstr "Opslag UID"
msgid "Default"
msgstr "Standaard waarde"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -189,19 +189,19 @@ msgstr ""
"Om dubbelingen te voorkomen worden recepten met dezelfde naam als een "
"bestaand recept genegeerd. Vink aan om alles te importeren."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Voeg een opmerking toe: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr "Laat leeg voor dropbox en vul het app wachtwoord in voor nextcloud."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr "Laat leeg voor nextcloud en vul de api token in voor dropbox."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -209,33 +209,33 @@ msgstr ""
"Laat leeg voor dropbox en vul enkel de base url voor nextcloud in. (<code>/"
"remote.php/webdav/</code> wordt automatisch toegevoegd.)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Opslag"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Actief"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Zoekopdracht"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "Bestands ID"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "Je moet minimaal één recept of titel te specificeren."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"Je kan in de instellingen standaard gebruikers in stellen om de recepten met "
"te delen."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -243,15 +243,15 @@ msgstr ""
"Je kunt markdown gebruiken om dit veld te op te maken. Bekijk de <a href=\"/"
"docs/markdown/\">documentatie hier</a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "Maximum aantal gebruikers voor deze ruimte bereikt."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "E-mailadres reeds in gebruik!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -259,15 +259,15 @@ msgstr ""
"Een e-mailadres is niet vereist, maar indien aanwezig zal de "
"uitnodigingslink naar de gebruiker worden gestuurd."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "Naam reeds in gebruik."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "Accepteer voorwaarden"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -275,7 +275,7 @@ msgstr ""
"Bepaalt hoe 'fuzzy' een zoekopdracht is als het trigram vergelijken gebruikt "
"(lage waarden betekenen bijvoorbeeld dat meer typefouten genegeerd worden)."
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
@@ -283,7 +283,7 @@ msgstr ""
"Selecteer zoekmethode. Klik <a href=\"/docs/search/\">hier</a> voor een "
"beschrijving van de keuzes."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -291,7 +291,7 @@ msgstr ""
"Gebruik 'fuzzy' koppelen bij eenheden, etiketten en ingrediënten bij "
"bewerken en importeren van recepten."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
@@ -300,7 +300,7 @@ msgstr ""
"deze optie kan de zoekkwaliteit afhankelijk van de taal, zowel verbeteren "
"als verslechteren"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
@@ -308,7 +308,7 @@ msgstr ""
"Velden doorzoeken op gedeelde overeenkomsten. (zoeken op 'Appel' vindt "
"'appel', 'aardappel' en 'appelsap')"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
@@ -316,7 +316,7 @@ msgstr ""
"Velden doorzoeken op overeenkomsten aan het begin van het woord. (zoeken op "
"'sa' vindt 'salade' en 'sandwich')"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -324,7 +324,7 @@ msgstr ""
"Velden 'fuzzy' doorzoeken. (zoeken op 'recetp' vindt ook 'recept') Noot: "
"deze optie conflicteert met de zoekmethoden 'web' en 'raw'."
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
@@ -332,35 +332,35 @@ msgstr ""
"Velden doorzoeken op volledige tekst. Noot: Web, Zin en Raw zoekmethoden "
"werken alleen met volledige tekstvelden."
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Zoekmethode"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "'Fuzzy' zoekopdrachten"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "Negeer accent"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "Gedeeltelijke overeenkomst"
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "Begint met"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "'Fuzzy' zoeken"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Volledige tekst"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -368,7 +368,7 @@ msgstr ""
"Gebruikers zien alle items die je op je boodschappenlijst zet. Ze moeten "
"jou toevoegen om items op hun lijst te zien."
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
@@ -376,7 +376,7 @@ msgstr ""
"Als een maaltijdplan aan de boodschappenlijst toegevoegd wordt (handmatig of "
"automatisch), neem dan alle recepten op."
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
@@ -384,94 +384,94 @@ msgstr ""
"Als een maaltijdplan aan de boodschappenlijst toegevoegd wordt (handmatig of "
"automatisch), sluit ingrediënten die op voorraad zijn dan uit."
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr "Standaard aantal uren om een boodschappenlijst item te vertragen."
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr "Filter boodschappenlijst om alleen supermarktcategorieën te bevatten."
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr "Dagen van recente boodschappenlijst items weer te geven."
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
"Markeer eten 'Op voorraad' wanneer het van het boodschappenlijstje is "
"afgevinkt."
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "Scheidingsteken te gebruiken voor CSV exports."
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr ""
"Toe te voegen Voorvoegsel bij het kopiëren van een lijst naar het klembord."
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Deel boodschappenlijst"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "Autosync"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "Voeg maaltijdplan automatisch toe"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "Sluit op voorraad uit"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "Neem gerelateerde op"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "Standaard vertraging in uren"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "Filter op supermarkt"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "Afgelopen dagen"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "CSV scheidingsteken"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "Lijst voorvoegsel"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "Auto op voorraad"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "Herstel Ingrediënt overname"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr "Herstel alle ingrediënten om de geconfigureerde velden over te nemen."
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr "Velden van ingrediënten die standaard overgenomen moeten worden."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "Toon recepten teller bij zoekfilters"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr "Gebruik de meervoudsvorm voor eenheden en voedsel in deze ruimte."
@@ -522,34 +522,32 @@ msgid "One of queryset or hash_key must be provided"
msgstr "Er moet een queryset of hash_key opgegeven worden"
#: .\cookbook\helper\recipe_url_import.py:266
#, fuzzy
#| msgid "Use fractions"
msgid "reverse rotation"
msgstr "Gebruik fracties"
msgstr "omgekeerde rotatie"
#: .\cookbook\helper\recipe_url_import.py:267
msgid "careful rotation"
msgstr ""
msgstr "voorzichtige rotatie"
#: .\cookbook\helper\recipe_url_import.py:268
msgid "knead"
msgstr ""
msgstr "kneden"
#: .\cookbook\helper\recipe_url_import.py:269
msgid "thicken"
msgstr ""
msgstr "verdikken"
#: .\cookbook\helper\recipe_url_import.py:270
msgid "warm up"
msgstr ""
msgstr "opwarmen"
#: .\cookbook\helper\recipe_url_import.py:271
msgid "ferment"
msgstr ""
msgstr "gisten"
#: .\cookbook\helper\recipe_url_import.py:272
msgid "sous-vide"
msgstr ""
msgstr "sous-vide"
#: .\cookbook\helper\shopping_helper.py:157
msgid "You must supply a servings size"
@@ -594,10 +592,8 @@ msgid "Imported %s recipes."
msgstr "%s recepten geïmporteerd."
#: .\cookbook\integration\openeats.py:26
#, fuzzy
#| msgid "Recipe Home"
msgid "Recipe source:"
msgstr "Recept thuis"
msgstr "Bron van het recept:"
#: .\cookbook\integration\paprika.py:49
msgid "Notes"

View File

@@ -11,9 +11,9 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"PO-Revision-Date: 2023-01-08 17:55+0000\n"
"Last-Translator: Joachim Weber <joachim.weber@gmx.de>\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-10-07 18:02+0000\n"
"Last-Translator: Guilherme Roda <glealroda@gmail.com>\n"
"Language-Team: Portuguese <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/pt/>\n"
"Language: pt\n"
@@ -114,7 +114,7 @@ msgstr "Número de casas decimais para arredondamentos."
msgid "If you want to be able to create and see comments underneath recipes."
msgstr "Ativar a funcionalidade comentar receitas."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -131,7 +131,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "Mantém a barra de navegação no topo da página."
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
@@ -151,11 +151,11 @@ msgstr ""
"Ambos os campos são opcionais. Se nenhum for preenchido o nome de utilizador "
"será apresentado"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "Nome"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "Palavras-chave"
@@ -167,7 +167,7 @@ msgstr "Tempo de preparação em minutos"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "Tempo de espera (cozedura) em minutos"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "Caminho"
@@ -179,7 +179,7 @@ msgstr "UID de armazenamento"
msgid "Default"
msgstr "Predefinição"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -187,55 +187,55 @@ msgstr ""
"Para evitar repetições, receitas com o mesmo nome de receitas já existentes "
"são ignoradas. Marque esta caixa para importar tudo."
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "Adicionar comentário: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
"Deixar vazio para Dropbox e inserir palavra-passe de aplicação para "
"Nextcloud."
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr "Deixar vazio para Nextcloud e inserir token api para Dropbox."
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
msgstr ""
"Deixar vazio para Dropbox e inserir apenas url base para Nextcloud (<code>/"
"remote.php/webdav/</code>é adicionado automaticamente). "
"Deixar vazio para Dropbox e inserir apenas url base para Nextcloud "
"(<code>/remote.php/webdav/</code>é adicionado automaticamente)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "Armazenamento"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Ativo"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "Procurar"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "ID the ficheiro"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "É necessário inserir uma receita ou um título."
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
"É possível escolher os utilizadores com quem partilhar receitas por defeitos "
"nas definições."
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
@@ -243,15 +243,15 @@ msgstr ""
"É possível utilizar markdown para editar este campo. Documentação <a href=\"/"
"docs/markdown/\">disponível aqui</a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "Número máximo de utilizadores alcançado."
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "Endereço email já utilizado!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -259,15 +259,15 @@ msgstr ""
"Um endereço de email não é obrigatório mas se fornecido será enviada uma "
"mensagem ao utilizador."
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "Nome já existente."
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "Aceitar Termos e Condições"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -276,19 +276,15 @@ msgstr ""
"de semelhança de trigrama (valores mais baixos significam que mais erros são "
"ignorados)."
#: .\cookbook\forms.py:444
#, fuzzy
#| msgid ""
#| "Select type method of search. Click <a href=\"/docs/search/\">here</a> "
#| "for full desciption of choices."
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
msgstr ""
"Selecionar o método de pesquisa. Uma descrição completa das opções pode ser "
"encontrada <a href=\"/docs/search/\">aqui</a>."
"Selecionar o método de pesquisa. Uma descrição completa das opções pode "
"ser encontrada <a href=\"/docs/search/\">aqui</a>."
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
@@ -296,7 +292,7 @@ msgstr ""
"Utilizar correspondência difusa em unidades, palavras-chave e ingredientes "
"ao editar e importar receitas."
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
@@ -304,171 +300,161 @@ msgstr ""
"Campos de pesquisa que ignoram pontuação. Esta opção pode aumentar ou "
"diminuir a qualidade de pesquisa dependendo da língua em uso"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
msgstr ""
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
msgstr ""
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
msgstr ""
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
msgstr ""
#: .\cookbook\forms.py:459
#, fuzzy
#| msgid "Search"
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "Procurar"
msgstr "Método de Pesquisa"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr ""
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr ""
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr ""
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr ""
#: .\cookbook\forms.py:464
#, fuzzy
#| msgid "Search"
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "Procurar"
msgstr "Pesquisa Fuzzy"
#: .\cookbook\forms.py:465
#, fuzzy
#| msgid "Text"
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "Texto"
msgstr "Texto Completo"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
msgstr ""
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
msgstr ""
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
msgstr ""
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr ""
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr ""
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr ""
#: .\cookbook\forms.py:507
#, fuzzy
#| msgid "Shopping"
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "Compras"
msgstr "Compartilhar Lista de Compras"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr ""
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr ""
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr ""
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr ""
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr ""
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr ""
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr ""
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr ""
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr ""
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr ""
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr ""
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr ""
#: .\cookbook\forms.py:540
#, fuzzy
#| msgid "Food that should be replaced."
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr "Prato a ser alterado."
msgstr "Campos do alimento que devem ser herdados por padrão."
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "Mostrar receitas recentes na página de pesquisa"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""
@@ -516,10 +502,8 @@ msgid "One of queryset or hash_key must be provided"
msgstr ""
#: .\cookbook\helper\recipe_url_import.py:266
#, fuzzy
#| msgid "Use fractions"
msgid "reverse rotation"
msgstr "Usar frações"
msgstr "rotação reversa"
#: .\cookbook\helper\recipe_url_import.py:267
msgid "careful rotation"
@@ -585,16 +569,12 @@ msgid "Imported %s recipes."
msgstr "%s receitas importadas."
#: .\cookbook\integration\openeats.py:26
#, fuzzy
#| msgid "Recipes"
msgid "Recipe source:"
msgstr "Receitas"
msgstr "Fonte da Receita:"
#: .\cookbook\integration\paprika.py:49
#, fuzzy
#| msgid "Note"
msgid "Notes"
msgstr "Nota"
msgstr "Notas"
#: .\cookbook\integration\paprika.py:52
msgid "Nutritional Information"
@@ -606,10 +586,8 @@ msgstr ""
#: .\cookbook\integration\recettetek.py:54
#: .\cookbook\integration\recipekeeper.py:70
#, fuzzy
#| msgid "Import"
msgid "Imported from"
msgstr "Importar"
msgstr "Importado de"
#: .\cookbook\integration\saffron.py:23
msgid "Servings"
@@ -706,32 +684,24 @@ msgid "Raw"
msgstr ""
#: .\cookbook\models.py:1231
#, fuzzy
#| msgid "New Food"
msgid "Food Alias"
msgstr "Novo Prato"
msgstr "Apelido do Alimento"
#: .\cookbook\models.py:1231
#, fuzzy
#| msgid "Units"
msgid "Unit Alias"
msgstr "Unidades"
msgstr "Apelido da Unidade"
#: .\cookbook\models.py:1231
#, fuzzy
#| msgid "Keywords"
msgid "Keyword Alias"
msgstr "Palavras-chave"
msgstr "Apelido de Palavra-chave"
#: .\cookbook\models.py:1232
msgid "Description Replace"
msgstr ""
#: .\cookbook\models.py:1232
#, fuzzy
#| msgid "Instructions"
msgid "Instruction Replace"
msgstr "Instruções"
msgstr "Substituir Instruções"
#: .\cookbook\models.py:1258 .\cookbook\views\delete.py:36
#: .\cookbook\views\edit.py:251 .\cookbook\views\new.py:48
@@ -739,10 +709,8 @@ msgid "Recipe"
msgstr "Receita"
#: .\cookbook\models.py:1259
#, fuzzy
#| msgid "New Food"
msgid "Food"
msgstr "Novo Prato"
msgstr "Alimento"
#: .\cookbook\models.py:1260 .\cookbook\templates\base.html:141
msgid "Keyword"
@@ -880,10 +848,8 @@ msgid "Primary"
msgstr ""
#: .\cookbook\templates\account\email.html:47
#, fuzzy
#| msgid "Make Header"
msgid "Make Primary"
msgstr "Adicionar Cabeçalho"
msgstr "Tornar Primeiro"
#: .\cookbook\templates\account\email.html:49
msgid "Re-send Verification"
@@ -1004,10 +970,8 @@ msgstr ""
#: .\cookbook\templates\account\password_change.html:12
#: .\cookbook\templates\account\password_set.html:12
#, fuzzy
#| msgid "Settings"
msgid "Password"
msgstr "Definições"
msgstr "Senha"
#: .\cookbook\templates\account\password_change.html:22
msgid "Forgot Password?"
@@ -1050,10 +1014,8 @@ msgid ""
msgstr ""
#: .\cookbook\templates\account\password_reset_from_key.html:33
#, fuzzy
#| msgid "Settings"
msgid "change password"
msgstr "Definições"
msgstr "alterar senha"
#: .\cookbook\templates\account\password_reset_from_key.html:36
#: .\cookbook\templates\account\password_reset_from_key_done.html:19
@@ -1125,10 +1087,8 @@ msgid "Shopping"
msgstr "Compras"
#: .\cookbook\templates\base.html:153 .\cookbook\views\lists.py:105
#, fuzzy
#| msgid "New Food"
msgid "Foods"
msgstr "Novo Prato"
msgstr "Alimentos"
#: .\cookbook\templates\base.html:165 .\cookbook\views\lists.py:122
msgid "Units"
@@ -1139,20 +1099,16 @@ msgid "Supermarket"
msgstr ""
#: .\cookbook\templates\base.html:191
#, fuzzy
#| msgid "Batch edit Category"
msgid "Supermarket Category"
msgstr "Editar Categorias em massa"
msgstr "Categoria de Supermercado"
#: .\cookbook\templates\base.html:203 .\cookbook\views\lists.py:171
msgid "Automations"
msgstr ""
#: .\cookbook\templates\base.html:217 .\cookbook\views\lists.py:207
#, fuzzy
#| msgid "File ID"
msgid "Files"
msgstr "ID the ficheiro"
msgstr "Arquivos"
#: .\cookbook\templates\base.html:229
msgid "Batch Edit"
@@ -1166,10 +1122,8 @@ msgstr "Histórico"
#: .\cookbook\templates\base.html:255
#: .\cookbook\templates\ingredient_editor.html:7
#: .\cookbook\templates\ingredient_editor.html:13
#, fuzzy
#| msgid "Ingredients"
msgid "Ingredient Editor"
msgstr "Ingredientes"
msgstr "Editor de Ingrediente"
#: .\cookbook\templates\base.html:267
#: .\cookbook\templates\export_response.html:7
@@ -1191,10 +1145,8 @@ msgid "External Recipes"
msgstr ""
#: .\cookbook\templates\base.html:301 .\cookbook\templates\space_manage.html:15
#, fuzzy
#| msgid "Settings"
msgid "Space Settings"
msgstr "Definições"
msgstr "Configurar Espaço"
#: .\cookbook\templates\base.html:306 .\cookbook\templates\system.html:13
msgid "System"
@@ -1206,10 +1158,8 @@ msgstr "Administração"
#: .\cookbook\templates\base.html:312
#: .\cookbook\templates\space_overview.html:25
#, fuzzy
#| msgid "Create"
msgid "Your Spaces"
msgstr "Criar"
msgstr "Seus Espaços"
#: .\cookbook\templates\base.html:323
#: .\cookbook\templates\space_overview.html:6
@@ -1288,19 +1238,15 @@ msgstr ""
#: .\cookbook\templates\batch\monitor.html:28
msgid "Sync Now!"
msgstr "Sincronizar"
msgstr "Sincronizar Agora!"
#: .\cookbook\templates\batch\monitor.html:29
#, fuzzy
#| msgid "Recipes"
msgid "Show Recipes"
msgstr "Receitas"
msgstr "Mostrar Receitas"
#: .\cookbook\templates\batch\monitor.html:30
#, fuzzy
#| msgid "View Log"
msgid "Show Log"
msgstr "Ver Registro"
msgstr "Mostrar Log"
#: .\cookbook\templates\batch\waiting.html:4
#: .\cookbook\templates\batch\waiting.html:10
@@ -1335,7 +1281,7 @@ msgstr "Editar Receita"
#: .\cookbook\templates\generic\delete_template.html:21
#, python-format
msgid "Are you sure you want to delete the %(title)s: <b>%(object)s</b> "
msgstr "Tem a certeza que quer apagar %(title)s: <b>%(object)s</b>"
msgstr "Tem certeza que deseja apagar %(title)s: <b>%(object)s</b> "
#: .\cookbook\templates\generic\delete_template.html:22
msgid "This cannot be undone!"
@@ -1369,7 +1315,7 @@ msgstr "Apagar ficheiro original"
#: .\cookbook\templates\generic\list_template.html:6
#: .\cookbook\templates\generic\list_template.html:22
msgid "List"
msgstr "Listar "
msgstr "Listar"
#: .\cookbook\templates\generic\list_template.html:36
msgid "Filter"
@@ -1422,13 +1368,13 @@ msgid ""
" "
msgstr ""
"\n"
" Os </b>campos da senha e Token</b> são guardados dentro da base de "
"dados como <b>texto simples.</b>\n"
"Isto é necessário porque eles são usados para fazer pedidos á API, mas "
"também aumenta o risco de\n"
"de alguém os roubar. <br/>\n"
"Para limitar os possíveis danos, tokens e contas com acesso limitado podem "
"ser usadas.\n"
" Os campos de <b>senha e Token</b> são armazenados na base de dados "
"como <b>texto simples</b>.\n"
" Isto é necessário porque eles são usados para fazer pedidos à API, "
"mas também aumenta o risco\n"
" de alguém os roubar.<br/>\n"
" Para limitar os possíveis danos, tokens e contas com acesso limitado "
"podem ser usadas.\n"
" "
#: .\cookbook\templates\index.html:29
@@ -1441,7 +1387,7 @@ msgstr "Nova Receita"
#: .\cookbook\templates\index.html:53
msgid "Advanced Search"
msgstr "Procura avançada "
msgstr "Pesquisa avançada"
#: .\cookbook\templates\index.html:57
msgid "Reset Search"
@@ -1493,8 +1439,6 @@ msgstr ""
#: .\cookbook\templates\markdown_info.html:57
#: .\cookbook\templates\markdown_info.html:73
#, fuzzy
#| msgid "or by leaving a blank line inbetween."
msgid "or by leaving a blank line in between."
msgstr "ou deixando uma linha em branco no meio."
@@ -1518,10 +1462,6 @@ msgid "Lists"
msgstr "Listas"
#: .\cookbook\templates\markdown_info.html:85
#, fuzzy
#| msgid ""
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
#| "before the list!</b>"
msgid ""
"Lists can ordered or unordered. It is <b>important to leave a blank line "
"before the list!</b>"
@@ -1598,7 +1538,7 @@ msgstr "Cabeçalho"
#: .\cookbook\templates\markdown_info.html:157
#: .\cookbook\templates\markdown_info.html:178
msgid "Cell"
msgstr "Célula "
msgstr "Célula"
#: .\cookbook\templates\no_groups_info.html:5
#: .\cookbook\templates\no_groups_info.html:12
@@ -1666,10 +1606,8 @@ msgstr ""
#: .\cookbook\templates\search_info.html:5
#: .\cookbook\templates\search_info.html:9
#: .\cookbook\templates\settings.html:24
#, fuzzy
#| msgid "Search String"
msgid "Search Settings"
msgstr "Procurar"
msgstr "Configurações de Pesquisa"
#: .\cookbook\templates\search_info.html:10
msgid ""
@@ -1684,10 +1622,8 @@ msgid ""
msgstr ""
#: .\cookbook\templates\search_info.html:19
#, fuzzy
#| msgid "Search"
msgid "Search Methods"
msgstr "Procurar"
msgstr "Métodos de Pesquisa"
#: .\cookbook\templates\search_info.html:23
msgid ""
@@ -1769,10 +1705,8 @@ msgid ""
msgstr ""
#: .\cookbook\templates\search_info.html:69
#, fuzzy
#| msgid "Search Recipe"
msgid "Search Fields"
msgstr "Procure Receita"
msgstr "Campos de Pesquisa"
#: .\cookbook\templates\search_info.html:73
msgid ""
@@ -1810,10 +1744,8 @@ msgid ""
msgstr ""
#: .\cookbook\templates\search_info.html:95
#, fuzzy
#| msgid "Search"
msgid "Search Index"
msgstr "Procurar"
msgstr "Índice de Pesquisa"
#: .\cookbook\templates\search_info.html:99
msgid ""
@@ -2012,10 +1944,8 @@ msgid "Owner"
msgstr ""
#: .\cookbook\templates\space_overview.html:57
#, fuzzy
#| msgid "Create"
msgid "Leave Space"
msgstr "Criar"
msgstr "Sair do Espaço"
#: .\cookbook\templates\space_overview.html:78
#: .\cookbook\templates\space_overview.html:88
@@ -2034,10 +1964,8 @@ msgstr ""
#: .\cookbook\templates\space_overview.html:96
#: .\cookbook\templates\space_overview.html:105
#, fuzzy
#| msgid "Create"
msgid "Create Space"
msgstr "Criar"
msgstr "Criar Espaço"
#: .\cookbook\templates\space_overview.html:99
msgid "Create your own recipe space."
@@ -2487,10 +2415,8 @@ msgid "Shopping Categories"
msgstr ""
#: .\cookbook\views\lists.py:187
#, fuzzy
#| msgid "Filter"
msgid "Custom Filters"
msgstr "Filtrar"
msgstr "Filtros Customizados"
#: .\cookbook\views\lists.py:224
msgid "Steps"

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -102,7 +102,7 @@ msgstr ""
msgid "If you want to be able to create and see comments underneath recipes."
msgstr ""
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -114,7 +114,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr ""
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
@@ -132,11 +132,11 @@ msgid ""
"instead"
msgstr ""
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr ""
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr ""
@@ -148,7 +148,7 @@ msgstr ""
msgid "Waiting time (cooking/baking) in minutes"
msgstr ""
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr ""
@@ -160,261 +160,261 @@ msgstr ""
msgid "Default"
msgstr ""
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
msgstr ""
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr ""
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr ""
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
msgstr ""
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr ""
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr ""
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr ""
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr ""
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr ""
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
msgstr ""
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr ""
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr ""
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
msgstr ""
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr ""
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr ""
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
msgstr ""
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
msgstr ""
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
msgstr ""
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
msgstr ""
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
msgstr ""
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
msgstr ""
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
msgstr ""
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
msgstr ""
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr ""
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr ""
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr ""
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr ""
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr ""
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr ""
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr ""
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
msgstr ""
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
msgstr ""
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
msgstr ""
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr ""
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr ""
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr ""
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr ""
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr ""
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr ""
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr ""
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr ""
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr ""
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr ""
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr ""
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr ""
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr ""
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr ""
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr ""
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr ""
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr ""
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr ""
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"PO-Revision-Date: 2023-04-27 08:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"Language-Team: Romanian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/ro/>\n"
@@ -456,7 +456,7 @@ msgstr "Sursă"
#: .\cookbook\templates\url_import.html:228
#: .\cookbook\templates\url_import.html:459
msgid "Servings"
msgstr "Porţii"
msgstr "Porții"
#: .\cookbook\integration\safron.py:25
msgid "Waiting time"
@@ -532,7 +532,7 @@ msgstr "Plan de alimentare"
#: .\cookbook\models.py:204 .\cookbook\templates\base.html:90
msgid "Books"
msgstr "Cărţi"
msgstr "Cărți"
#: .\cookbook\models.py:212
msgid "Small"

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-13 22:40+0200\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"PO-Revision-Date: 2023-05-01 07:55+0000\n"
"Last-Translator: axeron2036 <admin@axeron2036.ru>\n"
"Language-Team: Russian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/ru/>\n"
"Language: ru\n"
@@ -286,7 +286,7 @@ msgstr ""
#: .\cookbook\forms.py:497
msgid "Search Method"
msgstr ""
msgstr "Способ поиска"
#: .\cookbook\forms.py:498
msgid "Fuzzy Lookups"

View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
"PO-Revision-Date: 2023-04-12 11:55+0000\n"
"Last-Translator: noxonad <noxonad@proton.me>\n"
"PO-Revision-Date: 2023-08-13 08:19+0000\n"
"Last-Translator: Miha Perpar <miha.perpar2@gmail.com>\n"
"Language-Team: Slovenian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/sl/>\n"
"Language: sl\n"
@@ -964,7 +964,7 @@ msgstr ""
#: .\cookbook\templates\base.html:275
msgid "GitHub"
msgstr ""
msgstr "GitHub"
#: .\cookbook\templates\base.html:277
msgid "Translate Tandoor"
@@ -1961,7 +1961,7 @@ msgstr ""
#: .\cookbook\templates\space.html:106
msgid "user"
msgstr ""
msgstr "uporabnik"
#: .\cookbook\templates\space.html:107
msgid "guest"

View File

@@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2022-11-06 22:09+0000\n"
"Last-Translator: Gorkem <g.kalipcilar@gmail.com>\n"
"Language-Team: Turkish <http://translate.tandoor.dev/projects/tandoor/"
@@ -110,7 +110,7 @@ msgstr "Malzeme birimleri için yuvarlanma basamağı."
msgid "If you want to be able to create and see comments underneath recipes."
msgstr "Tariflerin altında yorumlar oluşturup görebilmek istiyorsanız."
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -127,7 +127,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr ""
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr ""
@@ -145,11 +145,11 @@ msgid ""
"instead"
msgstr ""
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "İsim"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr ""
@@ -161,7 +161,7 @@ msgstr ""
msgid "Waiting time (cooking/baking) in minutes"
msgstr ""
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr ""
@@ -173,263 +173,263 @@ msgstr ""
msgid "Default"
msgstr "Varsayılan"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
msgstr ""
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr ""
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr ""
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr ""
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
msgstr ""
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr ""
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "Aktif"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr ""
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr ""
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr ""
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr ""
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
msgstr ""
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr ""
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr ""
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
msgstr ""
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr ""
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr ""
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
msgstr ""
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
msgstr ""
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
msgstr ""
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
msgstr ""
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
msgstr ""
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
msgstr ""
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
msgstr ""
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
msgstr ""
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr ""
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr ""
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr ""
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr ""
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr ""
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr ""
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr ""
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
msgstr ""
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
msgstr ""
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
msgstr ""
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr ""
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr ""
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr ""
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr ""
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr ""
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr ""
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr ""
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr ""
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr ""
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr ""
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr ""
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr ""
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr ""
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr ""
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr ""
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr ""
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr ""
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr ""
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr ""
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr ""
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
#, fuzzy
#| msgid "Show recently viewed recipes on search page."
msgid "Show recipe counts on search filters"
msgstr "Son görüntülenen tarifleri arama sayfasında göster."
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr ""

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-04-26 07:46+0200\n"
"POT-Creation-Date: 2023-05-18 14:28+0200\n"
"PO-Revision-Date: 2023-02-26 13:15+0000\n"
"Last-Translator: 吕楪 <thy@irithys.com>\n"
"Language-Team: Chinese (Simplified) <http://translate.tandoor.dev/projects/"
@@ -104,7 +104,7 @@ msgstr "四舍五入食材的小数点数量。"
msgid "If you want to be able to create and see comments underneath recipes."
msgstr "如果你希望能够在菜谱下面创建并看到评论。"
#: .\cookbook\forms.py:79 .\cookbook\forms.py:492
#: .\cookbook\forms.py:79 .\cookbook\forms.py:509
msgid ""
"Setting to 0 will disable auto sync. When viewing a shopping list the list "
"is updated every set seconds to sync changes someone else might have made. "
@@ -119,7 +119,7 @@ msgstr ""
msgid "Makes the navbar stick to the top of the page."
msgstr "使导航栏悬浮在页面的顶部。"
#: .\cookbook\forms.py:83 .\cookbook\forms.py:495
#: .\cookbook\forms.py:83 .\cookbook\forms.py:512
msgid "Automatically add meal plan ingredients to shopping list."
msgstr "自动将膳食计划食材添加到购物清单中。"
@@ -137,11 +137,11 @@ msgid ""
"instead"
msgstr "这两个字段都是可选的。如果没有给出,将显示用户名"
#: .\cookbook\forms.py:123 .\cookbook\forms.py:297
#: .\cookbook\forms.py:123 .\cookbook\forms.py:314
msgid "Name"
msgstr "名字"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:298 .\cookbook\views\lists.py:88
#: .\cookbook\forms.py:124 .\cookbook\forms.py:315 .\cookbook\views\lists.py:88
msgid "Keywords"
msgstr "关键词"
@@ -153,7 +153,7 @@ msgstr "准备时间(分钟)"
msgid "Waiting time (cooking/baking) in minutes"
msgstr "等候(烹饪、烘焙等)时间(分钟)"
#: .\cookbook\forms.py:127 .\cookbook\forms.py:266 .\cookbook\forms.py:299
#: .\cookbook\forms.py:127 .\cookbook\forms.py:283 .\cookbook\forms.py:316
msgid "Path"
msgstr "路径"
@@ -165,7 +165,7 @@ msgstr "存储 UID"
msgid "Default"
msgstr "默认"
#: .\cookbook\forms.py:173
#: .\cookbook\forms.py:190
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
@@ -173,19 +173,19 @@ msgstr ""
"为防止重复,忽略与现有同名的菜谱。选中此框可导入所有内容(危险操作,请先备"
"份)。"
#: .\cookbook\forms.py:196
#: .\cookbook\forms.py:213
msgid "Add your comment: "
msgstr "发表评论: "
#: .\cookbook\forms.py:211
#: .\cookbook\forms.py:228
msgid "Leave empty for dropbox and enter app password for nextcloud."
msgstr "Dropbox 留空并输入 Nextcloud 应用密码。"
#: .\cookbook\forms.py:218
#: .\cookbook\forms.py:235
msgid "Leave empty for nextcloud and enter api token for dropbox."
msgstr "Nextcloud 留空并输入 Dropbox API 令牌。"
#: .\cookbook\forms.py:227
#: .\cookbook\forms.py:244
msgid ""
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
"php/webdav/</code> is added automatically)"
@@ -193,60 +193,60 @@ msgstr ""
"Dropbox 留空并输入基础 Nextcloud 网址(<code>/remote.php/webdav/</code> 会自"
"动添加)"
#: .\cookbook\forms.py:265 .\cookbook\views\edit.py:157
#: .\cookbook\forms.py:282 .\cookbook\views\edit.py:157
msgid "Storage"
msgstr "存储"
#: .\cookbook\forms.py:267
#: .\cookbook\forms.py:284
msgid "Active"
msgstr "活跃"
#: .\cookbook\forms.py:273
#: .\cookbook\forms.py:290
msgid "Search String"
msgstr "搜索字符串"
#: .\cookbook\forms.py:300
#: .\cookbook\forms.py:317
msgid "File ID"
msgstr "文件编号"
#: .\cookbook\forms.py:322
#: .\cookbook\forms.py:339
msgid "You must provide at least a recipe or a title."
msgstr "你必须至少提供一份菜谱或一个标题。"
#: .\cookbook\forms.py:335
#: .\cookbook\forms.py:352
msgid "You can list default users to share recipes with in the settings."
msgstr "你可以在设置中列出默认用户来分享菜谱。"
#: .\cookbook\forms.py:336
#: .\cookbook\forms.py:353
msgid ""
"You can use markdown to format this field. See the <a href=\"/docs/markdown/"
"\">docs here</a>"
msgstr ""
"可以使用 Markdown 设置此字段格式。<a href=\"/docs/markdown/\">查看文档</a>"
#: .\cookbook\forms.py:362
#: .\cookbook\forms.py:379
msgid "Maximum number of users for this space reached."
msgstr "已达到该空间的最大用户数。"
#: .\cookbook\forms.py:368
#: .\cookbook\forms.py:385
msgid "Email address already taken!"
msgstr "电子邮件地址已被注册!"
#: .\cookbook\forms.py:376
#: .\cookbook\forms.py:393
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
msgstr "电子邮件地址不是必需的,但如果存在,邀请链接将被发送给用户。"
#: .\cookbook\forms.py:391
#: .\cookbook\forms.py:408
msgid "Name already taken."
msgstr "名字已被占用。"
#: .\cookbook\forms.py:402
#: .\cookbook\forms.py:419
msgid "Accept Terms and Privacy"
msgstr "接受条款及隐私政策"
#: .\cookbook\forms.py:434
#: .\cookbook\forms.py:451
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
@@ -254,7 +254,7 @@ msgstr ""
"确定使用三元图相似性匹配时搜索的模糊程度(例如,较低的值意味着忽略更多的打字"
"错误)。"
#: .\cookbook\forms.py:444
#: .\cookbook\forms.py:461
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full description of choices."
@@ -262,31 +262,31 @@ msgstr ""
"选择搜索类型方法。 <a href=\"/docs/search/\">点击此处</a> 查看选项的完整说"
"明。"
#: .\cookbook\forms.py:445
#: .\cookbook\forms.py:462
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
msgstr "编辑和导入菜谱时,对单位、关键词和食材使用模糊匹配。"
#: .\cookbook\forms.py:447
#: .\cookbook\forms.py:464
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
msgstr "忽略搜索字段的重音。此选项会因语言差异导致搜索质量产生变化"
#: .\cookbook\forms.py:449
#: .\cookbook\forms.py:466
msgid ""
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
"'pie' and 'piece' and 'soapie')"
msgstr "用于搜索部分匹配的字段。如搜索“Pie”会返回“pie”、“piece”和“soapie”"
#: .\cookbook\forms.py:451
#: .\cookbook\forms.py:468
msgid ""
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
"will return 'salad' and 'sandwich')"
msgstr "用于搜索开头匹配的字段。如搜索“sa”会返回“salad”和“sandwich”"
#: .\cookbook\forms.py:453
#: .\cookbook\forms.py:470
msgid ""
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
"Note: this option will conflict with 'web' and 'raw' methods of search."
@@ -294,41 +294,41 @@ msgstr ""
"“模糊”搜索字段。例如搜索“recpie”将会找到“recipe”。注意此选项将"
"与“web”和“raw”搜索方法冲突。"
#: .\cookbook\forms.py:455
#: .\cookbook\forms.py:472
msgid ""
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
"only function with fulltext fields."
msgstr "全文搜索字段。“web”、“phrase”和“raw”搜索方法仅适用于全文字段。"
#: .\cookbook\forms.py:459
#: .\cookbook\forms.py:476
msgid "Search Method"
msgstr "搜索方法"
#: .\cookbook\forms.py:460
#: .\cookbook\forms.py:477
msgid "Fuzzy Lookups"
msgstr "模糊查找"
#: .\cookbook\forms.py:461
#: .\cookbook\forms.py:478
msgid "Ignore Accent"
msgstr "忽略重音"
#: .\cookbook\forms.py:462
#: .\cookbook\forms.py:479
msgid "Partial Match"
msgstr "部分匹配"
#: .\cookbook\forms.py:463
#: .\cookbook\forms.py:480
msgid "Starts With"
msgstr "起始于"
#: .\cookbook\forms.py:464
#: .\cookbook\forms.py:481
msgid "Fuzzy Search"
msgstr "模糊搜索"
#: .\cookbook\forms.py:465
#: .\cookbook\forms.py:482
msgid "Full Text"
msgstr "全文"
#: .\cookbook\forms.py:490
#: .\cookbook\forms.py:507
msgid ""
"Users will see all items you add to your shopping list. They must add you "
"to see items on their list."
@@ -336,103 +336,103 @@ msgstr ""
"用户将看到你添加到购物清单中的所有商品。他们必须将你添加到列表才能看到他们清"
"单上的项目。"
#: .\cookbook\forms.py:496
#: .\cookbook\forms.py:513
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"include all related recipes."
msgstr "将膳食计划(手动或自动)添加到购物清单时,包括所有相关食谱。"
#: .\cookbook\forms.py:497
#: .\cookbook\forms.py:514
msgid ""
"When adding a meal plan to the shopping list (manually or automatically), "
"exclude ingredients that are on hand."
msgstr "将膳食计划(手动或自动)添加到购物清单时,排除现有食材。"
#: .\cookbook\forms.py:498
#: .\cookbook\forms.py:515
msgid "Default number of hours to delay a shopping list entry."
msgstr "延迟购物清单条目的默认小时数。"
#: .\cookbook\forms.py:499
#: .\cookbook\forms.py:516
msgid "Filter shopping list to only include supermarket categories."
msgstr "筛选购物清单仅包含超市分类。"
#: .\cookbook\forms.py:500
#: .\cookbook\forms.py:517
msgid "Days of recent shopping list entries to display."
msgstr "显示最近几天的购物清单列表。"
#: .\cookbook\forms.py:501
#: .\cookbook\forms.py:518
msgid "Mark food 'On Hand' when checked off shopping list."
msgstr "在核对购物清单时,将食物标记为“入手”。"
#: .\cookbook\forms.py:502
#: .\cookbook\forms.py:519
msgid "Delimiter to use for CSV exports."
msgstr "用于 CSV 导出的分隔符。"
#: .\cookbook\forms.py:503
#: .\cookbook\forms.py:520
msgid "Prefix to add when copying list to the clipboard."
msgstr "将清单复制到剪贴板时要添加的前缀。"
#: .\cookbook\forms.py:507
#: .\cookbook\forms.py:524
msgid "Share Shopping List"
msgstr "分享购物清单"
#: .\cookbook\forms.py:508
#: .\cookbook\forms.py:525
msgid "Autosync"
msgstr "自动同步"
#: .\cookbook\forms.py:509
#: .\cookbook\forms.py:526
msgid "Auto Add Meal Plan"
msgstr "自动添加膳食计划"
#: .\cookbook\forms.py:510
#: .\cookbook\forms.py:527
msgid "Exclude On Hand"
msgstr "排除现有"
#: .\cookbook\forms.py:511
#: .\cookbook\forms.py:528
msgid "Include Related"
msgstr "包括相关"
#: .\cookbook\forms.py:512
#: .\cookbook\forms.py:529
msgid "Default Delay Hours"
msgstr "默认延迟时间"
#: .\cookbook\forms.py:513
#: .\cookbook\forms.py:530
msgid "Filter to Supermarket"
msgstr "按超市筛选"
#: .\cookbook\forms.py:514
#: .\cookbook\forms.py:531
msgid "Recent Days"
msgstr "最近几天"
#: .\cookbook\forms.py:515
#: .\cookbook\forms.py:532
msgid "CSV Delimiter"
msgstr "CSV 分隔符"
#: .\cookbook\forms.py:516
#: .\cookbook\forms.py:533
msgid "List Prefix"
msgstr "清单前缀"
#: .\cookbook\forms.py:517
#: .\cookbook\forms.py:534
msgid "Auto On Hand"
msgstr "自动入手"
#: .\cookbook\forms.py:527
#: .\cookbook\forms.py:544
msgid "Reset Food Inheritance"
msgstr "重置食物材料"
#: .\cookbook\forms.py:528
#: .\cookbook\forms.py:545
msgid "Reset all food to inherit the fields configured."
msgstr "重置所有食物以继承配置的字段。"
#: .\cookbook\forms.py:540
#: .\cookbook\forms.py:557
msgid "Fields on food that should be inherited by default."
msgstr "默认情况下应继承的食物上的字段。"
#: .\cookbook\forms.py:541
#: .\cookbook\forms.py:558
msgid "Show recipe counts on search filters"
msgstr "显示搜索筛选器上的食谱计数"
#: .\cookbook\forms.py:542
#: .\cookbook\forms.py:559
msgid "Use the plural form for units and food inside this space."
msgstr "在此空间内使用复数形式表示单位和食物。"

View File

@@ -1,9 +1,9 @@
from django.conf import settings
from django.contrib.postgres.search import SearchVector
from django.core.management.base import BaseCommand
from django_scopes import scopes_disabled
from django.utils import translation
from django.utils.translation import gettext_lazy as _
from django_scopes import scopes_disabled
from cookbook.managers import DICTIONARY
from cookbook.models import Recipe, Step
@@ -14,7 +14,7 @@ class Command(BaseCommand):
help = _('Rebuilds full text search index on Recipe')
def handle(self, *args, **options):
if settings.DATABASES['default']['ENGINE'] not in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']:
if settings.DATABASES['default']['ENGINE'] != 'django.db.backends.postgresql':
self.stdout.write(self.style.WARNING(_('Only Postgresql databases use full text search, no index to rebuild')))
try:

View File

@@ -34,35 +34,14 @@ class RecipeSearchManager(models.Manager):
+ SearchVector(StringAgg('steps__ingredients__food__name__unaccent', delimiter=' '), weight='B', config=language)
+ SearchVector(StringAgg('keywords__name__unaccent', delimiter=' '), weight='B', config=language))
search_rank = SearchRank(search_vectors, search_query)
# USING TRIGRAM BREAKS WEB SEARCH
# ADDING MULTIPLE TRIGRAMS CREATES DUPLICATE RESULTS
# DISTINCT NOT COMPAITBLE WITH ANNOTATE
# trigram_name = (TrigramSimilarity('name', search_text))
# trigram_description = (TrigramSimilarity('description', search_text))
# trigram_food = (TrigramSimilarity('steps__ingredients__food__name', search_text))
# trigram_keyword = (TrigramSimilarity('keywords__name', search_text))
# adding additional trigrams created duplicates
# + TrigramSimilarity('description', search_text)
# + TrigramSimilarity('steps__ingredients__food__name', search_text)
# + TrigramSimilarity('keywords__name', search_text)
return (
self.get_queryset()
.annotate(
search=search_vectors,
rank=search_rank,
# trigram=trigram_name+trigram_description+trigram_food+trigram_keyword
# trigram_name=trigram_name,
# trigram_description=trigram_description,
# trigram_food=trigram_food,
# trigram_keyword=trigram_keyword
)
.filter(
Q(search=search_query)
# | Q(trigram_name__gt=0.1)
# | Q(name__icontains=search_text)
# | Q(trigram_name__gt=0.2)
# | Q(trigram_description__gt=0.2)
# | Q(trigram_food__gt=0.2)
# | Q(trigram_keyword__gt=0.2)
)
.order_by('-rank'))

View File

@@ -9,7 +9,7 @@ from django.utils import translation
from django_scopes import scopes_disabled
from cookbook.managers import DICTIONARY
from cookbook.models import (Index, PermissionModelMixin, Recipe, Step, SearchFields)
from cookbook.models import Index, PermissionModelMixin, Recipe, SearchFields, Step
def allSearchFields():
@@ -21,7 +21,7 @@ def nameSearchField():
def set_default_search_vector(apps, schema_editor):
if settings.DATABASES['default']['ENGINE'] not in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']:
if settings.DATABASES['default']['ENGINE'] != 'django.db.backends.postgresql':
return
language = DICTIONARY.get(translation.get_language(), 'simple')
with scopes_disabled():

View File

@@ -0,0 +1,163 @@
# Generated by Django 4.1.9 on 2023-05-25 13:05
import cookbook.models
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django_prometheus.models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('cookbook', '0188_space_no_sharing_limit'),
]
operations = [
migrations.CreateModel(
name='Property',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('property_amount', models.DecimalField(decimal_places=4, default=0, max_digits=32)),
],
bases=(models.Model, cookbook.models.PermissionModelMixin),
),
migrations.CreateModel(
name='PropertyType',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128)),
('unit', models.CharField(blank=True, max_length=64, null=True)),
('icon', models.CharField(blank=True, max_length=16, null=True)),
('description', models.CharField(blank=True, max_length=512, null=True)),
('category', models.CharField(blank=True, choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'Price'), ('GOAL', 'Goal'), ('OTHER', 'Other')], max_length=64, null=True)),
('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)),
],
bases=(models.Model, cookbook.models.PermissionModelMixin),
),
migrations.CreateModel(
name='UnitConversion',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('base_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)),
('converted_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('open_data_slug', models.CharField(blank=True, default=None, max_length=128, null=True)),
],
bases=(django_prometheus.models.ExportModelOperationsMixin('unit_conversion'), models.Model, cookbook.models.PermissionModelMixin),
),
migrations.AddField(
model_name='food',
name='fdc_id',
field=models.CharField(blank=True, default=None, max_length=128, null=True),
),
migrations.AddField(
model_name='food',
name='open_data_slug',
field=models.CharField(blank=True, default=None, max_length=128, null=True),
),
migrations.AddField(
model_name='food',
name='preferred_shopping_unit',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_shopping_unit', to='cookbook.unit'),
),
migrations.AddField(
model_name='food',
name='preferred_unit',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_unit', to='cookbook.unit'),
),
migrations.AddField(
model_name='food',
name='properties_food_amount',
field=models.IntegerField(blank=True, default=100),
),
migrations.AddField(
model_name='food',
name='properties_food_unit',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='cookbook.unit'),
),
migrations.AddField(
model_name='supermarket',
name='open_data_slug',
field=models.CharField(blank=True, default=None, max_length=128, null=True),
),
migrations.AddField(
model_name='supermarketcategory',
name='open_data_slug',
field=models.CharField(blank=True, default=None, max_length=128, null=True),
),
migrations.AddField(
model_name='unit',
name='base_unit',
field=models.TextField(blank=True, default=None, max_length=256, null=True),
),
migrations.AddField(
model_name='unit',
name='open_data_slug',
field=models.CharField(blank=True, default=None, max_length=128, null=True),
),
migrations.AddConstraint(
model_name='supermarketcategoryrelation',
constraint=models.UniqueConstraint(fields=('supermarket', 'category'), name='unique_sm_category_relation'),
),
migrations.AddField(
model_name='unitconversion',
name='base_unit',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_base_relation', to='cookbook.unit'),
),
migrations.AddField(
model_name='unitconversion',
name='converted_unit',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_converted_relation', to='cookbook.unit'),
),
migrations.AddField(
model_name='unitconversion',
name='created_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='unitconversion',
name='food',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.food'),
),
migrations.AddField(
model_name='unitconversion',
name='space',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
),
migrations.AddField(
model_name='propertytype',
name='space',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
),
migrations.AddField(
model_name='property',
name='property_type',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.propertytype'),
),
migrations.AddField(
model_name='property',
name='space',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
),
migrations.AddField(
model_name='food',
name='properties',
field=models.ManyToManyField(blank=True, to='cookbook.property'),
),
migrations.AddField(
model_name='recipe',
name='properties',
field=models.ManyToManyField(blank=True, to='cookbook.property'),
),
migrations.AddConstraint(
model_name='unitconversion',
constraint=models.UniqueConstraint(fields=('space', 'base_unit', 'converted_unit', 'food'), name='f_unique_conversion_per_space'),
),
migrations.AddConstraint(
model_name='propertytype',
constraint=models.UniqueConstraint(fields=('space', 'name'), name='property_type_unique_name_per_space'),
),
]

View File

@@ -0,0 +1,38 @@
# Generated by Django 4.1.9 on 2023-05-25 13:06
from django.db import migrations
from django_scopes import scopes_disabled
from gettext import gettext as _
def migrate_old_nutrition_data(apps, schema_editor):
print('Transforming nutrition information, this might take a while on large databases')
with scopes_disabled():
PropertyType = apps.get_model('cookbook', 'PropertyType')
RecipeProperty = apps.get_model('cookbook', 'Property')
Recipe = apps.get_model('cookbook', 'Recipe')
Space = apps.get_model('cookbook', 'Space')
# TODO respect space
for s in Space.objects.all():
property_fat = PropertyType.objects.get_or_create(name=_('Fat'), unit=_('g'), space=s, )[0]
property_carbohydrates = PropertyType.objects.get_or_create(name=_('Carbohydrates'), unit=_('g'), space=s, )[0]
property_proteins = PropertyType.objects.get_or_create(name=_('Proteins'), unit=_('g'), space=s, )[0]
property_calories = PropertyType.objects.get_or_create(name=_('Calories'), unit=_('kcal'), space=s, )[0]
for r in Recipe.objects.filter(nutrition__isnull=False, space=s).all():
rp_fat = RecipeProperty.objects.create(property_type=property_fat, property_amount=r.nutrition.fats, space=s)
rp_carbohydrates = RecipeProperty.objects.create(property_type=property_carbohydrates, property_amount=r.nutrition.carbohydrates, space=s)
rp_proteins = RecipeProperty.objects.create(property_type=property_proteins, property_amount=r.nutrition.proteins, space=s)
rp_calories = RecipeProperty.objects.create(property_type=property_calories, property_amount=r.nutrition.calories, space=s)
r.properties.add(rp_fat, rp_carbohydrates, rp_proteins, rp_calories)
r.nutrition = None
r.save()
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0189_property_propertytype_unitconversion_food_fdc_id_and_more'),
]
operations = [
migrations.RunPython(migrate_old_nutrition_data)
]

View File

@@ -0,0 +1,49 @@
# Generated by Django 4.1.9 on 2023-06-20 13:07
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0190_auto_20230525_1506'),
]
operations = [
migrations.SeparateDatabaseAndState(
database_operations=[
migrations.RunSQL(
sql="ALTER TABLE cookbook_food_properties RENAME TO cookbook_foodproperty",
reverse_sql="ALTER TABLE cookbook_foodproperty RENAME TO cookbook_food_properties",
),
],
state_operations=[
migrations.CreateModel(
name='FoodProperty',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('food', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')),
('property', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.property')),
],
),
migrations.AlterField(
model_name='food',
name='properties',
field=models.ManyToManyField(blank=True, through='cookbook.FoodProperty', to='cookbook.property'),
),
]
),
migrations.AddConstraint(
model_name='foodproperty',
constraint=models.UniqueConstraint(fields=('food', 'property'), name='property_unique_food'),
),
migrations.AddField(
model_name='property',
name='import_food_id',
field=models.IntegerField(blank=True, null=True),
),
migrations.AddConstraint(
model_name='property',
constraint=models.UniqueConstraint(fields=('space', 'property_type', 'import_food_id'), name='property_unique_import_food_per_space'),
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 4.1.9 on 2023-06-20 13:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0191_foodproperty_property_import_food_id_and_more'),
]
operations = [
migrations.AddConstraint(
model_name='food',
constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='food_unique_open_data_slug_per_space'),
),
migrations.AddConstraint(
model_name='propertytype',
constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='property_type_unique_open_data_slug_per_space'),
),
migrations.AddConstraint(
model_name='supermarket',
constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='supermarket_unique_open_data_slug_per_space'),
),
migrations.AddConstraint(
model_name='supermarketcategory',
constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='supermarket_category_unique_open_data_slug_per_space'),
),
migrations.AddConstraint(
model_name='unit',
constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='unit_unique_open_data_slug_per_space'),
),
migrations.AddConstraint(
model_name='unitconversion',
constraint=models.UniqueConstraint(fields=('space', 'open_data_slug'), name='unit_conversion_unique_open_data_slug_per_space'),
),
]

Some files were not shown because too many files have changed in this diff Show More