Compare commits

..

2 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
16 changed files with 1722 additions and 1476 deletions

View File

@@ -17,7 +17,7 @@ jobs:
name: Build Package name: Build Package
uses: ./.github/workflows/build-package.yml uses: ./.github/workflows/build-package.yml
with: with:
tag: ${{ github.event.release.tag_name }} tag: release
publish: publish:
permissions: permissions:

View File

@@ -123,6 +123,7 @@
:image="recipe.image!" :image="recipe.image!"
:tags="recipe.tags!" :tags="recipe.tags!"
:recipe-id="recipe.id!" :recipe-id="recipe.id!"
@click="handleRecipeNavigation"
/> />
</v-col> </v-col>
</v-row> </v-row>
@@ -147,6 +148,7 @@
:image="recipe.image!" :image="recipe.image!"
:tags="recipe.tags!" :tags="recipe.tags!"
:recipe-id="recipe.id!" :recipe-id="recipe.id!"
@selected="handleRecipeNavigation"
/> />
</v-col> </v-col>
</v-row> </v-row>
@@ -171,6 +173,7 @@ import { useLazyRecipes } from "~/composables/recipes";
import type { Recipe } from "~/lib/api/types/recipe"; import type { Recipe } from "~/lib/api/types/recipe";
import { useUserSortPreferences } from "~/composables/use-users/preferences"; import { useUserSortPreferences } from "~/composables/use-users/preferences";
import type { RecipeSearchQuery } from "~/lib/api/user/recipes/recipe"; 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 REPLACE_RECIPES_EVENT = "replaceRecipes";
const APPEND_RECIPES_EVENT = "appendRecipes"; const APPEND_RECIPES_EVENT = "appendRecipes";
@@ -241,9 +244,11 @@ export default defineNuxtComponent({
const route = useRoute(); const route = useRoute();
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || ""); 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 perPage = 32;
const hasMore = ref(true); const hasMore = ref(recipeListState.state.hasMore);
const ready = ref(false); const ready = ref(false);
const loading = ref(false); const loading = ref(false);
@@ -282,8 +287,33 @@ export default defineNuxtComponent({
); );
} }
// Save scroll position
const throttledScrollSave = useThrottleFn(() => {
recipeListState.saveScrollPosition();
}, 1000);
onMounted(async () => { onMounted(async () => {
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(); await initRecipes();
}
ready.value = true; ready.value = true;
}); });
@@ -294,6 +324,10 @@ export default defineNuxtComponent({
const newValueString = JSON.stringify(newValue); const newValueString = JSON.stringify(newValue);
if (lastQuery !== newValueString) { if (lastQuery !== newValueString) {
lastQuery = newValueString; lastQuery = newValueString;
// Save scroll position before query change
recipeListState.saveScrollPosition();
ready.value = false; ready.value = false;
await initRecipes(); await initRecipes();
ready.value = true; ready.value = true;
@@ -315,6 +349,14 @@ export default defineNuxtComponent({
// since we doubled the first call, we also need to advance the page // since we doubled the first call, we also need to advance the page
page.value = page.value + 1; 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); context.emit(REPLACE_RECIPES_EVENT, newRecipes);
} }
@@ -331,6 +373,14 @@ export default defineNuxtComponent({
hasMore.value = false; hasMore.value = false;
} }
if (newRecipes.length) { 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); context.emit(APPEND_RECIPES_EVENT, newRecipes);
} }
@@ -408,6 +458,15 @@ export default defineNuxtComponent({
// fetch new recipes // fetch new recipes
const newRecipes = await fetchRecipes(); 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); context.emit(REPLACE_RECIPES_EVENT, newRecipes);
state.sortLoading = false; state.sortLoading = false;
@@ -427,6 +486,17 @@ export default defineNuxtComponent({
preferences.value.useMobileCards = !preferences.value.useMobileCards; 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 { return {
...toRefs(state), ...toRefs(state),
displayTitleIcon, displayTitleIcon,
@@ -439,6 +509,7 @@ export default defineNuxtComponent({
sortRecipes, sortRecipes,
toggleMobileCards, toggleMobileCards,
useMobileCards, useMobileCards,
handleRecipeNavigation,
}; };
}, },
}); });

View File

@@ -42,7 +42,7 @@
color="info" color="info"
variant="elevated" variant="elevated"
:items="bulkActions" :items="bulkActions"
v-on="bulkActionListener" v-bind="bulkActionListener"
/> />
<slot name="button-row" /> <slot name="button-row" />
</v-card-actions> </v-card-actions>
@@ -55,7 +55,7 @@
</div> </div>
<v-data-table <v-data-table
v-model="selected" v-model="selected"
return-object item-key="id"
:headers="activeHeaders" :headers="activeHeaders"
:show-select="bulkActions.length > 0" :show-select="bulkActions.length > 0"
:sort-by="sortBy" :sort-by="sortBy"

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

