1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-07-25 08:09:41 +02:00

chore: make vue domain components localizable (#1532)

This commit is contained in:
Philipp Fischbeck 2022-08-10 07:12:45 +02:00 committed by GitHub
parent e5bf7bce17
commit 32244988d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 254 additions and 144 deletions

View file

@ -18,7 +18,7 @@
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api";
import { defineComponent, useContext } from "@nuxtjs/composition-api";
import { parseISO, formatDistanceToNow } from "date-fns";
import { GroupDataExport } from "~/types/api-types/group";
export default defineComponent({
@ -29,11 +29,13 @@ export default defineComponent({
},
},
setup() {
const { i18n } = useContext();
const headers = [
{ text: "Export", value: "name" },
{ text: "File Name", value: "filename" },
{ text: "Size", value: "size" },
{ text: "Link Expires", value: "expires" },
{ text: i18n.t("export.export"), value: "name" },
{ text: i18n.t("export.file-name"), value: "filename" },
{ text: i18n.t("export.size"), value: "size" },
{ text: i18n.t("export.link-expires"), value: "expires" },
{ text: "", value: "actions" },
];

View file

@ -1,42 +1,24 @@
<template>
<div>
<div class="d-md-flex" style="gap: 10px">
<v-select v-model="inputDay" :items="MEAL_DAY_OPTIONS" label="Rule Day"></v-select>
<v-select v-model="inputEntryType" :items="MEAL_TYPE_OPTIONS" label="Meal Type"></v-select>
<v-select v-model="inputDay" :items="MEAL_DAY_OPTIONS" :label="$t('meal-plan.rule-day')"></v-select>
<v-select v-model="inputEntryType" :items="MEAL_TYPE_OPTIONS" :label="$t('meal-plan.meal-type')"></v-select>
</div>
<RecipeOrganizerSelector v-model="inputCategories" selector-type="categories" />
<RecipeOrganizerSelector v-model="inputTags" selector-type="tags" />
<!-- TODO Make this localizable -->
{{ inputDay === "unset" ? "This rule will apply to all days" : `This rule applies on ${inputDay}s` }}
{{ inputEntryType === "unset" ? "for all meal types" : ` and for ${inputEntryType} meal types` }}
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from "@nuxtjs/composition-api";
import { defineComponent, computed, useContext } from "@nuxtjs/composition-api";
import RecipeOrganizerSelector from "~/components/Domain/Recipe/RecipeOrganizerSelector.vue";
import { RecipeTag, RecipeCategory } from "~/types/api-types/group";
const MEAL_TYPE_OPTIONS = [
{ text: "Breakfast", value: "breakfast" },
{ text: "Lunch", value: "lunch" },
{ text: "Dinner", value: "dinner" },
{ text: "Side", value: "side" },
{ text: "Any", value: "unset" },
];
const MEAL_DAY_OPTIONS = [
{ text: "Monday", value: "monday" },
{ text: "Tuesday", value: "tuesday" },
{ text: "Wednesday", value: "wednesday" },
{ text: "Thursday", value: "thursday" },
{ text: "Friday", value: "friday" },
{ text: "Sunday", value: "saturday" },
{ text: "Sunday", value: "sunday" },
{ text: "Any", value: "unset" },
];
export default defineComponent({
components: {
RecipeOrganizerSelector,
@ -64,6 +46,27 @@ export default defineComponent({
},
},
setup(props, context) {
const { i18n } = useContext();
const MEAL_TYPE_OPTIONS = [
{ text: i18n.t("meal-plan.breakfast"), value: "breakfast" },
{ text: i18n.t("meal-plan.lunch"), value: "lunch" },
{ text: i18n.t("meal-plan.dinner"), value: "dinner" },
{ text: i18n.t("meal-plan.side"), value: "side" },
{ text: i18n.t("meal-plan.type-any"), value: "unset" },
];
const MEAL_DAY_OPTIONS = [
{ text: i18n.t("general.monday"), value: "monday" },
{ text: i18n.t("general.tuesday"), value: "tuesday" },
{ text: i18n.t("general.wednesday"), value: "wednesday" },
{ text: i18n.t("general.thursday"), value: "thursday" },
{ text: i18n.t("general.friday"), value: "friday" },
{ text: i18n.t("general.saturday"), value: "saturday" },
{ text: i18n.t("general.sunday"), value: "sunday" },
{ text: i18n.t("meal-plan.day-any"), value: "unset" },
];
const inputDay = computed({
get: () => {
return props.day;

View file

@ -1,9 +1,9 @@
<template>
<div>
<v-card-text>
<v-switch v-model="webhookCopy.enabled" label="Enabled"></v-switch>
<v-text-field v-model="webhookCopy.name" label="Webhook Name"></v-text-field>
<v-text-field v-model="webhookCopy.url" label="Webhook Url"></v-text-field>
<v-switch v-model="webhookCopy.enabled" label="$t('general.enabled')"></v-switch>
<v-text-field v-model="webhookCopy.name" label="$t('settings.webhooks.webhook-name')"></v-text-field>
<v-text-field v-model="webhookCopy.url" label="$t('settings.webhooks.webhook-url')"></v-text-field>
<v-time-picker v-model="scheduledTime" class="elevation-2" ampm-in-title format="ampm"></v-time-picker>
</v-card-text>
<v-card-actions class="py-0 justify-end">
@ -77,7 +77,7 @@ export default defineComponent({
},
head() {
return {
title: this.$tc("settings.webhooks.webhooks"),
title: this.$t("settings.webhooks.webhooks") as string,
};
},
});

View file

@ -36,7 +36,7 @@
<v-icon> {{ $globals.icons.lock }} </v-icon>
</v-btn>
</template>
<span> Locked by Owner </span>
<span> {{ $t("recipe.locked-by-owner") }} </span>
</v-tooltip>
<ClientOnly>

View file

@ -169,7 +169,7 @@ export default defineComponent({
async function addAsset() {
if (!validFields()) {
alert.error("Error Submitting Form");
alert.error(i18n.t("asset.error-submitting-form") as string);
return;
}

View file

@ -97,7 +97,7 @@
v-if="!$vuetify.breakpoint.xsOnly"
:items="[
{
title: 'Toggle View',
title: $t('general.toggle-view'),
icon: $globals.icons.eye,
event: 'toggle-dense-view',
},

View file

@ -19,7 +19,7 @@
outlined
auto-grow
rows="2"
placeholder="Join the Conversation"
:placeholder="$t('recipe.join-the-conversation')"
>
</v-textarea>
</div>
@ -45,7 +45,7 @@
x-small
@click="deleteComment(comment.id)"
>
Delete
{{ $t("general.delete") }}
</v-btn>
</v-card-actions>
</v-card>

View file

@ -15,7 +15,7 @@
</BaseDialog>
<BaseDialog
v-model="mealplannerDialog"
title="Add Recipe to Mealplan"
:title="$t('recipe.add-recipe-to-mealplan')"
color="primary"
:icon="$globals.icons.calendar"
@confirm="addRecipeToPlan()"
@ -32,8 +32,8 @@
<template #activator="{ on, attrs }">
<v-text-field
v-model="newMealdate"
label="Date"
hint="MM/DD/YYYY format"
:label="$t('general.date')"
:hint="$t('recipe.date-format-hint')"
persistent-hint
:prepend-icon="$globals.icons.calendar"
v-bind="attrs"
@ -43,10 +43,15 @@
</template>
<v-date-picker v-model="newMealdate" no-title @input="pickerMenu = false"></v-date-picker>
</v-menu>
<v-select v-model="newMealType" :return-object="false" :items="planTypeOptions" label="Entry Type"></v-select>
<v-select
v-model="newMealType"
:return-object="false"
:items="planTypeOptions"
:label="$t('recipe.entry-type')"
></v-select>
</v-card-text>
</BaseDialog>
<BaseDialog v-model="shoppingListDialog" title="Add to List" :icon="$globals.icons.cartCheck">
<BaseDialog v-model="shoppingListDialog" :title="$t('recipe.add-to-list')" :icon="$globals.icons.cartCheck">
<v-card-text>
<v-card
v-for="list in shoppingLists"
@ -213,13 +218,13 @@ export default defineComponent({
event: "download",
},
mealplanner: {
title: "Add to Plan",
title: i18n.t("recipe.add-to-plan") as string,
icon: $globals.icons.calendar,
color: undefined,
event: "mealplanner",
},
shoppingList: {
title: "Add to List",
title: i18n.t("recipe.add-to-list") as string,
icon: $globals.icons.cartCheck,
color: undefined,
event: "shoppingList",
@ -268,7 +273,7 @@ export default defineComponent({
async function addRecipeToList(listId: string) {
const { data } = await api.shopping.lists.addRecipe(listId, props.recipeId);
if (data) {
alert.success("Recipe added to list");
alert.success(i18n.t("recipe.recipe-added-to-list") as string);
state.shoppingListDialog = false;
}
}
@ -300,9 +305,9 @@ export default defineComponent({
});
if (response?.status === 201) {
alert.success("Recipe added to mealplan");
alert.success(i18n.t("recipe.recipe-added-to-mealplan") as string);
} else {
alert.error("Failed to add recipe to mealplan");
alert.error(i18n.t("recipe.failed-to-add-recipe-to-mealplan") as string);
}
}

View file

@ -42,7 +42,7 @@
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, ref } from "@nuxtjs/composition-api";
import { computed, defineComponent, onMounted, ref, useContext } from "@nuxtjs/composition-api";
import RecipeChip from "./RecipeChips.vue";
import { Recipe } from "~/types/api-types/recipe";
import { useUserApi } from "~/composables/api";
@ -93,6 +93,8 @@ export default defineComponent({
},
},
setup(props, context) {
const { i18n } = useContext();
function setValue(value: Recipe[]) {
context.emit(INPUT_EVENT, value);
}
@ -101,27 +103,27 @@ export default defineComponent({
const hdrs = [];
if (props.showHeaders.id) {
hdrs.push({ text: "Id", value: "id" });
hdrs.push({ text: i18n.t("general.id"), value: "id" });
}
if (props.showHeaders.owner) {
hdrs.push({ text: "Owner", value: "userId", align: "center" });
hdrs.push({ text: i18n.t("general.owner"), value: "userId", align: "center" });
}
hdrs.push({ text: "Name", value: "name" });
hdrs.push({ text: i18n.t("general.name"), value: "name" });
if (props.showHeaders.categories) {
hdrs.push({ text: "Categories", value: "recipeCategory" });
hdrs.push({ text: i18n.t("recipe.categories"), value: "recipeCategory" });
}
if (props.showHeaders.tags) {
hdrs.push({ text: "Tags", value: "tags" });
hdrs.push({ text: i18n.t("tag.tags"), value: "tags" });
}
if (props.showHeaders.tools) {
hdrs.push({ text: "Tools", value: "tools" });
hdrs.push({ text: i18n.t("tool.tools"), value: "tools" });
}
if (props.showHeaders.recipeYield) {
hdrs.push({ text: "Yield", value: "recipeYield" });
hdrs.push({ text: i18n.t("recipe.yield"), value: "recipeYield" });
}
if (props.showHeaders.dateAdded) {
hdrs.push({ text: "Date Added", value: "dateAdded" });
hdrs.push({ text: i18n.t("general.date-added"), value: "dateAdded" });
}
return hdrs;
@ -148,7 +150,7 @@ export default defineComponent({
return members.value.find((m) => m.id === id)?.username;
}
return "None";
return i18n.t("general.none");
}
return { setValue, headers, members, getMember };

View file

@ -36,7 +36,7 @@
</v-list-item-title>
<BaseButton small color="info" @click="util.action">
<template #icon> {{ $globals.icons.robot }}</template>
Run
{{ $t("general.run") }}
</BaseButton>
</v-list-item>
<v-divider :key="`divider-${idx}`" class="mx-2"></v-divider>

View file

@ -16,7 +16,7 @@
class="mx-2 arrow-search"
hide-details
single-line
placeholder="Search"
:placeholder="$t('search.search')"
:prepend-inner-icon="$globals.icons.search"
></v-text-field>

View file

@ -1,6 +1,6 @@
<template>
<div>
<BaseDialog v-model="dialog" title="Share Recipe" :icon="$globals.icons.link">
<BaseDialog v-model="dialog" :title="$t('recipe-share.share-recipe')" :icon="$globals.icons.link">
<v-card-text>
<v-menu
v-model="datePickerMenu"
@ -13,8 +13,8 @@
<template #activator="{ on, attrs }">
<v-text-field
v-model="expirationDate"
label="Expiration Date"
hint="Default 30 Days"
:label="$t('recipe-share.expiration-date')"
:hint="$t('recipe-share.default-30-days')"
persistent-hint
:prepend-icon="$globals.icons.calendar"
v-bind="attrs"
@ -35,7 +35,7 @@
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title> Expires At </v-list-item-title>
<v-list-item-title> {{ $t("recipe-share.expires-at") }} </v-list-item-title>
<v-list-item-subtitle>{{ $d(new Date(token.expiresAt), "long") }}</v-list-item-subtitle>
</v-list-item-content>
@ -152,7 +152,7 @@ export default defineComponent({
async function copyTokenLink(token: string) {
await copy(getTokenLink(token));
alert.success("Recipe link copied to clipboard");
alert.success(i18n.t("recipe-share.recipe-link-copied-message") as string);
}
async function shareRecipe(token: string) {

View file

@ -6,7 +6,7 @@
dense
hide-details
class="mx-1 mt-3 mb-4"
placeholder="Section Title"
:placeholder="$t('recipe.section-title')"
style="max-width: 500px"
>
</v-text-field>
@ -19,7 +19,7 @@
dense
class="mx-1"
type="number"
placeholder="Quantity"
:placeholder="$t('recipe.quantity')"
@keypress="quantityFilter"
>
<v-icon v-if="$listeners && $listeners.delete" slot="prepend" class="mr-n1 handle">
@ -38,12 +38,12 @@
:items="units || []"
item-text="name"
class="mx-1"
placeholder="Choose Unit"
:placeholder="$t('recipe.choose-unit')"
clearable
@keyup.enter="handleUnitEnter"
>
<template #no-data>
<div class="caption text-center pb-2">Press Enter to Create</div>
<div class="caption text-center pb-2">{{ $t("recipe.press-enter-to-create") }}</div>
</template>
<template #append-item>
<div class="px-2">
@ -65,12 +65,12 @@
:items="foods || []"
item-text="name"
class="mx-1 py-0"
placeholder="Choose Food"
:placeholder="$t('recipe.choose-food')"
clearable
@keyup.enter="handleFoodEnter"
>
<template #no-data>
<div class="caption text-center pb-2">Press Enter to Create</div>
<div class="caption text-center pb-2">{{ $t("recipe.press-enter-to-create") }}</div>
</template>
<template #append-item>
<div class="px-2">
@ -81,7 +81,7 @@
</v-col>
<v-col sm="12" md="" cols="12">
<div class="d-flex">
<v-text-field v-model="value.note" hide-details dense solo class="mx-1" placeholder="Notes">
<v-text-field v-model="value.note" hide-details dense solo class="mx-1" :placeholder="$t('recipe.notes')">
<v-icon v-if="disableAmount && $listeners && $listeners.delete" slot="prepend" class="mr-n1 handle">
{{ $globals.icons.arrowUpDown }}
</v-icon>
@ -93,12 +93,12 @@
:buttons="[
{
icon: $globals.icons.delete,
text: 'Delete',
text: $t('general.delete'),
event: 'delete',
},
{
icon: $globals.icons.dotsVertical,
text: 'Menu',
text: $t('general.menu'),
event: 'open',
children: contextMenuOptions,
},
@ -110,14 +110,16 @@
</div>
</v-col>
</v-row>
<p v-if="showOriginalText" class="text-caption">Original Text: {{ value.originalText }}</p>
<p v-if="showOriginalText" class="text-caption">
{{ $t("recipe.original-text-with-value", { originalText: value.originalText }) }}
</p>
<v-divider v-if="!$vuetify.breakpoint.mdAndUp" class="my-4"></v-divider>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, reactive, ref, toRefs } from "@nuxtjs/composition-api";
import { computed, defineComponent, reactive, ref, toRefs, useContext } from "@nuxtjs/composition-api";
import { useFoodStore, useFoodData, useUnitStore, useUnitData } from "~/composables/store";
import { validators } from "~/composables/use-validators";
import { RecipeIngredient } from "~/types/api-types/recipe";
@ -134,6 +136,8 @@ export default defineComponent({
},
},
setup(props) {
const { i18n } = useContext();
// ==================================================
// Foods
const foodStore = useFoodStore();
@ -199,7 +203,7 @@ export default defineComponent({
const contextMenuOptions = computed(() => {
const options = [
{
text: "Toggle Section",
text: i18n.t("recipe.toggle-section") as string,
event: "toggle-section",
},
];
@ -214,7 +218,7 @@ export default defineComponent({
if (props.value.originalText) {
options.push({
text: "See Original Text",
text: i18n.t("recipe.see-original-text") as string,
event: "toggle-original",
});
}

View file

@ -7,7 +7,7 @@
<v-icon large left>
{{ $globals.icons.link }}
</v-icon>
<v-toolbar-title class="headline"> Ingredient Linker </v-toolbar-title>
<v-toolbar-title class="headline"> {{ $t("recipe.ingredient-linker") }} </v-toolbar-title>
<v-spacer></v-spacer>
</v-app-bar>
@ -29,7 +29,7 @@
</v-checkbox>
<template v-if="usedIngredients.length > 0">
<h4 class="py-3 ml-1">Linked to other step</h4>
<h4 class="py-3 ml-1">{{ $t("recipe.linked-to-other-step") }}</h4>
<v-checkbox
v-for="ing in usedIngredients"
:key="ing.referenceId"
@ -51,7 +51,7 @@
<v-spacer></v-spacer>
<BaseButton color="info" @click="autoSetReferences">
<template #icon> {{ $globals.icons.robot }}</template>
Auto
{{ $t("recipe.auto") }}
</BaseButton>
<BaseButton save @click="setIngredientIds"> </BaseButton>
</v-card-actions>
@ -64,7 +64,7 @@
<template #icon>
{{ $globals.icons.primary }}
</template>
Cook Mode
{{ $t("recipe.cook-mode") }}
</BaseButton>
</div>
<draggable
@ -289,7 +289,7 @@ export default defineComponent({
},
setup(props, context) {
const { req } = useContext();
const { i18n, req } = useContext();
const BASE_URL = detectServerBaseUrl(req);
console.log("Base URL", BASE_URL);
@ -305,15 +305,15 @@ export default defineComponent({
const actionEvents = [
{
text: "Toggle Section",
text: i18n.t("recipe.toggle-section") as string,
event: "toggle-section",
},
{
text: "Link Ingredients",
text: i18n.t("recipe.link-ingredients") as string,
event: "link-ingredients",
},
{
text: "Merge Above",
text: i18n.t("recipe.merge-above") as string,
event: "merge-above",
},
];

View file

@ -23,7 +23,7 @@
:rules="[rules.required]"
autofocus
></v-text-field>
<v-checkbox v-if="itemType === Organizer.Tool" v-model="onHand" label="On Hand"></v-checkbox>
<v-checkbox v-if="itemType === Organizer.Tool" v-model="onHand" :label="$t('tool.on-hand')"></v-checkbox>
</v-card-text>
<v-card-actions>
<BaseButton cancel @click="dialog = false" />
@ -37,7 +37,7 @@
</template>
<script lang="ts">
import { computed, defineComponent, reactive, toRefs, watch } from "@nuxtjs/composition-api";
import { computed, defineComponent, reactive, toRefs, useContext, watch } from "@nuxtjs/composition-api";
import { useUserApi } from "~/composables/api";
import { useCategoryStore, useTagStore, useToolStore } from "~/composables/store";
import { RecipeOrganizer, Organizer } from "~/types/recipe/organizers";
@ -64,6 +64,8 @@ export default defineComponent({
},
},
setup(props, context) {
const { i18n } = useContext();
const state = reactive({
name: "",
onHand: false,
@ -102,27 +104,27 @@ export default defineComponent({
switch (props.itemType) {
case Organizer.Tag:
return {
title: "Create a Tag",
label: "Tag Name",
title: i18n.t("tag.create-a-tag"),
label: i18n.t("tag.tag-name"),
api: userApi.tags,
};
case Organizer.Tool:
return {
title: "Create a Tool",
label: "Tool Name",
title: i18n.t("tool.create-a-tool"),
label: i18n.t("tool.tool-name"),
api: userApi.tools,
};
default:
return {
title: "Create a Category",
label: "Category Name",
title: i18n.t("category.create-a-category"),
label: i18n.t("category.category-name"),
api: userApi.categories,
};
}
});
const rules = {
required: (val: string) => !!val || "A Name is Required",
required: (val: string) => !!val || (i18n.t("general.a-name-is-required") as string),
};
async function select() {

View file

@ -5,12 +5,12 @@
<BaseDialog
v-if="deleteTarget"
v-model="deleteDialog"
:title="`Delete ${deleteTarget.name}`"
:title="$t('general.delete-with-name', { name: deleteTarget.name })"
color="error"
:icon="$globals.icons.alertCircle"
@confirm="deleteOne()"
>
<v-card-text> Are you sure you want to delete this {{ deleteTarget.name }}? </v-card-text>
<v-card-text> {{ $t("general.confirm-delete-generic-with-name", { name: deleteTarget.name }) }} </v-card-text>
</BaseDialog>
<v-app-bar color="transparent" flat class="mt-n1 rounded align-center">
<v-icon large left>
@ -84,7 +84,9 @@ export default defineComponent({
if (!props.items) return byLetter;
props.items.sort((a, b) => a.name.localeCompare(b.name)).forEach((item) => {
props.items
.sort((a, b) => a.name.localeCompare(b.name))
.forEach((item) => {
const letter = item.name[0].toUpperCase();
if (!byLetter[letter]) {
byLetter[letter] = [];

View file

@ -103,7 +103,7 @@ export default defineComponent({
case Organizer.Tool:
return i18n.t("tool.tools");
default:
return "Organizer";
return i18n.t("general.organizer");
}
});

View file

@ -24,7 +24,7 @@
</v-icon>
</v-btn>
</template>
<span> Reset Scale </span>
<span> {{ $t("recipe.reset-scale") }} </span>
</v-tooltip>
</div>
</v-card-text>
@ -38,12 +38,12 @@
:buttons="[
{
icon: $globals.icons.minus,
text: 'Decrease Scale by 1',
text: $t('recipe.decrease-scale-label'),
event: 'decrement',
},
{
icon: $globals.icons.createAlt,
text: 'Increase Scale by 1',
text: $t('recipe.increase-scale-label'),
event: 'increment',
},
]"

View file

@ -57,12 +57,12 @@ export default defineComponent({
landscapeView: i18n.t("recipe.landscape-view-coming-soon"),
disableComments: i18n.t("recipe.disable-comments"),
disableAmount: i18n.t("recipe.disable-amount"),
locked: "Locked",
locked: i18n.t("recipe.locked"),
};
return {
labels,
}
};
},
});
</script>

View file

@ -28,15 +28,15 @@
</v-chip>
</template>
<template #append-outer>
<BaseDialog v-model="createDialog" title="Create New Tool" @submit="actions.createOne()">
<BaseDialog v-model="createDialog" :title="$t('tool.create-new-tool')" @submit="actions.createOne()">
<template #activator>
<v-btn icon @click="createDialog = true">
<v-icon> {{ $globals.icons.create }}</v-icon>
</v-btn>
</template>
<v-card-text>
<v-text-field v-model="workingToolData.name" label="Tool Name"></v-text-field>
<v-checkbox v-model="workingToolData.onHand" label="Show as On Hand (Checked)"></v-checkbox>
<v-text-field v-model="workingToolData.name" :label="$t('tool.tool-name')"></v-text-field>
<v-checkbox v-model="workingToolData.onHand" :label="$t('tool.on-hand-checkbox-label')"></v-checkbox>
</v-card-text>
</BaseDialog>
</template>

View file

@ -52,7 +52,7 @@
</template>
<script lang="ts">
import { defineComponent, computed, ref } from "@nuxtjs/composition-api";
import { defineComponent, computed, ref, useContext } from "@nuxtjs/composition-api";
import ShoppingListItemEditor from "./ShoppingListItemEditor.vue";
import MultiPurposeLabel from "./MultiPurposeLabel.vue";
import { ShoppingListItemCreate } from "~/types/api-types/group";
@ -65,21 +65,6 @@ interface actions {
event: string;
}
const contextMenu: actions[] = [
{
text: "Edit",
event: "edit",
},
{
text: "Delete",
event: "delete",
},
{
text: "Transfer",
event: "transfer",
},
];
export default defineComponent({
components: { ShoppingListItemEditor, MultiPurposeLabel },
props: {
@ -101,6 +86,23 @@ export default defineComponent({
},
},
setup(props, context) {
const { i18n } = useContext();
const contextMenu: actions[] = [
{
text: i18n.t("general.edit") as string,
event: "edit",
},
{
text: i18n.t("general.delete") as string,
event: "delete",
},
{
text: i18n.t("general.transfer") as string,
event: "transfer",
},
];
const listItem = computed({
get: () => {
return props.value;

View file

@ -7,26 +7,37 @@
v-model="listItem.food"
:items="foods"
:item-id.sync="listItem.foodId"
label="Food"
:label="$t('shopping-list.food')"
:icon="$globals.icons.foods"
/>
<InputLabelType
v-model="listItem.unit"
:items="units"
:item-id.sync="listItem.unitId"
label="Units"
:label="$t('general.units')"
:icon="$globals.icons.units"
/>
</div>
<div class="d-md-flex align-center" style="gap: 20px">
<v-textarea v-model="listItem.note" hide-details label="Note" rows="1" auto-grow></v-textarea>
<v-textarea
v-model="listItem.note"
hide-details
:label="$t('shopping-list.note')"
rows="1"
auto-grow
></v-textarea>
</div>
<div class="d-flex align-end" style="gap: 20px">
<div>
<InputQuantity v-model="listItem.quantity" />
</div>
<div style="max-width: 300px" class="mt-3 mr-auto">
<InputLabelType v-model="listItem.label" :items="labels" :item-id.sync="listItem.labelId" label="Label" />
<InputLabelType
v-model="listItem.label"
:items="labels"
:item-id.sync="listItem.labelId"
:label="$t('shopping-list.label')"
/>
</div>
<v-menu
@ -43,8 +54,7 @@
</template>
<v-card max-width="350px" class="left-warning-border">
<v-card-text>
This item is linked to one or more recipe. Adjusting the units or foods will yield unexpected results
when adding or removing the recipe from this list.
{{ $t("shopping-list.linked-item-warning") }}
</v-card-text>
</v-card>
</v-menu>
@ -66,7 +76,7 @@
},
{
icon: $globals.icons.foods,
text: 'Toggle Food',
text: $t('shopping-list.toggle-food'),
event: 'toggle-foods',
},
{

View file

@ -30,7 +30,8 @@
"new-asset": "New Asset",
"pdf": "PDF",
"recipe": "Recipe",
"show-assets": "Show Assets"
"show-assets": "Show Assets",
"error-submitting-form": "Error Submitting Form"
},
"category": {
"categories": "Categories",
@ -41,7 +42,9 @@
"category-filter": "Category Filter",
"category-update-failed": "Category update failed",
"category-updated": "Category updated",
"uncategorized-count": "Uncategorized {count}"
"uncategorized-count": "Uncategorized {count}",
"create-a-category": "Create a Category",
"category-name": "Category Name"
},
"events": {
"apprise-url": "Apprise URL",
@ -134,7 +137,20 @@
"foods": "Foods",
"units": "Units",
"back": "Back",
"next": "Next"
"next": "Next",
"toggle-view": "Toggle View",
"date": "Date",
"id": "Id",
"owner": "Owner",
"date-added": "Date Added",
"none": "None",
"run": "Run",
"menu": "Menu",
"a-name-is-required": "A Name is Required",
"delete-with-name": "Delete {name}",
"confirm-delete-generic-with-name": "Are you sure you want to delete this {name}?",
"organizer": "Organizer",
"transfer": "Transfer"
},
"group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
@ -186,7 +202,14 @@
"quick-week": "Quick Week",
"side": "Side",
"sides": "Sides",
"start-date": "Start Date"
"start-date": "Start Date",
"rule-day": "Rule Day",
"meal-type": "Meal Type",
"breakfast": "Breakfast",
"lunch": "Lunch",
"dinner": "Dinner",
"type-any": "Any",
"day-any": "Any"
},
"migration": {
"chowdown": {
@ -292,7 +315,36 @@
"title": "Title",
"total-time": "Total Time",
"unable-to-delete-recipe": "Unable to Delete Recipe",
"no-recipe": "No Recipe"
"no-recipe": "No Recipe",
"locked-by-owner": "Locked by Owner",
"join-the-conversation": "Join the Conversation",
"add-recipe-to-mealplan": "Add Recipe to Mealplan",
"entry-type": "Entry Type",
"date-format-hint": "MM/DD/YYYY format",
"add-to-list": "Add to List",
"add-to-plan": "Add to Plan",
"recipe-added-to-list": "Recipe added to list",
"recipe-added-to-mealplan": "Recipe added to mealplan",
"failed-to-add-recipe-to-mealplan": "Failed to add recipe to mealplan",
"yield": "Yield",
"quantity": "Quantity",
"choose-unit": "Choose Unit",
"press-enter-to-create": "Press Enter to Create",
"choose-food": "Choose Food",
"notes": "Notes",
"toggle-section": "Toggle Section",
"see-original-text": "See Original Text",
"original-text-with-value": "Original Text: {originalText}",
"ingredient-linker": "Ingredient Linker",
"linked-to-other-step": "Linked to other step",
"auto": "Auto",
"cook-mode": "Cook Mode",
"link-ingredients": "Link Ingredients",
"merge-above": "Merge Above",
"reset-scale": "Reset Scale",
"decrease-scale-label": "Decrease Scale by 1",
"increase-scale-label": "Increase Scale by 1",
"locked": "Locked"
},
"search": {
"advanced-search": "Advanced Search",
@ -399,7 +451,8 @@
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "The URLs listed below will receive webhooks containing the recipe data for the meal plan on it's scheduled day. Currently Webhooks will execute at",
"webhook-url": "Webhook URL",
"webhooks-caps": "WEBHOOKS",
"webhooks": "Webhooks"
"webhooks": "Webhooks",
"webhook-name": "Webhook Name"
}
},
"shopping-list": {
@ -410,7 +463,12 @@
"new-list": "New List",
"quantity": "Quantity: {0}",
"shopping-list": "Shopping List",
"shopping-lists": "Shopping Lists"
"shopping-lists": "Shopping Lists",
"food": "Food",
"note": "Note",
"label": "Label",
"linked-item-warning": "This item is linked to one or more recipe. Adjusting the units or foods will yield unexpected results when adding or removing the recipe from this list.",
"toggle-food": "Toggle Food"
},
"sidebar": {
"all-recipes": "All Recipes",
@ -446,10 +504,17 @@
"tag-update-failed": "Tag update failed",
"tag-updated": "Tag updated",
"tags": "Tags",
"untagged-count": "Untagged {count}"
"untagged-count": "Untagged {count}",
"create-a-tag": "Create a Tag",
"tag-name": "Tag Name"
},
"tool": {
"tools": "Tools"
"tools": "Tools",
"on-hand": "On Hand",
"create-a-tool": "Create a Tool",
"tool-name": "Tool Name",
"create-new-tool": "Create New Tool",
"on-hand-checkbox-label": "Show as On Hand (Checked)"
},
"user": {
"admin": "Admin",
@ -546,5 +611,18 @@
"group-name-is-taken": "Group name is taken",
"username-is-taken": "Username is taken",
"email-is-taken": "Email is taken"
},
"export": {
"export": "Export",
"file-name": "File Name",
"size": "Size",
"link-expires": "Link Expires"
},
"recipe-share": {
"expiration-date": "Expiration Date",
"share-recipe": "Share Recipe",
"default-30-days": "Default 30 Days",
"expires-at": "Expires At",
"recipe-link-copied-message": "Recipe link copied to clipboard"
}
}