Compare commits

...

5 Commits

Author SHA1 Message Date
Kuchenpirat
6e16a16cd8 Merge branch 'mealie-next' into reset-scroll-position 2025-07-12 01:32:32 +02:00
Kuchenpirat
78a0f74f33 reset scroll position 2025-07-11 23:29:09 +00:00
Hayden
8b9e80358b chore(l10n): New Crowdin updates (#5682) 2025-07-11 21:18:48 +00:00
github-actions[bot]
2bae6e9d02 docs(auto): Update image tag, for release v3.0.0 (#5675)
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
2025-07-11 22:38:46 +02:00
renovate[bot]
6b98a7cd74 fix(deps): update dependency openai to v1.95.0 (#5671)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 19:22:03 +02:00
13 changed files with 321 additions and 150 deletions

View File

@@ -31,7 +31,7 @@ To deploy mealie on your local network, it is highly recommended to use Docker t
We've gone through a few versions of Mealie v1 deployment targets. We have settled on a single container deployment, and we've begun publishing the nightly container on github containers. If you're looking to move from the old nightly (split containers _or_ the omni image) to the new nightly, there are a few things you need to do:
1. Take a backup just in case!
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v2.8.0`
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v3.0.0`
3. Take the external port from the frontend container and set that as the port mapped to port `9000` on the new container. The frontend is now served on port 9000 from the new container, so it will need to be mapped for you to have access.
4. Restart the container

View File

@@ -7,7 +7,7 @@ PostgreSQL might be considered if you need to support many concurrent users. In
```yaml
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v2.8.0 # (3)
image: ghcr.io/mealie-recipes/mealie:v3.0.0 # (3)
container_name: mealie
restart: always
ports:

View File

@@ -11,7 +11,7 @@ SQLite is a popular, open source, self-contained, zero-configuration database th
```yaml
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:v2.8.0 # (3)
image: ghcr.io/mealie-recipes/mealie:v3.0.0 # (3)
container_name: mealie
restart: always
ports:

View File

@@ -123,6 +123,7 @@
:image="recipe.image!"
:tags="recipe.tags!"
:recipe-id="recipe.id!"
@click="handleRecipeNavigation"
/>
</v-col>
</v-row>
@@ -147,6 +148,7 @@
:image="recipe.image!"
:tags="recipe.tags!"
:recipe-id="recipe.id!"
@selected="handleRecipeNavigation"
/>
</v-col>
</v-row>
@@ -171,6 +173,7 @@ import { useLazyRecipes } from "~/composables/recipes";
import type { Recipe } from "~/lib/api/types/recipe";
import { useUserSortPreferences } from "~/composables/use-users/preferences";
import type { RecipeSearchQuery } from "~/lib/api/user/recipes/recipe";
import { useRecipeListState } from "~/composables/recipe-page/use-recipe-list-state";
const REPLACE_RECIPES_EVENT = "replaceRecipes";
const APPEND_RECIPES_EVENT = "appendRecipes";
@@ -241,9 +244,11 @@ export default defineNuxtComponent({
const route = useRoute();
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || "");
const page = ref(1);
const recipeListState = useRecipeListState(props.query);
const page = ref(recipeListState.state.page || 1);
const perPage = 32;
const hasMore = ref(true);
const hasMore = ref(recipeListState.state.hasMore);
const ready = ref(false);
const loading = ref(false);
@@ -282,8 +287,33 @@ export default defineNuxtComponent({
);
}
// Save scroll position
const throttledScrollSave = useThrottleFn(() => {
recipeListState.saveScrollPosition();
}, 1000);
onMounted(async () => {
await initRecipes();
window.addEventListener("scroll", throttledScrollSave);
// cached state with scroll position
if (recipeListState.hasValidState() && recipeListState.isQueryMatch(props.query)) {
// Restore from cached state
page.value = recipeListState.state.page;
hasMore.value = recipeListState.state.hasMore;
ready.value = recipeListState.state.ready;
// Emit cached recipes
context.emit(REPLACE_RECIPES_EVENT, recipeListState.state.recipes);
// Restore scroll position after recipes are rendered
nextTick(() => {
recipeListState.restoreScrollPosition();
});
}
else {
// Initialize fresh recipes
await initRecipes();
}
ready.value = true;
});
@@ -294,6 +324,10 @@ export default defineNuxtComponent({
const newValueString = JSON.stringify(newValue);
if (lastQuery !== newValueString) {
lastQuery = newValueString;
// Save scroll position before query change
recipeListState.saveScrollPosition();
ready.value = false;
await initRecipes();
ready.value = true;
@@ -315,6 +349,14 @@ export default defineNuxtComponent({
// since we doubled the first call, we also need to advance the page
page.value = page.value + 1;
// Save state after fetching recipes
recipeListState.saveState({
recipes: newRecipes,
page: page.value,
hasMore: hasMore.value,
ready: true,
});
context.emit(REPLACE_RECIPES_EVENT, newRecipes);
}
@@ -331,6 +373,14 @@ export default defineNuxtComponent({
hasMore.value = false;
}
if (newRecipes.length) {
// Update cached state with new recipes
const allRecipes = [...(recipeListState.state.recipes || []), ...newRecipes] as Recipe[];
recipeListState.saveState({
recipes: allRecipes,
page: page.value,
hasMore: hasMore.value,
});
context.emit(APPEND_RECIPES_EVENT, newRecipes);
}
@@ -408,6 +458,15 @@ export default defineNuxtComponent({
// fetch new recipes
const newRecipes = await fetchRecipes();
// Update cached state
recipeListState.saveState({
recipes: newRecipes,
page: page.value,
hasMore: hasMore.value,
ready: true,
});
context.emit(REPLACE_RECIPES_EVENT, newRecipes);
state.sortLoading = false;
@@ -427,6 +486,17 @@ export default defineNuxtComponent({
preferences.value.useMobileCards = !preferences.value.useMobileCards;
}
// Save scroll position when component is unmounted or when navigating away
onBeforeUnmount(() => {
recipeListState.saveScrollPosition();
window.removeEventListener("scroll", throttledScrollSave);
});
// Save scroll position when navigating to recipe pages
function handleRecipeNavigation() {
recipeListState.saveScrollPosition();
}
return {
...toRefs(state),
displayTitleIcon,
@@ -439,6 +509,7 @@ export default defineNuxtComponent({
sortRecipes,
toggleMobileCards,
useMobileCards,
handleRecipeNavigation,
};
},
});

View File

@@ -0,0 +1,94 @@
import type { Recipe } from "~/lib/api/types/recipe";
import type { RecipeSearchQuery } from "~/lib/api/user/recipes/recipe";
interface RecipeListState {
recipes: Recipe[];
page: number;
hasMore: boolean;
scrollPosition: number;
query: RecipeSearchQuery | null;
ready: boolean;
}
const recipeListStates = new Map<string, RecipeListState>();
function generateStateKey(query: RecipeSearchQuery | null): string {
if (!query) return "default";
const keyParts = [
query.search || "",
query.orderBy || "",
query.orderDirection || "",
query.queryFilter || "",
JSON.stringify(query.categories || []),
JSON.stringify(query.tags || []),
JSON.stringify(query.tools || []),
JSON.stringify(query.foods || []),
JSON.stringify(query.households || []),
];
return keyParts.join("|");
}
export function useRecipeListState(query: RecipeSearchQuery | null) {
const stateKey = generateStateKey(query);
// Initialize state if it doesn't exist
if (!recipeListStates.has(stateKey)) {
recipeListStates.set(stateKey, {
recipes: [],
page: 1,
hasMore: true,
scrollPosition: 0,
query,
ready: false,
});
}
const state = recipeListStates.get(stateKey)!;
function saveState(newState: Partial<RecipeListState>) {
Object.assign(state, newState);
}
function saveScrollPosition() {
state.scrollPosition = window.scrollY || document.documentElement.scrollTop || 0;
}
function restoreScrollPosition() {
if (state.scrollPosition > 0) {
// Use nextTick to ensure DOM is updated before scrolling
nextTick(() => {
window.scrollTo(0, state.scrollPosition);
});
}
}
function clearState() {
recipeListStates.delete(stateKey);
}
function hasValidState(): boolean {
return state.recipes.length > 0 && state.ready;
}
function isQueryMatch(newQuery: RecipeSearchQuery | null): boolean {
const newKey = generateStateKey(newQuery);
return newKey === stateKey;
}
return {
state: readonly(state),
saveState,
saveScrollPosition,
restoreScrollPosition,
clearState,
hasValidState,
isQueryMatch,
};
}
// Clean up old states when navigating away from recipe sections
export function cleanupRecipeListStates() {
recipeListStates.clear();
}

View File

@@ -288,7 +288,7 @@
"household-group": "Группа домохозяйства",
"household-management": "Управление домохозяйствами",
"manage-households": "Управление Домами",
"admin-household-management": "Admin Household Management",
"admin-household-management": "Управление Домохозяйством",
"admin-household-management-text": "Изменения в данном домохозяйстве будут отражены немедленно.",
"household-id-value": "Id домохозяйства: {0}",
"private-household": "Частное домохозяйство",
@@ -298,7 +298,7 @@
"household-recipe-preferences": "Предпочтения для рецептов домашнего хозяйства",
"default-recipe-preferences-description": "Это настройки по умолчанию, когда в вашем домашнем хозяйстве создается новый рецепт. Они могут быть изменены для отдельных рецептов в меню настроек рецепта.",
"allow-users-outside-of-your-household-to-see-your-recipes": "Разрешить пользователям вне вашего домохозяйства видеть ваши рецепты",
"allow-users-outside-of-your-household-to-see-your-recipes-description": "When enabled you can use a public share link to share specific recipes without authorizing the user. When disabled, you can only share recipes with users who are in your household or with a pre-generated private link",
"allow-users-outside-of-your-household-to-see-your-recipes-description": "При включении данной функции, вы можете делиться публичной ссылкой на данный рецепт, чтобы поделиться им с людьми без аккаунта. Если функция выключена — поделиться рецептом можно только с пользователями внутри вашего домохозяйства или по предварительно сгенерированной приватной ссылке",
"household-preferences": "Параметры домохозяйства"
},
"meal-plan": {

View File

@@ -1,6 +1,6 @@
{
"name": "mealie",
"version": "2.8.0",
"version": "3.0.0",
"private": true,
"scripts": {
"dev": "nuxt dev",

View File

@@ -9,5 +9,11 @@ import RecipeExplorerPage from "~/components/Domain/Recipe/RecipeExplorerPage.vu
export default defineNuxtComponent({
components: { RecipeExplorerPage },
setup() {
// Enable scroll restoration for this page to work with our state management
definePageMeta({
scrollToTop: false,
});
},
});
</script>

View File

@@ -595,8 +595,8 @@
"broccoli slaw": {
"aliases": [],
"description": "",
"name": "broccoli slaw",
"plural_name": "broccoli slaws"
"name": "Brokkolisalat",
"plural_name": "Brokkolisalate"
},
"arbol chile pepper": {
"aliases": [],
@@ -1182,55 +1182,55 @@
"aliases": [],
"description": "",
"name": "Pluot",
"plural_name": "pluots"
"plural_name": "Pluots"
},
"soursop": {
"aliases": [],
"description": "",
"name": "soursop",
"plural_name": "soursops"
"name": "Stachelannone",
"plural_name": "Stachelannonen"
},
"hog plum": {
"aliases": [],
"description": "",
"name": "hog plum",
"name": "Mombinpflaumen",
"plural_name": "Mombinpflaume"
},
"bergamot orange": {
"aliases": [],
"description": "",
"name": "bergamot orange",
"plural_name": "bergamot oranges"
"name": "Bergamotte",
"plural_name": "Bergamotten"
},
"luo han guo": {
"aliases": [],
"description": "",
"name": "luo han guo",
"plural_name": "luo han guos"
"name": "Mönchsfrucht",
"plural_name": "Mönchsfrüchte"
},
"mamey": {
"aliases": [],
"description": "",
"name": "mamey",
"plural_name": "mameys"
"name": "Mammiapfel",
"plural_name": "Mammiäpfel"
},
"sapote": {
"aliases": [],
"description": "",
"name": "sapote",
"plural_name": "sapotes"
"name": "Sapote",
"plural_name": "Sapote"
},
"green ume plum": {
"aliases": [],
"description": "",
"name": "green ume plum",
"plural_name": "green ume plums"
"name": "Japanische Pflaume",
"plural_name": "Japanische Pflaumen"
},
"kiwano": {
"aliases": [],
"description": "",
"name": "kiwano",
"plural_name": "kiwanoes"
"name": "Horngurke",
"plural_name": "Horngurken"
}
}
},
@@ -1419,13 +1419,13 @@
"puffball": {
"aliases": [],
"description": "",
"name": "puffball",
"plural_name": "puffballs"
"name": "Riesenbovist",
"plural_name": "Riesenboviste"
},
"honey fungu": {
"aliases": [],
"description": "",
"name": "honey fungu",
"name": "",
"plural_name": "honey fungus"
},
"caesar's mushroom": {
@@ -1471,8 +1471,8 @@
"cranberry": {
"aliases": [],
"description": "",
"name": "cranberry",
"plural_name": "cranberries"
"name": "Cranberry",
"plural_name": "Cranberries"
},
"cherry": {
"aliases": [],
@@ -1483,7 +1483,7 @@
"blackberry": {
"aliases": [],
"description": "",
"name": "blackberry",
"name": "Brombeere",
"plural_name": "Brombeeren"
},
"berry mix": {
@@ -1495,8 +1495,8 @@
"maraschino cherry": {
"aliases": [],
"description": "",
"name": "maraschino cherry",
"plural_name": "maraschino cherries"
"name": "maraschino Kirsche",
"plural_name": "maraschino Kirschen"
},
"dried cherry": {
"aliases": [],
@@ -1507,8 +1507,8 @@
"juniper berry": {
"aliases": [],
"description": "",
"name": "juniper berry",
"plural_name": "juniper berries"
"name": "Wacholderbeere",
"plural_name": "Wacholderbeeren"
},
"sour cherry": {
"aliases": [],
@@ -1519,8 +1519,8 @@
"goji berry": {
"aliases": [],
"description": "",
"name": "goji berry",
"plural_name": "goji berries"
"name": "Goji-Beere",
"plural_name": "Goji-Beeren"
},
"dried blueberry": {
"aliases": [],
@@ -1561,8 +1561,8 @@
"mulberry": {
"aliases": [],
"description": "",
"name": "mulberry",
"plural_name": "mulberries"
"name": "Maulbeere",
"plural_name": "Maulbeeren"
},
"acai berry": {
"aliases": [],
@@ -1597,8 +1597,8 @@
"huckleberry": {
"aliases": [],
"description": "",
"name": "huckleberry",
"plural_name": "huckleberries"
"name": "Heidelbeere",
"plural_name": "Heidelbeeren"
},
"dried elderberry": {
"aliases": [],
@@ -1615,8 +1615,8 @@
"dried berry": {
"aliases": [],
"description": "",
"name": "dried berry",
"plural_name": "dried berries"
"name": "getrocknete Beere",
"plural_name": "getrocknete Beeren"
},
"sea buckthorn": {
"aliases": [],
@@ -1663,8 +1663,8 @@
"aronia berry": {
"aliases": [],
"description": "",
"name": "aronia berry",
"plural_name": "aronia berries"
"name": "Apfelbeere",
"plural_name": "Apfelbeeren"
},
"chokeberry": {
"aliases": [],
@@ -1681,8 +1681,8 @@
"blackcurrant leaf": {
"aliases": [],
"description": "",
"name": "blackcurrant leaf",
"plural_name": "blackcurrant leaves"
"name": "Schwarzes Johannisbeerblatt",
"plural_name": "Schwarze Johannisbeerblätter"
},
"haskap berry": {
"aliases": [],
@@ -1745,8 +1745,8 @@
"pine nut": {
"aliases": [],
"description": "",
"name": "pine nut",
"plural_name": "pine nuts"
"name": "Pinienkern",
"plural_name": "Pinienkerne"
},
"pistachio": {
"aliases": [],
@@ -1776,7 +1776,7 @@
"aliases": [],
"description": "",
"name": "slivered almond",
"plural_name": "slivered almonds"
"plural_name": "Mandelstifte"
},
"pumpkin seed": {
"aliases": [],
@@ -1853,8 +1853,8 @@
"onion seed": {
"aliases": [],
"description": "",
"name": "onion seed",
"plural_name": "onion seeds"
"name": "Zwiebelsamen",
"plural_name": "Zwiebelsamen"
},
"watermelon seed": {
"aliases": [],
@@ -1871,8 +1871,8 @@
"melon seed": {
"aliases": [],
"description": "",
"name": "melon seed",
"plural_name": "melon seeds"
"name": "Melonensamen",
"plural_name": "Melonensamen"
},
"lotus seed": {
"aliases": [],
@@ -1895,8 +1895,8 @@
"basil seed": {
"aliases": [],
"description": "",
"name": "basil seed",
"plural_name": "basil seeds"
"name": "Basilikumsamen",
"plural_name": "Basilikumsamen"
},
"candlenut": {
"aliases": [],
@@ -1907,8 +1907,8 @@
"peanut brittle": {
"aliases": [],
"description": "",
"name": "peanut brittle",
"plural_name": "peanut brittles"
"name": "Erdnusskrokant",
"plural_name": "Erdnusskrokant"
},
"jackfruit seed": {
"aliases": [],

View File

@@ -241,106 +241,106 @@
"aliases": [],
"description": "",
"name": "artisjok",
"plural_name": "artichokes"
"plural_name": "artisjokken"
},
"new potato": {
"aliases": [],
"description": "",
"name": "new potato",
"plural_name": "new potatoes"
"name": "krieltjes",
"plural_name": "krieltjes"
},
"summer squash": {
"aliases": [
"courgette",
"gem squash"
"edelpompoen"
],
"description": "",
"name": "summer squash",
"plural_name": "summer squashes"
"plural_name": "edelpompoenen"
},
"mixed green": {
"aliases": [],
"description": "",
"name": "mixed green",
"plural_name": "mixed greens"
"name": "gemengde groenten",
"plural_name": "gemengde groenten"
},
"parsnip": {
"aliases": [],
"description": "",
"name": "parsnip",
"plural_name": "parsnips"
"name": "pastinaak",
"plural_name": "pastinaken"
},
"baby carrot": {
"aliases": [],
"description": "",
"name": "baby carrot",
"plural_name": "baby carrots"
"name": "baby wortel",
"plural_name": "baby wortels"
},
"mixed vegetable": {
"aliases": [],
"description": "",
"name": "mixed vegetable",
"plural_name": "mixed vegetables"
"name": "gemengde groente",
"plural_name": "gemengde groenten"
},
"poblano pepper": {
"aliases": [],
"description": "",
"name": "poblano pepper",
"plural_name": "poblano peppers"
"name": "poblano pepers",
"plural_name": "poblano pepers"
},
"sweet pepper": {
"aliases": [],
"description": "",
"name": "sweet pepper",
"plural_name": "sweet peppers"
"name": "puntpaprika",
"plural_name": "puntpaprikas"
},
"serrano pepper": {
"aliases": [],
"description": "",
"name": "serrano pepper",
"plural_name": "serrano peppers"
"name": "serranopeper",
"plural_name": "serranopepers"
},
"cayenne pepper": {
"aliases": [],
"description": "",
"name": "cayenne pepper",
"plural_name": "cayenne peppers"
"name": "cayennepeper",
"plural_name": "cayennepepers"
},
"green tomato": {
"aliases": [],
"description": "",
"name": "green tomato",
"plural_name": "green tomatoes"
"name": "groene tomaat",
"plural_name": "groene tomaten"
},
"watercress": {
"aliases": [],
"description": "",
"name": "watercress",
"plural_name": "watercress"
"name": "waterkers",
"plural_name": "waterkersen"
},
"iceberg": {
"aliases": [],
"description": "",
"name": "iceberg",
"plural_name": "icebergs"
"name": "ijsbergsla",
"plural_name": "ijsbergsla"
},
"mashed potato": {
"aliases": [],
"description": "",
"name": "mashed potato",
"plural_name": "mashed potatoes"
"name": "aardappelpuree",
"plural_name": "aardappelpurees"
},
"horseradish": {
"aliases": [],
"description": "",
"name": "horseradish",
"plural_name": "horseradishes"
"name": "mierikswortel",
"plural_name": "mierikswortelen"
},
"chard": {
"aliases": [],
"description": "",
"name": "chard",
"plural_name": "chards"
"name": "snijbiet",
"plural_name": "snijbieten"
},
"pimiento": {
"aliases": [],
@@ -351,40 +351,40 @@
"spaghetti squash": {
"aliases": [],
"description": "",
"name": "spaghetti squash",
"plural_name": "spaghetti squashes"
"name": "spaghettipompoen",
"plural_name": "spaghettipompoenen"
},
"butter lettuce": {
"aliases": [],
"description": "",
"name": "butter lettuce",
"plural_name": "butter lettuces"
"name": "kropsla",
"plural_name": "kropsla"
},
"hash brown": {
"aliases": [],
"description": "",
"name": "hash brown",
"plural_name": "hash browns"
"name": "gehakte aardappel",
"plural_name": "gehakte aardappels"
},
"napa cabbage": {
"aliases": [
"chinese leaves"
"chinese kool"
],
"description": "",
"name": "napa cabbage",
"plural_name": "napa cabbages"
"name": "chinese kool",
"plural_name": "chinese kolen"
},
"celeriac": {
"aliases": [],
"description": "",
"name": "celeriac",
"plural_name": "celeriacs"
"name": "knolselderij",
"plural_name": "knolselders"
},
"water chestnut": {
"aliases": [],
"description": "",
"name": "water chestnut",
"plural_name": "water chestnuts"
"name": "waterkastanje",
"plural_name": "waterkastanjes"
},
"turnip": {
"aliases": [],
@@ -541,8 +541,8 @@
"ancho chile pepper": {
"aliases": [],
"description": "",
"name": "ancho chile pepper",
"plural_name": "ancho chile peppers"
"name": "ancho peper",
"plural_name": "ancho pepers"
},
"microgreen": {
"aliases": [],
@@ -553,8 +553,8 @@
"boston lettuce": {
"aliases": [],
"description": "",
"name": "boston lettuce",
"plural_name": "boston lettuces"
"name": "botersla",
"plural_name": "botersla"
},
"kohlrabi": {
"aliases": [],
@@ -608,19 +608,19 @@
"aliases": [],
"description": "",
"name": "golden beet",
"plural_name": "golden beets"
"plural_name": "gele biet"
},
"pea shoot": {
"aliases": [],
"description": "",
"name": "pea shoot",
"plural_name": "pea shoots"
"name": "erwtenspruit",
"plural_name": "erwtenspruiten"
},
"alfalfa": {
"aliases": [],
"description": "",
"name": "alfalfa",
"plural_name": "alfalfas"
"name": "luzerne",
"plural_name": "luzerne"
}
}
},
@@ -630,61 +630,61 @@
"aliases": [],
"description": "Yes they are a fruit",
"name": "tomato",
"plural_name": "tomatoes"
"plural_name": "tomaten"
},
"lemon": {
"aliases": [],
"description": "",
"name": "lemon",
"plural_name": "lemons"
"name": "citroen",
"plural_name": "citroenen"
},
"lime": {
"aliases": [],
"description": "",
"name": "lime",
"plural_name": "limes"
"name": "limoen",
"plural_name": "limoenen"
},
"apple": {
"aliases": [],
"description": "",
"name": "apple",
"plural_name": "apples"
"name": "appel",
"plural_name": "appels"
},
"banana": {
"aliases": [],
"description": "",
"name": "banana",
"plural_name": "bananas"
"name": "banaan",
"plural_name": "bananen"
},
"orange": {
"aliases": [],
"description": "",
"name": "orange",
"plural_name": "oranges"
"name": "sinaasappel",
"plural_name": "sinaasappels"
},
"raisin": {
"aliases": [],
"description": "",
"name": "raisin",
"plural_name": "raisins"
"name": "rozijn",
"plural_name": "rozijnen"
},
"pineapple": {
"aliases": [],
"description": "",
"name": "pineapple",
"plural_name": "pineapples"
"name": "ananas",
"plural_name": "ananassen"
},
"mango": {
"aliases": [],
"description": "",
"name": "mango",
"plural_name": "mangoes"
"plural_name": "mango's"
},
"peach": {
"aliases": [],
"description": "",
"name": "peach",
"plural_name": "peaches"
"name": "perzik",
"plural_name": "perziken"
},
"date": {
"aliases": [],
@@ -851,8 +851,8 @@
"dried fruit": {
"aliases": [],
"description": "",
"name": "dried fruit",
"plural_name": "dried fruits"
"name": "gedroogd fruit",
"plural_name": "gedroogd fruit"
},
"clementine": {
"aliases": [],
@@ -4349,14 +4349,14 @@
"chicken breast": {
"aliases": [],
"description": "",
"name": "chicken breast",
"plural_name": "chicken breasts"
"name": "kipfilet",
"plural_name": "kipfilet"
},
"chicken thigh": {
"aliases": [],
"description": "",
"name": "chicken thigh",
"plural_name": "chicken thighs"
"name": "kipdijfilet",
"plural_name": "kipdijfilet"
},
"cooked chicken": {
"aliases": [],
@@ -4385,14 +4385,14 @@
"chicken leg": {
"aliases": [],
"description": "",
"name": "chicken leg",
"plural_name": "chicken legs"
"name": "kippenpoot",
"plural_name": "kippenpoten"
},
"chicken wing": {
"aliases": [],
"description": "",
"name": "chicken wing",
"plural_name": "chicken wings"
"name": "kippenpoot",
"plural_name": "kippenpoten"
},
"turkey breast": {
"aliases": [],
@@ -8540,8 +8540,8 @@
"rice": {
"aliases": [],
"description": "",
"name": "rice",
"plural_name": "rices"
"name": "rijst",
"plural_name": "rijst"
},
"Rice Krispie Cereal": {
"aliases": [

View File

@@ -34,7 +34,7 @@
"zucchini": {
"aliases": [],
"description": "",
"name": "zucchini",
"name": "цукини",
"plural_name": "zucchinis"
},
"potato": {

6
poetry.lock generated
View File

@@ -1816,14 +1816,14 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"]
[[package]]
name = "openai"
version = "1.94.0"
version = "1.95.0"
description = "The official Python library for the openai API"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "openai-1.94.0-py3-none-any.whl", hash = "sha256:159c43b811669abe9bb4aafdc57a049966dfde2eac94b151aac3eb63bf9825b4"},
{file = "openai-1.94.0.tar.gz", hash = "sha256:31c6c213cc80365d54632296c4aef7cda1800003ca5c784ac50a05d6bc05c197"},
{file = "openai-1.95.0-py3-none-any.whl", hash = "sha256:a7afc9dca7e7d616371842af8ea6dbfbcb739a85d183f5f664ab1cc311b9ef18"},
{file = "openai-1.95.0.tar.gz", hash = "sha256:54bc42df9f7142312647dd485d34cca5df20af825fa64a30ca55164be2cf4cc9"},
]
[package.dependencies]

View File

@@ -3,7 +3,7 @@ authors = ["Hayden <hay-kot@pm.me>"]
description = "A Recipe Manager"
license = "AGPL"
name = "mealie"
version = "2.8.0"
version = "3.0.0"
include = [
# Explicit include to override .gitignore when packaging the frontend
{ path = "mealie/frontend/**/*", format = ["sdist", "wheel"] }