@@ -45,11 +45,28 @@ export const useGroupSelf = function () {
export const useGroups = function () { export const useGroups = function () {
const api = useUserApi(); const api = useUserApi();
const loading = ref(false); const loading = ref(false);
const groups = ref<GroupSummary[] | null>(null);
async function getAllGroups() { function getAllGroups() {
loading.value = true; loading.value = true;
const { data } = await api.groups.getAll(1, -1, { orderBy: "name", orderDirection: "asc" }); const asyncKey = String(Date.now());
const { data: groups } = useAsyncData(asyncKey, async () => {
const { data } = await api.groups.getAll(1, -1, { orderBy: "name", orderDirection: "asc" }); ;
if (data) {
return data.items;
}
else {
return null;
}
});
loading.value = false;
return groups;
}
async function refreshAllGroups() {
loading.value = true;
const { data } = await api.groups.getAll(1, -1, { orderBy: "name", orderDirection: "asc" }); ;
if (data) { if (data) {
groups.value = data.items; groups.value = data.items;
@@ -61,15 +78,11 @@ export const useGroups = function () {
loading.value = false; loading.value = false;
} }
async function refreshAllGroups() {
await getAllGroups();
}
async function deleteGroup(id: string | number) { async function deleteGroup(id: string | number) {
loading.value = true; loading.value = true;
const { data } = await api.groups.deleteOne(id); const { data } = await api.groups.deleteOne(id);
loading.value = false; loading.value = false;
await refreshAllGroups(); refreshAllGroups();
return data; return data;
} }
@@ -80,13 +93,9 @@ export const useGroups = function () {
if (data && groups.value) { if (data && groups.value) {
groups.value.push(data); groups.value.push(data);
} }
loading.value = false;
} }
// Initialize data on first call const groups = getAllGroups();
if (!groups.value) {
getAllGroups();
}
return { groups, getAllGroups, refreshAllGroups, deleteGroup, createGroup }; return { groups, getAllGroups, refreshAllGroups, deleteGroup, createGroup };
}; };

View File

@@ -48,12 +48,29 @@ export const useHouseholdSelf = function () {
export const useAdminHouseholds = function () { export const useAdminHouseholds = function () {
const api = useAdminApi(); const api = useAdminApi();
const loading = ref(false); const loading = ref(false);
const households = ref<HouseholdInDB[] | null>(null);
async function getAllHouseholds() { function getAllHouseholds() {
loading.value = true; loading.value = true;
const asyncKey = String(Date.now());
const { data: households } = useAsyncData(asyncKey, async () => {
const { data } = await api.households.getAll(1, -1, { orderBy: "name, group.name", orderDirection: "asc" }); const { data } = await api.households.getAll(1, -1, { orderBy: "name, group.name", orderDirection: "asc" });
if (data) {
return data.items;
}
else {
return null;
}
});
loading.value = false;
return households;
}
async function refreshAllHouseholds() {
loading.value = true;
const { data } = await api.households.getAll(1, -1, { orderBy: "name, group.name", orderDirection: "asc" }); ;
if (data) { if (data) {
households.value = data.items; households.value = data.items;
} }
@@ -64,15 +81,11 @@ export const useAdminHouseholds = function () {
loading.value = false; loading.value = false;
} }
async function refreshAllHouseholds() {
await getAllHouseholds();
}
async function deleteHousehold(id: string | number) { async function deleteHousehold(id: string | number) {
loading.value = true; loading.value = true;
const { data } = await api.households.deleteOne(id); const { data } = await api.households.deleteOne(id);
loading.value = false; loading.value = false;
await refreshAllHouseholds(); refreshAllHouseholds();
return data; return data;
} }
@@ -83,9 +96,9 @@ export const useAdminHouseholds = function () {
if (data && households.value) { if (data && households.value) {
households.value.push(data); households.value.push(data);
} }
loading.value = false;
} }
const households = getAllHouseholds();
function useHouseholdsInGroup(groupIdRef: Ref<string>) { function useHouseholdsInGroup(groupIdRef: Ref<string>) {
return computed( return computed(
() => { () => {
@@ -96,10 +109,6 @@ export const useAdminHouseholds = function () {
); );
} }
if (!households.value) {
getAllHouseholds();
}
return { return {
households, households,
useHouseholdsInGroup, useHouseholdsInGroup,

View File

@@ -93,7 +93,7 @@ export const LOCALES = [
{ {
name: "Nederlands (Dutch)", name: "Nederlands (Dutch)",
value: "nl-NL", value: "nl-NL",
progress: 42, progress: 39,
dir: "ltr", dir: "ltr",
}, },
{ {
@@ -135,7 +135,7 @@ export const LOCALES = [
{ {
name: "Magyar (Hungarian)", name: "Magyar (Hungarian)",
value: "hu-HU", value: "hu-HU",
progress: 39, progress: 38,
dir: "ltr", dir: "ltr",
}, },
{ {
@@ -213,7 +213,7 @@ export const LOCALES = [
{ {
name: "Deutsch (German)", name: "Deutsch (German)",
value: "de-DE", value: "de-DE",
progress: 55, progress: 46,
dir: "ltr", dir: "ltr",
}, },
{ {

View File

@@ -1,47 +1,47 @@
/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable @typescript-eslint/no-require-imports */
const datetimeFormats = { const datetimeFormats = {
// CODE_GEN_ID: DATE_LOCALES // CODE_GEN_ID: DATE_LOCALES
"tr-TR": require("./lang/dateTimeFormats/tr-TR.json"),
"zh-CN": require("./lang/dateTimeFormats/zh-CN.json"),
"ja-JP": require("./lang/dateTimeFormats/ja-JP.json"),
"en-GB": require("./lang/dateTimeFormats/en-GB.json"),
"ca-ES": require("./lang/dateTimeFormats/ca-ES.json"),
"it-IT": require("./lang/dateTimeFormats/it-IT.json"),
"pl-PL": require("./lang/dateTimeFormats/pl-PL.json"),
"pt-PT": require("./lang/dateTimeFormats/pt-PT.json"),
"ro-RO": require("./lang/dateTimeFormats/ro-RO.json"),
"sr-SP": require("./lang/dateTimeFormats/sr-SP.json"),
"hr-HR": require("./lang/dateTimeFormats/hr-HR.json"),
"de-DE": require("./lang/dateTimeFormats/de-DE.json"),
"zh-TW": require("./lang/dateTimeFormats/zh-TW.json"),
"af-ZA": require("./lang/dateTimeFormats/af-ZA.json"),
"fr-CA": require("./lang/dateTimeFormats/fr-CA.json"),
"he-IL": require("./lang/dateTimeFormats/he-IL.json"),
"pt-BR": require("./lang/dateTimeFormats/pt-BR.json"),
"cs-CZ": require("./lang/dateTimeFormats/cs-CZ.json"),
"fr-FR": require("./lang/dateTimeFormats/fr-FR.json"),
"ru-RU": require("./lang/dateTimeFormats/ru-RU.json"),
"is-IS": require("./lang/dateTimeFormats/is-IS.json"),
"sk-SK": require("./lang/dateTimeFormats/sk-SK.json"),
"el-GR": require("./lang/dateTimeFormats/el-GR.json"),
"fr-BE": require("./lang/dateTimeFormats/fr-BE.json"),
"da-DK": require("./lang/dateTimeFormats/da-DK.json"),
"hu-HU": require("./lang/dateTimeFormats/hu-HU.json"), "hu-HU": require("./lang/dateTimeFormats/hu-HU.json"),
"es-ES": require("./lang/dateTimeFormats/es-ES.json"),
"gl-ES": require("./lang/dateTimeFormats/gl-ES.json"),
"no-NO": require("./lang/dateTimeFormats/no-NO.json"), "no-NO": require("./lang/dateTimeFormats/no-NO.json"),
"lt-LT": require("./lang/dateTimeFormats/lt-LT.json"), "nl-NL": require("./lang/dateTimeFormats/nl-NL.json"),
"pl-PL": require("./lang/dateTimeFormats/pl-PL.json"),
"da-DK": require("./lang/dateTimeFormats/da-DK.json"),
"fr-CA": require("./lang/dateTimeFormats/fr-CA.json"),
"fr-BE": require("./lang/dateTimeFormats/fr-BE.json"),
"it-IT": require("./lang/dateTimeFormats/it-IT.json"),
"sl-SI": require("./lang/dateTimeFormats/sl-SI.json"),
"sr-SP": require("./lang/dateTimeFormats/sr-SP.json"),
"is-IS": require("./lang/dateTimeFormats/is-IS.json"),
"ja-JP": require("./lang/dateTimeFormats/ja-JP.json"),
"fr-FR": require("./lang/dateTimeFormats/fr-FR.json"),
"ca-ES": require("./lang/dateTimeFormats/ca-ES.json"),
"tr-TR": require("./lang/dateTimeFormats/tr-TR.json"),
"fi-FI": require("./lang/dateTimeFormats/fi-FI.json"),
"hr-HR": require("./lang/dateTimeFormats/hr-HR.json"),
"pt-BR": require("./lang/dateTimeFormats/pt-BR.json"),
"sk-SK": require("./lang/dateTimeFormats/sk-SK.json"),
"zh-CN": require("./lang/dateTimeFormats/zh-CN.json"),
"pt-PT": require("./lang/dateTimeFormats/pt-PT.json"),
"en-GB": require("./lang/dateTimeFormats/en-GB.json"),
"ro-RO": require("./lang/dateTimeFormats/ro-RO.json"),
"cs-CZ": require("./lang/dateTimeFormats/cs-CZ.json"),
"en-US": require("./lang/dateTimeFormats/en-US.json"), "en-US": require("./lang/dateTimeFormats/en-US.json"),
"sv-SE": require("./lang/dateTimeFormats/sv-SE.json"), "lv-LV": require("./lang/dateTimeFormats/lv-LV.json"),
"ko-KR": require("./lang/dateTimeFormats/ko-KR.json"), "ko-KR": require("./lang/dateTimeFormats/ko-KR.json"),
"bg-BG": require("./lang/dateTimeFormats/bg-BG.json"), "bg-BG": require("./lang/dateTimeFormats/bg-BG.json"),
"sl-SI": require("./lang/dateTimeFormats/sl-SI.json"), "gl-ES": require("./lang/dateTimeFormats/gl-ES.json"),
"uk-UA": require("./lang/dateTimeFormats/uk-UA.json"), "de-DE": require("./lang/dateTimeFormats/de-DE.json"),
"lv-LV": require("./lang/dateTimeFormats/lv-LV.json"), "lt-LT": require("./lang/dateTimeFormats/lt-LT.json"),
"ru-RU": require("./lang/dateTimeFormats/ru-RU.json"),
"he-IL": require("./lang/dateTimeFormats/he-IL.json"),
"el-GR": require("./lang/dateTimeFormats/el-GR.json"),
"zh-TW": require("./lang/dateTimeFormats/zh-TW.json"),
"af-ZA": require("./lang/dateTimeFormats/af-ZA.json"),
"es-ES": require("./lang/dateTimeFormats/es-ES.json"),
"sv-SE": require("./lang/dateTimeFormats/sv-SE.json"),
"ar-SA": require("./lang/dateTimeFormats/ar-SA.json"), "ar-SA": require("./lang/dateTimeFormats/ar-SA.json"),
"nl-NL": require("./lang/dateTimeFormats/nl-NL.json"),
"vi-VN": require("./lang/dateTimeFormats/vi-VN.json"), "vi-VN": require("./lang/dateTimeFormats/vi-VN.json"),
"fi-FI": require("./lang/dateTimeFormats/fi-FI.json"), "uk-UA": require("./lang/dateTimeFormats/uk-UA.json"),
// END: DATE_LOCALES // END: DATE_LOCALES
}; };

View File

@@ -599,7 +599,7 @@
"create-recipe-from-an-image": "Créer une recette à partir dune image", "create-recipe-from-an-image": "Créer une recette à partir dune image",
"create-recipe-from-an-image-description": "Créez une recette en téléchargeant une image de celle-ci. Mealie utilisera lIA pour tenter dextraire le texte et de créer une recette.", "create-recipe-from-an-image-description": "Créez une recette en téléchargeant une image de celle-ci. Mealie utilisera lIA pour tenter dextraire le texte et de créer une recette.",
"crop-and-rotate-the-image": "Rogner et pivoter limage pour que seul le texte soit visible, et quil soit dans la bonne orientation.", "crop-and-rotate-the-image": "Rogner et pivoter limage pour que seul le texte soit visible, et quil soit dans la bonne orientation.",
"create-from-images": "Créer à partir dimages", "create-from-images": "Create from Images",
"should-translate-description": "Traduire la recette dans ma langue", "should-translate-description": "Traduire la recette dans ma langue",
"please-wait-image-procesing": "Veuillez patienter, limage est en cours de traitement. Cela peut prendre du temps.", "please-wait-image-procesing": "Veuillez patienter, limage est en cours de traitement. Cela peut prendre du temps.",
"please-wait-images-processing": "Please wait, the images are processing. This may take some time.", "please-wait-images-processing": "Please wait, the images are processing. This may take some time.",

View File

@@ -241,48 +241,48 @@ export default defineNuxtConfig({
i18n: { i18n: {
locales: [ locales: [
// CODE_GEN_ID: MESSAGE_LOCALES // CODE_GEN_ID: MESSAGE_LOCALES
{ code: "tr-TR", file: "tr-TR.ts" },
{ code: "zh-CN", file: "zh-CN.ts" },
{ code: "ja-JP", file: "ja-JP.ts" },
{ code: "en-GB", file: "en-GB.ts" },
{ code: "ca-ES", file: "ca-ES.ts" },
{ code: "it-IT", file: "it-IT.ts" },
{ code: "pl-PL", file: "pl-PL.ts" },
{ code: "pt-PT", file: "pt-PT.ts" },
{ code: "ro-RO", file: "ro-RO.ts" },
{ code: "sr-SP", file: "sr-SP.ts" },
{ code: "hr-HR", file: "hr-HR.ts" },
{ code: "de-DE", file: "de-DE.ts" },
{ code: "zh-TW", file: "zh-TW.ts" },
{ code: "af-ZA", file: "af-ZA.ts" },
{ code: "fr-CA", file: "fr-CA.ts" },
{ code: "he-IL", file: "he-IL.ts" },
{ code: "pt-BR", file: "pt-BR.ts" },
{ code: "cs-CZ", file: "cs-CZ.ts" },
{ code: "fr-FR", file: "fr-FR.ts" },
{ code: "ru-RU", file: "ru-RU.ts" },
{ code: "is-IS", file: "is-IS.ts" },
{ code: "sk-SK", file: "sk-SK.ts" },
{ code: "el-GR", file: "el-GR.ts" },
{ code: "fr-BE", file: "fr-BE.ts" },
{ code: "da-DK", file: "da-DK.ts" },
{ code: "hu-HU", file: "hu-HU.ts" }, { code: "hu-HU", file: "hu-HU.ts" },
{ code: "es-ES", file: "es-ES.ts" },
{ code: "gl-ES", file: "gl-ES.ts" },
{ code: "no-NO", file: "no-NO.ts" }, { code: "no-NO", file: "no-NO.ts" },
{ code: "lt-LT", file: "lt-LT.ts" }, { code: "nl-NL", file: "nl-NL.ts" },
{ code: "pl-PL", file: "pl-PL.ts" },
{ code: "da-DK", file: "da-DK.ts" },
{ code: "fr-CA", file: "fr-CA.ts" },
{ code: "fr-BE", file: "fr-BE.ts" },
{ code: "it-IT", file: "it-IT.ts" },
{ code: "sl-SI", file: "sl-SI.ts" },
{ code: "sr-SP", file: "sr-SP.ts" },
{ code: "is-IS", file: "is-IS.ts" },
{ code: "ja-JP", file: "ja-JP.ts" },
{ code: "fr-FR", file: "fr-FR.ts" },
{ code: "ca-ES", file: "ca-ES.ts" },
{ code: "tr-TR", file: "tr-TR.ts" },
{ code: "fi-FI", file: "fi-FI.ts" },
{ code: "hr-HR", file: "hr-HR.ts" },
{ code: "pt-BR", file: "pt-BR.ts" },
{ code: "sk-SK", file: "sk-SK.ts" },
{ code: "zh-CN", file: "zh-CN.ts" },
{ code: "pt-PT", file: "pt-PT.ts" },
{ code: "en-GB", file: "en-GB.ts" },
{ code: "ro-RO", file: "ro-RO.ts" },
{ code: "cs-CZ", file: "cs-CZ.ts" },
{ code: "et-EE", file: "et-EE.ts" },
{ code: "en-US", file: "en-US.ts" }, { code: "en-US", file: "en-US.ts" },
{ code: "sv-SE", file: "sv-SE.ts" }, { code: "lv-LV", file: "lv-LV.ts" },
{ code: "ko-KR", file: "ko-KR.ts" }, { code: "ko-KR", file: "ko-KR.ts" },
{ code: "bg-BG", file: "bg-BG.ts" }, { code: "bg-BG", file: "bg-BG.ts" },
{ code: "sl-SI", file: "sl-SI.ts" }, { code: "gl-ES", file: "gl-ES.ts" },
{ code: "uk-UA", file: "uk-UA.ts" }, { code: "de-DE", file: "de-DE.ts" },
{ code: "et-EE", file: "et-EE.ts" }, { code: "lt-LT", file: "lt-LT.ts" },
{ code: "lv-LV", file: "lv-LV.ts" }, { code: "ru-RU", file: "ru-RU.ts" },
{ code: "he-IL", file: "he-IL.ts" },
{ code: "el-GR", file: "el-GR.ts" },
{ code: "zh-TW", file: "zh-TW.ts" },
{ code: "af-ZA", file: "af-ZA.ts" },
{ code: "es-ES", file: "es-ES.ts" },
{ code: "sv-SE", file: "sv-SE.ts" },
{ code: "ar-SA", file: "ar-SA.ts" }, { code: "ar-SA", file: "ar-SA.ts" },
{ code: "nl-NL", file: "nl-NL.ts" },
{ code: "vi-VN", file: "vi-VN.ts" }, { code: "vi-VN", file: "vi-VN.ts" },
{ code: "fi-FI", file: "fi-FI.ts" }, { code: "uk-UA", file: "uk-UA.ts" },
// END: MESSAGE_LOCALES // END: MESSAGE_LOCALES
], ],
strategy: "no_prefix", strategy: "no_prefix",

View File

@@ -14,6 +14,7 @@
:items="groups" :items="groups"
item-title="name" item-title="name"
item-value="id" item-value="id"
:return-object="false"
variant="filled" variant="filled"
:label="$t('household.household-group')" :label="$t('household.household-group')"
:rules="[validators.required]" :rules="[validators.required]"
@@ -93,7 +94,10 @@
icon icon
color="error" color="error"
variant="text" variant="text"
@click.stop="confirmDialog = true; deleteTarget = item.id" @click.stop="
confirmDialog = true;
deleteTarget = +item.id;
"
> >
<v-icon> <v-icon>
{{ $globals.icons.delete }} {{ $globals.icons.delete }}
@@ -110,7 +114,7 @@
</v-container> </v-container>
</template> </template>
<script setup lang="ts"> <script lang="ts">
import { fieldTypes } from "~/composables/forms"; import { fieldTypes } from "~/composables/forms";
import { useGroups } from "~/composables/use-groups"; import { useGroups } from "~/composables/use-groups";
import { useAdminHouseholds } from "~/composables/use-households"; import { useAdminHouseholds } from "~/composables/use-households";
@@ -118,28 +122,30 @@ import { validators } from "~/composables/use-validators";
import type { HouseholdInDB } from "~/lib/api/types/household"; import type { HouseholdInDB } from "~/lib/api/types/household";
import type { VForm } from "~/types/auto-forms"; import type { VForm } from "~/types/auto-forms";
definePageMeta({ export default defineNuxtComponent({
setup() {
definePageMeta({
layout: "admin", layout: "admin",
}); });
const i18n = useI18n(); const i18n = useI18n();
useSeoMeta({ // Set page title
useSeoMeta({
title: i18n.t("household.manage-households"), title: i18n.t("household.manage-households"),
}); });
const { groups } = useGroups(); const { groups } = useGroups();
const { households, deleteHousehold, createHousehold } = useAdminHouseholds(); const { households, refreshAllHouseholds, deleteHousehold, createHousehold } = useAdminHouseholds();
const refNewHouseholdForm = ref<VForm | null>(null);
const refNewHouseholdForm = ref<VForm | null>(null); const state = reactive({
createDialog: false,
const createDialog = ref(false); confirmDialog: false,
const confirmDialog = ref(false); loading: false,
const deleteTarget = ref<string>(""); deleteTarget: 0,
const search = ref(""); search: "",
const updateMode = ref(false); headers: [
const headers = [
{ {
title: i18n.t("household.household"), title: i18n.t("household.household"),
align: "start", align: "start",
@@ -151,9 +157,9 @@ const headers = [
{ title: i18n.t("user.total-users"), value: "users" }, { title: i18n.t("user.total-users"), value: "users" },
{ title: i18n.t("user.webhooks-enabled"), value: "webhookEnable" }, { title: i18n.t("user.webhooks-enabled"), value: "webhookEnable" },
{ title: i18n.t("general.delete"), value: "actions" }, { title: i18n.t("general.delete"), value: "actions" },
]; ],
updateMode: false,
const createHouseholdForm = reactive({ createHouseholdForm: {
items: [ items: [
{ {
label: i18n.t("household.household-name"), label: i18n.t("household.household-name"),
@@ -166,25 +172,42 @@ const createHouseholdForm = reactive({
groupId: "", groupId: "",
name: "", name: "",
}, },
}); },
});
function openDialog() { function openDialog() {
createDialog.value = true; state.createDialog = true;
createHouseholdForm.data.name = ""; state.createHouseholdForm.data.name = "";
createHouseholdForm.data.groupId = ""; state.createHouseholdForm.data.groupId = "";
} }
const router = useRouter(); const router = useRouter();
function handleRowClick(item: HouseholdInDB) { function handleRowClick(item: HouseholdInDB) {
router.push(`/admin/manage/households/${item.id}`); router.push(`/admin/manage/households/${item.id}`);
} }
async function handleCreateSubmit() { async function handleCreateSubmit() {
if (!refNewHouseholdForm.value?.validate()) { if (!refNewHouseholdForm.value?.validate()) {
return; return;
} }
createDialog.value = false;
await createHousehold(createHouseholdForm.data); state.createDialog = false;
} await createHousehold(state.createHouseholdForm.data);
}
return {
...toRefs(state),
refNewHouseholdForm,
groups,
households,
validators,
refreshAllHouseholds,
deleteHousehold,
handleCreateSubmit,
openDialog,
handleRowClick,
};
},
});
</script> </script>

View File

@@ -21,23 +21,26 @@
<v-card variant="outlined"> <v-card variant="outlined">
<v-card-text> <v-card-text>
<v-select <v-select
v-model="selectedGroup" v-if="groups"
:items="groups || []" v-model="selectedGroupId"
:items="groups"
item-title="name" item-title="name"
return-object item-value="id"
:return-object="false"
variant="filled" variant="filled"
:label="$t('group.user-group')" :label="$t('group.user-group')"
:rules="[validators.required]" :rules="[validators.required]"
/> />
<v-select <v-select
v-model="newUserData.household" v-model="newUserData.household"
:disabled="!selectedGroup" :disabled="!selectedGroupId"
:items="households" :items="households"
item-title="name" item-title="name"
item-value="name" item-value="name"
:return-object="false"
variant="filled" variant="filled"
:label="$t('household.user-household')" :label="$t('household.user-household')"
:hint="selectedGroup ? '' : $t('group.you-must-select-a-group-before-selecting-a-household')" :hint="selectedGroupId ? '' : $t('group.you-must-select-a-group-before-selecting-a-household')"
persistent-hint persistent-hint
:rules="[validators.required]" :rules="[validators.required]"
/> />
@@ -57,33 +60,46 @@
</v-container> </v-container>
</template> </template>
<script setup lang="ts"> <script lang="ts">
import { useAdminApi } from "~/composables/api"; import { useAdminApi } from "~/composables/api";
import { useGroups } from "~/composables/use-groups"; import { useGroups } from "~/composables/use-groups";
import { useAdminHouseholds } from "~/composables/use-households";
import { useUserForm } from "~/composables/use-users"; import { useUserForm } from "~/composables/use-users";
import { validators } from "~/composables/use-validators"; import { validators } from "~/composables/use-validators";
import type { GroupInDB, UserIn } from "~/lib/api/types/user"; import type { UserIn } from "~/lib/api/types/user";
import type { VForm } from "~/types/auto-forms"; import type { VForm } from "~/types/auto-forms";
definePageMeta({ export default defineNuxtComponent({
setup() {
definePageMeta({
layout: "admin", layout: "admin",
}); });
const { userForm } = useUserForm();
const { groups } = useGroups();
const router = useRouter();
const refNewUserForm = ref<VForm | null>(null); const { userForm } = useUserForm();
const adminApi = useAdminApi(); const { groups } = useGroups();
const { useHouseholdsInGroup } = useAdminHouseholds();
const router = useRouter();
const selectedGroup = ref<GroupInDB | undefined>(undefined); // ==============================================
const households = computed(() => selectedGroup.value?.households || []); // New User Form
const newUserData = ref({ const refNewUserForm = ref<VForm | null>(null);
const adminApi = useAdminApi();
const selectedGroupId = ref<string>("");
const households = useHouseholdsInGroup(selectedGroupId);
const selectedGroup = computed(() => {
return groups.value?.find(group => group.id === selectedGroupId.value);
});
const state = reactive({
newUserData: {
username: "", username: "",
fullName: "", fullName: "",
email: "", email: "",
admin: false, admin: false,
group: computed(() => selectedGroup.value?.name || ""), group: selectedGroup.value?.name || "",
household: "", household: "",
advanced: false, advanced: false,
canInvite: false, canInvite: false,
@@ -91,17 +107,35 @@ const newUserData = ref({
canOrganize: false, canOrganize: false,
password: "", password: "",
authMethod: "Mealie", authMethod: "Mealie",
}); },
});
watch(selectedGroup, (newGroup) => {
state.newUserData.group = newGroup?.name || "";
state.newUserData.household = "";
});
async function handleSubmit() { async function handleSubmit() {
if (!refNewUserForm.value?.validate()) return; if (!refNewUserForm.value?.validate()) return;
const { response } = await adminApi.users.createOne(newUserData.value as UserIn); const { response } = await adminApi.users.createOne(state.newUserData as UserIn);
if (response?.status === 201) { if (response?.status === 201) {
router.push("/admin/manage/users"); router.push("/admin/manage/users");
} }
} }
return {
...toRefs(state),
userForm,
refNewUserForm,
handleSubmit,
groups,
selectedGroupId,
households,
validators,
};
},
});
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -4,31 +4,31 @@
"garlic": { "garlic": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "fokhagyma", "name": "garlic",
"plural_name": "fokhagyma" "plural_name": "garlics"
}, },
"onion": { "onion": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "hagyma", "name": "onion",
"plural_name": "hagyma" "plural_name": "onions"
}, },
"bell pepper": { "bell pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kaliforniai paprika", "name": "bell pepper",
"plural_name": "kaliforniai paprika" "plural_name": "bell peppers"
}, },
"carrot": { "carrot": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "sárgarépa", "name": "carrot",
"plural_name": "sárgarépa" "plural_name": "carrots"
}, },
"scallion": { "scallion": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "újhagyma", "name": "scallion",
"plural_name": "zöldhagyma" "plural_name": "zöldhagyma"
}, },
"zucchini": { "zucchini": {
@@ -52,8 +52,8 @@
"yellow onion": { "yellow onion": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "vöröshagyma", "name": "yellow onion",
"plural_name": "vöröshagyma" "plural_name": "yellow onions"
}, },
"celery": { "celery": {
"aliases": [], "aliases": [],
@@ -82,8 +82,8 @@
"cherry tomato": { "cherry tomato": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "koktélparadicsom", "name": "cherry tomato",
"plural_name": "koktélparadicsom" "plural_name": "cherry tomatoes"
}, },
"cucumber": { "cucumber": {
"aliases": [], "aliases": [],
@@ -105,11 +105,11 @@
}, },
"chile pepper": { "chile pepper": {
"aliases": [ "aliases": [
"kaliforniai paprika" "capsicum"
], ],
"description": "", "description": "",
"name": "chili paprika", "name": "chile pepper",
"plural_name": "chili paprika" "plural_name": "chile peppers"
}, },
"sweet potato": { "sweet potato": {
"aliases": [], "aliases": [],
@@ -126,20 +126,20 @@
"heart of palm": { "heart of palm": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pálmarügy", "name": "heart of palm",
"plural_name": "pálmarügy" "plural_name": "heart of palms"
}, },
"baby green": { "baby green": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "salátakeverék", "name": "baby green",
"plural_name": "salátakeverék" "plural_name": "baby greens"
}, },
"pumpkin": { "pumpkin": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "sütőtök", "name": "pumpkin",
"plural_name": "sütőtök" "plural_name": "pumpkins"
}, },
"cauliflower": { "cauliflower": {
"aliases": [], "aliases": [],
@@ -151,258 +151,258 @@
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "káposzta", "name": "káposzta",
"plural_name": "fejes káposzta" "plural_name": "cabbages"
}, },
"asparagu": { "asparagu": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "spárga", "name": "asparagu",
"plural_name": "spárga" "plural_name": "asparagus"
}, },
"kale": { "kale": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kelkáposzta", "name": "kale",
"plural_name": "kelkáposzta" "plural_name": "kales"
}, },
"arugula": { "arugula": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "rukkola", "name": "arugula",
"plural_name": "rukkola" "plural_name": "arugulas"
}, },
"leek": { "leek": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "póréhagyma", "name": "leek",
"plural_name": "póréhagyma" "plural_name": "leeks"
}, },
"eggplant": { "eggplant": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "padlizsán", "name": "eggplant",
"plural_name": "padlizsán" "plural_name": "eggplants"
}, },
"lettuce": { "lettuce": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "saláta", "name": "lettuce",
"plural_name": "saláta" "plural_name": "lettuces"
}, },
"butternut squash": { "butternut squash": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kanadai sütőtök", "name": "butternut squash",
"plural_name": "kanadai sütőtök" "plural_name": "butternut squashes"
}, },
"romaine": { "romaine": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "római saláta", "name": "romaine",
"plural_name": "római saláta" "plural_name": "romaines"
}, },
"beetroot": { "beetroot": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "cékla", "name": "beetroot",
"plural_name": "cékla" "plural_name": "beetroots"
}, },
"brussels sprout": { "brussels sprout": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kelbimbó", "name": "brussels sprout",
"plural_name": "kelbimbó" "plural_name": "brussels sprouts"
}, },
"fennel": { "fennel": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "édeskömény", "name": "fennel",
"plural_name": "édeskömény" "plural_name": "fennels"
}, },
"sun dried tomato": { "sun dried tomato": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "szárított paradicsom", "name": "sun dried tomato",
"plural_name": "szárított paradicsom" "plural_name": "sun dried tomatoes"
}, },
"radish": { "radish": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "retek", "name": "radish",
"plural_name": "retkek" "plural_name": "radishes"
}, },
"red cabbage": { "red cabbage": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "vöröskáposzta", "name": "red cabbage",
"plural_name": "vöröskáposzta" "plural_name": "red cabbages"
}, },
"artichoke": { "artichoke": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "articsóka", "name": "artichoke",
"plural_name": "articsóka" "plural_name": "artichokes"
}, },
"new potato": { "new potato": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "újburgonya", "name": "new potato",
"plural_name": "újburgonya" "plural_name": "new potatoes"
}, },
"summer squash": { "summer squash": {
"aliases": [ "aliases": [
"cukkini", "courgette",
"kis tök" "gem squash"
], ],
"description": "", "description": "",
"name": "főzőtök", "name": "summer squash",
"plural_name": "főzőtök" "plural_name": "summer squashes"
}, },
"mixed green": { "mixed green": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "salátakeverék", "name": "mixed green",
"plural_name": "salátakeverék" "plural_name": "mixed greens"
}, },
"parsnip": { "parsnip": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "paszternák", "name": "parsnip",
"plural_name": "paszternák" "plural_name": "parsnips"
}, },
"baby carrot": { "baby carrot": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bébirépa", "name": "baby carrot",
"plural_name": "bébirépa" "plural_name": "baby carrots"
}, },
"mixed vegetable": { "mixed vegetable": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zöldségkeverék", "name": "mixed vegetable",
"plural_name": "zöldségkeverék" "plural_name": "mixed vegetables"
}, },
"poblano pepper": { "poblano pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "poblano paprika", "name": "poblano pepper",
"plural_name": "poblano paprika" "plural_name": "poblano peppers"
}, },
"sweet pepper": { "sweet pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "édes paprika", "name": "sweet pepper",
"plural_name": "édes paprika" "plural_name": "sweet peppers"
}, },
"serrano pepper": { "serrano pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "serrano paprika", "name": "serrano pepper",
"plural_name": "serrano paprika" "plural_name": "serrano peppers"
}, },
"cayenne pepper": { "cayenne pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "cayenne bors", "name": "cayenne pepper",
"plural_name": "cayenne bors" "plural_name": "cayenne peppers"
}, },
"green tomato": { "green tomato": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zöld paradicsom", "name": "green tomato",
"plural_name": "zöld paradicsom" "plural_name": "green tomatoes"
}, },
"watercress": { "watercress": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "vízitorma", "name": "watercress",
"plural_name": "vízitorma" "plural_name": "watercress"
}, },
"iceberg": { "iceberg": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "jégsaláta", "name": "iceberg",
"plural_name": "jégsaláta" "plural_name": "icebergs"
}, },
"mashed potato": { "mashed potato": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "burgonyapüré", "name": "mashed potato",
"plural_name": "burgonyapüré" "plural_name": "mashed potatoes"
}, },
"horseradish": { "horseradish": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "torma", "name": "horseradish",
"plural_name": "torma" "plural_name": "horseradishes"
}, },
"chard": { "chard": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "mángold", "name": "chard",
"plural_name": "mángold" "plural_name": "chards"
}, },
"pimiento": { "pimiento": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kápia paprika", "name": "pimiento",
"plural_name": "kápia paprika" "plural_name": "pimientoes"
}, },
"spaghetti squash": { "spaghetti squash": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "spagettitök", "name": "spaghetti squash",
"plural_name": "spagettitök" "plural_name": "spaghetti squashes"
}, },
"butter lettuce": { "butter lettuce": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "fejes saláta", "name": "butter lettuce",
"plural_name": "fejes saláta" "plural_name": "butter lettuces"
}, },
"hash brown": { "hash brown": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "tócsni", "name": "hash brown",
"plural_name": "tócsni" "plural_name": "hash browns"
}, },
"napa cabbage": { "napa cabbage": {
"aliases": [ "aliases": [
"kínai kel" "chinese leaves"
], ],
"description": "", "description": "",
"name": "kínai kel", "name": "napa cabbage",
"plural_name": "kínai kel" "plural_name": "napa cabbages"
}, },
"celeriac": { "celeriac": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zeller", "name": "celeriac",
"plural_name": "zeller" "plural_name": "celeriacs"
}, },
"water chestnut": { "water chestnut": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "vízigesztenye", "name": "water chestnut",
"plural_name": "vízigesztenye" "plural_name": "water chestnuts"
}, },
"turnip": { "turnip": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "tarlórépa", "name": "turnip",
"plural_name": "tarlórépa" "plural_name": "turnips"
}, },
"thai chile pepper": { "thai chile pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "thai csili paprika", "name": "thai chile pepper",
"plural_name": "thai csili paprika" "plural_name": "thai chile peppers"
}, },
"bok choy": { "bok choy": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bordáskel", "name": "bok choy",
"plural_name": "bordáskel" "plural_name": "bok choy"
}, },
"okra": { "okra": {
"aliases": [], "aliases": [],
@@ -413,44 +413,44 @@
"acorn squash": { "acorn squash": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "makktök", "name": "acorn squash",
"plural_name": "makktök" "plural_name": "acorn squashes"
}, },
"corn cob": { "corn cob": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kukoricacső", "name": "corn cob",
"plural_name": "kukoricacső" "plural_name": "corn cobs"
}, },
"radicchio": { "radicchio": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "vörös cikória", "name": "radicchio",
"plural_name": "vörös cikória" "plural_name": "radicchio"
}, },
"pearl onion": { "pearl onion": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gyöngyhagyma", "name": "pearl onion",
"plural_name": "gyöngyhagyma" "plural_name": "pearl onions"
}, },
"tenderstem broccoli": { "tenderstem broccoli": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "brokkolini", "name": "tenderstem broccoli",
"plural_name": "brokkolini" "plural_name": "tenderstem broccolis"
}, },
"plantain": { "plantain": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "főzőbanán", "name": "plantain",
"plural_name": "főzőbanán" "plural_name": "plantains"
}, },
"leaf lettuce": { "leaf lettuce": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "saláta", "name": "leaf lettuce",
"plural_name": "saláta" "plural_name": "leaf lettuces"
}, },
"pepperoncini": { "pepperoncini": {
"aliases": [], "aliases": [],
@@ -602,25 +602,25 @@
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "arbol chile pepper", "name": "arbol chile pepper",
"plural_name": "arbol csili paprika" "plural_name": "arbol chile peppers"
}, },
"golden beet": { "golden beet": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "sárga cékla", "name": "golden beet",
"plural_name": "sárga cékla" "plural_name": "golden beets"
}, },
"pea shoot": { "pea shoot": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "borsócsíra", "name": "pea shoot",
"plural_name": "borsócsíra" "plural_name": "pea shoots"
}, },
"alfalfa": { "alfalfa": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "lucernacsíra", "name": "alfalfa",
"plural_name": "lucernacsíra" "plural_name": "alfalfas"
} }
} }
}, },
@@ -628,129 +628,129 @@
"foods": { "foods": {
"tomato": { "tomato": {
"aliases": [], "aliases": [],
"description": "Igen, gyümölcs", "description": "Yes they are a fruit",
"name": "paradicsom", "name": "tomato",
"plural_name": "paradicsom" "plural_name": "tomatoes"
}, },
"lemon": { "lemon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "citrom", "name": "lemon",
"plural_name": "citrom" "plural_name": "lemons"
}, },
"lime": { "lime": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zöldcitrom", "name": "lime",
"plural_name": "zöldcitrom" "plural_name": "limes"
}, },
"apple": { "apple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "alma", "name": "apple",
"plural_name": "alma" "plural_name": "apples"
}, },
"banana": { "banana": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "banán", "name": "banana",
"plural_name": "banán" "plural_name": "bananas"
}, },
"orange": { "orange": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "narancs", "name": "orange",
"plural_name": "narancs" "plural_name": "oranges"
}, },
"raisin": { "raisin": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "mazsola", "name": "raisin",
"plural_name": "mazsola" "plural_name": "raisins"
}, },
"pineapple": { "pineapple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "ananász", "name": "pineapple",
"plural_name": "ananász" "plural_name": "pineapples"
}, },
"mango": { "mango": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "mangó", "name": "mango",
"plural_name": "mangó" "plural_name": "mangoes"
}, },
"peach": { "peach": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "őszibarack", "name": "peach",
"plural_name": "őszibarack" "plural_name": "peaches"
}, },
"date": { "date": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "datolya", "name": "date",
"plural_name": "datolya" "plural_name": "dates"
}, },
"coconut": { "coconut": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kókuszdió", "name": "coconut",
"plural_name": "kókuszdió" "plural_name": "coconuts"
}, },
"craisin": { "craisin": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "aszalt vörösáfonya", "name": "craisin",
"plural_name": "aszalt vörösáfonya" "plural_name": "craisins"
}, },
"pear": { "pear": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "körte", "name": "pear",
"plural_name": "körte" "plural_name": "pears"
}, },
"grape": { "grape": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "szőlő", "name": "grape",
"plural_name": "szőlő" "plural_name": "grapes"
}, },
"pomegranate": { "pomegranate": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gránátalma", "name": "pomegranate",
"plural_name": "gránátalma" "plural_name": "pomegranates"
}, },
"watermelon": { "watermelon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "görögdinnye", "name": "watermelon",
"plural_name": "görögdinnye" "plural_name": "watermelons"
}, },
"rhubarb": { "rhubarb": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "rebarbara", "name": "rhubarb",
"plural_name": "rebarbara" "plural_name": "rhubarbs"
}, },
"dried apricot": { "dried apricot": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "aszalt sárgabarack", "name": "dried apricot",
"plural_name": "aszalt sárgabarack" "plural_name": "dried apricots"
}, },
"kiwi": { "kiwi": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kivi", "name": "kiwi",
"plural_name": "kivi" "plural_name": "kiwis"
}, },
"grapefruit": { "grapefruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "grapefruit", "name": "grapefruit",
"plural_name": "grapefruit" "plural_name": "grapefruits"
}, },
"plum": { "plum": {
"aliases": [], "aliases": [],
@@ -905,86 +905,86 @@
"banana chip": { "banana chip": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "banánchips", "name": "banana chip",
"plural_name": "banánchips" "plural_name": "banana chips"
}, },
"kumquat": { "kumquat": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "törpemandarin", "name": "kumquat",
"plural_name": "törpemandarin" "plural_name": "kumquats"
}, },
"jackfruit": { "jackfruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "jackfruit", "name": "jackfruit",
"plural_name": "jackfruit" "plural_name": "jackfruits"
}, },
"dragon fruit": { "dragon fruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "sárkánygyümölcs", "name": "dragon fruit",
"plural_name": "sárkánygyümölcs" "plural_name": "dragon fruits"
}, },
"mixed fruit": { "mixed fruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "vegyes gyümölcs", "name": "mixed fruit",
"plural_name": "vegyes gyümölcs" "plural_name": "mixed fruits"
}, },
"asian pear": { "asian pear": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "japán körte", "name": "asian pear",
"plural_name": "japán körte" "plural_name": "asian pears"
}, },
"lychee": { "lychee": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "licsi", "name": "lychee",
"plural_name": "licsi" "plural_name": "lychees"
}, },
"young coconut": { "young coconut": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zsenge kókuszdió", "name": "young coconut",
"plural_name": "zsenge kókuszdió" "plural_name": "young coconuts"
}, },
"kaffir lime": { "kaffir lime": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kaffir lime", "name": "kaffir lime",
"plural_name": "kaffir lime" "plural_name": "kaffir limes"
}, },
"star fruit": { "star fruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "csillaggyümölcs", "name": "star fruit",
"plural_name": "csillaggyümölcs" "plural_name": "star fruits"
}, },
"green papaya": { "green papaya": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zöld papaya", "name": "green papaya",
"plural_name": "zöld papaya" "plural_name": "green papayas"
}, },
"pomelo": { "pomelo": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pomelo", "name": "pomelo",
"plural_name": "pomelo" "plural_name": "pomeloes"
}, },
"chestnut puree": { "chestnut puree": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gesztenyepüré", "name": "chestnut puree",
"plural_name": "gesztenyepüré" "plural_name": "chestnut purees"
}, },
"prickly pear": { "prickly pear": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kaktuszfüge", "name": "prickly pear",
"plural_name": "kaktuszfüge" "plural_name": "prickly pears"
}, },
"calamansi": { "calamansi": {
"aliases": [], "aliases": [],

View File

@@ -255,7 +255,7 @@
"edelpompoen" "edelpompoen"
], ],
"description": "", "description": "",
"name": "edelpompoenen", "name": "summer squash",
"plural_name": "edelpompoenen" "plural_name": "edelpompoenen"
}, },
"mixed green": { "mixed green": {
@@ -536,7 +536,7 @@
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "yamswortel", "name": "yamswortel",
"plural_name": "yamswortel" "plural_name": "yams"
}, },
"ancho chile pepper": { "ancho chile pepper": {
"aliases": [], "aliases": [],
@@ -547,8 +547,8 @@
"microgreen": { "microgreen": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "microgroen", "name": "microgreen",
"plural_name": "kiemgroenten" "plural_name": "microgreens"
}, },
"boston lettuce": { "boston lettuce": {
"aliases": [], "aliases": [],
@@ -559,55 +559,55 @@
"kohlrabi": { "kohlrabi": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "koolrabi", "name": "kohlrabi",
"plural_name": "koolrabi's" "plural_name": "kohlrabis"
}, },
"fresno chile": { "fresno chile": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "fresno peper", "name": "fresno chile",
"plural_name": "fresno pepers" "plural_name": "fresno chiles"
}, },
"delicata squash": { "delicata squash": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "delicata pompoen", "name": "delicata squash",
"plural_name": "delicata pompoenen" "plural_name": "delicata squashes"
}, },
"frisee": { "frisee": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "krulandijvie", "name": "frisee",
"plural_name": "krulandijvie" "plural_name": "frisees"
}, },
"anaheim pepper": { "anaheim pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "anaheim peper", "name": "anaheim pepper",
"plural_name": "anaheim pepers" "plural_name": "anaheim peppers"
}, },
"cres": { "cres": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kropsla", "name": "cres",
"plural_name": "kropsla" "plural_name": "cress"
}, },
"broccoli slaw": { "broccoli slaw": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "broccoli salade", "name": "broccoli slaw",
"plural_name": "broccoli salades" "plural_name": "broccoli slaws"
}, },
"arbol chile pepper": { "arbol chile pepper": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "arbol peper", "name": "arbol chile pepper",
"plural_name": "arbol pepers" "plural_name": "arbol chile peppers"
}, },
"golden beet": { "golden beet": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gele biet", "name": "golden beet",
"plural_name": "gele biet" "plural_name": "gele biet"
}, },
"pea shoot": { "pea shoot": {
@@ -628,8 +628,8 @@
"foods": { "foods": {
"tomato": { "tomato": {
"aliases": [], "aliases": [],
"description": "Ja, ze zijn fruit", "description": "Yes they are a fruit",
"name": "tomaat", "name": "tomato",
"plural_name": "tomaten" "plural_name": "tomaten"
}, },
"lemon": { "lemon": {
@@ -839,14 +839,14 @@
"meyer lemon": { "meyer lemon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "meyer citroen", "name": "meyer lemon",
"plural_name": "meyer citroenen" "plural_name": "meyer lemons"
}, },
"honeydew melon": { "honeydew melon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "honing meloen", "name": "honeydew melon",
"plural_name": "honing meloenen" "plural_name": "honeydew melons"
}, },
"dried fruit": { "dried fruit": {
"aliases": [], "aliases": [],
@@ -863,50 +863,50 @@
"persimmon": { "persimmon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kakivrucht", "name": "persimmon",
"plural_name": "kakivruchten" "plural_name": "persimmons"
}, },
"melon": { "melon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "meloen", "name": "melon",
"plural_name": "meloenen" "plural_name": "melons"
}, },
"tangerine": { "tangerine": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "mandarijn", "name": "tangerine",
"plural_name": "mandarijnen" "plural_name": "tangerines"
}, },
"dried mango": { "dried mango": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogde mango", "name": "dried mango",
"plural_name": "gedroogde mango's" "plural_name": "dried mangoes"
}, },
"dried apple": { "dried apple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogde appel", "name": "dried apple",
"plural_name": "gedroogde appels" "plural_name": "dried apples"
}, },
"quince": { "quince": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kweepeer", "name": "quince",
"plural_name": "kweeperen" "plural_name": "quinces"
}, },
"guava": { "guava": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "guave", "name": "guava",
"plural_name": "guava's" "plural_name": "guavas"
}, },
"banana chip": { "banana chip": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bananen chip", "name": "banana chip",
"plural_name": "bananen chips" "plural_name": "banana chips"
}, },
"kumquat": { "kumquat": {
"aliases": [], "aliases": [],
@@ -923,20 +923,20 @@
"dragon fruit": { "dragon fruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "drakenfruit", "name": "dragon fruit",
"plural_name": "drakenfruit vruchten" "plural_name": "dragon fruits"
}, },
"mixed fruit": { "mixed fruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gemixte vruchten", "name": "mixed fruit",
"plural_name": "gemengde vruchten" "plural_name": "mixed fruits"
}, },
"asian pear": { "asian pear": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "aziatische peer", "name": "asian pear",
"plural_name": "aziatische peren" "plural_name": "asian pears"
}, },
"lychee": { "lychee": {
"aliases": [], "aliases": [],
@@ -947,44 +947,44 @@
"young coconut": { "young coconut": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "jonge kokokosnoot", "name": "young coconut",
"plural_name": "jonge kokokosnoten" "plural_name": "young coconuts"
}, },
"kaffir lime": { "kaffir lime": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kaffir limoen", "name": "kaffir lime",
"plural_name": "kaffir limoenen" "plural_name": "kaffir limes"
}, },
"star fruit": { "star fruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "stervrucht", "name": "star fruit",
"plural_name": "stervruchten" "plural_name": "star fruits"
}, },
"green papaya": { "green papaya": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "groene papaya", "name": "green papaya",
"plural_name": "groene papaya's" "plural_name": "green papayas"
}, },
"pomelo": { "pomelo": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pompelmoes", "name": "pomelo",
"plural_name": "pompelmoezen" "plural_name": "pomeloes"
}, },
"chestnut puree": { "chestnut puree": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kastanje puree", "name": "chestnut puree",
"plural_name": "kastanje puree" "plural_name": "chestnut purees"
}, },
"prickly pear": { "prickly pear": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "cactusvijg", "name": "prickly pear",
"plural_name": "cactusvijgen" "plural_name": "prickly pears"
}, },
"calamansi": { "calamansi": {
"aliases": [], "aliases": [],
@@ -1055,56 +1055,56 @@
"dried lemon": { "dried lemon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogde limoen", "name": "dried lemon",
"plural_name": "gedroogde limoenen" "plural_name": "dried lemons"
}, },
"young jackfruit": { "young jackfruit": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "jonge jackfruit", "name": "young jackfruit",
"plural_name": "jonge jackfruits" "plural_name": "young jackfruits"
}, },
"durian": { "durian": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "doerian", "name": "durian",
"plural_name": "doerians" "plural_name": "durians"
}, },
"freeze-dried apple": { "freeze-dried apple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gevriesdroogde appel", "name": "freeze-dried apple",
"plural_name": "gevriesdroogde appels" "plural_name": "freeze-dried apples"
}, },
"dried tamarind": { "dried tamarind": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogte tamarinde", "name": "dried tamarind",
"plural_name": "gedroogde tamarindes" "plural_name": "dried tamarinds"
}, },
"honey date": { "honey date": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "honing dadel", "name": "honey date",
"plural_name": "honing dadels" "plural_name": "honey dates"
}, },
"physali": { "physali": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "ananaskers", "name": "physali",
"plural_name": "ananaskersen" "plural_name": "physalis"
}, },
"tamarillo": { "tamarillo": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "tamarillo", "name": "tamarillo",
"plural_name": "tamarillo's" "plural_name": "tamarilloes"
}, },
"ice-apple": { "ice-apple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "ijsappel", "name": "ice-apple",
"plural_name": "ijsappels" "plural_name": "ice-apples"
}, },
"longan": { "longan": {
"aliases": [], "aliases": [],
@@ -1115,98 +1115,98 @@
"finger lime": { "finger lime": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "citroenkaviaar", "name": "finger lime",
"plural_name": "citroenkaviaar" "plural_name": "finger limes"
}, },
"bitter orange": { "bitter orange": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bittersinaasappel", "name": "bitter orange",
"plural_name": "bittersinaasappels" "plural_name": "bitter oranges"
}, },
"feijoa": { "feijoa": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "ananasguave", "name": "feijoa",
"plural_name": "ananasguaves" "plural_name": "feijoas"
}, },
"dried persimmon": { "dried persimmon": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogde kakivrucht", "name": "dried persimmon",
"plural_name": "gedroogde kakivruchten" "plural_name": "dried persimmons"
}, },
"rambutan": { "rambutan": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "ramboetan", "name": "rambutan",
"plural_name": "ramboetans" "plural_name": "rambutans"
}, },
"rose apple": { "rose apple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "rozenappel", "name": "rose apple",
"plural_name": "rozenappels" "plural_name": "rose apples"
}, },
"dried orange slice": { "dried orange slice": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogd sinaasappel partje", "name": "dried orange slice",
"plural_name": "gedroogdesinaasappel partjes" "plural_name": "dried orange slices"
}, },
"loquat": { "loquat": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "japanse pruim", "name": "loquat",
"plural_name": "japanse pruimen" "plural_name": "loquats"
}, },
"crabapple": { "crabapple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "wilde appel", "name": "crabapple",
"plural_name": "wilde appels" "plural_name": "crabapples"
}, },
"fig leaf": { "fig leaf": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "vijgenblad", "name": "fig leaf",
"plural_name": "vijgenbladeren" "plural_name": "fig leaves"
}, },
"freeze-dried pineapple": { "freeze-dried pineapple": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gevriesdroogde ananas", "name": "freeze-dried pineapple",
"plural_name": "gevriesdroogde ananas" "plural_name": "freeze-dried pineapples"
}, },
"pluot": { "pluot": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pruim-abrikoos", "name": "pluot",
"plural_name": "pruim-abrikozen" "plural_name": "pluots"
}, },
"soursop": { "soursop": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zuurzak", "name": "soursop",
"plural_name": "zuurzakken" "plural_name": "soursops"
}, },
"hog plum": { "hog plum": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "varkenspruim", "name": "hog plum",
"plural_name": "varkenspruimen" "plural_name": "hog plums"
}, },
"bergamot orange": { "bergamot orange": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bergamot", "name": "bergamot orange",
"plural_name": "bergamotten" "plural_name": "bergamot oranges"
}, },
"luo han guo": { "luo han guo": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "monniksfruit", "name": "luo han guo",
"plural_name": "monniksfruit" "plural_name": "luo han guos"
}, },
"mamey": { "mamey": {
"aliases": [], "aliases": [],
@@ -1223,14 +1223,14 @@
"green ume plum": { "green ume plum": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "groene ume pruim", "name": "green ume plum",
"plural_name": "groene ume pruimen" "plural_name": "green ume plums"
}, },
"kiwano": { "kiwano": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "hoornmeloen", "name": "kiwano",
"plural_name": "hoornmeloenen" "plural_name": "kiwanoes"
} }
} }
}, },
@@ -1239,104 +1239,104 @@
"button mushroom": { "button mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "champignon", "name": "button mushroom",
"plural_name": "champignons" "plural_name": "button mushrooms"
}, },
"shiitake mushroom": { "shiitake mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "shiitake", "name": "shiitake mushroom",
"plural_name": "shiitakes" "plural_name": "shiitake mushrooms"
}, },
"portobello mushroom": { "portobello mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "portobello", "name": "portobello mushroom",
"plural_name": "portobello's" "plural_name": "portobello mushrooms"
}, },
"wild mushroom": { "wild mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "wilde paddenstoel", "name": "wild mushroom",
"plural_name": "wilde paddenstoelen" "plural_name": "wild mushrooms"
}, },
"porcini": { "porcini": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "eekhoorntjesbrood", "name": "porcini",
"plural_name": "eekhoorntjesbrood" "plural_name": "porcinis"
}, },
"mixed mushroom": { "mixed mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gemengde paddenstoelen", "name": "mixed mushroom",
"plural_name": "gemengde paddenstoelen" "plural_name": "mixed mushrooms"
}, },
"oyster mushroom": { "oyster mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "oesterzwam", "name": "oyster mushroom",
"plural_name": "oesterzwammen" "plural_name": "oyster mushrooms"
}, },
"chestnut mushroom": { "chestnut mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kastanje champignon", "name": "chestnut mushroom",
"plural_name": "kastanje champignons" "plural_name": "chestnut mushrooms"
}, },
"enoki mushroom": { "enoki mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "enoki-paddenstoel", "name": "enoki mushroom",
"plural_name": "enoki-paddenstoeltjes" "plural_name": "enoki mushrooms"
}, },
"black fungu": { "black fungu": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "boomoor", "name": "black fungu",
"plural_name": "boomoren" "plural_name": "black fungus"
}, },
"black truffle": { "black truffle": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zwarte truffel", "name": "black truffle",
"plural_name": "zwarte truffels" "plural_name": "black truffles"
}, },
"morel mushroom": { "morel mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "morel paddenstoel", "name": "morel mushroom",
"plural_name": "morel paddenstoelen" "plural_name": "morel mushrooms"
}, },
"field mushroom": { "field mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "veld paddestoel", "name": "field mushroom",
"plural_name": "veld paddenstoelen" "plural_name": "field mushrooms"
}, },
"king oyster mushroom": { "king oyster mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "koning oesterzwam", "name": "king oyster mushroom",
"plural_name": "koning oesterzwammen" "plural_name": "king oyster mushrooms"
}, },
"shimeji mushroom": { "shimeji mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "shimeji paddenstoel", "name": "shimeji mushroom",
"plural_name": "shimeji paddenstoelen" "plural_name": "shimeji mushrooms"
}, },
"straw mushroom": { "straw mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "stro paddenstoel", "name": "straw mushroom",
"plural_name": "stro paddenstoelen" "plural_name": "straw mushrooms"
}, },
"dried chinese mushroom": { "dried chinese mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogde chinese paddenstoel", "name": "dried chinese mushroom",
"plural_name": "gedroogde chinese paddenstoelen" "plural_name": "dried chinese mushrooms"
}, },
"maitake": { "maitake": {
"aliases": [], "aliases": [],
@@ -1347,79 +1347,79 @@
"trumpet mushroom": { "trumpet mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "trompet paddenstoel", "name": "trumpet mushroom",
"plural_name": "trompet paddenstoelen" "plural_name": "trumpet mushrooms"
}, },
"white truffle": { "white truffle": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "witte truffel", "name": "white truffle",
"plural_name": "witte truffels" "plural_name": "white truffles"
}, },
"white fungu": { "white fungu": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "witte zwam", "name": "white fungu",
"plural_name": "witte zwammen" "plural_name": "white fungus"
}, },
"pioppini": { "pioppini": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pioppino-zwam", "name": "pioppini",
"plural_name": "pioppino-zwammen" "plural_name": "pioppinis"
}, },
"snow fungu": { "snow fungu": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "sneeuwzwam", "name": "snow fungu",
"plural_name": "sneeuwzwammen" "plural_name": "snow fungus"
}, },
"white beech mushroom": { "white beech mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "witte beukenzwam", "name": "white beech mushroom",
"plural_name": "witte beukenzwammen" "plural_name": "white beech mushrooms"
}, },
"boletu": { "boletu": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "boleet", "name": "boletu",
"plural_name": "boleten" "plural_name": "boletus"
}, },
"huitlacoche": { "huitlacoche": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "maïsbrand", "name": "huitlacoche",
"plural_name": "maïsbrand" "plural_name": "huitlacoches"
}, },
"matsutake": { "matsutake": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pijnboomzwam", "name": "matsutake",
"plural_name": "pijnboomzwammen" "plural_name": "matsutakes"
}, },
"nameko": { "nameko": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bundelzwam", "name": "nameko",
"plural_name": "bundelzwammen" "plural_name": "namekoes"
}, },
"djon djon mushroom": { "djon djon mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zwarte trompetzwam", "name": "djon djon mushroom",
"plural_name": "zwarte trompetzwammen" "plural_name": "djon djon mushrooms"
}, },
"mixed asian mushroom": { "mixed asian mushroom": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gemengde aziatische paddenstoelen", "name": "mixed asian mushroom",
"plural_name": "gemengde aziatische paddenstoelen" "plural_name": "mixed asian mushrooms"
}, },
"puffball": { "puffball": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bovist", "name": "puffball",
"plural_name": "puffballs" "plural_name": "puffballs"
}, },
"honey fungu": { "honey fungu": {
@@ -1453,98 +1453,98 @@
"strawberry": { "strawberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "aardbei", "name": "strawberry",
"plural_name": "aardbeien" "plural_name": "strawberries"
}, },
"blueberry": { "blueberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "bosbes", "name": "blueberry",
"plural_name": "bosbessen" "plural_name": "blueberries"
}, },
"raspberry": { "raspberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "framboos", "name": "raspberry",
"plural_name": "frambozen" "plural_name": "raspberries"
}, },
"cranberry": { "cranberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "veenbes", "name": "cranberry",
"plural_name": "veenbessen" "plural_name": "cranberries"
}, },
"cherry": { "cherry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kers", "name": "cherry",
"plural_name": "kersen" "plural_name": "cherries"
}, },
"blackberry": { "blackberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "braam", "name": "blackberry",
"plural_name": "bramen" "plural_name": "blackberries"
}, },
"berry mix": { "berry mix": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gemengde bessen", "name": "berry mix",
"plural_name": "gemengde bessen" "plural_name": "berry mixes"
}, },
"maraschino cherry": { "maraschino cherry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "maraschino kers", "name": "maraschino cherry",
"plural_name": "maraschino kersen" "plural_name": "maraschino cherries"
}, },
"dried cherry": { "dried cherry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogde kers", "name": "dried cherry",
"plural_name": "gedroogde kersen" "plural_name": "dried cherries"
}, },
"juniper berry": { "juniper berry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "jeneverbes", "name": "juniper berry",
"plural_name": "jeneverbessen" "plural_name": "juniper berries"
}, },
"sour cherry": { "sour cherry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "zure kers", "name": "sour cherry",
"plural_name": "zure kersen" "plural_name": "sour cherries"
}, },
"goji berry": { "goji berry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "goji bes", "name": "goji berry",
"plural_name": "goji bessen" "plural_name": "goji berries"
}, },
"dried blueberry": { "dried blueberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gedroogde bosbes", "name": "dried blueberry",
"plural_name": "gedroogde bosbessen" "plural_name": "dried blueberries"
}, },
"freeze-dried strawberry": { "freeze-dried strawberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gevriesdroogde aardbei", "name": "freeze-dried strawberry",
"plural_name": "gevriesdroogde aardbeien" "plural_name": "freeze-dried strawberries"
}, },
"gooseberry": { "gooseberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kruisbes", "name": "gooseberry",
"plural_name": "kruisbessen" "plural_name": "gooseberries"
}, },
"freeze-dried raspberry": { "freeze-dried raspberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "gevriesdroogde framboos", "name": "freeze-dried raspberry",
"plural_name": "gevriesdroogde frambozen" "plural_name": "freeze-dried raspberries"
}, },
"lingonberry": { "lingonberry": {
"aliases": [], "aliases": [],
@@ -1640,19 +1640,19 @@
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "hawthorn", "name": "hawthorn",
"plural_name": "meidoorns" "plural_name": "hawthorns"
}, },
"boysenberry": { "boysenberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "wilde braam", "name": "boysenberry",
"plural_name": "wilde bramen" "plural_name": "boysenberries"
}, },
"cloudberry": { "cloudberry": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "kruipbraam", "name": "cloudberry",
"plural_name": "kruipbramen" "plural_name": "cloudberries"
}, },
"freeze-dried berry": { "freeze-dried berry": {
"aliases": [], "aliases": [],
@@ -1715,20 +1715,20 @@
"walnut": { "walnut": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "walnoot", "name": "walnut",
"plural_name": "walnoten" "plural_name": "walnuts"
}, },
"pecan": { "pecan": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pecannoot", "name": "pecan",
"plural_name": "pecannoten" "plural_name": "pecans"
}, },
"almond": { "almond": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "amandel", "name": "almond",
"plural_name": "amandelen" "plural_name": "almonds"
}, },
"sesame seed": { "sesame seed": {
"aliases": [], "aliases": [],
@@ -1739,8 +1739,8 @@
"cashew": { "cashew": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "cashewnoot", "name": "cashew",
"plural_name": "cashewnoten" "plural_name": "cashews"
}, },
"pine nut": { "pine nut": {
"aliases": [], "aliases": [],
@@ -1751,14 +1751,14 @@
"pistachio": { "pistachio": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pistachenoot", "name": "pistachio",
"plural_name": "pistachenoten" "plural_name": "pistachios"
}, },
"peanut": { "peanut": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "pinda", "name": "peanut",
"plural_name": "pinda's" "plural_name": "peanuts"
}, },
"chia": { "chia": {
"aliases": [], "aliases": [],
@@ -1811,8 +1811,8 @@
"roasted peanut": { "roasted peanut": {
"aliases": [], "aliases": [],
"description": "", "description": "",
"name": "geroosterde pinda", "name": "roasted peanut",
"plural_name": "geroosterde pinda's" "plural_name": "roasted peanuts"
}, },
"chopped nut": { "chopped nut": {
"aliases": [], "aliases": [],