diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index a37cfd007..fe02ce452 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -49,7 +49,9 @@
"onCreateCommand": "sudo chown -R vscode:vscode /workspaces/mealie/frontend/node_modules && task setup",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
- // "features": {
- // "git": "latest"
- // }
+ "features": {
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {
+ "dockerDashComposeVersion": "v2"
+ }
+ }
}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 78162ddcf..8417fff33 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -49,6 +49,9 @@ jobs:
needs:
- build-release
runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
steps:
- name: Checkout 🛎
uses: actions/checkout@v4
@@ -58,11 +61,12 @@ jobs:
sed -i 's/:v[0-9]*.[0-9]*.[0-9]*/:${{ github.event.release.tag_name }}/' docs/docs/documentation/getting-started/installation/sqlite.md
sed -i 's/:v[0-9]*.[0-9]*.[0-9]*/:${{ github.event.release.tag_name }}/' docs/docs/documentation/getting-started/installation/postgres.md
- - name: Commit updates
- uses: test-room-7/action-update-file@v1
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v6
with:
- file-path: |
- docs/docs/documentation/getting-started/installation/sqlite.md
- docs/docs/documentation/getting-started/installation/postgres.md
- commit-msg: "Change image tag, for release ${{ github.event.release.tag_name }}"
- github-token: ${{ secrets.GITHUB_TOKEN }}
+ commit-message: "Update image tag, for release ${{ github.event.release.tag_name }}"
+ branch: "docs/newrelease-update-version-${{ github.event.release.tag_name }}"
+ delete-branch: true
+ base: mealie-next
+ title: "docs(auto): Update image tag, for release ${{ github.event.release.tag_name }}"
+ body: "Auto-generated by `.github/workflows/release.yml`, on publish of release ${{ github.event.release.tag_name }}"
diff --git a/Taskfile.yml b/Taskfile.yml
index ed3f47d01..085d9cf8c 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -14,7 +14,9 @@ env:
SMTP_HOST: localhost
SMTP_PORT: 1025
SMTP_FROM_NAME: MealieDev
+ SMTP_FROM_EMAIL: mealie@example.com
SMTP_AUTH_STRATEGY: NONE
+ BASE_URL: http://localhost:3000
LANG: en-US
# loads .env file if it exists
diff --git a/docs/docs/documentation/getting-started/installation/backend-config.md b/docs/docs/documentation/getting-started/installation/backend-config.md
index dce06309b..80f678b48 100644
--- a/docs/docs/documentation/getting-started/installation/backend-config.md
+++ b/docs/docs/documentation/getting-started/installation/backend-config.md
@@ -54,8 +54,8 @@ Changing the webworker settings may cause unforeseen memory leak issues with Mea
| ---------------- | :-----: | --------------------------------------------------------------------------------------------------------------------------------- |
| WEB_GUNICORN | false | Enables Gunicorn to manage Uvicorn web for multiple works |
| WORKERS_PER_CORE | 1 | Set the number of workers to the number of CPU cores multiplied by this value (Value \* CPUs). More info [here][workers_per_core] |
-| MAX_WORKERS | 1 | Set the maximum number of workers to use. Default is not set meaning unlimited. More info [here][max_workers] |
-| WEB_CONCURRENCY | 1 | Override the automatic definition of number of workers. More info [here][web_concurrency] |
+| MAX_WORKERS | None | Set the maximum number of workers to use. Default is not set meaning unlimited. More info [here][max_workers] |
+| WEB_CONCURRENCY | 2 | Override the automatic definition of number of workers. More info [here][web_concurrency] |
### LDAP
@@ -95,3 +95,8 @@ Setting the following environmental variables will change the theme of the front
| THEME_DARK_INFO | #1976D2 | Dark Theme Config Variable |
| THEME_DARK_WARNING | #FF6D00 | Dark Theme Config Variable |
| THEME_DARK_ERROR | #EF5350 | Dark Theme Config Variable |
+
+
+[workers_per_core]: https://github.com/tiangolo/uvicorn-gunicorn-docker/blob/2daa3e3873c837d5781feb4ff6a40a89f791f81b/README.md#workers_per_core
+[max_workers]: https://github.com/tiangolo/uvicorn-gunicorn-docker/blob/2daa3e3873c837d5781feb4ff6a40a89f791f81b/README.md#max_workers
+[web_concurrency]: https://github.com/tiangolo/uvicorn-gunicorn-docker/blob/2daa3e3873c837d5781feb4ff6a40a89f791f81b/README.md#web_concurrency
diff --git a/docs/docs/overrides/api.html b/docs/docs/overrides/api.html
index 28fdc391d..4e7f1d6d2 100644
--- a/docs/docs/overrides/api.html
+++ b/docs/docs/overrides/api.html
@@ -14,7 +14,7 @@
diff --git a/frontend/components/Domain/Recipe/RecipeNutrition.vue b/frontend/components/Domain/Recipe/RecipeNutrition.vue
index 9b90fe990..f53ea29bd 100644
--- a/frontend/components/Domain/Recipe/RecipeNutrition.vue
+++ b/frontend/components/Domain/Recipe/RecipeNutrition.vue
@@ -19,11 +19,11 @@
-
+
{{ item.label }}
- {{ value[key] }}
+ {{ item.value }}
{{ item.suffix }}
@@ -37,6 +37,14 @@
import { computed, defineComponent, useContext } from "@nuxtjs/composition-api";
import { Nutrition } from "~/lib/api/types/recipe";
+type NutritionLabelType = {
+ [key: string]: {
+ label: string;
+ suffix: string;
+ value?: string;
+ };
+};
+
export default defineComponent({
props: {
value: {
@@ -50,34 +58,34 @@ export default defineComponent({
},
setup(props, context) {
const { i18n } = useContext();
- const labels = {
+ const labels = {
calories: {
- label: i18n.t("recipe.calories"),
- suffix: i18n.t("recipe.calories-suffix"),
+ label: i18n.tc("recipe.calories"),
+ suffix: i18n.tc("recipe.calories-suffix"),
},
fatContent: {
- label: i18n.t("recipe.fat-content"),
- suffix: i18n.t("recipe.grams"),
+ label: i18n.tc("recipe.fat-content"),
+ suffix: i18n.tc("recipe.grams"),
},
fiberContent: {
- label: i18n.t("recipe.fiber-content"),
- suffix: i18n.t("recipe.grams"),
+ label: i18n.tc("recipe.fiber-content"),
+ suffix: i18n.tc("recipe.grams"),
},
proteinContent: {
- label: i18n.t("recipe.protein-content"),
- suffix: i18n.t("recipe.grams"),
+ label: i18n.tc("recipe.protein-content"),
+ suffix: i18n.tc("recipe.grams"),
},
sodiumContent: {
- label: i18n.t("recipe.sodium-content"),
- suffix: i18n.t("recipe.milligrams"),
+ label: i18n.tc("recipe.sodium-content"),
+ suffix: i18n.tc("recipe.milligrams"),
},
sugarContent: {
- label: i18n.t("recipe.sugar-content"),
- suffix: i18n.t("recipe.grams"),
+ label: i18n.tc("recipe.sugar-content"),
+ suffix: i18n.tc("recipe.grams"),
},
carbohydrateContent: {
- label: i18n.t("recipe.carbohydrate-content"),
- suffix: i18n.t("recipe.grams"),
+ label: i18n.tc("recipe.carbohydrate-content"),
+ suffix: i18n.tc("recipe.grams"),
},
};
const valueNotNull = computed(() => {
@@ -96,11 +104,25 @@ export default defineComponent({
context.emit("input", { ...props.value, [key]: event });
}
+ // Build a new list that only contains nutritional information that has a value
+ const renderedList = computed(() => {
+ return Object.entries(labels).reduce((item: NutritionLabelType, [key, label]) => {
+ if (props.value[key]?.trim()) {
+ item[key] = {
+ ...label,
+ value: props.value[key],
+ };
+ }
+ return item;
+ }, {});
+ });
+
return {
labels,
valueNotNull,
showViewer,
updateValue,
+ renderedList,
};
},
});
diff --git a/frontend/lang/messages/bg-BG.json b/frontend/lang/messages/bg-BG.json
index 0c7a74e3e..35e0b0872 100644
--- a/frontend/lang/messages/bg-BG.json
+++ b/frontend/lang/messages/bg-BG.json
@@ -200,7 +200,7 @@
"created-on-date": "Създадено на {0}",
"unsaved-changes": "Имате незапазени промени. Желаете ли да ги запазите преди да излезете? Натиснете Ок за запазване и Отказ за отхвърляне на промените.",
"clipboard-copy-failure": "Линкът към рецептата е копиран в клипборда.",
- "confirm-delete-generic-items": "Are you sure you want to delete the following items?"
+ "confirm-delete-generic-items": "Сигурни ли сте, че желаете да изтриете следните елементи?"
},
"group": {
"are-you-sure-you-want-to-delete-the-group": "Сигурни ли сте, че искате да изтриете {groupName}?",
@@ -259,7 +259,7 @@
},
"meal-plan": {
"create-a-new-meal-plan": "Създаване на нов хранителен план",
- "update-this-meal-plan": "Update this Meal Plan",
+ "update-this-meal-plan": "Обнови този План за хранене",
"dinner-this-week": "Вечеря тази седмица",
"dinner-today": "Вечеря Днес",
"dinner-tonight": "Вечеря ТАЗИ ВЕЧЕР",
@@ -474,11 +474,11 @@
"add-to-timeline": "Добави към времевата линия",
"recipe-added-to-list": "Рецептата е добавена към списъка",
"recipes-added-to-list": "Рецептите са добавени към списъка",
- "successfully-added-to-list": "Successfully added to list",
+ "successfully-added-to-list": "Успешно добавено в списъка",
"recipe-added-to-mealplan": "Рецептата е добавена към хранителния план",
"failed-to-add-recipes-to-list": "Неуспешно добавяне на рецепта към списъка",
"failed-to-add-recipe-to-mealplan": "Рецептата не беше добавена към хранителния план",
- "failed-to-add-to-list": "Failed to add to list",
+ "failed-to-add-to-list": "Неуспешно добавяне към списъка",
"yield": "Добив",
"quantity": "Количество",
"choose-unit": "Избери единица",
@@ -537,8 +537,8 @@
"new-recipe-names-must-be-unique": "Името на рецептата трябва да бъде уникално",
"scrape-recipe": "Обхождане на рецепта",
"scrape-recipe-description": "Обходи рецепта по линк. Предоставете линк за сайт, който искате да бъде обходен. Mealie ще опита да обходи рецептата от този сайт и да я добави във Вашата колекция.",
- "scrape-recipe-have-a-lot-of-recipes": "Have a lot of recipes you want to scrape at once?",
- "scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
+ "scrape-recipe-have-a-lot-of-recipes": "Имате много рецепти, които искате да обходите наведнъж?",
+ "scrape-recipe-suggest-bulk-importer": "Пробвайте масовото импорторане",
"import-original-keywords-as-tags": "Импортирай оригиналните ключови думи като тагове",
"stay-in-edit-mode": "Остани в режим на редакция",
"import-from-zip": "Импортирай от Zip",
@@ -562,7 +562,7 @@
"upload-image": "Качване на изображение",
"screen-awake": "Запази екрана активен",
"remove-image": "Премахване на изображение",
- "nextStep": "Next step"
+ "nextStep": "Следваща стъпка"
},
"search": {
"advanced-search": "Разширено търсене",
@@ -1187,7 +1187,7 @@
"require-all-tools": "Изискване на всички инструменти",
"cookbook-name": "Име на книгата с рецепти",
"cookbook-with-name": "Книга с рецепти {0}",
- "create-a-cookbook": "Create a Cookbook",
- "cookbook": "Cookbook"
+ "create-a-cookbook": "Създай Готварска книга",
+ "cookbook": "Готварска книга"
}
}
diff --git a/frontend/lang/messages/he-IL.json b/frontend/lang/messages/he-IL.json
index 05c04b935..b4a604930 100644
--- a/frontend/lang/messages/he-IL.json
+++ b/frontend/lang/messages/he-IL.json
@@ -200,7 +200,7 @@
"created-on-date": "נוצר ב-{0}",
"unsaved-changes": "יש שינויים שלא נשמרו. לצאת לפני שמירה? אשר לשמירה, בטל למחיקת שינויים.",
"clipboard-copy-failure": "כשלון בהעתקה ללוח ההדבקה.",
- "confirm-delete-generic-items": "Are you sure you want to delete the following items?"
+ "confirm-delete-generic-items": "האם אתה בטוח שברצונך למחוק את הפריטים הנבחרים?"
},
"group": {
"are-you-sure-you-want-to-delete-the-group": "האם את/ה בטוח/ה שברצונך למחוק את {groupName}?",
@@ -259,7 +259,7 @@
},
"meal-plan": {
"create-a-new-meal-plan": "יצירת תכנית ארוחות חדשה",
- "update-this-meal-plan": "Update this Meal Plan",
+ "update-this-meal-plan": "עדכן את תכנון הארוחות",
"dinner-this-week": "ארוחות ערב השבוע",
"dinner-today": "ארוחת ערב היום",
"dinner-tonight": "ארוחת ערב היום",
@@ -474,11 +474,11 @@
"add-to-timeline": "הוסף לציר הזמן",
"recipe-added-to-list": "מתכון נוסף לרשימה",
"recipes-added-to-list": "מתכונים הוספו לרשימה",
- "successfully-added-to-list": "Successfully added to list",
+ "successfully-added-to-list": "נוסף לרשימה בהצלחה",
"recipe-added-to-mealplan": "מתכון נוסף לתכנון ארוחות",
"failed-to-add-recipes-to-list": "כשלון בהוספת מתכון לרשימה",
"failed-to-add-recipe-to-mealplan": "הוספת מתכון לתכנון ארוחות נכשלה",
- "failed-to-add-to-list": "Failed to add to list",
+ "failed-to-add-to-list": "כשלון בהוספה לרשימה",
"yield": "תשואה",
"quantity": "כמות",
"choose-unit": "בחירת יחידת מידה",
@@ -515,7 +515,7 @@
"how-did-it-turn-out": "איך יצא?",
"user-made-this": "{user} הכין את זה",
"last-made-date": "נעשה לאחרונה ב{date}",
- "api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.",
+ "api-extras-description": "מתכונים נוספים הם יכולת מפתח של Mealie API. הם מאפשרים ליצור צמדי key/value בצורת JSON על מנת לקרוא אותם בתוכנת צד שלישית. תוכלו להשתמש בצמדים האלה כדי לספק מידע, לדוגמא להפעיל אוטומציות או הודעות מותאמות אישית למכשירים מסויימים.",
"message-key": "מפתח הודעה",
"parse": "ניתוח",
"attach-images-hint": "הוסף תמונות ע\"י גרירה ושחרור אל תוך העורך",
@@ -537,8 +537,8 @@
"new-recipe-names-must-be-unique": "שם מתכון חדש חייב להיות ייחודי",
"scrape-recipe": "קריאת מתכון",
"scrape-recipe-description": "קריאת מתכון בעזרת לינק. ספק את הלינק של האתר שברצונך לקרוא, ומילי תנסה לקרוא את המתכון מהאתר ולהוסיף אותו לאוסף.",
- "scrape-recipe-have-a-lot-of-recipes": "Have a lot of recipes you want to scrape at once?",
- "scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
+ "scrape-recipe-have-a-lot-of-recipes": "יש לך הרבה מתכונים שאתה רוצה לקרוא בבת אחת?",
+ "scrape-recipe-suggest-bulk-importer": "נסה את יכולת קריאת רשימה",
"import-original-keywords-as-tags": "ייבא שמות מפתח מקוריות כתגיות",
"stay-in-edit-mode": "השאר במצב עריכה",
"import-from-zip": "ייבא מקובץ",
@@ -562,7 +562,7 @@
"upload-image": "העלה תמונה",
"screen-awake": "השאר את המסך פעיל",
"remove-image": "האם למחוק את התמונה?",
- "nextStep": "Next step"
+ "nextStep": "השלב הבא"
},
"search": {
"advanced-search": "חיפוש מתקדם",
@@ -797,7 +797,7 @@
"untagged-count": "לא מתוייג {count}",
"create-a-tag": "צור תגית",
"tag-name": "שם תגית",
- "tag": "Tag"
+ "tag": "תגית"
},
"tool": {
"tools": "כלים",
@@ -807,7 +807,7 @@
"create-new-tool": "יצירת כלי חדש",
"on-hand-checkbox-label": "הראה מה יש לי במטבח",
"required-tools": "צריך כלים",
- "tool": "Tool"
+ "tool": "כלי"
},
"user": {
"admin": "אדמין",
@@ -898,10 +898,10 @@
"user-can-organize-group-data": "משתמש יכול לשנות מידע של קבוצה",
"enable-advanced-features": "אפשר אפשרויות מתקדמות",
"it-looks-like-this-is-your-first-time-logging-in": "נראה שזו ההתחברות הראשונה שלך.",
- "dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!",
+ "dont-want-to-see-this-anymore-be-sure-to-change-your-email": "לא רוצה לראות את זה יותר? דאג לשנות את המייל של בהגדרות המשתמש!",
"forgot-password": "שכחתי סיסמא",
- "forgot-password-text": "Please enter your email address and we will send you a link to reset your password.",
- "changes-reflected-immediately": "Changes to this user will be reflected immediately."
+ "forgot-password-text": "נא לספק כתובת דוא\"ל. אנו נשלח לך הודעת דוא\"ל לצורך איפוס הסיסמה שלך.",
+ "changes-reflected-immediately": "השינויים למשתמש זה יבוצעו מיידית."
},
"language-dialog": {
"translated": "תורגם",
@@ -923,8 +923,8 @@
"food-label": "תוית אוכל",
"edit-food": "עריכת מזון",
"food-data": "נתוני אוכל",
- "example-food-singular": "ex: Onion",
- "example-food-plural": "ex: Onions"
+ "example-food-singular": "דוגמא: בצל",
+ "example-food-plural": "דוגמא: בצלים"
},
"units": {
"seed-dialog-text": "אכלס את מסד הנתונים עם יחידות מדידה בהתאם לשפה המקומית שלך.",
@@ -935,7 +935,7 @@
"merging-unit-into-unit": "ממזג את {0} לתוך {1}",
"create-unit": "יצירת יחידה",
"abbreviation": "קיצור",
- "plural-abbreviation": "Plural Abbreviation",
+ "plural-abbreviation": "צורת הרבית",
"description": "תיאור",
"display-as-fraction": "הצגה כשבר",
"use-abbreviation": "השתמש בקיצור",
@@ -943,10 +943,10 @@
"unit-data": "נתוני יחידה",
"use-abbv": "השתמש בקיצור",
"fraction": "שבר",
- "example-unit-singular": "ex: Tablespoon",
- "example-unit-plural": "ex: Tablespoons",
- "example-unit-abbreviation-singular": "ex: Tbsp",
- "example-unit-abbreviation-plural": "ex: Tbsps"
+ "example-unit-singular": "דוגמא: כפית",
+ "example-unit-plural": "דוגמא: כפיות",
+ "example-unit-abbreviation-singular": "דוגמא: כף",
+ "example-unit-abbreviation-plural": "דוגמא: כפות"
},
"labels": {
"seed-dialog-text": "אכלס את מסד הנתונים בתגיות נפוצות בהתאם לשפה המקומית שלך.",
@@ -1187,7 +1187,7 @@
"require-all-tools": "זקוק לכל הכלים",
"cookbook-name": "שם ספר בישול",
"cookbook-with-name": "ספר בישול {0}",
- "create-a-cookbook": "Create a Cookbook",
- "cookbook": "Cookbook"
+ "create-a-cookbook": "צור ספר בישול חדש",
+ "cookbook": "ספר בישול"
}
}
diff --git a/frontend/lang/messages/nl-NL.json b/frontend/lang/messages/nl-NL.json
index d76d2fc2c..a0dfdd8c8 100644
--- a/frontend/lang/messages/nl-NL.json
+++ b/frontend/lang/messages/nl-NL.json
@@ -200,7 +200,7 @@
"created-on-date": "Gemaakt op {0}",
"unsaved-changes": "Er zijn niet-opgeslagen wijzigingen. Wil je eerst opslaan voordat je vertrekt? Okay om op te slaan, Annuleren om wijzigingen ongedaan te maken.",
"clipboard-copy-failure": "Kopiëren naar klembord mislukt.",
- "confirm-delete-generic-items": "Are you sure you want to delete the following items?"
+ "confirm-delete-generic-items": "Weet u zeker dat u de volgende items wilt verwijderen?"
},
"group": {
"are-you-sure-you-want-to-delete-the-group": "Weet je zeker dat je {groupName} wil verwijderen?",
diff --git a/frontend/lang/messages/ru-RU.json b/frontend/lang/messages/ru-RU.json
index e395d82d1..409702108 100644
--- a/frontend/lang/messages/ru-RU.json
+++ b/frontend/lang/messages/ru-RU.json
@@ -707,7 +707,7 @@
"email-configured": "Email настроен",
"email-test-results": "Результаты теста Email",
"ready": "Готово",
- "not-ready": "Не готово - Проверьте переменные окружающей среды",
+ "not-ready": "Не готово - Проверьте переменные окружения",
"succeeded": "Выполнено успешно",
"failed": "Ошибка",
"general-about": "Общая информация",
diff --git a/frontend/pages/admin/manage/users/_id.vue b/frontend/pages/admin/manage/users/_id.vue
index 182378eda..31ad6fc8e 100644
--- a/frontend/pages/admin/manage/users/_id.vue
+++ b/frontend/pages/admin/manage/users/_id.vue
@@ -31,7 +31,24 @@
{{ $t("user.generate-password-reset-link") }}
-
+
+
+
+
+ {{ resetUrl }}
+
+
+
+ {{ $t("general.close") }}
+
+
+
+ {{ $globals.icons.email }}
+
+ {{ $t("user.email") }}
+
+
+
@@ -46,7 +63,7 @@