Compare commits

...

76 Commits

Author SHA1 Message Date
mealie-commit-bot[bot]
70b5865dce chore: bump version to v3.9.2 2026-01-02 19:40:19 +00:00
Michael Genson
3be7056f2c fix: Exception handling for recipe image reprocessing (#6822) 2026-01-02 13:17:07 -06:00
Arsène Reymond
1b57310535 fix: allow start attribute on ordered lists (SafeMarkdown) (#6820)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2026-01-02 19:02:11 +00:00
Patrick Lehner (he/him)
2b15d9a515 fix: Make quantity input in shopping list item editor visually consistent with other inputs (#6810) 2026-01-02 12:51:53 -06:00
Hayden
adc9c0b970 chore(l10n): New Crowdin updates (#6804) 2025-12-31 00:36:01 +00:00
renovate[bot]
bec1708891 chore(deps): update node.js to b52a8d1 (#6800)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-30 10:33:30 -06:00
Patrick Lehner (he/him)
66bb545454 dev: Small .gitignore fixes (#6796) 2025-12-30 15:42:38 +00:00
renovate[bot]
c1ebf04291 chore(deps): update node.js to 33587cf (#6795)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-30 05:20:34 +00:00
mealie-commit-bot[bot]
3166060644 chore: bump version to v3.9.1 2025-12-30 01:56:10 +00:00
Michael Genson
bde7cf6f9d fix: Revert extended touch on shopping list (#6794) 2025-12-29 19:24:03 -06:00
Hayden
8ea9bb19f6 chore(l10n): New Crowdin updates (#6792) 2025-12-29 17:11:05 -06:00
mealie-commit-bot[bot]
6d0f9b0d35 chore: bump version to v3.9.0 2025-12-29 20:46:19 +00:00
Hayden
df541c1924 chore(l10n): New Crowdin updates (#6789) 2025-12-29 14:34:07 -06:00
Hayden
9af92ff397 chore(l10n): New Crowdin updates (#6788) 2025-12-28 21:54:38 +00:00
renovate[bot]
554d50b079 chore(deps): update dependency coverage to v7.13.1 (#6787) 2025-12-28 15:43:41 -06:00
github-actions[bot]
a00e2e8b68 chore(l10n): Crowdin locale sync (#6786)
Co-authored-by: GitHub Action <action@github.com>
2025-12-28 00:02:46 -06:00
renovate[bot]
4fcfbaff3b fix(deps): update dependency fastapi to v0.128.0 (#6783)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 12:56:10 -06:00
renovate[bot]
7792f0504d fix(deps): update dependency fastapi to v0.127.1 (#6779) 2025-12-26 12:13:31 -06:00
Hayden
3ca6c67f25 chore(l10n): New Crowdin updates (#6778) 2025-12-25 14:30:16 +00:00
Arsène Reymond
2eb0fdc863 fix: resize pwa maskable icons (#6777) 2025-12-24 18:20:10 +00:00
Hayden
192d48c4a6 chore(l10n): New Crowdin updates (#6776) 2025-12-24 09:42:26 -06:00
Michael Genson
e4f38685b3 fix(deps): Bump various frontend deps (#6774) 2025-12-23 17:12:52 -06:00
Michael Genson
d02023e12c fix: Only fetch recipes with a household id (#6773) 2025-12-23 16:48:27 -06:00
Michael Genson
64d8786d8f fix: Improve recipe bulk deletion (#6772) 2025-12-23 12:31:53 -06:00
Michael Genson
0971d59fa6 fix: Can't remove organizer (#6771) 2025-12-23 11:32:14 -06:00
Hayden
9b799ca441 chore(l10n): New Crowdin updates (#6768) 2025-12-22 23:36:50 -06:00
Michael Genson
193b823688 feat: Replace number inputs with new v-number-input compontent (#6767) 2025-12-22 18:45:52 -06:00
Michael Genson
c64c2d25e7 fix: Add resiliency to LDAP admin filter (#6766) 2025-12-22 15:37:15 -06:00
onemustpersist
8b4111d68f fix: Imported API keys not working on a new server #6477 (#6496)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
Co-authored-by: Michael Genson <genson.michael@gmail.com>
2025-12-22 12:08:44 -06:00
miah
9d601ea4b5 feat: Animate shopping list and increase touch target (#6569)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-22 11:55:25 -06:00
gitolicious
95e1bbce2b feat: persist selected dates in meal planner (#6512)
Co-authored-by: Michael Genson <genson.michael@gmail.com>
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-22 11:10:23 -06:00
Aurelien
7b32508201 fix: the add_pagination_to_query now always returns the correct count (#6505)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-22 10:39:35 -06:00
Hayden
6ed85d72d7 chore(l10n): New Crowdin updates (#6765) 2025-12-22 15:59:19 +00:00
github-actions[bot]
cd2a522f25 chore(auto): Update pre-commit hooks (#6760)
Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
2025-12-22 15:48:53 +00:00
Arsène Reymond
6bd6400aba fix: add loader for create backup button (#6763) 2025-12-22 09:38:44 -06:00
Michael Genson
8b92d6ee04 fix: Backup selection doesn't work sometimes (#6759) 2025-12-21 20:56:51 -06:00
Michael Genson
7cc2ed75e5 fix: Consistant Shopping List Recipe State (#6758) 2025-12-21 20:27:00 -06:00
renovate[bot]
cb7f46c0ad fix(deps): update dependency fastapi to v0.127.0 (#6756)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-21 13:52:34 -06:00
renovate[bot]
cb12aedf72 fix(deps): update dependency openai to v2.14.0 (#6745) 2025-12-21 12:48:06 -06:00
renovate[bot]
8c35a26ab0 chore(deps): update dependency mkdocs-material to v9.7.1 (#6741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-21 18:05:50 +00:00
github-actions[bot]
b2d0f46dd2 chore(l10n): Crowdin locale sync (#6754)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-21 11:53:25 -06:00
Hayden
2c4b7bf611 chore(l10n): New Crowdin updates (#6748)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-21 11:52:47 -06:00
renovate[bot]
38e542bcd3 fix(deps): update dependency python-multipart to v0.0.21 (#6737)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-21 11:52:15 -06:00
renovate[bot]
e53452c19c fix(deps): update dependency uvicorn to v0.40.0 (#6757)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-21 11:35:48 -06:00
Hayden
13213476d8 docs: add --no-project flags to skip mealie installation (#6755) 2025-12-20 21:23:11 -06:00
Hayden
9925450173 docs: isolate docs dependencies to avoid python-ldap build (#6753) 2025-12-20 20:45:59 -06:00
Hayden
efb9dae681 docs: add GitHub Actions workflow for docs deployment (#6752) 2025-12-20 20:26:14 -06:00
renovate[bot]
cee93d2a87 fix(deps): update dependency fastapi to v0.126.0 (#6750)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-20 16:06:03 -06:00
Arsène Reymond
0d4a8654c1 fix: PWA maskable android icons & enctype shared_target (#6731)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-19 05:06:27 +00:00
Hayden
95b1be07bb chore(l10n): New Crowdin updates (#6744)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-19 04:53:09 +00:00
mealie-commit-bot[bot]
a6fc98fc82 chore: bump version to v3.8.0 2025-12-19 01:37:16 +00:00
Michael Genson
6f03010f6c fix: Security Patches (#6743) 2025-12-18 22:54:16 +00:00
renovate[bot]
69397c91b8 fix(deps): update dependency openai to v2.13.0 (#6726)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-18 21:45:42 +00:00
Hayden
798792dcdc chore(l10n): New Crowdin updates (#6736)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-18 15:32:22 -06:00
renovate[bot]
cc32dd9fa6 chore(deps): update dependency ruff to v0.14.10 (#6742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-18 15:32:00 -06:00
renovate[bot]
0c64eb29f9 fix(deps): update dependency fastapi to v0.125.0 (#6740)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-17 17:37:43 -06:00
renovate[bot]
8baa5cc315 chore(deps): update dependency pre-commit to v4.5.1 (#6734)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-17 00:07:49 +00:00
Hayden
6f3a5c6c8f chore(l10n): New Crowdin updates (#6733) 2025-12-16 17:42:13 +00:00
Hayden
778078590b chore(l10n): New Crowdin updates (#6729) 2025-12-15 22:54:37 -06:00
github-actions[bot]
53c82e5491 chore(auto): Update pre-commit hooks (#6724) 2025-12-15 18:16:59 +00:00
Hayden
fef114d97f chore(l10n): New Crowdin updates (#6725) 2025-12-15 08:55:48 -06:00
Hayden
e80cbfad7f chore(l10n): New Crowdin updates (#6722)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-14 23:31:48 -06:00
renovate[bot]
99527ce738 chore(deps): update dependency mypy to v1.19.1 (#6723)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-14 23:31:34 -06:00
Arsène Reymond
08ccced734 fix: localize text validators message (#6719) 2025-12-14 09:56:11 -06:00
github-actions[bot]
43c2c9552b chore(l10n): Crowdin locale sync (#6716)
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
2025-12-13 22:10:43 -06:00
Hayden
db5741c7ee chore(l10n): New Crowdin updates (#6710) 2025-12-13 22:10:23 -06:00
renovate[bot]
a1e394cf36 fix(deps): update dependency tzdata to v2025.3 (#6713) 2025-12-13 15:21:42 -06:00
Michael Genson
bdbef1ab9e fix: More lenient postgres override parsing (#6712) 2025-12-13 14:21:54 -06:00
Michael Genson
e5276f6c20 fix: Put tooltips behind app bar (#6711) 2025-12-13 10:56:18 -06:00
Michael Genson
20a6e71b31 feat: Optionally include URL when importing via HTML/JSON (#6709) 2025-12-12 23:20:26 -06:00
Michael Genson
24c111af7b chore: Miscellaneous cleanup (#6708) 2025-12-12 22:48:49 -06:00
davidschinkel
ab4559319e fix: Improved bulk deletion by reducing refreshs (#6634)
Co-authored-by: David Schinkel <david@zollsoft.de>
Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
2025-12-13 04:08:04 +00:00
Michael Genson
2f8625ac44 fix: Disable submit on enter when editing timeline events (#6707) 2025-12-12 21:56:36 -06:00
Hayden
dd146afa57 chore(l10n): New Crowdin updates (#6706) 2025-12-12 21:20:34 -06:00
renovate[bot]
91d15f671e fix(deps): update dependency authlib to v1.6.6 (#6700)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-13 01:54:41 +00:00
renovate[bot]
7008b13246 fix(deps): update dependency fastapi to v0.124.4 (#6702)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 19:43:35 -06:00
150 changed files with 2801 additions and 2375 deletions

View File

@@ -13,6 +13,7 @@ RUN echo "export PROMPT_COMMAND='history -a'" >> /home/vscode/.bashrc \
&& chown vscode:vscode -R /home/vscode/
RUN npm install -g @go-task/cli
RUN npm install -g json-schema-to-typescript
# Install additional OS packages
RUN apt-get update \

View File

@@ -23,7 +23,6 @@
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"mypy.runUsingActiveInterpreter": true
},
@@ -34,6 +33,7 @@
"ms-python.pylint",
"ms-python.python",
"ms-python.vscode-pylance",
"streetsidesoftware.code-spell-checker-cspell-bundled-dictionaries",
"Vue.volar"
]
}
@@ -41,6 +41,7 @@
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [
3000,
8000, // used by mkdocs
9000,
9091, // used by docker production
24678 // used by nuxt when hot-reloading using polling

50
.github/workflows/docs.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Deploy Documentation
on:
push:
branches: [mealie-next]
paths:
- 'docs/**'
- '.github/workflows/docs.yml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync --only-group docs --no-install-project
- name: Build docs
run: uv run --no-project mkdocs build -d site
working-directory: docs
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/site
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

6
.gitignore vendored
View File

@@ -20,6 +20,7 @@ dev/data/backups/*
dev/data/debug/*
dev/data/img/*
dev/data/migration/*
dev/data/templates/*
dev/data/users/*
dev/data/groups/*
@@ -69,8 +70,11 @@ wheels/
.installed.cfg
*.egg
# packaged output - temporarily written here by `uv build`
/mealie-*
# frontend copied into Python module for packaging purposes
/mealie/frontend/
/mealie/frontend
# PyInstaller
# Usually these files are written by a python script from a template

View File

@@ -12,7 +12,7 @@ repos:
exclude: ^tests/data/
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.14.8
rev: v0.14.10
hooks:
- id: ruff
- id: ruff-format

View File

@@ -1,7 +1,7 @@
###############################################
# Frontend Build
###############################################
FROM node:24@sha256:20988bcdc6dc76690023eb2505dd273bdeefddcd0bde4bfd1efe4ebf8707f747 \
FROM node:24@sha256:b52a8d1206132b36d60e51e413d9a81336e8a0206d3b648cabd6d5a49c4c0f54 \
AS frontend-builder
WORKDIR /frontend

View File

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

View File

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

View File

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

View File

File diff suppressed because one or more lines are too long

View File

@@ -32,8 +32,8 @@ theme:
markdown_extensions:
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
- def_list
- pymdownx.highlight
- pymdownx.superfences

View File

@@ -14,7 +14,7 @@
<BaseButton
download
size="small"
:download-url="`/api/recipes/bulk-actions/export/download?path=${item.path}`"
:download-url="`/api/recipes/bulk-actions/export/${item.id}/download`"
/>
</template>
</v-data-table>

View File

@@ -144,11 +144,13 @@
variant="underlined"
@update:model-value="setFieldValue(field, index, $event)"
/>
<v-text-field
<v-number-input
v-else-if="field.type === 'number'"
:model-value="field.value"
type="number"
variant="underlined"
control-variant="stacked"
inset
:precision="null"
@update:model-value="setFieldValue(field, index, $event)"
/>
<v-checkbox

View File

@@ -126,7 +126,7 @@ withDefaults(defineProps<Props>(), {
canEdit: false,
});
const emit = defineEmits(["print", "input", "delete", "close", "edit"]);
const emit = defineEmits(["print", "input", "save", "delete", "close", "json", "edit"]);
const deleteDialog = ref(false);

View File

@@ -6,7 +6,7 @@
:title="$t('recipe.add-to-list')"
:icon="$globals.icons.cartCheck"
>
<v-container v-if="!shoppingListChoices.length">
<v-container v-if="!filteredShoppingLists.length">
<BasePageTitle>
<template #title>
{{ $t('shopping-list.no-shopping-lists-found') }}
@@ -15,7 +15,7 @@
</v-container>
<v-card-text>
<v-card
v-for="list in shoppingListChoices"
v-for="list in filteredShoppingLists"
:key="list.id"
hover
class="my-2 left-border"
@@ -222,6 +222,10 @@ const api = useUserApi();
const preferences = useShoppingListPreferences();
const ready = ref(false);
// Capture values at initialization to avoid reactive updates
const currentHouseholdSlug = ref("");
const filteredShoppingLists = ref<ShoppingListSummary[]>([]);
const state = reactive({
shoppingListDialog: true,
shoppingListIngredientDialog: false,
@@ -230,31 +234,25 @@ const state = reactive({
const { shoppingListDialog, shoppingListIngredientDialog, shoppingListShowAllToggled: _shoppingListShowAllToggled } = toRefs(state);
const userHousehold = computed(() => {
return $auth.user.value?.householdSlug || "";
});
const shoppingListChoices = computed(() => {
return props.shoppingLists.filter(list => preferences.value.viewAllLists || list.userId === $auth.user.value?.id);
});
const recipeIngredientSections = ref<ShoppingListRecipeIngredientSection[]>([]);
const selectedShoppingList = ref<ShoppingListSummary | null>(null);
watchEffect(
() => {
if (shoppingListChoices.value.length === 1 && !state.shoppingListShowAllToggled) {
selectedShoppingList.value = shoppingListChoices.value[0];
watch(dialog, (newVal, oldVal) => {
if (newVal && !oldVal) {
currentHouseholdSlug.value = $auth.user.value?.householdSlug || "";
filteredShoppingLists.value = props.shoppingLists.filter(
list => preferences.value.viewAllLists || list.userId === $auth.user.value?.id,
);
if (filteredShoppingLists.value.length === 1 && !state.shoppingListShowAllToggled) {
selectedShoppingList.value = filteredShoppingLists.value[0];
openShoppingListIngredientDialog(selectedShoppingList.value);
}
else {
ready.value = true;
}
},
);
watch(dialog, (val) => {
if (!val) {
}
else if (!newVal) {
initState();
}
});
@@ -274,22 +272,26 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
continue;
}
if (!(recipe.id && recipe.name && recipe.recipeIngredient)) {
const { data } = await api.recipes.getOne(recipe.slug);
// Create a local copy to avoid mutating props
let recipeData = { ...recipe };
if (!(recipeData.id && recipeData.name && recipeData.recipeIngredient)) {
const { data } = await api.recipes.getOne(recipeData.slug);
if (!data?.recipeIngredient?.length) {
continue;
}
recipe.id = data.id || "";
recipe.name = data.name || "";
recipe.recipeIngredient = data.recipeIngredient;
recipeData = {
...recipeData,
id: data.id || "",
name: data.name || "",
recipeIngredient: data.recipeIngredient,
};
}
else if (!recipe.recipeIngredient.length) {
else if (!recipeData.recipeIngredient.length) {
continue;
}
const shoppingListIngredients: ShoppingListIngredient[] = [];
function flattenRecipeIngredients(ing: RecipeIngredient, parentTitle = ""): ShoppingListIngredient[] {
const householdsWithFood = ing.food?.householdsWithIngredientFood || [];
if (ing.referencedRecipe) {
// Recursively flatten all ingredients in the referenced recipe
return (ing.referencedRecipe.recipeIngredient ?? []).flatMap((subIng) => {
@@ -303,8 +305,9 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
}
else {
// Regular ingredient
const householdsWithFood = ing.food?.householdsWithIngredientFood || [];
return [{
checked: !householdsWithFood.includes(userHousehold.value),
checked: !householdsWithFood.includes(currentHouseholdSlug.value),
ingredient: {
...ing,
title: ing.title || parentTitle,
@@ -313,7 +316,7 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
}
}
recipe.recipeIngredient.forEach((ing) => {
recipeData.recipeIngredient.forEach((ing) => {
const flattened = flattenRecipeIngredients(ing, "");
shoppingListIngredients.push(...flattened);
});
@@ -343,7 +346,7 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
// Store the on-hand ingredients for later
const householdsWithFood = (ing.ingredient?.food?.householdsWithIngredientFood || []);
if (householdsWithFood.includes(userHousehold.value)) {
if (householdsWithFood.includes(currentHouseholdSlug.value)) {
onHandIngs.push(ing);
return sections;
}
@@ -357,9 +360,9 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
shoppingListIngredientSections[shoppingListIngredientSections.length - 1].ingredients.push(...onHandIngs);
recipeSectionMap.set(recipe.slug, {
recipeId: recipe.id,
recipeName: recipe.name,
recipeScale: recipe.scale,
recipeId: recipeData.id,
recipeName: recipeData.name,
recipeScale: recipeData.scale,
ingredientSections: shoppingListIngredientSections,
});
}

View File

@@ -101,4 +101,14 @@ const { store: tags } = isOwnGroup.value ? useTagStore() : usePublicTagStore(gro
const { store: tools } = isOwnGroup.value ? useToolStore() : usePublicToolStore(groupSlug.value);
const { store: foods } = isOwnGroup.value ? useFoodStore() : usePublicFoodStore(groupSlug.value);
const { store: households } = isOwnGroup.value ? useHouseholdStore() : usePublicHouseholdStore(groupSlug.value);
watch(
households,
() => {
// if exactly one household exists, then we shouldn't be filtering by household
if (households.value.length == 1) {
selectedHouseholds.value = [];
}
},
);
</script>

View File

@@ -22,12 +22,15 @@
cols="12"
class="flex-grow-0 flex-shrink-0"
>
<v-text-field
<v-number-input
v-model="model.quantity"
variant="solo"
:precision="null"
:min="0"
hide-details
control-variant="stacked"
inset
density="compact"
type="number"
:placeholder="$t('recipe.quantity')"
@keypress="quantityFilter"
>
@@ -38,7 +41,7 @@
{{ $globals.icons.arrowUpDown }}
</v-icon>
</template>
</v-text-field>
</v-number-input>
</v-col>
<v-col
v-if="!state.isRecipe"

View File

@@ -10,14 +10,17 @@
v-for="(item, key, index) in modelValue"
:key="index"
>
<v-text-field
density="compact"
<v-number-input
:model-value="modelValue[key]"
:label="labels[key].label"
:suffix="labels[key].suffix"
type="number"
density="compact"
autocomplete="off"
variant="underlined"
control-variant="stacked"
inset
:precision="null"
:min="0"
@update:model-value="updateValue(key, $event)"
/>
</div>

View File

@@ -48,8 +48,7 @@
</template>
<script setup lang="ts">
import type { IngredientFood, RecipeCategory, RecipeTag } from "~/lib/api/types/recipe";
import type { RecipeTool } from "~/lib/api/types/admin";
import type { IngredientFood, RecipeCategory, RecipeTag, RecipeTool } from "~/lib/api/types/recipe";
import { Organizer, type RecipeOrganizer } from "~/lib/api/types/non-generated";
import type { HouseholdSummary } from "~/lib/api/types/household";
import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store";
@@ -166,6 +165,15 @@ const items = computed<any[]>(() => {
return list;
});
function removeByIndex(index: number) {
if (selected.value === undefined) {
return;
}
const newSelected = selected.value.filter((_, i) => i !== index);
selected.value = [...newSelected];
}
function appendCreated(item: any) {
if (selected.value === undefined) {
return;

View File

@@ -47,7 +47,7 @@ const props = withDefaults(defineProps<Props>(), {
landscape: false,
});
defineEmits(["save", "delete"]);
defineEmits(["save", "delete", "print"]);
const { recipeImage } = useStaticRoutes();
const { imageKey, setMode, toggleEditMode, isEditMode } = usePageState(props.recipe.slug);

View File

@@ -11,27 +11,27 @@
<v-container class="ma-0 pa-0">
<v-row>
<v-col cols="3">
<v-text-field
:model-value="recipeServings"
type="number"
<v-number-input
:model-value="recipe.recipeServings"
:min="0"
hide-spin-buttons
:precision="null"
density="compact"
:label="$t('recipe.servings')"
variant="underlined"
@update:model-value="validateInput($event, 'recipeServings')"
control-variant="hidden"
@update:model-value="recipe.recipeServings = $event"
/>
</v-col>
<v-col cols="3">
<v-text-field
:model-value="recipeYieldQuantity"
type="number"
<v-number-input
:model-value="recipe.recipeYieldQuantity"
:min="0"
hide-spin-buttons
:precision="null"
density="compact"
:label="$t('recipe.yield')"
variant="underlined"
@update:model-value="validateInput($event, 'recipeYieldQuantity')"
control-variant="hidden"
@update:model-value="recipe.recipeYieldQuantity = $event"
/>
</v-col>
<v-col cols="6">
@@ -85,37 +85,4 @@ import type { NoUndefinedField } from "~/lib/api/types/non-generated";
import type { Recipe } from "~/lib/api/types/recipe";
const recipe = defineModel<NoUndefinedField<Recipe>>({ required: true });
const recipeServings = computed<number>({
get() {
return recipe.value.recipeServings;
},
set(val) {
validateInput(val.toString(), "recipeServings");
},
});
const recipeYieldQuantity = computed<number>({
get() {
return recipe.value.recipeYieldQuantity;
},
set(val) {
validateInput(val.toString(), "recipeYieldQuantity");
},
});
function validateInput(value: string | null, property: "recipeServings" | "recipeYieldQuantity") {
if (!value) {
recipe.value[property] = 0;
return;
}
const number = parseFloat(value.replace(/[^0-9.]/g, ""));
if (isNaN(number) || number <= 0) {
recipe.value[property] = 0;
return;
}
recipe.value[property] = number;
}
</script>

View File

@@ -65,13 +65,13 @@
</v-card-title>
<v-card-text class="mt-n5">
<div class="mt-4 d-flex align-center">
<v-text-field
<v-number-input
:model-value="yieldQuantity"
type="number"
:precision="null"
:min="0"
variant="underlined"
hide-spin-buttons
@update:model-value="recalculateScale(parseFloat($event) || 0)"
control-variant="hidden"
@update:model-value="recalculateScale($event || 0)"
/>
<v-tooltip
location="end"

View File

@@ -5,6 +5,7 @@
:title="$t('recipe.edit-timeline-event')"
:icon="$globals.icons.edit"
can-submit
disable-submit-on-enter
:submit-text="$t('general.save')"
@submit="submitEdit"
>

View File

@@ -15,7 +15,10 @@
density="compact"
class="mt-0 flex-shrink-0"
color="null"
@change="$emit('checked', listItem)"
@click="() => {
listItem.checked = !listItem.checked
$emit('checked', listItem)
}"
/>
<div
class="ml-2 text-truncate"

View File

@@ -4,7 +4,16 @@
<v-card-text class="pb-3 pt-1">
<div class="d-md-flex align-center mb-2" style="gap: 20px">
<div>
<InputQuantity v-model="listItem.quantity" />
<v-number-input
v-model="listItem.quantity"
hide-details
:label="$t('form.quantity-label-abbreviated')"
:min="0"
:precision="null"
control-variant="stacked"
inset
style="width: 100px;"
/>
</div>
<InputLabelType
v-model="listItem.unit"
@@ -158,6 +167,15 @@ export default defineNuxtComponent({
},
});
watch(
() => props.modelValue.quantity,
() => {
if (!props.modelValue.quantity) {
listItem.value.quantity = 0;
}
},
);
watch(
() => props.modelValue.food,
(newFood) => {

View File

@@ -149,6 +149,6 @@ export default defineNuxtComponent({
<style scoped>
.v-toolbar {
z-index: 1010 !important;
z-index: 2010 !important;
}
</style>

View File

@@ -1,61 +0,0 @@
<template>
<div
class="d-flex align-center"
style="max-width: 60px"
>
<v-text-field
v-model.number="quantity"
hide-details
:label="$t('form.quantity-label-abbreviated')"
:min="min"
:max="max"
type="number"
variant="plain"
density="compact"
style="width: 60px;"
/>
</div>
</template>
<script lang="ts">
export default defineNuxtComponent({
name: "VInputNumber",
props: {
min: {
type: Number,
default: 0,
},
max: {
type: Number,
default: 9999,
},
rules: {
type: Array,
default: () => [],
},
step: {
type: Number,
default: 1,
},
modelValue: {
type: Number,
default: 0,
},
},
emits: ["update:modelValue"],
setup(props, context) {
const quantity = computed({
get: () => {
return Number(props.modelValue);
},
set: (val) => {
context.emit("update:modelValue", val);
},
});
return {
quantity,
};
},
});
</script>

View File

@@ -29,9 +29,9 @@ export default defineNuxtComponent({
"ul", "ol", "li", "dl", "dt", "dd", "abbr", "a", "img", "blockquote", "iframe",
"del", "ins", "table", "thead", "tbody", "tfoot", "tr", "th", "td", "colgroup",
],
ADD_ATTR: [
ALLOWED_ATTR: [
"href", "src", "alt", "height", "width", "class", "allow", "title", "allowfullscreen", "frameborder",
"scrolling", "cite", "datetime", "name", "abbr", "target", "border",
"scrolling", "cite", "datetime", "name", "abbr", "target", "border", "start",
],
});

View File

@@ -0,0 +1,58 @@
import { describe, expect, test, vi } from "vitest";
import { ref } from "vue";
import { useStoreActions } from "./use-actions-factory";
import type { BaseCRUDAPI } from "~/lib/api/base/base-clients";
describe("useStoreActions", () => {
const mockApi = {
getAll: vi.fn(),
createOne: vi.fn(),
updateOne: vi.fn(),
deleteOne: vi.fn(),
} as unknown as BaseCRUDAPI<unknown, unknown, unknown>;
const mockStore = ref([]);
const mockLoading = ref(false);
test("deleteMany calls deleteOne for each ID and refreshes once", async () => {
const actions = useStoreActions("test-store", mockApi, mockStore, mockLoading);
mockApi.deleteOne = vi.fn().mockResolvedValue({ response: { data: {} } });
mockApi.getAll = vi.fn().mockResolvedValue({ data: { items: [] } });
const ids = ["1", "2", "3"];
await actions.deleteMany(ids);
expect(mockApi.deleteOne).toHaveBeenCalledTimes(3);
expect(mockApi.deleteOne).toHaveBeenCalledWith("1");
expect(mockApi.deleteOne).toHaveBeenCalledWith("2");
expect(mockApi.deleteOne).toHaveBeenCalledWith("3");
expect(mockApi.getAll).toHaveBeenCalledTimes(1);
});
test("deleteMany handles empty array", async () => {
const actions = useStoreActions("test-store", mockApi, mockStore, mockLoading);
mockApi.deleteOne = vi.fn();
mockApi.getAll = vi.fn().mockResolvedValue({ data: { items: [] } });
await actions.deleteMany([]);
expect(mockApi.deleteOne).not.toHaveBeenCalled();
expect(mockApi.getAll).toHaveBeenCalledTimes(1);
});
test("deleteMany sets loading state", async () => {
const actions = useStoreActions("test-store", mockApi, mockStore, mockLoading);
mockApi.deleteOne = vi.fn().mockResolvedValue({});
mockApi.getAll = vi.fn().mockResolvedValue({ data: { items: [] } });
const promise = actions.deleteMany(["1"]);
expect(mockLoading.value).toBe(true);
await promise;
expect(mockLoading.value).toBe(false);
});
});

View File

@@ -12,6 +12,7 @@ interface StoreActions<T extends BoundT> extends ReadOnlyStoreActions<T> {
createOne(createData: T): Promise<T | null>;
updateOne(updateData: T): Promise<T | null>;
deleteOne(id: string | number): Promise<T | null>;
deleteMany(ids: (string | number)[]): Promise<void>;
}
/**
@@ -165,11 +166,23 @@ export function useStoreActions<T extends BoundT>(
return response?.data || null;
}
async function deleteMany(ids: (string | number)[]) {
loading.value = true;
for (const id of ids) {
await api.deleteOne(id);
}
if (allRef?.value) {
await refresh();
}
loading.value = false;
}
return {
getAll,
refresh,
createOne,
updateOne,
deleteOne,
deleteMany,
};
}

View File

@@ -27,7 +27,7 @@ export const LOCALES = [
{
name: "Türkçe (Turkish)",
value: "tr-TR",
progress: 36,
progress: 39,
dir: "ltr",
},
{
@@ -69,7 +69,7 @@ export const LOCALES = [
{
name: "Português (Portuguese)",
value: "pt-PT",
progress: 40,
progress: 39,
dir: "ltr",
},
{
@@ -81,7 +81,7 @@ export const LOCALES = [
{
name: "Polski (Polish)",
value: "pl-PL",
progress: 53,
progress: 52,
dir: "ltr",
},
{
@@ -93,13 +93,13 @@ export const LOCALES = [
{
name: "Nederlands (Dutch)",
value: "nl-NL",
progress: 55,
progress: 58,
dir: "ltr",
},
{
name: "Latviešu (Latvian)",
value: "lv-LV",
progress: 36,
progress: 35,
dir: "ltr",
},
{
@@ -111,7 +111,7 @@ export const LOCALES = [
{
name: "한국어 (Korean)",
value: "ko-KR",
progress: 9,
progress: 22,
dir: "ltr",
},
{
@@ -123,13 +123,13 @@ export const LOCALES = [
{
name: "Italiano (Italian)",
value: "it-IT",
progress: 47,
progress: 48,
dir: "ltr",
},
{
name: "Íslenska (Icelandic)",
value: "is-IS",
progress: 44,
progress: 45,
dir: "ltr",
},
{
@@ -147,7 +147,7 @@ export const LOCALES = [
{
name: "עברית (Hebrew)",
value: "he-IL",
progress: 73,
progress: 72,
dir: "rtl",
},
{
@@ -159,7 +159,7 @@ export const LOCALES = [
{
name: "Français (French)",
value: "fr-FR",
progress: 69,
progress: 70,
dir: "ltr",
},
{
@@ -201,13 +201,13 @@ export const LOCALES = [
{
name: "British English",
value: "en-GB",
progress: 44,
progress: 43,
dir: "ltr",
},
{
name: "Ελληνικά (Greek)",
value: "el-GR",
progress: 41,
progress: 42,
dir: "ltr",
},
{
@@ -225,19 +225,19 @@ export const LOCALES = [
{
name: "Čeština (Czech)",
value: "cs-CZ",
progress: 42,
progress: 41,
dir: "ltr",
},
{
name: "Català (Catalan)",
value: "ca-ES",
progress: 38,
progress: 39,
dir: "ltr",
},
{
name: "Български (Bulgarian)",
value: "bg-BG",
progress: 49,
progress: 51,
dir: "ltr",
},
{

View File

@@ -1,12 +1,13 @@
import type { RequestResponse } from "~/lib/api/types/non-generated";
import type { ValidationResponse } from "~/lib/api/types/response";
import { required, email, whitespace, url, minLength, maxLength } from "~/lib/validators";
import { required, email, whitespace, url, urlOptional, minLength, maxLength } from "~/lib/validators";
export const validators = {
required,
email,
whitespace,
url,
urlOptional,
minLength,
maxLength,
};

View File

@@ -4,10 +4,10 @@
"about-mealie": "Meer oor Mealie",
"api-docs": "API Dokumentasie",
"api-port": "API Poort",
"application-mode": "Applikasie modues",
"application-mode": "Applikasie Modus",
"database-type": "Databasis Tipe",
"database-url": "Databasis URL",
"default-group": "Standaard groep",
"default-group": "Standaard Groep",
"default-household": "Default Household",
"demo": "Demonstrasie",
"demo-status": "Demonstrasie Status",
@@ -65,7 +65,7 @@
"something-went-wrong": "Iets het verkeerd geloop!",
"subscribed-events": "Ingetekende Gebeure",
"test-message-sent": "Toets Boodskap Gestuur",
"message-sent": "Message Sent",
"message-sent": "Boodskap Gestuur",
"new-notification": "Nuwe kennisgewing",
"event-notifiers": "Gebeurteniskennisgewers",
"apprise-url-skipped-if-blank": "Apprise URL (oorgeslaan indien leeg)",
@@ -84,7 +84,7 @@
"label-events": "Label Events"
},
"general": {
"add": "Add",
"add": "Voeg by",
"cancel": "Kanselleer",
"clear": "Maak skoon",
"close": "Maak toe",
@@ -134,7 +134,7 @@
"no-recipe-found": "Geen resep gevind nie",
"ok": "OK",
"options": "Opsies:",
"plural-name": "Plural Name",
"plural-name": "Meervoudsnaam",
"print": "Druk",
"print-preferences": "Drukvoorkeure",
"random": "Willekeurig",
@@ -148,23 +148,23 @@
"save": "Stoor",
"settings": "Verstellings",
"share": "Deel",
"show-all": "Show All",
"show-all": "Wys Alles",
"shuffle": "Skommel",
"sort": "Sorteer",
"sort-ascending": "Sort Ascending",
"sort-descending": "Sort Descending",
"sort-ascending": "Sorteer Oplopend",
"sort-descending": "Sorteer Aflopend",
"sort-alphabetically": "Alfabeties",
"status": "Status",
"subject": "Onderwerp",
"submit": "Dien in",
"success-count": "Sukses: {count}",
"sunday": "Sondag",
"system": "System",
"system": "Sisteem",
"templates": "Sjablone:",
"test": "Toets",
"themes": "Temas",
"thursday": "Donderdag",
"title": "Title",
"title": "Titel",
"token": "Token",
"tuesday": "Dinsdag",
"type": "Tipe",
@@ -179,12 +179,12 @@
"units": "Eenhede",
"back": "Terug",
"next": "Volgende",
"start": "Start",
"start": "Begin",
"toggle-view": "Wissel aansig",
"date": "Datum",
"id": "Id",
"owner": "Eienaar",
"change-owner": "Change Owner",
"change-owner": "Verander Eienaar",
"date-added": "Datum bygevoeg",
"none": "Geen",
"run": "Hardloop",
@@ -212,13 +212,13 @@
"upload-file": "Laai dokument op",
"created-on-date": "Geskep op: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes.",
"clipboard-copy-failure": "Failed to copy to the clipboard.",
"confirm-delete-generic-items": "Are you sure you want to delete the following items?",
"organizers": "Organizers",
"clipboard-copy-failure": "Kon nie kopieer na die knipbord toe nie.",
"confirm-delete-generic-items": "Is jy seker jy wil die volgende items verwyder?",
"organizers": "Organiseerders",
"caution": "Caution",
"show-advanced": "Show Advanced",
"add-field": "Add Field",
"date-created": "Date Created",
"date-created": "Datum Geskep",
"date-updated": "Date Updated"
},
"group": {
@@ -343,8 +343,8 @@
"lunch": "Middagete",
"dinner": "Aandete",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"drink": "Drank",
"dessert": "Nagereg",
"type-any": "Enige",
"day-any": "Enige",
"editor": "Editor",
@@ -441,10 +441,11 @@
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Plak jou resepdata in. Elke reël sal as 'n item in 'n lys hanteer word",
"recipe-markup-specification": "Resep formaat spesifikasie",
"recipe-url": "Resep URL",
"recipe-html-or-json": "Recipe HTML or JSON",
"recipe-html-or-json": "Resep HTML of JSON",
"upload-a-recipe": "Laai 'n resep op",
"upload-individual-zip-file": "Laai 'n .zip-lêer op wat vanaf 'n ander Mealie-instansie uitgevoer is.",
"url-form-hint": "Kopieer en plak 'n skakel vanaf jou gunstelingresepwebwerf",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Bekyk opgespoorde data",
"trim-whitespace-description": "Knip voorste en agterste witspasie sowel as leë reëls",
"trim-prefix-description": "Knip die eerste karakter van elke reël af",
@@ -453,7 +454,7 @@
"create-manually": "Skep 'n resep met die hand",
"make-recipe-image": "Maak dit die prentjie vir hierdie resep",
"add-food": "Add Food",
"add-recipe": "Add Recipe"
"add-recipe": "Voeg Resep By"
},
"page": {
"404-page-not-found": "404 Bladsy nie gevind nie",
@@ -520,8 +521,8 @@
"recipe-deleted": "Resep uitgevee",
"recipe-image": "Resep foto",
"recipe-image-updated": "Resep foto is opgedateer",
"delete-image": "Delete Recipe Image",
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
"delete-image": "Verwyder Resep Beeld",
"delete-image-confirmation": "Is jy seker jy wil dié beeld van die resep verwyder?",
"recipe-image-deleted": "Recipe image deleted",
"recipe-name": "Resepnaam",
"recipe-settings": "Resep verstellings",
@@ -555,7 +556,7 @@
"add-to-plan": "Voeg by plan",
"add-to-timeline": "Voeg by tydlyn",
"recipe-added-to-list": "Resep by lys gevoeg",
"recipes-added-to-list": "Recipes added to list",
"recipes-added-to-list": "Resepte toegevoeg tot lys",
"successfully-added-to-list": "Successfully added to list",
"recipe-added-to-mealplan": "Resep is by die maaltydplan gevoeg",
"failed-to-add-recipes-to-list": "Failed to add recipe to list",
@@ -568,7 +569,7 @@
"choose-unit": "Kies 'n eenheid",
"press-enter-to-create": "Druk Enter om te skep",
"choose-food": "Keuse van kos",
"choose-recipe": "Choose Recipe",
"choose-recipe": "Kies Resep",
"notes": "Notas",
"toggle-section": "Wissel afdeling",
"see-original-text": "Sien oorspronklike teks",
@@ -659,7 +660,7 @@
"report-deletion-failed": "Kon nie verslag uitvee nie",
"recipe-debugger": "Resep debugger",
"recipe-debugger-description": "Gryp die URL van die resep wat jy wil debug en plak dit hier. Die URL sal deur die resepskraper geskraap word en die resultate sal vertoon word. As jy nie enige data terugstuur sien nie, word die webwerf wat jy probeer skraap nie deur Mealie of sy skraperbiblioteek ondersteun nie.",
"use-openai": "Use OpenAI",
"use-openai": "Gebruik OpenAI",
"recipe-debugger-use-openai-description": "Use OpenAI to parse the results instead of relying on the scraper library. When creating a recipe via URL, this is done automatically if the scraper library fails, but you may test it manually here.",
"debug": "Debug",
"tree-view": "Boomstruktuur",
@@ -670,8 +671,8 @@
"upload-image": "Laai prent",
"screen-awake": "Hou die skerm aan",
"remove-image": "Verwyder prent",
"nextStep": "Next step",
"recipe-actions": "Recipe Actions",
"nextStep": "Volgende stap",
"recipe-actions": "Resep Aksies",
"parser": {
"ingredient-parser": "Ingredient Parser",
"explanation": "To use the ingredient parser, click the 'Parse All' button to start the process. Once the processed ingredients are available, you can review the items and verify that they were parsed correctly. The model's confidence score is displayed on the right of the item title. This score is an average of all the individual scores and may not always be completely accurate.",
@@ -681,7 +682,7 @@
"brute-parser": "Brute Parser",
"openai-parser": "OpenAI Parser",
"parse-all": "Parse All",
"no-unit": "No unit",
"no-unit": "Geen eenheid",
"missing-unit": "Create missing unit: {unit}",
"missing-food": "Create missing food: {food}",
"this-unit-could-not-be-parsed-automatically": "This unit could not be parsed automatically",
@@ -692,12 +693,12 @@
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
"delete-item": "Delete Item"
"delete-item": "Verwyder Item"
},
"reset-servings-count": "Reset Servings Count",
"not-linked-ingredients": "Additional Ingredients",
"not-linked-ingredients": "Bykomende Bestanddele",
"upload-another-image": "Upload another image",
"upload-images": "Upload images",
"upload-images": "Laai beelde op",
"upload-more-images": "Upload more images",
"set-as-cover-image": "Set as recipe cover image",
"cover-image": "Cover image",
@@ -889,7 +890,7 @@
"oidc-ready": "OIDC Klar",
"oidc-ready-error-text": "Ikke alle OIDC værdier er konfigureret. Dette kan ignoreres hvis du ikke bruger OIDC godkendelse.",
"oidc-ready-success-text": "Krævede OIDC variabler er udfyldt.",
"openai-ready": "OpenAI Ready",
"openai-ready": "OpenAI Gereed",
"openai-ready-error-text": "Not all OpenAI Values are configured. This can be ignored if you are not using OpenAI features.",
"openai-ready-success-text": "Required OpenAI variables are all set."
},
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "تحميل وصفة",
"upload-individual-zip-file": "تحميل مِلَفّ zip فردي تم تصديره من مثيل Malie آخر.",
"url-form-hint": "نسخ ولصق رابط من موقعك المفضل للوصفة",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "عرض البيانات المحللة",
"trim-whitespace-description": "قص المسافات البيضاء البادئة واللاحقة وكذلك الأسطر الفارغة",
"trim-prefix-description": "قص الحرف الأول من كل سطر",
@@ -1427,5 +1428,13 @@
"is-like": "هو مثل",
"is-not-like": "ليس مثل"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Качи рецепта",
"upload-individual-zip-file": "Качи като индивидуален .zip файлов формат от друга инстанция на Mealie.",
"url-form-hint": "Копирай и постави линк от твоя любим сайт за рецепти",
"copy-and-paste-the-source-url-of-your-data-optional": "Копирайте и поставете URL адреса на източника на вашите данни (по избор)",
"view-scraped-data": "Виж събраните данни",
"trim-whitespace-description": "Премахни интервалите в началото и края на текста, също така и празните редове",
"trim-prefix-description": "Премахни първия символ от всеки ред",
@@ -1427,5 +1428,13 @@
"is-like": "е като",
"is-not-like": "не е като"
}
},
"validators": {
"required": "Това поле е задължително",
"invalid-email": "Email адресът трябва да бъде валиден",
"invalid-url": "Линкът трябва да е валиден",
"no-whitespace": "Не са позволени интервали",
"min-length": "Трябва да съдържа поне {min} знака",
"max-length": "Трябва да съдържа най-много {max} знака"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Puja una recepta",
"upload-individual-zip-file": "Puja només un arxiu zip, exportat d'altre Mealie.",
"url-form-hint": "Copia i enganxa l'enllaç del teu lloc web de receptes preferit",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Visualitza les dades recuperades",
"trim-whitespace-description": "Elimina els espais a principi i final; i elimina les línies buides",
"trim-prefix-description": "Elimina el primer caràcter de cada línia",
@@ -1427,5 +1428,13 @@
"is-like": "és com",
"is-not-like": "no és com"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -342,9 +342,9 @@
"breakfast": "Snídaně",
"lunch": "Oběd",
"dinner": "Večeře",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"snack": "Svačina",
"drink": "Nápoje",
"dessert": "Dezerty",
"type-any": "Libovolné",
"day-any": "Libovolný",
"editor": "Editor",
@@ -403,7 +403,7 @@
"title": "Recepty Tandoor"
},
"cookn": {
"description-long": "Mealie can import recipes from DVO Cook'n X3. Export a cookbook or menu in the \"Cook'n\" format, rename the export extension to .zip, then upload the .zip below.",
"description-long": "Mealie může importovat recept z DVO Cook'n X3. Exportujte kuchařku nebo menu ve formátu \"Cook'n\", přejmenujte rozšíření exportu na .zip, poté nahrajte .zip níže.",
"title": "DVO Cook'n X3"
},
"recipe-data-migrations": "Migrace dat receptů",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Nahrát recept",
"upload-individual-zip-file": "Nahrát individuální .zip soubor exportovaný z jiné instance Mealie.",
"url-form-hint": "Zkopírujte a vložte odkaz z vaší oblíbené stránky s recepty",
"copy-and-paste-the-source-url-of-your-data-optional": "Zkopírujte a vložte zdrojovou adresu URL vašich dat (volitelné)",
"view-scraped-data": "Zobrazit scrapovaná data",
"trim-whitespace-description": "Oříznout počáteční a koncové mezery stejně jako prázdné řádky",
"trim-prefix-description": "Oříznout první znak z každé řádky",
@@ -452,8 +453,8 @@
"import-by-url": "Importovat recept podle URL",
"create-manually": "Vytvořit recept ručně",
"make-recipe-image": "Nastavit jako obrázek receptu",
"add-food": "Add Food",
"add-recipe": "Add Recipe"
"add-food": "Přidat jídlo",
"add-recipe": "Přidat recept"
},
"page": {
"404-page-not-found": "404 Stránka nebyla nalezena",
@@ -520,9 +521,9 @@
"recipe-deleted": "Recept smazán",
"recipe-image": "Obrázek receptu",
"recipe-image-updated": "Obrázek receptu aktualizován",
"delete-image": "Delete Recipe Image",
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
"recipe-image-deleted": "Recipe image deleted",
"delete-image": "Smazat recept",
"delete-image-confirmation": "Opravdu chcete smazat tento recept?",
"recipe-image-deleted": "Recept smazán",
"recipe-name": "Název receptu",
"recipe-settings": "Nastavení receptu",
"recipe-update-failed": "Aktualizace receptu se nezdařila",
@@ -568,7 +569,7 @@
"choose-unit": "Vybrat jednotku",
"press-enter-to-create": "Stiskněte enter pro vytvoření",
"choose-food": "Zvolte jídlo",
"choose-recipe": "Choose Recipe",
"choose-recipe": "Vybrat recept",
"notes": "Poznámky",
"toggle-section": "Přidat/odebrat název sekce",
"see-original-text": "Zobrazit původní text",
@@ -596,7 +597,7 @@
"made-this": "Toto jsem uvařil",
"how-did-it-turn-out": "Jak to dopadlo?",
"user-made-this": "{user} udělal toto",
"made-for-recipe": "Made for {recipe}",
"made-for-recipe": "Vytvořeno pro {recipe}",
"added-to-timeline": "Přidáno na časovou osu",
"failed-to-add-to-timeline": "Přidání na časovou osu selhalo",
"failed-to-update-recipe": "Aktualizace receptu selhala",
@@ -636,11 +637,11 @@
"scrape-recipe-suggest-bulk-importer": "Vyzkoušejte hromadný import",
"scrape-recipe-have-raw-html-or-json-data": "Máte surová data HTML nebo JSON?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Můžete importovat přímo ze surových dat",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Webové stránky jsou blokovány?",
"scrape-recipe-try-importing-raw-html-instead": "Zkuste namísto toho importovat raw HTML.",
"import-original-keywords-as-tags": "Importovat původní klíčová slova jako štítky",
"stay-in-edit-mode": "Zůstat v režimu úprav",
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
"parse-recipe-ingredients-after-import": "Po importu analyzovat ingredience receptu",
"import-from-zip": "Importovat ze zipu",
"import-from-zip-description": "Importovat jeden recept, který byl exportován z jiné instance Mealie.",
"import-from-html-or-json": "Importovat z HTML nebo JSON",
@@ -687,12 +688,12 @@
"this-unit-could-not-be-parsed-automatically": "Tuto jednotku nelze analyzovat automaticky",
"this-food-could-not-be-parsed-automatically": "Toto jídlo nelze analyzovat automaticky",
"no-food": "Žádné jídlo",
"review-parsed-ingredients": "Review parsed ingredients",
"confidence-score": "Confidence Score",
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
"delete-item": "Delete Item"
"review-parsed-ingredients": "Zkontrolovat analyzované ingredience",
"confidence-score": "Skóre spolehlivosti",
"ingredient-parser-description": "Vaše suroviny byly úspěšně analyzovány. Prosím zkontrolujte ingredience, o kterých si nejsme jisti.",
"ingredient-parser-final-review-description": "Jakmile budou všechny ingredience zkontrolovány, budete mít ještě jednu šanci zkontrolovat všechny ingredience před použitím změn ve vašem receptu.",
"add-text-as-alias-for-item": "Přidat \"{text}\" jako alias pro {item}",
"delete-item": "Odstranit položku"
},
"reset-servings-count": "Resetovat počet porcí",
"not-linked-ingredients": "Další ingredience",
@@ -701,9 +702,9 @@
"upload-more-images": "Nahrát více obrázků",
"set-as-cover-image": "Nastavit recept jako úvodní obrázek",
"cover-image": "Úvodní obrázek",
"include-linked-recipes": "Include Linked Recipes",
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
"toggle-recipe": "Toggle Recipe"
"include-linked-recipes": "Zahrnout připojené recepty",
"include-linked-recipe-ingredients": "Zahrnout připojené ingredience",
"toggle-recipe": "Přidat/odebrat název sekce"
},
"recipe-finder": {
"recipe-finder": "Vyhledávač receptů",
@@ -741,7 +742,7 @@
"advanced": "Pokročilé",
"auto-search": "Automatické vyhledávání",
"no-results": "Nebyly nalezeny žádné výsledky",
"type-to-search": "Type to search..."
"type-to-search": "Zadejte hledaný výraz..."
},
"settings": {
"add-a-new-theme": "Přidat nový motiv",
@@ -1080,8 +1081,8 @@
"forgot-password": "Zapomenuté heslo",
"forgot-password-text": "Zadejte prosím svou e-mailovou adresu a my vám zašleme odkaz pro obnovení hesla.",
"changes-reflected-immediately": "Změny tohoto uživatele budou okamžitě zohledněny.",
"default-activity": "Default Activity",
"default-activity-hint": "Select which page you'd like to navigate to upon logging in from this device"
"default-activity": "Výchozí aktivita",
"default-activity-hint": "Vyberte stránku, na kterou chcete přejít po přihlášení z tohoto zařízení"
},
"language-dialog": {
"translated": "přeloženo",
@@ -1427,5 +1428,13 @@
"is-like": "je jako",
"is-not-like": "není jako"
}
},
"validators": {
"required": "Toto pole je povinné",
"invalid-email": "E-mail musí být platný",
"invalid-url": "Musí být platná URL adresa",
"no-whitespace": "Prázdný prostor není povolen",
"min-length": "Musí být alespoň {min} znaků",
"max-length": "Musí být nejvíce {max} znaků"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Upload en opskrift",
"upload-individual-zip-file": "Upload en individuel .zip-fil, eksporteret fra en anden Mealie-instans.",
"url-form-hint": "Kopiér og indsæt et link fra din foretrukne opskrifts hjemmeside",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Vis dataudtræk",
"trim-whitespace-description": "Fjern indledende og efterfølgende mellemrum samt blanke linjer",
"trim-prefix-description": "Beskær første tegn fra hver linje",
@@ -1427,5 +1428,13 @@
"is-like": "er ligesom",
"is-not-like": "er ikke som"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -51,7 +51,7 @@
"category": "Kategorie"
},
"events": {
"apprise-url": "Apprise-URL",
"apprise-url": "Apprise URL",
"database": "Datenbank",
"delete-event": "Ereignis löschen",
"event-delete-confirmation": "Bist du dir sicher, dass du dieses Ereignis löschen möchtest?",
@@ -191,7 +191,7 @@
"menu": "Menü",
"a-name-is-required": "Ein Name wird benötigt",
"delete-with-name": "{name} löschen",
"confirm-delete-generic-with-name": "Bist du dir sicher, dass du dies löschen möchtest?",
"confirm-delete-generic-with-name": "Bist du dir sicher, dass du {name} löschen möchtest?",
"confirm-delete-own-admin-account": "Bitte beachte, dass du versuchst, dein eigenes Administrator-Konto zu löschen! Diese Aktion kann nicht rückgängig gemacht werden und wird dein Konto dauerhaft löschen?",
"organizer": "Organisator",
"transfer": "Übertragen",
@@ -342,9 +342,9 @@
"breakfast": "Frühstück",
"lunch": "Mittagessen",
"dinner": "Abendessen",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"snack": "Zwischenmahlzeit ",
"drink": "Getränk",
"dessert": "Nachspeise",
"type-any": "Alle",
"day-any": "Alle",
"editor": "Bearbeiten",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Rezept hochladen",
"upload-individual-zip-file": "Lade eine individuelle .zip-Datei hoch, die von einer anderen Mealie-Instanz exportiert wird.",
"url-form-hint": "Kopiere einen Link von deiner Lieblingsrezept-Website und füge ihn ein",
"copy-and-paste-the-source-url-of-your-data-optional": "Kopieren und fügen Sie die Quell-URL Ihrer Daten ein (optional)",
"view-scraped-data": "Gesammelte Daten anzeigen",
"trim-whitespace-description": "Leerzeichen am Anfang und Ende sowie leere Zeilen entfernen",
"trim-prefix-description": "Erste Zeichen aus jeder Zeile entfernen",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Probiere den Massenimporter aus",
"scrape-recipe-have-raw-html-or-json-data": "Hast du Roh-HTML oder JSON Daten?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Du kannst direkt von Rohdaten importieren",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Die Website wird blockiert?",
"scrape-recipe-try-importing-raw-html-instead": "Versuchen Sie stattdessen das reine HTML zu importieren.",
"import-original-keywords-as-tags": "Importiere ursprüngliche Stichwörter als Schlagwörter",
"stay-in-edit-mode": "Im Bearbeitungsmodus bleiben",
"parse-recipe-ingredients-after-import": "Zutaten nach dem Import parsen",
@@ -1427,5 +1428,13 @@
"is-like": "ist wie",
"is-not-like": "ist nicht wie"
}
},
"validators": {
"required": "Dieses Feld ist erforderlich",
"invalid-email": "E-Mail muss gültig sein",
"invalid-url": "Muss eine gültige URL sein",
"no-whitespace": "Kein Leerzeichen erlaubt",
"min-length": "Muss mindestens {min} Zeichen haben",
"max-length": "Darf mindestens {max} Zeichen haben"
}
}

View File

@@ -334,7 +334,7 @@
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Μόνο συνταγές με αυτές τις κατηγορίες θα χρησιμοποιηθούν στα προγράμματα γευμάτων",
"planner": "Προγραμματισμός",
"quick-week": "Γρήγορη προβολή",
"side": "Πλευρά",
"side": "Συνοδευτικό",
"sides": "Πλευρές",
"start-date": "Ημερομηνία έναρξης",
"rule-day": "Ημέρα/ες Κανόνα",
@@ -362,7 +362,7 @@
"for-type-meal-types": "για γεύματα τύπου {0}",
"meal-plan-rules": "Κανόνες Προγράμματος Γευμάτων",
"new-rule": "Νέος κανόνας",
"meal-plan-rules-description": "Μπορείτε να δημιουργήσετε κανόνες για την αυτόματη επιλογή συνταγών για τα προγράμματα γευμάτων. Αυτοί οι κανόνες χρησιμοποιούνται από το διακομιστή για τον προσδιορισμό της τυχαίας δεξαμενής συνταγών από τις οποίες μπορείτε να επιλέξετε κατά τη δημιουργία προγραμμάτων γευμάτων. Σημειώστε ότι αν οι κανόνες έχουν τους ίδιους περιορισμούς ημέρας/τύπου τότε τα φίλτρα κανόνων θα συγχωνευθούν. Στην πράξη, είναι περιττή η δημιουργία διπλότυπων κανόνων, είναι όμως εφικτή.",
"meal-plan-rules-description": "Μπορείτε να δημιουργήσετε κανόνες για την αυτόματη επιλογή συνταγών για τα προγράμματα γευμάτων. Αυτοί οι κανόνες χρησιμοποιούνται από το διακομιστή για τον προσδιορισμό της δεξαμενής τυχαίας επιλογής συνταγής, κατά τη δημιουργία προγραμμάτων γευμάτων. Σημειώστε ότι αν οι κανόνες έχουν τους ίδιους περιορισμούς ημέρας/τύπου τότε τα φίλτρα κανόνων θα συγχωνευθούν. Στην πράξη, είναι περιττή η δημιουργία διπλότυπων κανόνων, είναι όμως εφικτή.",
"new-rule-description": "Κατά τη δημιουργία ενός νέου κανόνα για ένα σχέδιο γεύματος, μπορείτε να περιορίσετε τον κανόνα ώστε να ισχύει για μια συγκεκριμένη ημέρα της εβδομάδας ή/και ένα συγκεκριμένο τύπο γεύματος. Για να εφαρμόσετε έναν κανόνα σε όλες τις ημέρες ή σε όλους τους τύπους γεύματος μπορείτε να ορίσετε τον κανόνα σε \"Ολα\" που θα τον εφαρμόσει σε όλες τις πιθανές τιμές για την ημέρα ή/και τον τύπο γεύματος.",
"recipe-rules": "Κανόνες Συνταγής",
"applies-to-all-days": "Εφαρμόζεται για όλες τις ημέρες",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Ανεβάστε μια συνταγή",
"upload-individual-zip-file": "Ανεβάστε ένα μεμονωμένο αρχείο .zip που εξάγεται από μια άλλη περίπτωση Mealie.",
"url-form-hint": "Αντιγράψτε και επικολλήστε έναν σύνδεσμο από την αγαπημένη σας ιστοσελίδα συνταγών",
"copy-and-paste-the-source-url-of-your-data-optional": "Αντιγράψτε και επικολλήστε το πηγαίο URL των δεδομένων σας (προαιρετικό)",
"view-scraped-data": "Προβολή Παραγόμενων Δεδομένων",
"trim-whitespace-description": "Περικοπή κενών στην αρχή και το τέλος καθώς και των κενών γραμμών",
"trim-prefix-description": "Περικοπή πρώτου χαρακτήρα από κάθε γραμμή",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Δοκιμάστε τον μαζικό εισαγωγέα συνταγών μας",
"scrape-recipe-have-raw-html-or-json-data": "Εχουν ακατέργαστα δεδομένα HTML ή JSON;",
"scrape-recipe-you-can-import-from-raw-data-directly": "Μπορείτε να κάνετε εισαγωγή απευθείας από ακατέργαστα δεδομένα",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Η ιστοσελίδα μπλοκάρεται;",
"scrape-recipe-try-importing-raw-html-instead": "Δοκιμάστε να εισάγετε τον ακατέργαστο κώδικα HTML.",
"import-original-keywords-as-tags": "Εισαγωγή αρχικών λέξεων-κλειδιών ως ετικέτες",
"stay-in-edit-mode": "Παραμονή σε λειτουργία επεξεργασίας",
"parse-recipe-ingredients-after-import": "Ανάλυση συστατικών συνταγής μετά την εισαγωγή",
@@ -878,9 +879,9 @@
"secure-site": "Ασφαλής Ιστοσελίδα",
"secure-site-error-text": "Παροχή μέσω localhost ή ασφάλεια με https. Το πρόχειρο και τα πρόσθετα API προγράμματος περιήγησης μπορεί να μην λειτουργούν.",
"secure-site-success-text": "Ο ιστότοπος έχει πρόσβαση από localhost ή https",
"server-side-base-url": "Βασική Διεύθυνση URL Πλευράς Διακομιστή",
"server-side-base-url": "Βασική διεύθυνση URL πλευράς διακομιστή",
"server-side-base-url-error-text": "Το `BASE_URL` εξακολουθεί να είναι η προεπιλεγμένη τιμή στο διακομιστή API. Αυτό θα προκαλέσει προβλήματα με τις συνδέσεις ειδοποιήσεων που δημιουργούνται στο διακομιστή για email, κλπ.",
"server-side-base-url-success-text": "Το URL Πλευράς Διακομιστή δεν ταιριάζει με την προεπιλογή",
"server-side-base-url-success-text": "Η διεύθυνση URL πλευράς διακομιστή δεν ταιριάζει με την προεπιλεγμένη",
"ldap-ready": "Ετοιμο για LDAP",
"ldap-ready-error-text": "Δεν έχουν ρυθμιστεί όλες οι τιμές LDAP. Αυτό μπορεί να αγνοηθεί αν δεν χρησιμοποιείτε έλεγχο ταυτότητας LDAP.",
"ldap-ready-success-text": "Ολες οι απαιτούμενες μεταβλητές LDAP έχουν οριστεί.",
@@ -1427,5 +1428,13 @@
"is-like": "είναι όμοιο με",
"is-not-like": "δεν είναι όμοιο με"
}
},
"validators": {
"required": "Αυτό το πεδίο είναι υποχρεωτικό",
"invalid-email": "Το e-mail πρέπει να είναι έγκυρο",
"invalid-url": "Πρέπει να είναι μια έγκυρη διεύθυνση URL",
"no-whitespace": "Δεν επιτρέπονται κενοί χαρακτήρες",
"min-length": "Πρέπει να αποτελείται από τουλάχιστον {min} χαρακτήρες",
"max-length": "Πρέπει να αποτελείται το πολύ από {max} χαρακτήρες"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Upload a Recipe",
"upload-individual-zip-file": "Upload an individual .zip file exported from another Mealie instance.",
"url-form-hint": "Copy and paste a link from your favourite recipe website",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "View Scraped Data",
"trim-whitespace-description": "Trim leading and trailing whitespace as well as blank lines",
"trim-prefix-description": "Trim first character from each line",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Upload a Recipe",
"upload-individual-zip-file": "Upload an individual .zip file exported from another Mealie instance.",
"url-form-hint": "Copy and paste a link from your favorite recipe website",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "View Scraped Data",
"trim-whitespace-description": "Trim leading and trailing whitespace as well as blank lines",
"trim-prefix-description": "Trim first character from each line",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Subir una receta",
"upload-individual-zip-file": "Sube un archivo .zip individual exportado desde otra instancia de Mealie.",
"url-form-hint": "Copia y pega un enlace desde tu página web favorita",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Ver información recuperada",
"trim-whitespace-description": "Eliminar espacios en blanco iniciales y finales así como líneas en blanco",
"trim-prefix-description": "Eliminar el primer carácter de cada línea",
@@ -1427,5 +1428,13 @@
"is-like": "es como",
"is-not-like": "no es como"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Retsepti üleslaadimne",
"upload-individual-zip-file": "Lae üles üksik .zip fail, mis eksporditi teisest Mealie ekspemplarist.",
"url-form-hint": "Kopeeri ja kleebi link oma lemmikust retsepti leheküljest",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Kuva omandatud andmed",
"trim-whitespace-description": "Eemalda alguses ning lõpus olevad tühikud ning tühjad read",
"trim-prefix-description": "Eemalda esimene tähemärk igast reast",
@@ -1427,5 +1428,13 @@
"is-like": "on nagu",
"is-not-like": "ei ole nagu"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -2,7 +2,7 @@
"about": {
"about": "Tietoja",
"about-mealie": "Tietoja Mealiestä",
"api-docs": "API-dokumentit",
"api-docs": "API-dokumentaatio",
"api-port": "API-portti",
"application-mode": "Sovellustila",
"database-type": "Tietokannan tyyppi",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Lataa resepti",
"upload-individual-zip-file": "Tuo yksittäinen pakattu kansio toisesta Mealie instanssista.",
"url-form-hint": "Liitä linkki lempireseptiverkkosivultasi",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Näytä hankittu data",
"trim-whitespace-description": "Leikkaa alussa ja lopussa olevat välilyönnit sekä tyhjät rivit",
"trim-prefix-description": "Poista joka rivin ensimmäinen merkki",
@@ -1427,5 +1428,13 @@
"is-like": "on kuin",
"is-not-like": "ei ole kuin"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -342,8 +342,8 @@
"breakfast": "Petit-déjeuner",
"lunch": "Déjeuner",
"dinner": "Souper",
"snack": "Snack",
"drink": "Drink",
"snack": "Goûter",
"drink": "Boissons",
"dessert": "Dessert",
"type-any": "Tous",
"day-any": "Tous",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Télécharger une recette",
"upload-individual-zip-file": "Chargez un fichier .zip exporté depuis une autre instance Mealie.",
"url-form-hint": "Copiez et collez un lien depuis votre site de recettes favori",
"copy-and-paste-the-source-url-of-your-data-optional": "Copiez et collez l'URL source de vos données (facultatif)",
"view-scraped-data": "Voir les données récupérées",
"trim-whitespace-description": "Ajuster les espaces de début et de fin ainsi que les lignes vides",
"trim-prefix-description": "Couper le premier caractère de chaque ligne",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Essayez limportateur de masse",
"scrape-recipe-have-raw-html-or-json-data": "Vous avez des données brutes en HTML ou JSON ?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Vous pouvez directement importer des données brutes",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Le site web est bloqué ?",
"scrape-recipe-try-importing-raw-html-instead": "Essayez plutôt d'importer le code HTML brut.",
"import-original-keywords-as-tags": "Importer les mots-clés d'origine en tant que tags",
"stay-in-edit-mode": "Rester en mode édition",
"parse-recipe-ingredients-after-import": "Analyser les ingrédients de la recette après l'import",
@@ -1427,5 +1428,13 @@
"is-like": "est comme",
"is-not-like": "n'est pas similaire à"
}
},
"validators": {
"required": "Ce champ est obligatoire",
"invalid-email": "Le-mail doit être valide",
"invalid-url": "Doit être une URL valide",
"no-whitespace": "Aucun espace n'est autorisé",
"min-length": "Doit contenir au moins {min} caractères",
"max-length": "Doit contenir au maximum {max} caractères"
}
}

View File

@@ -342,8 +342,8 @@
"breakfast": "Petit déjeuner",
"lunch": "Dîner",
"dinner": "Souper",
"snack": "Snack",
"drink": "Drink",
"snack": "Goûter",
"drink": "Boissons",
"dessert": "Dessert",
"type-any": "Tous",
"day-any": "Tous",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Télécharger une recette",
"upload-individual-zip-file": "Téléverser un fichier .zip exporté depuis une autre instance Mealie.",
"url-form-hint": "Copiez et collez un lien depuis votre site de recettes favori",
"copy-and-paste-the-source-url-of-your-data-optional": "Copiez et collez l'URL source de vos données (facultatif)",
"view-scraped-data": "Voir les données récupérées",
"trim-whitespace-description": "Ajuster les espaces de début et de fin ainsi que les lignes vides",
"trim-prefix-description": "Couper le premier caractère de chaque ligne",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Essayez limportateur de masse",
"scrape-recipe-have-raw-html-or-json-data": "Vous avez des données brutes en HTML ou JSON ?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Vous pouvez directement importer des données brutes",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Le site web est bloqué ?",
"scrape-recipe-try-importing-raw-html-instead": "Essayez plutôt d'importer le code HTML brut.",
"import-original-keywords-as-tags": "Importer les mots-clés d'origine en tant que tags",
"stay-in-edit-mode": "Rester en mode édition",
"parse-recipe-ingredients-after-import": "Analyser les ingrédients de la recette après l'import",
@@ -1427,5 +1428,13 @@
"is-like": "est similaire à",
"is-not-like": "n'est pas similaire à"
}
},
"validators": {
"required": "Ce champ est obligatoire",
"invalid-email": "Le-mail doit être valide",
"invalid-url": "Doit être une URL valide",
"no-whitespace": "Aucun espace n'est autorisé",
"min-length": "Doit contenir au moins {min} caractères",
"max-length": "Doit contenir au maximum {max} caractères"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Télécharger une recette",
"upload-individual-zip-file": "Chargez un fichier .zip exporté depuis une autre instance Mealie.",
"url-form-hint": "Copiez et collez un lien depuis votre site de recettes favori",
"copy-and-paste-the-source-url-of-your-data-optional": "Copiez et collez l'URL source de vos données (facultatif)",
"view-scraped-data": "Voir les données récupérées",
"trim-whitespace-description": "Ajuster les espaces de début et de fin ainsi que les lignes vides",
"trim-prefix-description": "Couper le premier caractère de chaque ligne",
@@ -1427,5 +1428,13 @@
"is-like": "est comme",
"is-not-like": "n'est pas similaire à"
}
},
"validators": {
"required": "Ce champ est obligatoire",
"invalid-email": "Le-mail doit être valide",
"invalid-url": "Doit être une URL valide",
"no-whitespace": "Aucun espace n'est autorisé",
"min-length": "Doit contenir au moins {min} caractères",
"max-length": "Doit contenir au maximum {max} caractères"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Cargar unha Receita",
"upload-individual-zip-file": "Cargar un ficheiro .zip individual, exportado de outra instancia do Mealie.",
"url-form-hint": "Copie e pegue un link do seu site de receitas favorito",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Ver datos recollidos",
"trim-whitespace-description": "Eliminar os espazos en branco no início e no fin, asi como as liñas en branco",
"trim-prefix-description": "Eliminar o primeiro caracter de cada liña",
@@ -1427,5 +1428,13 @@
"is-like": "é como",
"is-not-like": "non é como"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "העלאת מתכון",
"upload-individual-zip-file": "העלאת קובץ זיפ שיוצא ממילי אחר.",
"url-form-hint": "העתק והדבק קישור מאתר המתכונים המועדף עליך",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "צפייה במידע שנאסף",
"trim-whitespace-description": "הסר רווחים מתחילת / סוף שורה ושורות ריקות",
"trim-prefix-description": "חתוך תו ראשון מכל שורה",
@@ -1427,5 +1428,13 @@
"is-like": "דומה ל-",
"is-not-like": "לא דומה לא-"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Učitaj Recept",
"upload-individual-zip-file": "Prenesite pojedinačnu .zip datoteku koja je izvezena iz druge instance Mealie aplikacije.",
"url-form-hint": "Kopirajte i zalijepite poveznicu s vaše omiljene web stranice za recepte",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Prikaz Prikupljenih Podataka",
"trim-whitespace-description": "Ukloni vodeće i slijedeće praznine, kao i prazne linije",
"trim-prefix-description": "Ukloni prvi znak sa svake linije",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Recept feltöltése",
"upload-individual-zip-file": "Tölts fel egy .zíp archívumot, ami egy másik Mealie példányból lett exportálva.",
"url-form-hint": "Másold be a linket a kedvenc recept weboldaladról",
"copy-and-paste-the-source-url-of-your-data-optional": "Másolja és illessze be az adatok forrás URL-jét (opcionális)",
"view-scraped-data": "Letöltött adat megtekintése",
"trim-whitespace-description": "Vágja le a kezdő és a záró fehérjeleket, valamint az üres sorokat",
"trim-prefix-description": "Minden sor első karakterének levágása",
@@ -1427,5 +1428,13 @@
"is-like": "hasonló",
"is-not-like": "nem hasonló"
}
},
"validators": {
"required": "Ez kötelező mező",
"invalid-email": "E-mail-nek érvényesnek kell lennie",
"invalid-url": "Érvényes URL-nek kell lennie",
"no-whitespace": "Szóközt nem tartalmazhat",
"min-length": "Legalább {min} karakter legyen",
"max-length": "Legfeljebb {max} karakter legyen"
}
}

View File

@@ -69,7 +69,7 @@
"new-notification": "Ný tilkynning",
"event-notifiers": "Viðburðar tilkynningar",
"apprise-url-skipped-if-blank": "Apprise URL (sleppt ef tómt)",
"apprise-url-is-left-intentionally-blank": "Þar sem \"Apprise\" slóðir innihalda yfirleitt viðkvæmar upplýsingar, er þessum reit viljandi skilið eftir auðum við breytingar. Ef þú vilt uppfæra slóðina skaltu slá inn þá nýju hér, annars skaltu skilja reitinn eftir auðan til að halda núverandi slóð.",
"apprise-url-is-left-intentionally-blank": "Þar sem \"Apprise\" slóðir innihalda yfirleitt viðkvæmar upplýsingar, er þessi reitur viljandi skilinn eftir auður. Ef þú vilt uppfæra slóðina skaltu slá inn hana inn hér, annars skaltu skilja reitinn eftir auðan til að halda núverandi slóð.",
"enable-notifier": "Virkja tilkynningar",
"what-events": "Hvaða viðburði ætti þessi tilkynnir að vera áskrifandi að?",
"user-events": "Notenda viðburðir",
@@ -342,9 +342,9 @@
"breakfast": "Morgunverður",
"lunch": "Hádegisverður",
"dinner": "Kvöldverður",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"snack": "Snarl",
"drink": "Drykkur",
"dessert": "Eftirréttur",
"type-any": "Allir",
"day-any": "Alla",
"editor": "Ritill",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Hlaða inn uppskrift",
"upload-individual-zip-file": "Hlaða inn .zip skrá sem er flutt úr annarri Mealie uppsetningu.",
"url-form-hint": "Afritaðu og límdu tengil frá uppáhalds uppskriftar síðunni þinni",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Skoða unnin gögn",
"trim-whitespace-description": "Fjarlægja bil fremst og aftast í texta sem og auðum línum",
"trim-prefix-description": "Eyða fyrsta staf úr hverri línu",
@@ -619,8 +620,8 @@
"create-recipe-description": "Stofna nýja uppskrift frá grunni.",
"create-recipes": "Stofna uppskriftir",
"import-with-zip": "Hlaða inn með .zip",
"create-recipe-from-an-image": "Create Recipe from an Image",
"create-recipe-from-an-image-description": "Create a recipe by uploading an image of it. Mealie will attempt to extract the text from the image using AI and create a recipe from it.",
"create-recipe-from-an-image": "Stofna uppskrift út frá mynd",
"create-recipe-from-an-image-description": "Stofna uppskrift með því hlaða inn myndum af uppskriftartextanum. Mealie mun reyna að vinna texta úr myndunum með gervigreind og stofna nýja uppskrift út frá textanum.",
"crop-and-rotate-the-image": "Sníða og snúa mynd svo bara textinn sé sýnilegur og að myndin snúi rétt.",
"create-from-images": "Stofna uppskrift frá mynd",
"should-translate-description": "Þýða uppskrift á mitt tungumál",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Prófaðu að setja inn margar uppskriftir í einu",
"scrape-recipe-have-raw-html-or-json-data": "Ertu með hrá HTML eða JSON gögn?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Það er hægt að hlaða inn hráum gögnum beint",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Er vefsíðan lokuð?",
"scrape-recipe-try-importing-raw-html-instead": "Reyndu að flytja inn HTML kóðann í staðinn.",
"import-original-keywords-as-tags": "Nota upprunanleg merki",
"stay-in-edit-mode": "Vera í breytingarham",
"parse-recipe-ingredients-after-import": "Greina innhald uppskriftar eftir að búið er að hlaða inn uppskrift",
@@ -660,7 +661,7 @@
"recipe-debugger": "Yfirfara uppskrift",
"recipe-debugger-description": "Náðu í slóðina af uppskriftinni sem þú villt yfirfara og límdu hana hér. Síðan með uppskriftinni verður greind með greiningarverkfærinu og þú munnt sjá niðurstöðuna. Ef þú sérð að engin gögn skila sér þá er slóðin sem þú ert að greina ekki studd af Mealie eða greiningarverkfærinu.",
"use-openai": "Nota OpenAI",
"recipe-debugger-use-openai-description": "Nota OpenAI til að greina í staðinn fyrir að treysta á greiningar verkfærið. Þegar er fengin af slóð þá gerist þetta sjálfkrafa ef almenn greining mistekst, en þú getur prófað þ hér.",
"recipe-debugger-use-openai-description": "Nota OpenAI til að greina í staðinn fyrir að treysta á greiningar verkfærið. Ef greiningar verkfærinu mistekst að greina uppskrift af vefslóð þá gerist það sjálfvirkt að OpenAI greinir uppskriftina en þú getur prófað þetta sjálfur hér.",
"debug": "Villuleit",
"tree-view": "Tré sýn",
"recipe-servings": "Fjöldi skammta",
@@ -852,7 +853,7 @@
"webhooks-caps": "WEBHOOKS",
"webhooks": "Webhook-vefkrækjur",
"webhook-name": "Vefkrækju nafn",
"description": "Vefkrækjur (webhooks) sem skilgreindar eru hér að neðan verða keyrðar þegar máltíð er skilgreind fyrir daginn. Á fyrirfram ákveðnum tíma verða vefkrækjurnar sendar með gögnum úr þeirri uppskrift sem skipulögð er í dag. Athugaðu að keyrsla vefkrækja er ekki alveg nákvæm, þær eru keyrðar á 5 mínútna fresti, þannig að sendingin getur farið fram allt að 5 mínútum fyrir eða eftir áætlaðan tíma."
"description": "Vefkrækjur sem skilgreindar eru hér að neðan verða keyrðar þegar máltíð er skilgreind fyrir daginn. Á fyrirfram ákveðnum tíma verða vefkrækjurnar sendar með gögnum úr þeirri uppskrift sem skipulögð er í dag. Athugaðu að keyrsla vefkrækja er ekki alveg nákvæm, þær eru keyrðar á 5 mínútna fresti, þannig að sendingin getur farið fram allt að 5 mínútum fyrir eða eftir áætlaðan tíma."
},
"bug-report": "Villu skýrsla",
"bug-report-information": "Notaður þessar upplýsingar til að tilkynna um villu. Með því að veita þróunaraðilum upplýsingar um þína uppsetningu hjálpar þú þeim að leysa vandamálið hraðar.",
@@ -1307,7 +1308,7 @@
},
"ingredients-natural-language-processor": "Innihaldsefna málgreining (Natural Language Processor)",
"ingredients-natural-language-processor-explanation": "Mealie notar Conditional Random Fields (CRFs) til að greina og vinna með innihaldsefni. Líkanið sem notað er byggir á gagnasafni með yfir 100.000 innihaldsefnum úr gagnasafni sem New York Times tók saman. Athugaðu að þar sem líkanið er einungis þjálfað á ensku geturðu fengið misjafnar niðurstöður þegar það er notað á önnur tungumál. Þessi síða er ætluð til að prófa líkanið.",
"ingredients-natural-language-processor-explanation-2": "Þetta er ekki fullkomið en skilar almennt góðum niðurstöðum og er góður grunnur fyrir handvirka greiningu innihaldsefna í einstaka reiti. Þú getur einnig notað „Brute“ vinnsluna, sem notar mynsturgreiningu til að bera kennsl á innihaldsefni.",
"ingredients-natural-language-processor-explanation-2": "Þetta er ekki fullkomið en skilar almennt góðum niðurstöðum og er góður grunnur fyrir handvirka greiningu innihaldsefna í einstaka reiti. Þú getur einnig notað „Grófgreinir“ vinnsluna, sem notar mynsturgreiningu til að bera kennsl á innihaldsefni.",
"nlp": "NLP",
"brute": "Grófgreinir",
"openai": "OpenAI",
@@ -1338,7 +1339,7 @@
"household-delete-note": "Heimili með notendum er ekki hægt að eyða"
},
"profile": {
"welcome-user": "👋 Velkomin/Velkominn/Velkomið, {0}!",
"welcome-user": "👋 Halló, {0}",
"description": "Umsjá með prófíl, uppskriftum og hópstillingum.",
"invite-link": "Boð tengill",
"get-invite-link": "Fá boð tengil",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "Þessi reitur er nauðsynlegur",
"invalid-email": "Verður að vera gilt netfang",
"invalid-url": "Verður að vera gild vefslóð",
"no-whitespace": "Engin bil leyfð",
"min-length": "Verður að vera að lágmarki {min} stafir",
"max-length": "Má vera að hámarki {max} stafir"
}
}

View File

@@ -343,7 +343,7 @@
"lunch": "Pranzo",
"dinner": "Cena",
"snack": "Snack",
"drink": "Drink",
"drink": "Bevanda",
"dessert": "Dessert",
"type-any": "Qualsiasi",
"day-any": "Qualsiasi",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Carica una Ricetta",
"upload-individual-zip-file": "Carica un singolo file .zip esportato da un'altra istanza di Mealie.",
"url-form-hint": "Copia e incolla un link dal tuo sito di ricette preferito",
"copy-and-paste-the-source-url-of-your-data-optional": "Copia e incolla lo URL della fonte dei dati (opzionale)",
"view-scraped-data": "Visualizza Dati Ottenuti dallo Scraping",
"trim-whitespace-description": "Tagliare lo spazio bianco iniziale e finale così come le linee vuote",
"trim-prefix-description": "Taglia il primo carattere da ogni riga",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Prova l'importatore massivo",
"scrape-recipe-have-raw-html-or-json-data": "Hai dei dati grezzi HTML o JSON?",
"scrape-recipe-you-can-import-from-raw-data-directly": "È possibile importare direttamente dai dati grezzi",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Il sito viene bloccato?",
"scrape-recipe-try-importing-raw-html-instead": "Prova a importare l'HTML puro.",
"import-original-keywords-as-tags": "Importa parole chiave originali come tag",
"stay-in-edit-mode": "Rimani in modalità Modifica",
"parse-recipe-ingredients-after-import": "Analizza gli ingredienti della ricetta dopo l'importazione",
@@ -1427,5 +1428,13 @@
"is-like": "è simile",
"is-not-like": "non è come"
}
},
"validators": {
"required": "Questo Campo è Obbligatorio",
"invalid-email": "L'Email Deve Essere Valida",
"invalid-url": "Lo URL Deve Essere Valido",
"no-whitespace": "Gli Spazi Non Sono Ammessi",
"min-length": "Deve Essere Almeno {min} Caratteri",
"max-length": "Deve Essere Al Massimo {max} Caratteri"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "レシピのアップロード",
"upload-individual-zip-file": "別のMealieインスタンスからエクスポートされた個別の.zipファイルをアップロードします。",
"url-form-hint": "お気に入りのレシピサイトからリンクをコピーして貼り付け",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "スクライピングされたデータの表示",
"trim-whitespace-description": "先頭と末尾の空白、空白行をトリミングします。",
"trim-prefix-description": "各行の最初の文字をトリミングする",
@@ -1427,5 +1428,13 @@
"is-like": "次のようなものです",
"is-not-like": "というわけではありません"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -69,7 +69,7 @@
"new-notification": "새 알림",
"event-notifiers": "이벤트 알림이",
"apprise-url-skipped-if-blank": "Apprise URL (비워두면 생략합니다)",
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
"apprise-url-is-left-intentionally-blank": "Apprise URL에는 일반적으로 민감한 정보가 포함되므로, 편집 시 이 필드는 의도적으로 비워둡니다. URL을 업데이트하려면 여기에 새 주소를 입력하시고, 현재 URL을 유지하려면 비워두십시오.",
"enable-notifier": "알림 활성화",
"what-events": "이 알리미는 어떤 이벤트를 구독해야 합니까?",
"user-events": "사용자 이벤트",
@@ -81,7 +81,7 @@
"category-events": "카테고리 이벤트",
"when-a-new-user-joins-your-group": "새로운 사용자가 그룹에 가입하면",
"recipe-events": "레시피 이벤트",
"label-events": "Label Events"
"label-events": "라벨 이벤트"
},
"general": {
"add": "추가",
@@ -99,7 +99,7 @@
"delete": "삭제",
"disabled": "비활성화됨",
"download": "다운로드",
"duplicate": "Duplicate",
"duplicate": "복제",
"edit": "편집",
"enabled": "활성화됨",
"exception": "예외",
@@ -184,16 +184,16 @@
"date": "날짜",
"id": "",
"owner": "작성자",
"change-owner": "Change Owner",
"change-owner": "소유자 변경",
"date-added": "추가된 날짜",
"none": "없음",
"run": "실행",
"menu": "메뉴",
"a-name-is-required": "이름은 필수 항목 입니다.",
"delete-with-name": "{name} 삭제",
"confirm-delete-generic-with-name": "Are you sure you want to delete this {name}?",
"confirm-delete-generic-with-name": "{name}을(를) 정말 삭제하시겠습니까?",
"confirm-delete-own-admin-account": "본인의 관리자 계정을 삭제하려고 한다는 점에 유의하세요! 이 작업은 취소할 수 없으며 계정이 영구적으로 삭제됩니다.",
"organizer": "Organizer",
"organizer": "분류자",
"transfer": "전송",
"copy": "복사",
"color": "색상",
@@ -204,7 +204,7 @@
"clipboard-not-supported": "클립보드가 지원되지 않음",
"copied-to-clipboard": "클립보드에 복사되었습니다",
"your-browser-does-not-support-clipboard": "브라우저가 클립보드를 지원하지 않습니다.",
"copied-items-to-clipboard": "No item copied to clipboard|One item copied to clipboard|Copied {count} items to clipboard",
"copied-items-to-clipboard": "클립보드에 항목이 복사되지 않았습니다|클립보드에 항목이 하나 복사되었습니다|클립보드에 {count}개 항목이 복사되었습니다",
"actions": "동작",
"selected-count": "선택됨: {count}",
"export-all": "전체 내보내기",
@@ -214,7 +214,7 @@
"unsaved-changes": "저장되지 않은 변경 사항이 있습니다. 떠나기 전에 저장하시겠습니까? 저장하려면 확인을 클릭하고, 변경 사항을 삭제하려면 취소를 클릭합니다.",
"clipboard-copy-failure": "클립보드에 복사하는 데 실패했습니다.",
"confirm-delete-generic-items": "이 항목을 삭제하시겠습니까?",
"organizers": "Organizers",
"organizers": "분류자",
"caution": "주의",
"show-advanced": "고급 표시",
"add-field": "필드 추가",
@@ -240,59 +240,59 @@
"manage-groups": "그룹 관리",
"user-group": "사용자 그룹",
"user-group-created": "사용자 그룹 생성됨",
"user-group-creation-failed": "User Group Creation Failed",
"user-group-creation-failed": "사용자 그룹 생성 실패",
"settings": {
"keep-my-recipes-private": "Keep My Recipes Private",
"keep-my-recipes-private-description": "Sets your group and all recipes defaults to private. You can always change this later."
"keep-my-recipes-private": "내 레시피를 비공개로 유지",
"keep-my-recipes-private-description": "그룹 및 모든 레시피를 기본적으로 비공개로 설정합니다. 나중에 언제든지 변경할 수 있습니다."
},
"manage-members": "회원 관리",
"manage-members-description": "Manage the permissions of the members in your household. {manage} allows the user to access the data-management page, and {invite} allows the user to generate invitation links for other users. Group owners cannot change their own permissions.",
"manage": "Manage",
"manage-household": "Manage Household",
"manage-members-description": "가구 구성원의 권한을 관리하세요. {manage}는 데이터 관리 페이지에 접근할 수 있게 하며, {invite}는 다른 사용자를 위한 초대 링크를 생성할 수 있게 합니다. 그룹 소유자는 자신의 권한을 변경할 수 없습니다.",
"manage": "관리",
"manage-household": "가구 관리",
"invite": "초대하기",
"looking-to-update-your-profile": "Looking to Update Your Profile?",
"default-recipe-preferences-description": "These are the default settings when a new recipe is created in your group. These can be changed for individual recipes in the recipe settings menu.",
"default-recipe-preferences": "Default Recipe Preferences",
"group-preferences": "Group Preferences",
"looking-to-update-your-profile": "프로필을 업데이트하시겠습니까?",
"default-recipe-preferences-description": "이 설정은 그룹에서 새 레시피를 생성할 때 적용되는 기본값입니다. 레시피 설정 메뉴에서 개별 레시피별로 변경할 수 있습니다.",
"default-recipe-preferences": "기본 레시피 설정",
"group-preferences": "그룹 설정",
"private-group": "비공개 그룹",
"private-group-description": "Setting your group to private will disable all public view options. This overrides any individual public view settings",
"enable-public-access": "Enable Public Access",
"enable-public-access-description": "Make group recipes public by default, and allow visitors to view recipes without logging-in",
"allow-users-outside-of-your-group-to-see-your-recipes": "Allow users outside of your group to see your recipes",
"allow-users-outside-of-your-group-to-see-your-recipes-description": "When enabled you can use a public share link to share specific recipes without authorizing the user. When disabled, you can only share recipes with users who are in your group or with a pre-generated private link",
"show-nutrition-information": "Show nutrition information",
"show-nutrition-information-description": "When enabled the nutrition information will be shown on the recipe if available. If there is no nutrition information available, the nutrition information will not be shown",
"show-recipe-assets": "Show recipe assets",
"show-recipe-assets-description": "When enabled the recipe assets will be shown on the recipe if available",
"default-to-landscape-view": "Default to landscape view",
"default-to-landscape-view-description": "When enabled the recipe header section will be shown in landscape view",
"disable-users-from-commenting-on-recipes": "Disable users from commenting on recipes",
"disable-users-from-commenting-on-recipes-description": "Hides the comment section on the recipe page and disables commenting",
"disable-organizing-recipe-ingredients-by-units-and-food": "Disable organizing recipe ingredients by units and food",
"disable-organizing-recipe-ingredients-by-units-and-food-description": "Hides the Food, Unit, and Amount fields for ingredients and treats ingredients as plain text fields",
"general-preferences": "General Preferences",
"group-recipe-preferences": "Group Recipe Preferences",
"report": "Report",
"report-with-id": "Report ID: {id}",
"private-group-description": "그룹을 비공개로 설정하면 모든 공개 보기 옵션이 비활성화됩니다. 이는 개별 공개 보기 설정을 모두 무효화합니다.",
"enable-public-access": "공개 액세스 활성화",
"enable-public-access-description": "그룹 레시피를 기본적으로 공개 상태로 설정하고, 방문자가 로그인 없이 레시피를 볼 수 있도록 허용하세요.",
"allow-users-outside-of-your-group-to-see-your-recipes": "그룹 외부 사용자가 여러분의 레시피를 볼 수 있도록 허용하세요",
"allow-users-outside-of-your-group-to-see-your-recipes-description": "이 기능을 활성화하면 사용자에게 권한을 부여하지 않고도 공개 공유 링크를 통해 특정 레시피를 공유할 수 있습니다. 비활성화 시에는 본인 그룹에 속한 사용자나 미리 생성된 비공개 링크를 통해서만 레시피를 공유할 수 있습니다.",
"show-nutrition-information": "영양 정보 표시",
"show-nutrition-information-description": "영양 정보가 제공되는 경우 레시피에 표시됩니다. 영양 정보가 제공되지 않으면 표시되지 않습니다.",
"show-recipe-assets": "레시피 에셋 표시",
"show-recipe-assets-description": "이 기능이 활성화되면 레시피에 사용 가능한 레시피 에셋이 표시됩니다.",
"default-to-landscape-view": "가로 보기로 기본 설정",
"default-to-landscape-view-description": "활성화 시 레시피 헤더 섹션이 가로 보기 모드로 표시됩니다",
"disable-users-from-commenting-on-recipes": "사용자가 레시피에 댓글을 달 수 없도록 설정",
"disable-users-from-commenting-on-recipes-description": "레시피 페이지의 댓글 섹션을 숨기고 댓글 작성을 비활성화합니다",
"disable-organizing-recipe-ingredients-by-units-and-food": "단위 및 음식별로 레시피 재료를 정렬하는 기능을 비활성화합니다",
"disable-organizing-recipe-ingredients-by-units-and-food-description": "재료의 '음식', '단위', '양' 필드를 숨기고 재료를 일반 텍스트 필드로 처리합니다",
"general-preferences": "일반 설정",
"group-recipe-preferences": "그룹 레시피 설정",
"report": "보고서",
"report-with-id": "보고서 ID: {id}",
"group-management": "그룹 관리",
"admin-group-management": "Admin Group Management",
"admin-group-management-text": "Changes to this group will be reflected immediately.",
"group-id-value": "Group Id: {0}",
"total-households": "Total Households",
"you-must-select-a-group-before-selecting-a-household": "You must select a group before selecting a household"
"admin-group-management": "관리자 그룹 관리",
"admin-group-management-text": "이 그룹에 대한 변경 사항은 즉시 반영됩니다.",
"group-id-value": "그룹 Id: {0}",
"total-households": "전체 가구 수",
"you-must-select-a-group-before-selecting-a-household": "가구를 선택하기 전에 반드시 그룹을 선택해야 합니다."
},
"household": {
"household": "Household",
"households": "Households",
"user-household": "User Household",
"create-household": "Create Household",
"household-name": "Household Name",
"household-group": "Household Group",
"household-management": "Household Management",
"manage-households": "Manage Households",
"admin-household-management": "Admin Household Management",
"admin-household-management-text": "Changes to this household will be reflected immediately.",
"household-id-value": "Household Id: {0}",
"household": "가구",
"households": "가구",
"user-household": "사용자 가구",
"create-household": "가구 생성",
"household-name": "가구 이름",
"household-group": "가구 그룹",
"household-management": "가구 관리",
"manage-households": "가구 관리하기",
"admin-household-management": "관리자 가구 관리",
"admin-household-management-text": "이 가구에 대한 변경 사항은 즉시 반영됩니다.",
"household-id-value": "가구 Id: {0}",
"private-household": "개인 가정",
"private-household-description": "귀하의 가구를 비공개로 설정하면 모든 공개 보기 옵션이 비활성화됩니다. 이는 개별 공개 보기 설정을 재정의합니다.",
"lock-recipe-edits-from-other-households": "다른 가구의 레시피 편집 잠금",
@@ -301,7 +301,7 @@
"default-recipe-preferences-description": "이는 가정에서 새로운 레시피를 만들 때의 기본 설정입니다. 레시피 설정 메뉴에서 개별 레시피에 대해 이를 변경할 수 있습니다.",
"allow-users-outside-of-your-household-to-see-your-recipes": "가족 외의 사용자에게도 요리법을 볼 수 있도록 허용",
"allow-users-outside-of-your-household-to-see-your-recipes-description": "활성화하면 공개 공유 링크를 사용하여 사용자에게 권한을 부여하지 않고도 특정 레시피를 공유할 수 있습니다. 비활성화하면 가족 구성원 또는 사전 생성된 비공개 링크로만 레시피를 공유할 수 있습니다.",
"household-preferences": "Household Preferences"
"household-preferences": "가구 설정"
},
"meal-plan": {
"create-a-new-meal-plan": "새로운 식사 계획 생성",
@@ -342,9 +342,9 @@
"breakfast": "조식",
"lunch": "점심",
"dinner": "저녁 식사",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"snack": "간식",
"drink": "음료",
"dessert": "디저트",
"type-any": "모두",
"day-any": "모두",
"editor": "편집기",
@@ -352,74 +352,74 @@
"meal-title": "식사 제목",
"meal-note": "식사 노트",
"note-only": "참고사항만",
"random-meal": "Random Meal",
"random-dinner": "Random Dinner",
"random-side": "Random Side",
"this-rule-will-apply": "This rule will apply {dayCriteria} {mealTypeCriteria}.",
"to-all-days": "to all days",
"on-days": "on {0}s",
"for-all-meal-types": "for all meal types",
"for-type-meal-types": "for {0} meal types",
"meal-plan-rules": "Meal Plan Rules",
"new-rule": "New Rule",
"meal-plan-rules-description": "You can create rules for auto selecting recipes for your meal plans. These rules are used by the server to determine the random pool of recipes to select from when creating meal plans. Note that if rules have the same day/type constraints then the rule filters will be merged. In practice, it's unnecessary to create duplicate rules, but it's possible to do so.",
"new-rule-description": "When creating a new rule for a meal plan you can restrict the rule to be applicable for a specific day of the week and/or a specific type of meal. To apply a rule to all days or all meal types you can set the rule to \"Any\" which will apply it to all the possible values for the day and/or meal type.",
"recipe-rules": "Recipe Rules",
"applies-to-all-days": "Applies to all days",
"applies-on-days": "Applies on {0}s",
"meal-plan-settings": "Meal Plan Settings"
"random-meal": "랜덤 식사",
"random-dinner": "랜덤 저녁식사",
"random-side": "랜덤 사이드 메뉴",
"this-rule-will-apply": "이 규칙은 {dayCriteria} {mealTypeCriteria}에 적용됩니다.",
"to-all-days": "모든 날에",
"on-days": "{0}",
"for-all-meal-types": "모든 식사 종류에",
"for-type-meal-types": "{0} 식사 종류에",
"meal-plan-rules": "식사 플랜 규칙",
"new-rule": "새 규칙",
"meal-plan-rules-description": "식사 플랜에 사용할 레시피를 자동 선택하는 규칙을 생성할 수 있습니다. 이 규칙들은 서버가 식사 플랜을 생성할 때 선택할 무작위 레시피 풀을 결정하는 데 사용됩니다. 동일한 요일/유형 제약 조건을 가진 규칙들은 필터가 병합된다는 점에 유의하세요. 실제로 중복 규칙을 생성할 필요는 없지만, 생성하는 것은 가능합니다.",
"new-rule-description": "식사 플랜에 새 규칙을 생성할 때, 특정 요일 및/또는 특정 식사 유형에만 적용되도록 규칙을 제한할 수 있습니다. 모든 요일 또는 모든 식사 유형에 규칙을 적용하려면 규칙을 \"모든\"으로 설정하면 됩니다. 이렇게 하면 해당 요일 및/또는 식사 유형의 모든 가능한 값에 규칙이 적용됩니다.",
"recipe-rules": "레시피 규칙",
"applies-to-all-days": "모든 날짜에 적용됨",
"applies-on-days": "{0}에 적용됨",
"meal-plan-settings": "식사 플랜 설정"
},
"migration": {
"migration-data-removed": "Migration data removed",
"migration-data-removed": "이전된 데이터 제거됨",
"new-migration": "새 마이그레이션",
"no-file-selected": "No File Selected",
"no-migration-data-available": "No Migration Data Available",
"previous-migrations": "Previous Migrations",
"recipe-migration": "Recipe Migration",
"no-file-selected": "선택된 파일이 없습니다",
"no-migration-data-available": "이전 데이터가 없습니다.",
"previous-migrations": "이전 데이터 이전",
"recipe-migration": "레시피 데이터 이전",
"chowdown": {
"description": "Migrate data from Chowdown",
"description-long": "Mealie natively supports the chowdown repository format. Download the code repository as a .zip file and upload it below.",
"description": "Chowdown에서 데이터를 이전합니다",
"description-long": "Mealie는 기본적으로 Chowdown 저장소 형식을 지원합니다. 코드 저장소를 .zip 파일로 다운로드한 후 아래에 업로드하세요.",
"title": "Chowdown"
},
"nextcloud": {
"description": "Migrate data from a Nextcloud Cookbook instance",
"description-long": "Nextcloud recipes can be imported from a zip file that contains the data stored in Nextcloud. See the example folder structure below to ensure your recipes are able to be imported.",
"description": "Nextcloud Cookbook 인스턴스에서 데이터 이전",
"description-long": "Nextcloud 레시피는 Nextcloud에 저장된 데이터를 포함하는 zip 파일에서 가져올 수 있습니다. 레시피를 가져올 수 있도록 하려면 아래의 예시 폴더 구조를 참조하십시오.",
"title": "Nextcloud Cookbook"
},
"copymethat": {
"description-long": "Mealie can import recipes from Copy Me That. Export your recipes in HTML format, then upload the .zip below.",
"title": "Copy Me That Recipe Manager"
"description-long": "Mealie는 Copy Me That에서 레시피를 가져올 수 있습니다. 레시피를 HTML 형식으로 내보낸 후, 아래의 .zip 파일을 업로드하세요.",
"title": "Copy Me That 레시피 매니저"
},
"paprika": {
"description-long": "Mealie can import recipes from the Paprika application. Export your recipes from paprika, rename the export extension to .zip and upload it below.",
"title": "Paprika Recipe Manager"
"description-long": "Mealie는 Paprika 애플리케이션에서 레시피를 가져올 수 있습니다. Paprika에서 레시피를 내보낸 후, 내보낸 파일의 확장자를 .zip으로 변경하여 아래에 업로드하세요.",
"title": "Paprika 레시피 매니저"
},
"mealie-pre-v1": {
"description-long": "Mealie can import recipes from the Mealie application from a pre v1.0 release. Export your recipes from your old instance, and upload the zip file below. Note that only recipes can be imported from the export.",
"description-long": "Mealie는 v1.0 이전 버전의 Mealie 애플리케이션에서 레시피를 가져올 수 있습니다. 기존 인스턴스에서 레시피를 내보낸 후 아래의 zip 파일을 업로드하세요. 내보낸 파일에서 레시피만 가져올 수 있다는 점에 유의하십시오.",
"title": "Mealie Pre v1.0"
},
"tandoor": {
"description-long": "Mealie can import recipes from Tandoor. Export your data in the \"Default\" format, then upload the .zip below.",
"title": "Tandoor Recipes"
"description-long": "Mealie는 Tandoor에서 레시피를 가져올 수 있습니다. 데이터를 \"기본\" 형식으로 내보낸 후 아래의 .zip 파일을 업로드하세요.",
"title": "Tandoor 레시피"
},
"cookn": {
"description-long": "Mealie can import recipes from DVO Cook'n X3. Export a cookbook or menu in the \"Cook'n\" format, rename the export extension to .zip, then upload the .zip below.",
"description-long": "Mealie는 DVO Cook'n X3의 레시피를 가져올 수 있습니다. \"Cook'n\" 형식으로 요리책이나 메뉴를 내보낸 후, 내보낸 파일의 확장자를 .zip으로 변경하고 아래에 .zip 파일을 업로드하세요.",
"title": "DVO Cook'n X3"
},
"recipe-data-migrations": "Recipe Data Migrations",
"recipe-data-migrations-explanation": "Recipes can be migrated from another supported application to Mealie. This is a great way to get started with Mealie.",
"coming-from-another-application-or-an-even-older-version-of-mealie": "Coming from another application or an even older version of Mealie? Check out migrations and see if your data can be imported.",
"choose-migration-type": "Choose Migration Type",
"tag-all-recipes": "Tag all recipes with {tag-name} tag",
"nextcloud-text": "Nextcloud recipes can be imported from a zip file that contains the data stored in Nextcloud. See the example folder structure below to ensure your recipes are able to be imported.",
"chowdown-text": "Mealie natively supports the chowdown repository format. Download the code repository as a .zip file and upload it below.",
"recipe-1": "Recipe 1",
"recipe-2": "Recipe 2",
"paprika-text": "Mealie can import recipes from the Paprika application. Export your recipes from paprika, rename the export extension to .zip and upload it below.",
"mealie-text": "Mealie can import recipes from the Mealie application from a pre v1.0 release. Export your recipes from your old instance, and upload the zip file below. Note that only recipes can be imported from the export.",
"recipe-data-migrations": "레시피 데이터 이전",
"recipe-data-migrations-explanation": "다른 지원되는 애플리케이션에서 Mealie로 레시피를 이전할 수 있습니다. 이것은 Mealie를 시작하는 아주 좋은 방법입니다.",
"coming-from-another-application-or-an-even-older-version-of-mealie": "다른 애플리케이션이나 더 오래된 버전의 Mealie에서 오셨나요? 데이터 이전 기능을 확인하고 데이터를 가져올 수 있는지 살펴보세요.",
"choose-migration-type": "이전 종류 선택",
"tag-all-recipes": "모든 레시피에 {태그 이름} 태그를 지정하세요",
"nextcloud-text": "Nextcloud 레시피는 Nextcloud에 저장된 데이터를 포함하는 zip 파일에서 가져올 수 있습니다. 레시피를 가져올 수 있도록 하려면 아래의 예시 폴더 구조를 참조하십시오.",
"chowdown-text": "Mealie는 기본적으로 Chowdown 저장소 형식을 지원합니다. 코드 저장소를 .zip 파일로 다운로드한 후 아래에 업로드하세요.",
"recipe-1": "레시피 1",
"recipe-2": "레시피 2",
"paprika-text": "Mealie는 Paprika 애플리케이션에서 레시피를 가져올 수 있습니다. Paprika에서 레시피를 내보낸 후, 내보낸 파일의 확장자를 .zip으로 변경하여 아래에 업로드하세요.",
"mealie-text": "Mealie는 v1.0 이전 버전의 Mealie 애플리케이션에서 레시피를 가져올 수 있습니다. 기존 인스턴스에서 레시피를 내보낸 후 아래의 zip 파일을 업로드하세요. 내보낸 파일에서 레시피만 가져올 수 있다는 점에 유의하십시오.",
"plantoeat": {
"title": "Plan to Eat",
"description-long": "Mealie can import recipies from Plan to Eat."
"description-long": "Mealie는 Plan to Eat에서 레시피를 가져올 수 있습니다."
},
"myrecipebox": {
"title": "내 레시피 박스",
@@ -435,8 +435,8 @@
"error-details": "Mealie는 ld+json 또는 microdata를 포함하는 웹사이트만 가져올 수 있습니다. 대부분의 주요 레시피 웹사이트는 이 데이터 구조를 지원합니다. 사이트를 가져올 수 없지만 로그에 json 데이터가 있는 경우 URL과 데이터와 함께 github 이슈를 제출하세요.",
"error-title": "아무것도 찾지 못한 것 같습니다",
"from-url": "레시피 가져오기",
"github-issues": "GitHub Issues",
"google-ld-json-info": "Google ld+json Info",
"github-issues": "GitHub 이슈",
"google-ld-json-info": "Google ld+json 정보",
"must-be-a-valid-url": "유효한 URL이어야 합니다.",
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "레시피 데이터를 붙여넣습니다. 각 줄은 목록의 항목으로 처리됩니다.",
"recipe-markup-specification": "레시피 마크업 사양",
@@ -445,15 +445,16 @@
"upload-a-recipe": "레시피 업로드",
"upload-individual-zip-file": "다른 Mealie 인스턴스에서 내보낸 개별 .zip 파일을 업로드합니다.",
"url-form-hint": "좋아하는 레시피 웹사이트에서 링크를 복사하여 붙여넣으세요",
"copy-and-paste-the-source-url-of-your-data-optional": "데이터의 소스 URL을 복사하여 붙여넣으세요 (선택 사항)",
"view-scraped-data": "스크랩된 데이터 보기",
"trim-whitespace-description": "앞뒤 공백과 빈 줄을 잘라냅니다.",
"trim-prefix-description": "Trim first character from each line",
"trim-prefix-description": "각 줄의 첫 문자 제거하기",
"split-by-numbered-line-description": "'1)' 또는 '1.' 패턴을 일치시켜 문단을 분할하려고 시도합니다.",
"import-by-url": "URL로 레시피 가져오기",
"create-manually": "수동으로 레시피 만들기",
"make-recipe-image": "이것을 레시피 이미지로 만드세요.",
"add-food": "Add Food",
"add-recipe": "Add Recipe"
"add-food": "식품 추가",
"add-recipe": "레시피 추가"
},
"page": {
"404-page-not-found": "404. 페이지를 찾을 수 없음",
@@ -467,13 +468,13 @@
"page-updated": "페이지 업데이트됨",
"pages-update-failed": "페이지 업데이트 실패",
"pages-updated": "페이지 업데이트됨",
"404-not-found": "404 Not Found",
"404-not-found": "404 찾을 수 없음",
"an-error-occurred": "오류가 발생했습니다!"
},
"recipe": {
"add-key": "키 추가",
"add-to-favorites": "즐겨찾기에 추가",
"api-extras": "API Extras",
"api-extras": "API 기타",
"calories": "칼로리",
"calories-suffix": "칼로리",
"carbohydrate-content": "탄수화물",
@@ -483,7 +484,7 @@
"comment": "댓글",
"comments": "댓글",
"delete-confirmation": "이 레시피를 정말 삭제하시겠습니까?",
"admin-delete-confirmation": "You're about to delete a recipe that isn't yours using admin permissions. Are you sure?",
"admin-delete-confirmation": "관리자 권한으로 본인 소유가 아닌 레시피를 삭제하려 합니다. 정말 삭제하시겠습니까?",
"delete-recipe": "레시피 삭제",
"description": "설명",
"disable-amount": "재료량 비활성화",
@@ -494,63 +495,63 @@
"fat-content": "지방",
"fiber-content": "섬유질",
"grams": "그램",
"ingredient": "Ingredient",
"ingredients": "Ingredients",
"insert-ingredient": "Insert Ingredient",
"insert-section": "Insert Section",
"insert-above": "Insert Above",
"insert-below": "Insert Below",
"instructions": "Instructions",
"key-name-required": "Key Name Required",
"ingredient": "재료",
"ingredients": "재료",
"insert-ingredient": "재료 추가",
"insert-section": "섹션 추가",
"insert-above": "위에 추가",
"insert-below": "아래에 추가",
"instructions": "지침",
"key-name-required": "키 이름 필수",
"landscape-view-coming-soon": "Landscape View (Coming Soon)",
"milligrams": "milligrams",
"new-key-name": "New Key Name",
"no-white-space-allowed": "No White Space Allowed",
"note": "Note",
"nutrition": "Nutrition",
"object-key": "Object Key",
"object-value": "Object Value",
"original-url": "Original URL",
"perform-time": "Cook Time",
"prep-time": "Prep Time",
"protein-content": "Protein",
"public-recipe": "Public Recipe",
"recipe-created": "Recipe created",
"recipe-creation-failed": "Recipe creation failed",
"recipe-deleted": "Recipe deleted",
"recipe-image": "Recipe Image",
"recipe-image-updated": "Recipe image updated",
"delete-image": "Delete Recipe Image",
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
"recipe-image-deleted": "Recipe image deleted",
"recipe-name": "Recipe Name",
"recipe-settings": "Recipe Settings",
"recipe-update-failed": "Recipe update failed",
"recipe-updated": "Recipe updated",
"remove-from-favorites": "Remove from Favorites",
"remove-section": "Remove Section",
"saturated-fat-content": "Saturated fat",
"save-recipe-before-use": "Save recipe before use",
"section-title": "Section Title",
"servings": "Servings",
"serves-amount": "Serves {amount}",
"share-recipe-message": "I wanted to share my {0} recipe with you.",
"show-nutrition-values": "Show Nutrition Values",
"sodium-content": "Sodium",
"step-index": "Step: {step}",
"sugar-content": "Sugar",
"title": "Title",
"total-time": "Total Time",
"trans-fat-content": "Trans-fat",
"unable-to-delete-recipe": "Unable to Delete Recipe",
"unsaturated-fat-content": "Unsaturated fat",
"milligrams": "밀리그램",
"new-key-name": "새 키 이름",
"no-white-space-allowed": "공백 허용 안 됨",
"note": "메모",
"nutrition": "영양성분",
"object-key": "객체 키",
"object-value": "객체 값",
"original-url": "원래 URL",
"perform-time": "요리 시간",
"prep-time": "준비 시간",
"protein-content": "단백질",
"public-recipe": "공개 레시피",
"recipe-created": "레시피 생성됨",
"recipe-creation-failed": "레시피 생성 실패",
"recipe-deleted": "레시피 삭제됨",
"recipe-image": "레시피 사진",
"recipe-image-updated": "레시피 사진 업데이트됨",
"delete-image": "레시피 사진 삭제",
"delete-image-confirmation": "이 레시피 이미지를 삭제하시겠습니까?",
"recipe-image-deleted": "레시피 이미지 삭제됨",
"recipe-name": "레시피 이름",
"recipe-settings": "레시피 설정",
"recipe-update-failed": "레시피 수정 실패",
"recipe-updated": "레시피 수정됨",
"remove-from-favorites": "즐겨찾기에서 제거",
"remove-section": "섹션 제거",
"saturated-fat-content": "포화지방",
"save-recipe-before-use": "사용 전 레시피 저장",
"section-title": "섹션 제목",
"servings": "제공량",
"serves-amount": "{amount}인분",
"share-recipe-message": "{0} 레시피를 당신과 공유하고 싶었어요.",
"show-nutrition-values": "영양 성분 표시",
"sodium-content": "나트륨",
"step-index": "단계: {step}",
"sugar-content": "당류",
"title": "제목",
"total-time": "총 시간",
"trans-fat-content": "트랜스지방",
"unable-to-delete-recipe": "레시피를 삭제할 수 없음",
"unsaturated-fat-content": "불포화지방",
"no-recipe": "레시피 없음",
"locked-by-owner": "소유자에 의해 잠김",
"join-the-conversation": "대화에 참여하기",
"add-recipe-to-mealplan": "식사 계획에 레시피 추가",
"entry-type": "항목 유형",
"date-format-hint": "MM/DD/YYYY format",
"date-format-hint-yyyy-mm-dd": "YYYY-MM-DD format",
"date-format-hint": "MM/DD/YYYY 형식",
"date-format-hint-yyyy-mm-dd": "YYYY-MM-DD 형식",
"add-to-list": "목록에 추가",
"add-to-plan": "계획에 추가",
"add-to-timeline": "타임라인에 추가하기",
@@ -562,234 +563,234 @@
"failed-to-add-recipe-to-mealplan": "식사 계획에 레시피를 추가하지 못했습니다.",
"failed-to-add-to-list": "목록에 추가하지 못했습니다.",
"yield": "용량",
"yields-amount-with-text": "Yields {amount} {text}",
"yield-text": "Yield Text",
"yields-amount-with-text": "{amount} {text} 생성",
"yield-text": "생성 단위",
"quantity": "수량",
"choose-unit": "단위 선택",
"press-enter-to-create": "Enter 키를 눌러 생성하세요",
"choose-food": "음식 선택",
"choose-recipe": "Choose Recipe",
"choose-recipe": "레시피 선택",
"notes": "노트",
"toggle-section": "Toggle Section",
"see-original-text": "See Original Text",
"original-text-with-value": "Original Text: {originalText}",
"ingredient-linker": "Ingredient Linker",
"unlinked": "Not linked yet",
"linked-to-other-step": "Linked to other step",
"toggle-section": "섹션 활성화",
"see-original-text": "원래 텍스트 보기",
"original-text-with-value": "원래 텍스트: {originalText}",
"ingredient-linker": "단계별로 재료 연결하기",
"unlinked": "아직 연결되지 않음",
"linked-to-other-step": "다른 단계와 연결됨",
"auto": "자동",
"cook-mode": "Cook Mode",
"link-ingredients": "Link Ingredients",
"merge-above": "Merge Above",
"cook-mode": "요리 모드",
"link-ingredients": "재료 연결하기",
"merge-above": "위 항목과 합치기",
"move-to-bottom": "맨 아래로 이동",
"move-to-top": "맨 위로 이동",
"reset-scale": "Reset Scale",
"decrease-scale-label": "Decrease Scale by 1",
"increase-scale-label": "Increase Scale by 1",
"reset-scale": "배율 재설정",
"decrease-scale-label": "배율 1만큼 감소",
"increase-scale-label": "배율 1만큼 증가",
"locked": "잠김",
"public-link": "Public Link",
"edit-timeline-event": "Edit Timeline Event",
"public-link": "공개 링크",
"edit-timeline-event": "타임라인 이벤트 수정",
"timeline": "타임라인",
"timeline-is-empty": "Nothing on the timeline yet. Try making this recipe!",
"timeline-no-events-found-try-adjusting-filters": "No events found. Try adjusting your search filters.",
"group-global-timeline": "{groupName} Global Timeline",
"open-timeline": "Open Timeline",
"made-this": "I Made This",
"how-did-it-turn-out": "How did it turn out?",
"user-made-this": "{user} made this",
"made-for-recipe": "Made for {recipe}",
"added-to-timeline": "Added to timeline",
"failed-to-add-to-timeline": "Failed to add to timeline",
"failed-to-update-recipe": "Failed to update recipe",
"added-to-timeline-but-failed-to-add-image": "Added to timeline, but failed to add image",
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.",
"message-key": "Message Key",
"parse": "Parse",
"timeline-is-empty": "아직 타임라인에 아무것도 없습니다. 이 레시피를 만들어 보세요!",
"timeline-no-events-found-try-adjusting-filters": "찾은 이벤트가 없습니다. 검색 필터를 조정해 보세요.",
"group-global-timeline": "{groupName} 전체 타임라인",
"open-timeline": "타임라인 열기",
"made-this": "내가 만들었어!",
"how-did-it-turn-out": "어떻게 완성됐나요?",
"user-made-this": "{user}이(가) 이것을 만듦",
"made-for-recipe": "{recipe}를 위해 만들어짐",
"added-to-timeline": "타임라인에 추가됨",
"failed-to-add-to-timeline": "타임라인에 추가 실패",
"failed-to-update-recipe": "레시피 수정 실패",
"added-to-timeline-but-failed-to-add-image": "타임라인에 추가되었으나, 이미지 추가에 실패했습니다.",
"api-extras-description": "레시피 추가 항목은 Mealie API의 핵심 기능입니다. 이를 통해 레시피 내에서 사용자 정의 JSON 키/값 쌍을 생성하여 타사 애플리케이션에서 참조할 수 있습니다. 이러한 키를 활용하여 정보를 제공할 수 있으며, 예를 들어 자동화를 트리거하거나 원하는 기기로 전달할 사용자 정의 메시지를 설정하는 데 사용할 수 있습니다.",
"message-key": "메시지 키",
"parse": "추출하기",
"ingredients-not-parsed-description": "It looks like your ingredients aren't parsed yet. Click the \"{parse}\" button below to parse your ingredients into structured foods.",
"attach-images-hint": "Attach images by dragging & dropping them into the editor",
"drop-image": "Drop image",
"enable-ingredient-amounts-to-use-this-feature": "Enable ingredient amounts to use this feature",
"recipes-with-units-or-foods-defined-cannot-be-parsed": "Recipes with units or foods defined cannot be parsed.",
"parse-ingredients": "Parse ingredients",
"edit-markdown": "Edit Markdown",
"recipe-creation": "Recipe Creation",
"select-one-of-the-various-ways-to-create-a-recipe": "Select one of the various ways to create a recipe",
"looking-for-migrations": "Looking For Migrations?",
"import-with-url": "Import with URL",
"create-recipe": "Create Recipe",
"create-recipe-description": "Create a new recipe from scratch.",
"create-recipes": "Create Recipes",
"import-with-zip": "Import with .zip",
"attach-images-hint": "이미지를 편집기로 끌어다 놓아 첨부하세요",
"drop-image": "이미지 끌어다 놓기",
"enable-ingredient-amounts-to-use-this-feature": "이 기능을 사용하려면 재료 양을 활성화하세요",
"recipes-with-units-or-foods-defined-cannot-be-parsed": "단위나 정의된 식품이 포함된 레시피는 추출할 수 없습니다.",
"parse-ingredients": "재료 추출하기",
"edit-markdown": "마크다운 수정",
"recipe-creation": "레시피 생성",
"select-one-of-the-various-ways-to-create-a-recipe": "레시피를 만드는 다양한 방법 중 하나를 선택하세요",
"looking-for-migrations": "데이터 이전 기능을 찾고 계신가요?",
"import-with-url": "URL로 가져오기",
"create-recipe": "레시피 생성",
"create-recipe-description": "처음부터 새로운 레시피를 만드세요.",
"create-recipes": "레시피 생성",
"import-with-zip": ".zip 파일로 가져오기",
"create-recipe-from-an-image": "Create Recipe from an Image",
"create-recipe-from-an-image-description": "Create a recipe by uploading an image of it. Mealie will attempt to extract the text from the image using AI and create a recipe from it.",
"crop-and-rotate-the-image": "Crop and rotate the image so that only the text is visible, and it's in the correct orientation.",
"create-from-images": "Create from Images",
"should-translate-description": "Translate the recipe into my language",
"please-wait-image-procesing": "Please wait, the image is processing. This may take some time.",
"please-wait-images-processing": "Please wait, the images are processing. This may take some time.",
"bulk-url-import": "Bulk URL Import",
"debug-scraper": "Debug Scraper",
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Create a recipe by providing the name. All recipes must have unique names.",
"new-recipe-names-must-be-unique": "New recipe names must be unique",
"scrape-recipe": "Scrape Recipe",
"scrape-recipe-description": "Scrape a recipe by url. Provide the url for the site you want to scrape, and Mealie will attempt to scrape the recipe from that site and add it to your collection.",
"scrape-recipe-have-a-lot-of-recipes": "Have a lot of recipes you want to scrape at once?",
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
"scrape-recipe-have-raw-html-or-json-data": "Have raw HTML or JSON data?",
"scrape-recipe-you-can-import-from-raw-data-directly": "You can import from raw data directly",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"import-original-keywords-as-tags": "Import original keywords as tags",
"stay-in-edit-mode": "Stay in Edit mode",
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
"import-from-zip": "Import from Zip",
"import-from-zip-description": "Import a single recipe that was exported from another Mealie instance.",
"import-from-html-or-json": "Import from HTML or JSON",
"import-from-html-or-json-description": "Import a single recipe from raw HTML or JSON. This is useful if you have a recipe from a site that Mealie can't scrape normally, or from some other external source.",
"json-import-format-description-colon": "To import via JSON, it must be in valid format:",
"json-editor": "JSON Editor",
"zip-files-must-have-been-exported-from-mealie": ".zip files must have been exported from Mealie",
"create-a-recipe-by-uploading-a-scan": "Create a recipe by uploading a scan.",
"upload-a-png-image-from-a-recipe-book": "Upload a png image from a recipe book",
"recipe-bulk-importer": "Recipe Bulk Importer",
"recipe-bulk-importer-description": "The Bulk recipe importer allows you to import multiple recipes at once by queueing the sites on the backend and running the task in the background. This can be useful when initially migrating to Mealie, or when you want to import a large number of recipes.",
"set-categories-and-tags": "Set Categories and Tags",
"bulk-imports": "Bulk Imports",
"bulk-import-process-has-started": "Bulk Import process has started",
"bulk-import-process-has-failed": "Bulk import process has failed",
"report-deletion-failed": "Report deletion failed",
"recipe-debugger": "Recipe Debugger",
"recipe-debugger-description": "Grab the URL of the recipe you want to debug and paste it here. The URL will be scraped by the recipe scraper and the results will be displayed. If you don't see any data returned, the site you are trying to scrape is not supported by Mealie or its scraper library.",
"use-openai": "Use OpenAI",
"recipe-debugger-use-openai-description": "Use OpenAI to parse the results instead of relying on the scraper library. When creating a recipe via URL, this is done automatically if the scraper library fails, but you may test it manually here.",
"debug": "Debug",
"tree-view": "Tree View",
"recipe-servings": "Recipe Servings",
"recipe-yield": "Recipe Yield",
"recipe-yield-text": "Recipe Yield Text",
"unit": "Unit",
"crop-and-rotate-the-image": "이미지를 잘라내고 회전시켜 텍스트만 보이도록 하고 올바른 방향으로 배치하십시오.",
"create-from-images": "이미지에서 생성",
"should-translate-description": "레시피를 내 언어로 번역하기",
"please-wait-image-procesing": "잠시만 기다려 주세요, 이미지가 처리 중입니다. 시간이 다소 걸릴 수 있습니다.",
"please-wait-images-processing": "잠시만 기다려 주세요, 이미지가 처리 중입니다. 시간이 다소 걸릴 수 있습니다.",
"bulk-url-import": "대량 URL 가져오기",
"debug-scraper": "스크랩퍼 디버깅하기",
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "이름을 입력하여 레시피를 생성하세요. 모든 레시피는 고유한 이름을 가져야 합니다.",
"new-recipe-names-must-be-unique": "새로운 레시피 이름은 반드시 고유해야 합니다",
"scrape-recipe": "레시피 스크랩하기",
"scrape-recipe-description": "URL로 레시피를 스크랩하세요. 스크랩하려는 사이트의 URL을 제공하면, Mealie가 해당 사이트에서 레시피를 스크랩하여 여러분의 컬렉션에 추가합니다.",
"scrape-recipe-have-a-lot-of-recipes": "한 번에 스크랩하고 싶은 레시피가 많으신가요?",
"scrape-recipe-suggest-bulk-importer": "대량 가져오기 도구를 사용해 보세요",
"scrape-recipe-have-raw-html-or-json-data": "원본 HTML 또는 JSON 데이터를 가지고 계신가요?",
"scrape-recipe-you-can-import-from-raw-data-directly": "원본 데이터에서 직접 가져올 수 있습니다",
"scrape-recipe-website-being-blocked": "웹사이트가 차단되고 있나요?",
"scrape-recipe-try-importing-raw-html-instead": "대신 원본 HTML 가져오기를 시도해보세요.",
"import-original-keywords-as-tags": "원본 키워드를 태그로 가져오기",
"stay-in-edit-mode": "편집 모드 유지",
"parse-recipe-ingredients-after-import": "가져오기 후 레시피 재료 추출",
"import-from-zip": "Zip 파일에서 가져오기",
"import-from-zip-description": "다른 Mealie 인스턴스에서 내보낸 단일 레시피를 가져옵니다.",
"import-from-html-or-json": "HTML 또는 JSON에서 가져오기",
"import-from-html-or-json-description": "원본 HTML 또는 JSON에서 단일 레시피를 가져옵니다. 이는 Mealie가 일반적으로 스크랩할 수 없는 사이트나 기타 외부 출처의 레시피가 있을 때 유용합니다.",
"json-import-format-description-colon": "JSON을 통해 가져오려면 유효한 형식이어야 합니다:",
"json-editor": "JSON 편집기",
"zip-files-must-have-been-exported-from-mealie": ".zip 파일은 Mealie에서 내보낸 파일이어야 합니다.",
"create-a-recipe-by-uploading-a-scan": "스캔본을 업로드하여 레시피를 생성하세요.",
"upload-a-png-image-from-a-recipe-book": "레시피 책에서 png 이미지를 업로드하세요",
"recipe-bulk-importer": "레시피 대량 가져오기 도구",
"recipe-bulk-importer-description": "대량 레시피 가져오기 도구는 백엔드에서 사이트를 대기열에 추가하고 백그라운드에서 작업을 실행함으로써 여러 레시피를 한 번에 가져올 수 있게 합니다. 이는 Mealie로 처음 이전할 때나 대량의 레시피를 가져오고 싶을 때 유용합니다.",
"set-categories-and-tags": "카테고리 및 태그 설정",
"bulk-imports": "대량 가져오기",
"bulk-import-process-has-started": "대량 가져오기 시작됨",
"bulk-import-process-has-failed": "대량 가져오기 실패함",
"report-deletion-failed": "보고서 삭제 실패",
"recipe-debugger": "레시피 디버깅 도구",
"recipe-debugger-description": "디버깅하려는 레시피의 URL을 복사하여 여기에 붙여넣으세요. 레시피 스크랩 도구가 URL을 추출하여 결과를 표시합니다. 데이터가 반환되지 않는다면, 해당 사이트는 Mealie 또는 그 스크랩 라이브러리가 지원하지 않는 사이트입니다.",
"use-openai": "OpenAI 사용하기",
"recipe-debugger-use-openai-description": "스크랩 라이브러리에 의존하지 말고 OpenAI를 사용하여 결과를 파싱하세요. URL을 통해 레시피를 생성할 때 스크랩 라이브러리가 실패하면 이 작업이 자동으로 수행되지만, 여기에서 수동으로 테스트할 수 있습니다.",
"debug": "디버그",
"tree-view": "계층적 보기",
"recipe-servings": "레시피 제공량",
"recipe-yield": "레시피 생성량",
"recipe-yield-text": "레시피 생성 단위",
"unit": "단위",
"upload-image": "이미지 업로드",
"screen-awake": "화면을 항상 켠 상태로 유지",
"remove-image": "이미지 제거",
"nextStep": "다음 단계",
"recipe-actions": "Recipe Actions",
"recipe-actions": "레시피 액션",
"parser": {
"ingredient-parser": "Ingredient Parser",
"explanation": "To use the ingredient parser, click the 'Parse All' button to start the process. Once the processed ingredients are available, you can review the items and verify that they were parsed correctly. The model's confidence score is displayed on the right of the item title. This score is an average of all the individual scores and may not always be completely accurate.",
"alerts-explainer": "Alerts will be displayed if a matching foods or unit is found but does not exists in the database.",
"select-parser": "Select Parser",
"natural-language-processor": "Natural Language Processor",
"brute-parser": "Brute Parser",
"openai-parser": "OpenAI Parser",
"parse-all": "Parse All",
"no-unit": "No unit",
"missing-unit": "Create missing unit: {unit}",
"missing-food": "Create missing food: {food}",
"this-unit-could-not-be-parsed-automatically": "This unit could not be parsed automatically",
"this-food-could-not-be-parsed-automatically": "This food could not be parsed automatically",
"no-food": "No Food",
"review-parsed-ingredients": "Review parsed ingredients",
"confidence-score": "Confidence Score",
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
"delete-item": "Delete Item"
"ingredient-parser": "재료 분석기",
"explanation": "재료 분석기를 사용하려면 '모두 분석' 버튼을 클릭하여 프로세스를 시작하세요. 처리된 재료가 준비되면 항목을 검토하고 올바르게 분석되었는지 확인할 수 있습니다. 항목 제목 오른쪽에는 모델의 신뢰도 점수가 표시됩니다. 이 점수는 개별 점수의 평균값으로 항상 완벽하게 정확한 것은 아닙니다.",
"alerts-explainer": "일치하는 식품 또는 단위가 발견되었으나 데이터베이스에 존재하지 않을 경우 경고가 표시됩니다.",
"select-parser": "분석기 선택",
"natural-language-processor": "자연어 처리기",
"brute-parser": "무차별 분석기",
"openai-parser": "OpenAI 분석기",
"parse-all": "모두 분석",
"no-unit": "단위 없음",
"missing-unit": "새 단위 생성: {unit}",
"missing-food": "새 식품 생성: {food}",
"this-unit-could-not-be-parsed-automatically": "이 단위는 자동으로 분석(추출)할 수 없습니다.",
"this-food-could-not-be-parsed-automatically": "이 식품은 자동으로 분석(추출)할 수 없습니다.",
"no-food": "식품 없음",
"review-parsed-ingredients": "분석(추출)된 재료 확인",
"confidence-score": "신뢰도 점수",
"ingredient-parser-description": "재료가 성공적으로 분석되었습니다. 확실하지 않은 재료는 검토해 주세요.",
"ingredient-parser-final-review-description": "모든 재료를 검토한 후, 레시피에 변경 사항을 적용하기 전에 모든 재료를 한 번 더 검토할 기회가 주어집니다.",
"add-text-as-alias-for-item": "{text}을(를) {item}의 별칭으로 추가",
"delete-item": "항목 삭제"
},
"reset-servings-count": "Reset Servings Count",
"not-linked-ingredients": "Additional Ingredients",
"upload-another-image": "Upload another image",
"upload-images": "Upload images",
"upload-more-images": "Upload more images",
"set-as-cover-image": "Set as recipe cover image",
"cover-image": "Cover image",
"include-linked-recipes": "Include Linked Recipes",
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
"toggle-recipe": "Toggle Recipe"
"reset-servings-count": "제공량 재설정",
"not-linked-ingredients": "추가 재료",
"upload-another-image": "추가 이미지 업로드",
"upload-images": "이미지 업로드",
"upload-more-images": "이미지 추가 업로드",
"set-as-cover-image": "레시피 표지 이미지로 설정",
"cover-image": "표지 이미지",
"include-linked-recipes": "링크된 레시피 포함",
"include-linked-recipe-ingredients": "링크된 레시피 재료 포함",
"toggle-recipe": "레시피로 전환"
},
"recipe-finder": {
"recipe-finder": "Recipe Finder",
"recipe-finder-description": "Search for recipes based on ingredients you have on hand. You can also filter by tools you have available, and set a maximum number of missing ingredients or tools.",
"selected-ingredients": "Selected Ingredients",
"no-ingredients-selected": "No ingredients selected",
"missing": "Missing",
"no-recipes-found": "No recipes found",
"no-recipes-found-description": "Try adding more ingredients to your search or adjusting your filters",
"include-ingredients-on-hand": "Include Ingredients On Hand",
"include-tools-on-hand": "Include Tools On Hand",
"max-missing-ingredients": "Max Missing Ingredients",
"max-missing-tools": "Max Missing Tools",
"selected-tools": "Selected Tools",
"other-filters": "Other Filters",
"ready-to-make": "Ready to Make",
"almost-ready-to-make": "Almost Ready to Make"
"recipe-finder": "레시피 찾기",
"recipe-finder-description": "가지고 있는 재료로 레시피를 검색하세요. 사용 가능한 도구로도 필터링할 수 있으며, 부족한 재료나 도구의 최대 개수를 설정할 수 있습니다.",
"selected-ingredients": "선택된 재료",
"no-ingredients-selected": "선택된 재료 없음",
"missing": "없음",
"no-recipes-found": "검색 결과가 없습니다.",
"no-recipes-found-description": "검색어에 더 많은 항목을 추가하거나 필터를 조정해 보세요.",
"include-ingredients-on-hand": "가지고 있는 재료 포함",
"include-tools-on-hand": "가지고 있는 도구 포함",
"max-missing-ingredients": "없는 재료 최대 수",
"max-missing-tools": "없는 도구 최대 수",
"selected-tools": "선택된 도구",
"other-filters": "기타 필터",
"ready-to-make": "만들 수 있음",
"almost-ready-to-make": "거의 만들 수 있음"
},
"search": {
"advanced-search": "고급 검색",
"and": "and",
"exclude": "Exclude",
"include": "Include",
"max-results": "Max Results",
"or": "Or",
"has-any": "Has Any",
"has-all": "Has All",
"clear-selection": "Clear Selection",
"results": "Results",
"and": "그리고",
"exclude": "제외",
"include": "포함",
"max-results": "최대 결과 수",
"or": "또는",
"has-any": "적어도 하나 포함",
"has-all": "전부 포함",
"clear-selection": "모두 선택 취소",
"results": "결과",
"search": "검색",
"search-mealie": "Search Mealie (press /)",
"search-mealie": "Mealie 검색 (/를 누르세요)",
"search-placeholder": "검색...",
"tag-filter": "태그 필터",
"search-hint": "Press '/'",
"advanced": "Advanced",
"search-hint": "'/'를 누르세요",
"advanced": "고급",
"auto-search": "자동 검색",
"no-results": "검색 결과가 없습니다.",
"type-to-search": "Type to search..."
"type-to-search": "검색어를 입력하세요..."
},
"settings": {
"add-a-new-theme": "새 테마 추가",
"admin-settings": "관리자 설정",
"backup": {
"backup-created": "백업이 성공적으로 완료되었습니다.",
"backup-created-at-response-export_path": "Backup Created at {path}",
"backup-created-at-response-export_path": "백업 생성 위치: {path}",
"backup-deleted": "백업 삭제됨",
"restore-success": "복원 성공!",
"restore-fail": "Restore failed. Check your server logs for more details",
"backup-tag": "Backup Tag",
"restore-fail": "복원이 실패했습니다. 자세한 내용은 서버 로그를 확인하십시오.",
"backup-tag": "백업 태그",
"create-heading": "Create a Backup",
"delete-backup": "백업 삭제",
"error-creating-backup-see-log-file": "Error Creating Backup. See Log File",
"error-creating-backup-see-log-file": "백업 생성 중 오류 발생. 로그 파일을 참조하십시오.",
"full-backup": "전체 백업",
"import-summary": "Import Summary",
"partial-backup": "Partial Backup",
"unable-to-delete-backup": "Unable to Delete Backup.",
"experimental-description": "Backups are total snapshots of the database and data directory of the site. This includes all data and cannot be set to exclude subsets of data. You can think of this as a snapshot of Mealie at a specific time. These serve as a database agnostic way to export and import data, or back up the site to an external location.",
"import-summary": "가져오기 요약",
"partial-backup": "부분 백업",
"unable-to-delete-backup": "백업을 삭제할 수 없습니다.",
"experimental-description": "백업은 사이트의 데이터베이스와 데이터 디렉터리의 전체 스냅샷입니다. 여기에는 모든 데이터가 포함되며 데이터의 일부를 제외하도록 설정할 수 없습니다. 특정 시점의 Mealie 스냅샷이라고 생각하시면 됩니다. 이는 데이터베이스에 구애받지 않는 방식으로 데이터를 내보내고 가져오거나, 사이트를 외부 위치에 백업하는 역할을 합니다.",
"backup-restore": "백업/복원",
"back-restore-description": "Restoring this backup will overwrite all the current data in your database and in the data directory and replace them with the contents of this backup. {cannot-be-undone} If the restoration is successful, you will be logged out.",
"cannot-be-undone": "This action cannot be undone - use with caution.",
"postgresql-note": "If you are using PostgreSQL, please review the {backup-restore-process} prior to restoring.",
"backup-restore-process-in-the-documentation": "backup/restore process in the documentation",
"irreversible-acknowledgment": "I understand that this action is irreversible, destructive and may cause data loss",
"restore-backup": "Restore Backup"
"back-restore-description": "이 백업을 복원하면 데이터베이스와 데이터 디렉터리의 현재 데이터가 모두 덮어쓰기되며, 해당 백업의 내용으로 대체됩니다. {cannot-be-undone} 복원이 성공하면 로그아웃됩니다.",
"cannot-be-undone": "이 작업은 되돌릴 수 없습니다 - 주의해서 사용하십시오.",
"postgresql-note": "PostgreSQL을 사용 중인 경우, 복원 전에 {backup-restore-process}를 검토하십시오.",
"backup-restore-process-in-the-documentation": "공식 문서의 백업/복원 가이드",
"irreversible-acknowledgment": "이 작업은 되돌릴 수 없으며 파괴적일 수 있고 데이터 손실을 초래할 수 있음을 이해합니다.",
"restore-backup": "백업 복원"
},
"backup-and-exports": "Backups",
"change-password": "Change Password",
"current": "Version:",
"custom-pages": "Custom Pages",
"edit-page": "Edit Page",
"events": "Events",
"first-day-of-week": "First day of the week",
"group-settings-updated": "Group Settings Updated",
"backup-and-exports": "백업",
"change-password": "비밀번호 변경",
"current": "버전:",
"custom-pages": "사용자 정의 페이지",
"edit-page": "페이지 수정",
"events": "이벤트",
"first-day-of-week": "일주일의 시작 요일",
"group-settings-updated": "그룹 설정 수정됨",
"homepage": {
"all-categories": "All Categories",
"card-per-section": "Card Per Section",
"home-page": "Home Page",
"home-page-sections": "Home Page Sections",
"show-recent": "Show Recent"
"all-categories": "모든 카테고리",
"card-per-section": "섹션당 카드",
"home-page": "홈페이지",
"home-page-sections": "홈페이지 섹션",
"show-recent": "최근 표시"
},
"language": "언어",
"latest": "Latest",
"local-api": "Local API",
"locale-settings": "Locale settings",
"latest": "가장 최근",
"local-api": "로컬 API",
"locale-settings": "국가별 설정",
"migrations": "마이그레이션",
"new-page": "New Page",
"new-page": "새 페이지",
"notify": "알림",
"organize": "Organize",
"page-name": "Page Name",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Įkelti receptą",
"upload-individual-zip-file": "Įkelkite .zip failą, eksportuotą iš kitos \"Mealie\" sistemos.",
"url-form-hint": "Nukopijuokite ir įklijuokite nuorodą iš mėgstamų receptų svetainės",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Peržiūrėti nuskaitytus duomenis",
"trim-whitespace-description": "Pašalinti tarpus bei tuščias eilutes pradžioje ir pabaigoje",
"trim-prefix-description": "Pašalinti kiekvienos eilutės pirmąjį ženklą",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Augšupielādējiet recepti",
"upload-individual-zip-file": "Augšupielādējiet atsevišķu.zip failu, kas eksportēts no citas Mealie instances.",
"url-form-hint": "Kopējiet un ielīmējiet saiti no savas iecienītākās receptes vietnes",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Skatīt nokasītos datus",
"trim-whitespace-description": "Apgrieziet priekšējo un aizmugurējo atstarpi, kā arī tukšas rindas",
"trim-prefix-description": "Izgrieziet pirmo rakstzīmi no katras rindas",
@@ -1427,5 +1428,13 @@
"is-like": "ir kā",
"is-not-like": "nav tāds, kā"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Upload een recept",
"upload-individual-zip-file": "Upload een .zip-bestand dat uit een andere Mealie-instantie is geëxporteerd.",
"url-form-hint": "Kopieer en plak een link vanuit jouw favoriete receptenwebsite",
"copy-and-paste-the-source-url-of-your-data-optional": "Kopieer en plak de bron URL van uw gegevens (optioneel)",
"view-scraped-data": "Bekijk opgehaalde data",
"trim-whitespace-description": "Haal witruimtes en witregels aan het begin en einde weg",
"trim-prefix-description": "Verwijder het eerste teken van elke regel",
@@ -1427,5 +1428,13 @@
"is-like": "is zoals",
"is-not-like": "is niet zoals"
}
},
"validators": {
"required": "Dit is een verplicht veld",
"invalid-email": "E-mailadres moet geldig zijn",
"invalid-url": "Moet een geldige URL zijn",
"no-whitespace": "Geen spaties toegestaan",
"min-length": "Moet minimaal {min} tekens bevatten",
"max-length": "Zorg dat je {max} tekens gebruikt"
}
}

View File

@@ -342,7 +342,7 @@
"breakfast": "Frokost",
"lunch": "Lunsj",
"dinner": "Middag",
"snack": "Snack",
"snack": "Snacks",
"drink": "Drink",
"dessert": "Dessert",
"type-any": "Enhver",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Last opp oppskrift",
"upload-individual-zip-file": "Last opp en individuell .zip-fil eksportert fra en annen Mealie-instans.",
"url-form-hint": "Kopier og lim inn en lenke fra nettstedet med favorittoppskriftene dine",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Vis skrapte data",
"trim-whitespace-description": "Fjern innledende og etterfølgende mellomrom i tillegg til tomme linjer",
"trim-prefix-description": "Fjern første tegn fra hver linje",
@@ -1427,5 +1428,13 @@
"is-like": "er som",
"is-not-like": "er ikke som"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Wrzuć przepis",
"upload-individual-zip-file": "Prześlij pojedynczy plik .zip wyeksportowany z innej instancji Mealie.",
"url-form-hint": "Skopiuj i wklej link ze swojej ulubionej strony z przepisami",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Wyświetl zebrane dane",
"trim-whitespace-description": "Przytnij pustą przestrzeń przed i po zawartości oraz puste linie",
"trim-prefix-description": "Przytnij pierwszy znak z każdej linii",
@@ -1427,5 +1428,13 @@
"is-like": "jest jak",
"is-not-like": "nie jest jak"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -342,9 +342,9 @@
"breakfast": "Café da manhã",
"lunch": "Almoço",
"dinner": "Jantar",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"snack": "Lanche",
"drink": "Bebida",
"dessert": "Sobremesa",
"type-any": "Qualquer",
"day-any": "Qualquer",
"editor": "Editor",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Enviar uma Receita",
"upload-individual-zip-file": "Enviar um arquivo .zip individual exportado a partir de outra instância do Mealie.",
"url-form-hint": "Copie e cole um link do seu site de receita favorito",
"copy-and-paste-the-source-url-of-your-data-optional": "Copie e cole o URL de origem dos seus dados (opcional)",
"view-scraped-data": "Visualizar Dados Rastreados",
"trim-whitespace-description": "Aparar o espaço em branco e à direita, bem como linhas em branco",
"trim-prefix-description": "Aparar primeiro caractere de cada linha",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Tente o importador em massa",
"scrape-recipe-have-raw-html-or-json-data": "Tem dados HTML ou JSON brutos?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Você pode importar diretamente de dados brutos",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Site sendo bloqueado?",
"scrape-recipe-try-importing-raw-html-instead": "Tente importar o HTML ao invés disso.",
"import-original-keywords-as-tags": "Importar palavras-chave originais como marcadores",
"stay-in-edit-mode": "Permanecer no modo de edição",
"parse-recipe-ingredients-after-import": "Interpretar os ingredientes da receita após importar",
@@ -1427,5 +1428,13 @@
"is-like": "é como",
"is-not-like": "não é como"
}
},
"validators": {
"required": "Este campo é obrigatório",
"invalid-email": "O e-mail deve ser válido",
"invalid-url": "Precisa ser uma URL válida",
"no-whitespace": "Nenhum espaço em branco é permitido",
"min-length": "Precisa ter pelo menos {min} caracteres",
"max-length": "Pode ter até {max} caracteres"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Enviar uma Receita",
"upload-individual-zip-file": "Carregar um ficheiro .zip individual, exportado de outra instância do Mealie.",
"url-form-hint": "Copie e cole um link do seu site de receitas favorito",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Ver dados recolhidos",
"trim-whitespace-description": "Eliminar os espaços em branco no início e no fim, bem como as linhas em branco",
"trim-prefix-description": "Apagar o primeiro caractere de cada linha",
@@ -1427,5 +1428,13 @@
"is-like": "é como",
"is-not-like": "não é como"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Încarcă o rețetă",
"upload-individual-zip-file": "Încărcaţi un fişier individual .zip exportat dintr-o altă instanţă de Mealie.",
"url-form-hint": "Copiază și lipește un link de pe site-ul tău web preferat de rețete",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Vezi datele colectate",
"trim-whitespace-description": "Elimină spațiile albe de la început și sfârșit precum și liniile goale",
"trim-prefix-description": "Elimină primul caracter din fiecare linie",
@@ -1427,5 +1428,13 @@
"is-like": "este similar",
"is-not-like": "nu este similar"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -19,10 +19,10 @@
"log-lines": "Строки журнала",
"not-demo": "Не демо",
"portfolio": "Портфолио",
"production": "Production",
"production": "Продуктивная среда",
"support": "Поддержка",
"version": "Версия",
"unknown-version": "неизвестно",
"unknown-version": "Неизвестная версия",
"sponsor": "Спонсор"
},
"asset": {
@@ -342,9 +342,9 @@
"breakfast": "Завтрак",
"lunch": "Обед",
"dinner": "Ужин",
"snack": "Snack",
"drink": "Drink",
"dessert": "Dessert",
"snack": "Закуска",
"drink": "Напиток",
"dessert": "Десерт",
"type-any": "Любой",
"day-any": "Любой",
"editor": "Редактор",
@@ -445,6 +445,7 @@
"upload-a-recipe": "Загрузить рецепт",
"upload-individual-zip-file": "Загрузить отдельный .zip файл, экспортированный из другой Mealie.",
"url-form-hint": "Скопируйте и вставьте ссылку из вашего любимого сайта рецептов",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Просмотр отсканированных данных",
"trim-whitespace-description": "Обрезать ведущие и конечные пробелы, а также пустые строки",
"trim-prefix-description": "Обрезать первый символ из каждой строки",
@@ -636,8 +637,8 @@
"scrape-recipe-suggest-bulk-importer": "Воспользуйтесь массовым импортом",
"scrape-recipe-have-raw-html-or-json-data": "У Вас есть данные HTML или JSON?",
"scrape-recipe-you-can-import-from-raw-data-directly": "Вы можете импортировать напрямую из необработанных данных",
"scrape-recipe-website-being-blocked": "Website being blocked?",
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
"scrape-recipe-website-being-blocked": "Сайт заблокирован?",
"scrape-recipe-try-importing-raw-html-instead": "Попробуйте импортировать необработанный HTML файл.",
"import-original-keywords-as-tags": "Импортировать исходные ключевые слова как теги",
"stay-in-edit-mode": "Остаться в режиме редактирования",
"parse-recipe-ingredients-after-import": "Распознавание ингредиентов рецепта после импорта",
@@ -1427,5 +1428,13 @@
"is-like": "содержит",
"is-not-like": "не содержит"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Nahrať recept",
"upload-individual-zip-file": "Nahrať súbor .zip exportovaný z inej Mealie inštalácie.",
"url-form-hint": "Okopírujte a zložte odkaz z vašej obľúbenej webstránky",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Náhľad získaných údajov",
"trim-whitespace-description": "Vymazať medzery a prázdne riadky na začiatku a na konci",
"trim-prefix-description": "Vymazať prvé písmeno z každého riadku",
@@ -1427,5 +1428,13 @@
"is-like": "je ako",
"is-not-like": "nie je ako"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Naloži recept",
"upload-individual-zip-file": "Naloži posamezno .zip datoteko, izvoženo iz druge Mealie namestitve.",
"url-form-hint": "Kopiraj in prilepi povezavo iz vaše priljubljene strani z recepti",
"copy-and-paste-the-source-url-of-your-data-optional": "Kopirajte in prilepite izvorni URL svojih podatkov (neobvezno)",
"view-scraped-data": "Poglej postrgane podatke",
"trim-whitespace-description": "Poreži začetne in končne presledke, kot tudi prazne vrstice",
"trim-prefix-description": "Poreži prvi znak v vsaki vrstici",
@@ -1427,5 +1428,13 @@
"is-like": "je kot",
"is-not-like": "ni kot"
}
},
"validators": {
"required": "To polje je obvezno",
"invalid-email": "E-pošta mora biti veljavna",
"invalid-url": "URL mora biti veljaven",
"no-whitespace": "Presledki niso dovoljeni",
"min-length": "Mora vsebovati vsaj {min} znakov",
"max-length": "Lahko je največ {max} znakov"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Upload a Recipe",
"upload-individual-zip-file": "Upload an individual .zip file exported from another Mealie instance.",
"url-form-hint": "Копирајте и налепите везу са вашег омиљеног сајта за рецепте",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "View Scraped Data",
"trim-whitespace-description": "Trim leading and trailing whitespace as well as blank lines",
"trim-prefix-description": "Trim first character from each line",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Ladda upp ett recept",
"upload-individual-zip-file": "Ladda upp en individuell .zip-fil som exporteras från en annan Mealie-instans.",
"url-form-hint": "Kopiera och klistra in en länk från din favorit recept webbplats",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Visa skrapade data",
"trim-whitespace-description": "Ta bort inledande och avslutande blanksteg samt tomma rader",
"trim-prefix-description": "Ta bort första tecknet från varje rad",
@@ -1427,5 +1428,13 @@
"is-like": "är som",
"is-not-like": "är inte som"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Tarif Yükle",
"upload-individual-zip-file": "Başka bir Mealie örneğinden dışa aktarılan ayrı bir .zip dosyası yükleyin.",
"url-form-hint": "Favori tarif sitenizden bir bağlantıyı kopyalayıp yapıştırın",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Kazınmış Verileri Görüntüle",
"trim-whitespace-description": "Baştaki ve sondaki boşlukların yanı sıra boş satırları da kırpın",
"trim-prefix-description": "Her satırın ilk karakterini kırpın",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Завантажити рецепт",
"upload-individual-zip-file": "Завантажити окремий .zip файл, експортований з іншого Mealie.",
"url-form-hint": "Скопіюйте та вставте посилання з вашого улюбленого кулінарного веб-сайту",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "Переглянути зібрані дані",
"trim-whitespace-description": "Обрізати початкові та кінцеву пробілів і порожні лінії",
"trim-prefix-description": "Обрізати перший символ з кожного рядка",
@@ -1427,5 +1428,13 @@
"is-like": "схожий",
"is-not-like": "не схожий"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "Upload a Recipe",
"upload-individual-zip-file": "Upload an individual .zip file exported from another Mealie instance.",
"url-form-hint": "Copy and paste a link from your favorite recipe website",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "View Scraped Data",
"trim-whitespace-description": "Trim leading and trailing whitespace as well as blank lines",
"trim-prefix-description": "Trim first character from each line",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "上传食谱",
"upload-individual-zip-file": "上传从Mealie导出的.zip文件。",
"url-form-hint": "从您最喜爱的食谱网站复制并粘贴链接",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "查看爬取的数据",
"trim-whitespace-description": "删除开头和结尾的空格和空行",
"trim-prefix-description": "删除每行的首个字符",
@@ -1427,5 +1428,13 @@
"is-like": "匹配",
"is-not-like": "不匹配"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -445,6 +445,7 @@
"upload-a-recipe": "上傳食譜",
"upload-individual-zip-file": "上傳從另一個Mealie匯出的zip壓縮檔",
"url-form-hint": "複製您最喜歡的食譜網站的網址並在此貼上",
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
"view-scraped-data": "查看網頁擷取資料",
"trim-whitespace-description": "Trim leading and trailing whitespace as well as blank lines",
"trim-prefix-description": "Trim first character from each line",
@@ -1427,5 +1428,13 @@
"is-like": "is like",
"is-not-like": "is not like"
}
},
"validators": {
"required": "This Field is Required",
"invalid-email": "Email Must Be Valid",
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
}
}

View File

@@ -110,80 +110,6 @@ export interface CreateBackup {
options: BackupOptions;
templates?: string[] | null;
}
export interface CustomPageBase {
name: string;
slug: string | null;
position: number;
categories?: RecipeCategoryResponse[];
}
export interface RecipeCategoryResponse {
name: string;
id: string;
groupId?: string | null;
slug: string;
recipes?: RecipeSummary[];
}
export interface RecipeSummary {
id?: string | null;
userId?: string;
householdId?: string;
groupId?: string;
name?: string | null;
slug?: string;
image?: unknown;
recipeServings?: number;
recipeYieldQuantity?: number;
recipeYield?: string | null;
totalTime?: string | null;
prepTime?: string | null;
cookTime?: string | null;
performTime?: string | null;
description?: string | null;
recipeCategory?: RecipeCategory[] | null;
tags?: RecipeTag[] | null;
tools?: RecipeTool[];
rating?: number | null;
orgURL?: string | null;
dateAdded?: string | null;
dateUpdated?: string | null;
createdAt?: string | null;
updatedAt?: string | null;
lastMade?: string | null;
}
export interface RecipeCategory {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
[k: string]: unknown;
}
export interface RecipeTag {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
[k: string]: unknown;
}
export interface RecipeTool {
id: string;
groupId?: string | null;
name: string;
slug: string;
householdsWithTool?: string[];
[k: string]: unknown;
}
export interface CustomPageImport {
name: string;
status: boolean;
exception?: string | null;
}
export interface CustomPageOut {
name: string;
slug: string | null;
position: number;
categories?: RecipeCategoryResponse[];
id: number;
}
export interface DebugResponse {
success: boolean;
response?: string | null;
@@ -248,11 +174,6 @@ export interface Migrations {
type: string;
files?: MigrationFile[];
}
export interface NotificationImport {
name: string;
status: boolean;
exception?: string | null;
}
export interface RecipeImport {
name: string;
status: boolean;

View File

@@ -44,7 +44,6 @@ export interface QueryFilterJSONPart {
attributeName?: string | null;
relationalOperator?: RelationalKeyword | RelationalOperator | null;
value?: string | string[] | null;
[k: string]: unknown;
}
export interface SaveCookBook {
name: string;

View File

@@ -334,7 +334,6 @@ export interface IngredientUnit {
}
export interface IngredientUnitAlias {
name: string;
[k: string]: unknown;
}
export interface CreateIngredientUnit {
id?: string | null;
@@ -349,11 +348,9 @@ export interface CreateIngredientUnit {
pluralAbbreviation?: string | null;
useAbbreviation?: boolean;
aliases?: CreateIngredientUnitAlias[];
[k: string]: unknown;
}
export interface CreateIngredientUnitAlias {
name: string;
[k: string]: unknown;
}
export interface IngredientFood {
id: string;
@@ -372,7 +369,6 @@ export interface IngredientFood {
}
export interface IngredientFoodAlias {
name: string;
[k: string]: unknown;
}
export interface MultiPurposeLabelSummary {
name: string;
@@ -391,11 +387,9 @@ export interface CreateIngredientFood {
labelId?: string | null;
aliases?: CreateIngredientFoodAlias[];
householdsWithIngredientFood?: string[];
[k: string]: unknown;
}
export interface CreateIngredientFoodAlias {
name: string;
[k: string]: unknown;
}
export interface Recipe {
id?: string | null;
@@ -433,21 +427,18 @@ export interface Recipe {
[k: string]: unknown;
} | null;
comments?: RecipeCommentOut[] | null;
[k: string]: unknown;
}
export interface RecipeCategory {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
[k: string]: unknown;
}
export interface RecipeTag {
id?: string | null;
groupId?: string | null;
name: string;
slug: string;
[k: string]: unknown;
}
export interface RecipeTool {
id: string;
@@ -455,7 +446,6 @@ export interface RecipeTool {
name: string;
slug: string;
householdsWithTool?: string[];
[k: string]: unknown;
}
export interface RecipeStep {
id?: string | null;
@@ -463,11 +453,9 @@ export interface RecipeStep {
summary?: string | null;
text: string;
ingredientReferences?: IngredientReferences[];
[k: string]: unknown;
}
export interface IngredientReferences {
referenceId?: string | null;
[k: string]: unknown;
}
export interface Nutrition {
calories?: string | null;
@@ -481,7 +469,6 @@ export interface Nutrition {
sugarContent?: string | null;
transFatContent?: string | null;
unsaturatedFatContent?: string | null;
[k: string]: unknown;
}
export interface RecipeSettings {
public?: boolean;
@@ -490,18 +477,15 @@ export interface RecipeSettings {
landscapeView?: boolean;
disableComments?: boolean;
locked?: boolean;
[k: string]: unknown;
}
export interface RecipeAsset {
name: string;
icon: string;
fileName?: string | null;
[k: string]: unknown;
}
export interface RecipeNote {
title: string;
text: string;
[k: string]: unknown;
}
export interface RecipeCommentOut {
recipeId: string;
@@ -511,14 +495,12 @@ export interface RecipeCommentOut {
updatedAt: string;
userId: string;
user: UserBase;
[k: string]: unknown;
}
export interface UserBase {
id: string;
username?: string | null;
admin: boolean;
fullName?: string | null;
[k: string]: unknown;
}
export interface ShoppingListAddRecipeParamsBulk {
recipeIncrementQuantity?: number;

View File

@@ -510,6 +510,7 @@ export interface ScrapeRecipeBase {
export interface ScrapeRecipeData {
includeTags?: boolean;
data: string;
url?: string | null;
}
export interface ScrapeRecipeTest {
url: string;

View File

@@ -146,8 +146,8 @@ export class RecipeAPI extends BaseCRUDAPI<CreateRecipe, Recipe, Recipe> {
return await this.requests.post<Recipe | null>(routes.recipesTestScrapeUrl, { url, useOpenAI });
}
async createOneByHtmlOrJson(data: string, includeTags: boolean) {
return await this.requests.post<string>(routes.recipesCreateFromHtmlOrJson, { data, includeTags });
async createOneByHtmlOrJson(data: string, includeTags: boolean, url: string | null = null) {
return await this.requests.post<string>(routes.recipesCreateFromHtmlOrJson, { data, includeTags, url });
}
async createOneByUrl(url: string, includeTags: boolean) {

View File

@@ -1,2 +1,2 @@
export { scorePassword } from "./password";
export { required, email, whitespace, url, minLength, maxLength } from "./inputs";
export { required, email, whitespace, url, urlOptional, minLength, maxLength } from "./inputs";

View File

@@ -1,10 +1,33 @@
import { expect, test } from "vitest";
import { expect, test, vi } from "vitest";
import enUS from "~/lang/messages/en-US.json";
import { required, email, whitespace, url, minLength, maxLength } from "./inputs";
vi.mock("~/composables/use-global-i18n", () => {
const interpolate = (msg: string, params?: Record<string, unknown>) => {
if (!params) return msg;
return msg
.replace("{min}", String(params.min ?? ""))
.replace("{max}", String(params.max ?? ""));
};
const t = (key: string, params?: Record<string, unknown>) => {
const parts = key.split(".");
let acc: any = enUS as any;
for (const p of parts) acc = acc?.[p];
const msg: string | undefined = acc;
return interpolate(msg ?? key, params);
};
return { useGlobalI18n: () => ({ t }) };
});
export { scorePassword } from "./password";
// Tests
test("validator required", () => {
const falsey = "This Field is Required";
const falsey = enUS.validators.required;
expect(required("123")).toBe(true);
expect(required("")).toBe(falsey);
expect(required(undefined)).toBe(falsey);
@@ -14,7 +37,7 @@ test("validator required", () => {
const nulls = [undefined, null];
test("validator email", () => {
const falsey = "Email Must Be Valid";
const falsey = enUS.validators["invalid-email"];
expect(email("123")).toBe(falsey);
expect(email("email@example.com")).toBe(true);
@@ -24,7 +47,7 @@ test("validator email", () => {
});
test("whitespace", () => {
const falsey = "No Whitespace Allowed";
const falsey = enUS.validators["no-whitespace"];
expect(whitespace("123")).toBe(true);
expect(whitespace(" ")).toBe(falsey);
expect(whitespace("123 123")).toBe(falsey);
@@ -35,7 +58,7 @@ test("whitespace", () => {
});
test("url", () => {
const falsey = "Must Be A Valid URL";
const falsey = enUS.validators["invalid-url"];
expect(url("https://example.com")).toBe(true);
expect(url("")).toBe(falsey);
@@ -46,7 +69,7 @@ test("url", () => {
test("minLength", () => {
const min = 3;
const falsey = `Must Be At Least ${min} Characters`;
const falsey = enUS.validators["min-length"].replace("{min}", String(min));
const fn = minLength(min);
expect(fn("123")).toBe(true);
expect(fn("12")).toBe(falsey);
@@ -59,7 +82,7 @@ test("minLength", () => {
test("maxLength", () => {
const max = 3;
const falsey = `Must Be At Most ${max} Characters`;
const falsey = enUS.validators["max-length"].replace("{max}", String(max));
const fn = maxLength(max);
expect(fn("123")).toBe(true);
expect(fn("1234")).toBe(falsey);

View File

@@ -1,28 +1,40 @@
import { useGlobalI18n } from "~/composables/use-global-i18n";
const EMAIL_REGEX
= /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
const URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
export function required(v: string | undefined | null) {
return !!v || "This Field is Required";
const i18n = useGlobalI18n();
return !!v || i18n.t("validators.required");
}
export function email(v: string | undefined | null) {
return (!!v && EMAIL_REGEX.test(v)) || "Email Must Be Valid";
const i18n = useGlobalI18n();
return (!!v && EMAIL_REGEX.test(v)) || i18n.t("validators.invalid-email");
}
export function whitespace(v: string | null | undefined) {
return (!!v && v.split(" ").length <= 1) || "No Whitespace Allowed";
const i18n = useGlobalI18n();
return (!!v && v.split(" ").length <= 1) || i18n.t("validators.no-whitespace");
}
export function url(v: string | undefined | null) {
return (!!v && URL_REGEX.test(v)) || "Must Be A Valid URL";
const i18n = useGlobalI18n();
return (!!v && URL_REGEX.test(v)) || i18n.t("validators.invalid-url");
}
export function urlOptional(v: string | undefined | null) {
return v ? url(v) : true;
}
export function minLength(min: number) {
return (v: string | undefined | null) => (!!v && v.length >= min) || `Must Be At Least ${min} Characters`;
const i18n = useGlobalI18n();
return (v: string | undefined | null) => (!!v && v.length >= min) || i18n.t("validators.min-length", { min });
}
export function maxLength(max: number) {
return (v: string | undefined | null) => !v || v.length <= max || `Must Be At Most ${max} Characters`;
const i18n = useGlobalI18n();
return (v: string | undefined | null) => !v || v.length <= max || i18n.t("validators.max-length", { max });
}

View File

@@ -257,6 +257,7 @@ export default defineNuxtConfig({
share_target: {
action: "/r/create/url",
method: "GET",
enctype: "application/x-www-form-urlencoded",
params: {
text: "recipe_import_url",
},

View File

@@ -1,6 +1,6 @@
{
"name": "mealie",
"version": "3.7.0",
"version": "3.9.2",
"private": true,
"scripts": {
"dev": "nuxt dev",
@@ -34,7 +34,7 @@
"vue-advanced-cropper": "^2.8.9",
"vue-draggable-plus": "^0.6.0",
"vuetify": "^3.9.7",
"vuetify-nuxt-module": "^0.18.8"
"vuetify-nuxt-module": "^0.18.9"
},
"devDependencies": {
"@nuxt/eslint": "^1.2.0",
@@ -58,6 +58,9 @@
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
"resolutions": {
"esbuild": ">=0.25.0"
"esbuild": ">=0.25.0",
"glob": ">=10.5.0",
"js-yaml": ">=4.1.1",
"node-forge": ">=1.3.2"
}
}

View File

@@ -37,7 +37,6 @@
$t('settings.backup.backup-restore-process-in-the-documentation') }}</a>
</template>
</i18n-t>
{{ $t('') }}
</p>
<v-checkbox
@@ -82,6 +81,7 @@
>
<BaseButton
class="mr-2"
:loading="runningBackup"
@click="createBackup"
>
{{ $t("settings.backup.create-heading") }}
@@ -183,6 +183,7 @@ export default defineNuxtComponent({
}
async function createBackup() {
state.runningBackup = true;
const { data } = await adminApi.backups.create();
if (data?.error === false) {
@@ -192,6 +193,7 @@ export default defineNuxtComponent({
else {
alert.error(i18n.t("settings.backup.error-creating-backup-see-log-file"));
}
state.runningBackup = false;
}
async function restoreBackup(fileName: string) {
@@ -228,6 +230,7 @@ export default defineNuxtComponent({
deleteDialog: false,
createDialog: false,
importDialog: false,
runningBackup: false,
runningRestore: false,
search: "",
headers: [
@@ -239,7 +242,7 @@ export default defineNuxtComponent({
});
function setSelected(data: { name: string; date: string }) {
if (selected.value === null || selected.value === undefined) {
if (!data.name) {
return;
}
selected.value = data.name;

View File

@@ -1,7 +1,7 @@
<template>
<v-form
ref="domUrlForm"
@submit.prevent="createFromHtmlOrJson(newRecipeData, importKeywordsAsTags)"
@submit.prevent="createFromHtmlOrJson(newRecipeData, importKeywordsAsTags, newRecipeUrl)"
>
<div>
<v-card-title class="headline">
@@ -21,14 +21,28 @@
<v-switch
v-model="isEditJSON"
:label="$t('recipe.json-editor')"
color="primary"
class="mt-2"
@change="handleIsEditJson"
/>
<v-text-field
v-model="newRecipeUrl"
:label="$t('new-recipe.recipe-url')"
:prepend-inner-icon="$globals.icons.link"
validate-on="blur"
variant="solo-filled"
clearable
rounded
:rules="[validators.urlOptional]"
:hint="$t('new-recipe.copy-and-paste-the-source-url-of-your-data-optional')"
persistent-hint
class="mt-10 mb-4"
style="max-width: 500px"
/>
<RecipeJsonEditor
v-if="isEditJSON"
v-model="newRecipeData"
height="250px"
class="mt-10"
mode="code"
:main-menu-bar="false"
/>
@@ -41,10 +55,7 @@
autofocus
variant="solo-filled"
clearable
class="rounded-lg mt-2"
rounded
:hint="$t('new-recipe.url-form-hint')"
persistent-hint
/>
<v-checkbox
v-model="importKeywordsAsTags"
@@ -124,6 +135,7 @@ export default defineNuxtComponent({
}
const newRecipeData = ref<string | object | null>(null);
const newRecipeUrl = ref<string | null>(null);
function handleIsEditJson() {
if (state.isEditJSON) {
@@ -148,8 +160,13 @@ export default defineNuxtComponent({
}
handleIsEditJson();
async function createFromHtmlOrJson(htmlOrJsonData: string | object | null, importKeywordsAsTags: boolean) {
if (!htmlOrJsonData || !domUrlForm.value?.validate()) {
async function createFromHtmlOrJson(htmlOrJsonData: string | object | null, importKeywordsAsTags: boolean, url: string | null = null) {
if (!htmlOrJsonData) {
return;
}
const isValid = await domUrlForm.value?.validate();
if (!isValid?.valid) {
return;
}
@@ -162,7 +179,7 @@ export default defineNuxtComponent({
}
state.loading = true;
const { response } = await api.recipes.createOneByHtmlOrJson(dataString, importKeywordsAsTags);
const { response } = await api.recipes.createOneByHtmlOrJson(dataString, importKeywordsAsTags, url);
handleResponse(response, importKeywordsAsTags);
}
@@ -172,6 +189,7 @@ export default defineNuxtComponent({
stayInEditMode,
parseRecipe,
newRecipeData,
newRecipeUrl,
handleIsEditJson,
createFromHtmlOrJson,
...toRefs(state),

View File

@@ -134,18 +134,22 @@
<v-card>
<v-card-text>
<div>
<v-text-field
<v-number-input
v-model="settings.maxMissingFoods"
type="number"
:precision="null"
:min="0"
control-variant="stacked"
inset
hide-details
hide-spin-buttons
:label="$t('recipe-finder.max-missing-ingredients')"
/>
<v-text-field
<v-number-input
v-model="settings.maxMissingTools"
type="number"
:precision="null"
:min="0"
control-variant="stacked"
inset
hide-details
hide-spin-buttons
:label="$t('recipe-finder.max-missing-tools')"
class="mt-4"
/>

View File

@@ -209,12 +209,8 @@ export default defineNuxtComponent({
}
async function deleteSelected() {
for (const item of bulkDeleteTarget.value) {
if (!item.id) {
continue;
}
await categoryStore.actions.deleteOne(item.id);
}
const ids = bulkDeleteTarget.value.map(item => item.id).filter(id => !!id);
await categoryStore.actions.deleteMany(ids);
bulkDeleteTarget.value = [];
}

View File

@@ -528,9 +528,8 @@ export default defineNuxtComponent({
}
async function deleteSelected() {
for (const item of bulkDeleteTarget.value) {
await foodStore.actions.deleteOne(item.id);
}
const ids = bulkDeleteTarget.value.map(item => item.id);
await foodStore.actions.deleteMany(ids);
bulkDeleteTarget.value = [];
}

View File

@@ -261,9 +261,8 @@ export default defineNuxtComponent({
}
async function deleteSelected() {
for (const item of bulkDeleteTarget.value) {
await labelStore.actions.deleteOne(item.id);
}
const ids = bulkDeleteTarget.value.map(item => item.id);
await labelStore.actions.deleteMany(ids);
bulkDeleteTarget.value = [];
}

View File

@@ -249,9 +249,8 @@ export default defineNuxtComponent({
}
async function deleteSelected() {
for (const item of bulkDeleteTarget.value) {
await actionStore.actions.deleteOne(item.id);
}
const ids = bulkDeleteTarget.value.map(item => item.id);
await actionStore.actions.deleteMany(ids);
bulkDeleteTarget.value = [];
}

View File

@@ -211,12 +211,8 @@ export default defineNuxtComponent({
}
async function deleteSelected() {
for (const item of bulkDeleteTarget.value) {
if (!item.id) {
continue;
}
await tagStore.actions.deleteOne(item.id);
}
const ids = bulkDeleteTarget.value.map(item => item.id).filter(id => !!id);
await tagStore.actions.deleteMany(ids);
bulkDeleteTarget.value = [];
}

View File

@@ -263,9 +263,8 @@ export default defineNuxtComponent({
}
async function deleteSelected() {
for (const item of bulkDeleteTarget.value) {
await toolStore.actions.deleteOne(item.id);
}
const ids = bulkDeleteTarget.value.map(item => item.id);
await toolStore.actions.deleteMany(ids);
bulkDeleteTarget.value = [];
}

View File

@@ -465,9 +465,8 @@ export default defineNuxtComponent({
}
async function deleteSelected() {
for (const item of bulkDeleteTarget.value) {
await unitActions.deleteOne(item.id);
}
const ids = bulkDeleteTarget.value.map(item => item.id);
await unitActions.deleteMany(ids);
bulkDeleteTarget.value = [];
}

View File

@@ -30,9 +30,11 @@
/>
<v-card-text>
<v-text-field
<v-number-input
v-model="numberOfDays"
type="number"
:min="1"
control-variant="stacked"
inset
:label="$t('meal-plan.numberOfDays-label')"
:hint="$t('meal-plan.numberOfDays-hint')"
persistent-hint
@@ -43,10 +45,10 @@
<div class="d-flex flex-wrap align-center justify-space-between mb-2">
<v-tabs style="width: fit-content;">
<v-tab :to="`/household/mealplan/planner/view`">
<v-tab :to="{ name: 'household-mealplan-planner-view', query: route.query }">
{{ $t('meal-plan.meal-planner') }}
</v-tab>
<v-tab :to="`/household/mealplan/planner/edit`">
<v-tab :to="{ name: 'household-mealplan-planner-edit', query: route.query }">
{{ $t('general.edit') }}
</v-tab>
</v-tabs>
@@ -69,7 +71,7 @@
</template>
<script lang="ts">
import { isSameDay, addDays, parseISO } from "date-fns";
import { isSameDay, addDays, parseISO, format, isValid } from "date-fns";
import { useHouseholdSelf } from "~/composables/use-households";
import { useMealplans } from "~/composables/use-group-mealplan";
import { useUserMealPlanPreferences } from "~/composables/use-users/preferences";
@@ -93,14 +95,31 @@ export default defineNuxtComponent({
// Force to /view if current route is /planner
if (route.path === "/household/mealplan/planner") {
router.push("/household/mealplan/planner/view");
router.push({
name: "household-mealplan-planner-view",
query: route.query,
});
}
function safeParseISO(date: string, fallback: Date | undefined = undefined) {
try {
const parsed = parseISO(date);
return isValid(parsed) ? parsed : fallback;
}
catch {
return fallback;
}
}
// Initialize dates from query parameters or defaults
const initialStartDate = safeParseISO(route.query.start as string, new Date());
const initialEndDate = safeParseISO(route.query.end as string, addDays(new Date(), adjustForToday(numberOfDays.value)));
const state = ref({
range: [new Date(), addDays(new Date(), adjustForToday(numberOfDays.value))] as [Date, Date],
start: new Date(),
range: [initialStartDate, initialEndDate] as [Date, Date],
start: initialStartDate,
picker: false,
end: addDays(new Date(), adjustForToday(numberOfDays.value)),
end: initialEndDate,
});
const firstDayOfWeek = computed(() => {
@@ -122,6 +141,20 @@ export default defineNuxtComponent({
};
});
// Update query parameters when date range changes
watch(weekRange, (newRange) => {
// Keep current route name and params, just update the query
router.replace({
name: route.name || "household-mealplan-planner-view",
params: route.params,
query: {
...route.query,
start: format(newRange.start, "yyyy-MM-dd"),
end: format(newRange.end, "yyyy-MM-dd"),
},
});
}, { immediate: true });
const { mealplans, actions } = useMealplans(weekRange);
function filterMealByDate(date: Date) {
@@ -161,6 +194,7 @@ export default defineNuxtComponent({
});
return {
route,
state,
actions,
mealsByDate,

View File

@@ -179,41 +179,45 @@
</BaseButton>
</div>
<BaseExpansionPanels v-for="(value, key) in itemsByLabel" :key="key" :v-model="0" start-open>
<v-expansion-panel class="shopping-list-section">
<v-expansion-panel-title
:color="getLabelColor(key)"
class="body-1 font-weight-bold section-title"
>
{{ key }}
</v-expansion-panel-title>
<v-expansion-panel-text eager>
<VueDraggable
:model-value="value"
handle=".handle"
:delay="250"
:delay-on-touch-only="true"
@start="loadingCounter += 1"
@end="loadingCounter -= 1"
@update:model-value="updateIndexUncheckedByLabel(key.toString(), $event)"
<TransitionGroup name="scroll-x-transition">
<BaseExpansionPanels v-for="(value, key) in itemsByLabel" :key="key" :v-model="0" start-open>
<v-expansion-panel class="shopping-list-section">
<v-expansion-panel-title
:color="getLabelColor(key)"
class="body-1 font-weight-bold section-title"
>
<ShoppingListItem
v-for="(item, index) in value"
:key="item.id"
v-model="value[index]"
class="ml-2 my-2 w-auto"
:labels="allLabels || []"
:units="allUnits || []"
:foods="allFoods || []"
:recipes="recipeMap"
@checked="saveListItem"
@save="saveListItem"
@delete="deleteListItem(item)"
/>
</VueDraggable>
</v-expansion-panel-text>
</v-expansion-panel>
</BaseExpansionPanels>
{{ key }}
</v-expansion-panel-title>
<v-expansion-panel-text eager>
<VueDraggable
:model-value="value"
handle=".handle"
:delay="250"
:delay-on-touch-only="true"
@start="loadingCounter += 1"
@end="loadingCounter -= 1"
@update:model-value="updateIndexUncheckedByLabel(key.toString(), $event)"
>
<TransitionGroup name="scroll-x-transition">
<ShoppingListItem
v-for="(item, index) in value"
:key="item.id"
v-model="value[index]"
class="ml-2 my-2 w-auto"
:labels="allLabels || []"
:units="allUnits || []"
:foods="allFoods || []"
:recipes="recipeMap"
@checked="saveListItem"
@save="saveListItem"
@delete="deleteListItem(item)"
/>
</TransitionGroup>
</VueDraggable>
</v-expansion-panel-text>
</v-expansion-panel>
</BaseExpansionPanels>
</TransitionGroup>
<!-- Checked Items -->
<v-expansion-panels flat>
<v-expansion-panel v-if="listItems.checked && listItems.checked.length > 0">
@@ -243,18 +247,20 @@
</div>
</v-expansion-panel-title>
<v-expansion-panel-text eager>
<div v-for="(item, idx) in listItems.checked" :key="item.id">
<ShoppingListItem
v-model="listItems.checked[idx]"
class="strike-through-note"
:labels="allLabels || []"
:units="allUnits || []"
:foods="allFoods || []"
@checked="saveListItem"
@save="saveListItem"
@delete="deleteListItem(item)"
/>
</div>
<TransitionGroup name="scroll-x-transition">
<div v-for="(item, idx) in listItems.checked" :key="item.id">
<ShoppingListItem
v-model="listItems.checked[idx]"
class="strike-through-note"
:labels="allLabels || []"
:units="allUnits || []"
:foods="allFoods || []"
@checked="saveListItem"
@save="saveListItem"
@delete="deleteListItem(item)"
/>
</div>
</TransitionGroup>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -27,7 +27,6 @@ import type HelpIcon from "@/components/global/HelpIcon.vue";
import type ImageCropper from "@/components/global/ImageCropper.vue";
import type InputColor from "@/components/global/InputColor.vue";
import type InputLabelType from "@/components/global/InputLabelType.vue";
import type InputQuantity from "@/components/global/InputQuantity.vue";
import type LanguageDialog from "@/components/global/LanguageDialog.vue";
import type MarkdownEditor from "@/components/global/MarkdownEditor.vue";
import type RecipeJsonEditor from "@/components/global/RecipeJsonEditor.vue";
@@ -69,7 +68,6 @@ declare module "vue" {
ImageCropper: typeof ImageCropper;
InputColor: typeof InputColor;
InputLabelType: typeof InputLabelType;
InputQuantity: typeof InputQuantity;
LanguageDialog: typeof LanguageDialog;
MarkdownEditor: typeof MarkdownEditor;
RecipeJsonEditor: typeof RecipeJsonEditor;

View File

@@ -1550,18 +1550,6 @@
dependencies:
"@isaacs/balanced-match" "^4.0.1"
"@isaacs/cliui@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
dependencies:
string-width "^5.1.2"
string-width-cjs "npm:string-width@^4.2.0"
strip-ansi "^7.0.1"
strip-ansi-cjs "npm:strip-ansi@^6.0.1"
wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
"@isaacs/fs-minipass@^4.0.0":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32"
@@ -2689,11 +2677,6 @@
"@parcel/watcher-win32-ia32" "2.5.1"
"@parcel/watcher-win32-x64" "2.5.1"
"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@pkgr/core@^0.1.0":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.2.tgz#1cf95080bb7072fafaa3cb13b442fab4695c3893"
@@ -4108,7 +4091,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1:
ansi-styles@^6.0.0, ansi-styles@^6.2.1:
version "6.2.3"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041"
integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==
@@ -5309,11 +5292,6 @@ duplexer@^0.1.2:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
eastasianwidth@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
easy-bem@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/easy-bem/-/easy-bem-1.1.1.tgz#1bfcc10425498090bcfddc0f9c000aba91399e03"
@@ -5346,11 +5324,6 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
emoji-regex@^9.2.2:
version "9.2.2"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
encodeurl@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
@@ -6320,14 +6293,6 @@ for-each@^0.3.3, for-each@^0.3.5:
dependencies:
is-callable "^1.2.7"
foreground-child@^3.1.0:
version "3.3.1"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
dependencies:
cross-spawn "^7.0.6"
signal-exit "^4.0.1"
form-data@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4"
@@ -6359,11 +6324,6 @@ fs-extra@^9.0.1:
jsonfile "^6.0.1"
universalify "^2.0.0"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
@@ -6522,29 +6482,14 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
glob@^10.0.0, glob@^10.4.5:
version "10.4.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
glob@>=10.5.0, glob@^10.0.0, glob@^10.4.5, glob@^7.1.6:
version "13.0.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-13.0.0.tgz#9d9233a4a274fc28ef7adce5508b7ef6237a1be3"
integrity sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==
dependencies:
foreground-child "^3.1.0"
jackspeak "^3.1.2"
minimatch "^9.0.4"
minimatch "^10.1.1"
minipass "^7.1.2"
package-json-from-dist "^1.0.0"
path-scurry "^1.11.1"
glob@^7.1.6:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.1.1"
once "^1.3.0"
path-is-absolute "^1.0.0"
path-scurry "^2.0.0"
global-directory@^4.0.1:
version "4.0.1"
@@ -6835,15 +6780,7 @@ indent-string@^5.0.0:
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5"
integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@2.0.4, inherits@~2.0.3:
inherits@2.0.4, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -7269,15 +7206,6 @@ isomorphic-dompurify@^2.28.0:
dompurify "^3.2.7"
jsdom "^27.0.0"
jackspeak@^3.1.2:
version "3.4.3"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
dependencies:
"@isaacs/cliui" "^8.0.2"
optionalDependencies:
"@pkgjs/parseargs" "^0.11.0"
jake@^10.8.5:
version "10.9.4"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.4.tgz#d626da108c63d5cfb00ab5c25fadc7e0084af8e6"
@@ -7339,10 +7267,10 @@ js-tokens@^9.0.1:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4"
integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
js-yaml@>=4.1.1, js-yaml@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b"
integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==
dependencies:
argparse "^2.0.1"
@@ -7729,11 +7657,16 @@ loupe@^3.1.0, loupe@^3.1.4:
resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76"
integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==
lru-cache@^10.2.0, lru-cache@^10.4.3:
lru-cache@^10.4.3:
version "10.4.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
lru-cache@^11.0.0:
version "11.2.4"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.4.tgz#ecb523ebb0e6f4d837c807ad1abaea8e0619770d"
integrity sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==
lru-cache@^11.2.1:
version "11.2.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.2.tgz#40fd37edffcfae4b2940379c0722dc6eeaa75f24"
@@ -7911,7 +7844,14 @@ minimatch@9.0.3:
dependencies:
brace-expansion "^2.0.1"
minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
minimatch@^10.1.1:
version "10.1.1"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.1.1.tgz#e6e61b9b0c1dcab116b5a7d1458e8b6ae9e73a55"
integrity sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==
dependencies:
"@isaacs/brace-expansion" "^5.0.0"
minimatch@^3.0.4, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -7944,7 +7884,7 @@ minimist@^1.2.0, minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2:
minipass@^7.0.4, minipass@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
@@ -8119,10 +8059,10 @@ node-fetch@^2.6.7, node-fetch@^2.7.0:
dependencies:
whatwg-url "^5.0.0"
node-forge@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
node-forge@>=1.3.2, node-forge@^1.3.1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.3.tgz#0ad80f6333b3a0045e827ac20b7f735f93716751"
integrity sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==
node-gyp-build@^4.2.2:
version "4.8.4"
@@ -8339,13 +8279,6 @@ on-finished@^2.4.1:
dependencies:
ee-first "1.1.1"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
onetime@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
@@ -8541,11 +8474,6 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
package-json-from-dist@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
package-manager-detector@^1.1.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.5.0.tgz#8dcf7b78554047ddf5da453e6ba07ebc915c507e"
@@ -8637,11 +8565,6 @@ path-exists@^5.0.0:
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7"
integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
@@ -8657,13 +8580,13 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-scurry@^1.11.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
path-scurry@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.1.tgz#4b6572376cfd8b811fca9cd1f5c24b3cbac0fe10"
integrity sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==
dependencies:
lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
lru-cache "^11.0.0"
minipass "^7.1.2"
path-type@^4.0.0:
version "4.0.0"
@@ -9778,7 +9701,7 @@ siginfo@^2.0.0:
resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30"
integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==
signal-exit@^4.0.1, signal-exit@^4.1.0:
signal-exit@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
@@ -9973,15 +9896,6 @@ string-argv@^0.3.2:
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@@ -9991,15 +9905,6 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
dependencies:
eastasianwidth "^0.2.0"
emoji-regex "^9.2.2"
strip-ansi "^7.0.1"
string-width@^7.0.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc"
@@ -10083,13 +9988,6 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@@ -10097,7 +9995,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
strip-ansi@^7.1.0:
version "7.1.2"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba"
integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==
@@ -11082,7 +10980,7 @@ vite-plugin-vue-tracer@^1.0.1:
pathe "^2.0.3"
source-map-js "^1.2.1"
vite-plugin-vuetify@^2.1.0:
vite-plugin-vuetify@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/vite-plugin-vuetify/-/vite-plugin-vuetify-2.1.2.tgz#8e28dcb5b20f4635d350010547654cf2b4dad373"
integrity sha512-I/wd6QS+DO6lHmuGoi1UTyvvBTQ2KDzQZ9oowJQEJ6OcjWfJnscYXx2ptm6S7fJSASuZT8jGRBL3LV4oS3LpaA==
@@ -11224,10 +11122,10 @@ vue@^3.4, vue@^3.5.13, vue@^3.5.22:
"@vue/server-renderer" "3.5.22"
"@vue/shared" "3.5.22"
vuetify-nuxt-module@^0.18.8:
version "0.18.8"
resolved "https://registry.yarnpkg.com/vuetify-nuxt-module/-/vuetify-nuxt-module-0.18.8.tgz#04b7b04606cbf22cb9b8317309db6166a8058654"
integrity sha512-57J0MgmRTyEX4ZIIXZUyY+UodDi+hoJ9/UnUZQoBbpTc/9WAZyRonaJedIcHLnTBKyIxxWdvtWHkJdosngX3NQ==
vuetify-nuxt-module@^0.18.9:
version "0.18.9"
resolved "https://registry.yarnpkg.com/vuetify-nuxt-module/-/vuetify-nuxt-module-0.18.9.tgz#154b8f8e689da4fac3bcb2372ef0e745b8e0b536"
integrity sha512-jr+Hujsw5U465LKJD1/SQgqJIXuJNbXM0HOp9vPmtPFPlGFwZ4kb1YfUPNmuCEDaSIY6rkb7+W+FEJvt9PQELQ==
dependencies:
"@nuxt/kit" "^3.12.4"
defu "^6.1.4"
@@ -11238,7 +11136,7 @@ vuetify-nuxt-module@^0.18.8:
ufo "^1.5.4"
unconfig "^0.5.5"
upath "^2.0.1"
vite-plugin-vuetify "^2.1.0"
vite-plugin-vuetify "^2.1.2"
vuetify "^3.7.0"
vuetify@^3.7.0:
@@ -11558,15 +11456,6 @@ workbox-window@7.3.0, workbox-window@^7.3.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.3.0"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@@ -11576,15 +11465,6 @@ wrap-ansi@^7.0.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
dependencies:
ansi-styles "^6.1.0"
string-width "^5.0.1"
strip-ansi "^7.0.1"
wrap-ansi@^9.0.0:
version "9.0.2"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz#956832dea9494306e6d209eb871643bb873d7c98"
@@ -11594,11 +11474,6 @@ wrap-ansi@^9.0.0:
string-width "^7.0.0"
strip-ansi "^7.1.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
ws@^8.18.2, ws@^8.18.3:
version "8.18.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472"

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