Merge branch 'mealie-next' into fix/translation-issues-when-scraping

This commit is contained in:
Michael Genson 2024-01-02 19:17:26 -06:00 committed by GitHub
commit e90f05d2dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 1047 additions and 2503 deletions

View File

@ -67,7 +67,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install libsasl2-dev libldap2-dev libssl-dev tesseract-ocr-all sudo apt-get install libsasl2-dev libldap2-dev libssl-dev
poetry install poetry install
poetry add "psycopg2-binary==2.8.6" poetry add "psycopg2-binary==2.8.6"
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' || steps.cache-validate.outputs.cache-hit-success != 'true' if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' || steps.cache-validate.outputs.cache-hit-success != 'true'

View File

@ -50,7 +50,6 @@ RUN apt-get update \
build-essential \ build-essential \
libpq-dev \ libpq-dev \
libwebp-dev \ libwebp-dev \
tesseract-ocr-all \
# LDAP Dependencies # LDAP Dependencies
libsasl2-dev libldap2-dev libssl-dev \ libsasl2-dev libldap2-dev libssl-dev \
gnupg gnupg2 gnupg1 \ gnupg gnupg2 gnupg1 \
@ -89,8 +88,8 @@ RUN apt-get update \
&& apt-get install --no-install-recommends -y \ && apt-get install --no-install-recommends -y \
gosu \ gosu \
iproute2 \ iproute2 \
tesseract-ocr-all \
libldap-common \ libldap-common \
libldap-2.5 \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# copying poetry and venv into image # copying poetry and venv into image

View File

@ -64,9 +64,7 @@ No. Due to limitations from the Javascript Framework, mealie doesn't support ser
## Can I install Mealie without docker? ## Can I install Mealie without docker?
Yes, you can install Mealie on your local machine. HOWEVER, it is recommended that you don't. Managing non-system versions of python, node, and npm is a pain. Moreover, updating and upgrading your system with this configuration is unsupported and will likely require manual interventions. If you insist on installing Mealie on your local machine, you can use the links below to help guide your path. Yes, you can install Mealie on your local machine. HOWEVER, it is recommended that you don't. Managing non-system versions of python, node, and npm is a pain. Moreover, updating and upgrading your system with this configuration is unsupported and will likely require manual interventions.
- [Advanced Installation](../installation/advanced/)
## What is fuzzy search and how do I use it? ## What is fuzzy search and how do I use it?
Mealie can use fuzzy search, which is robust to minor typos. For example, searching for "brocolli" will still find your recipe for "broccoli soup". But fuzzy search is only functional on a Postgres database backend. To enable fuzzy search you will need to migrate to Postgres: Mealie can use fuzzy search, which is robust to minor typos. For example, searching for "brocolli" will still find your recipe for "broccoli soup". But fuzzy search is only functional on a Postgres database backend. To enable fuzzy search you will need to migrate to Postgres:

View File

@ -46,7 +46,7 @@ services:
image: postgres:15 image: postgres:15
restart: always restart: always
volumes: volumes:
- ./mealie-pgdata:/var/lib/postgresql/data - mealie-pgdata:/var/lib/postgresql/data
environment: environment:
POSTGRES_PASSWORD: mealie POSTGRES_PASSWORD: mealie
POSTGRES_USER: mealie POSTGRES_USER: mealie

File diff suppressed because one or more lines are too long

View File

@ -102,7 +102,6 @@ const SAVE_EVENT = "save";
const DELETE_EVENT = "delete"; const DELETE_EVENT = "delete";
const CLOSE_EVENT = "close"; const CLOSE_EVENT = "close";
const JSON_EVENT = "json"; const JSON_EVENT = "json";
const OCR_EVENT = "ocr";
export default defineComponent({ export default defineComponent({
components: { RecipeContextMenu, RecipeFavoriteBadge, RecipeTimerMenu, RecipeTimelineBadge }, components: { RecipeContextMenu, RecipeFavoriteBadge, RecipeTimerMenu, RecipeTimelineBadge },
@ -139,10 +138,6 @@ export default defineComponent({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
showOcrButton: {
type: Boolean,
default: false,
},
}, },
setup(props, context) { setup(props, context) {
const deleteDialog = ref(false); const deleteDialog = ref(false);
@ -175,15 +170,6 @@ export default defineComponent({
}, },
]; ];
if (props.showOcrButton) {
editorButtons.splice(2, 0, {
text: i18n.t("ocr-editor.ocr-editor"),
icon: $globals.icons.eye,
event: OCR_EVENT,
color: "accent",
});
}
function emitHandler(event: string) { function emitHandler(event: string) {
switch (event) { switch (event) {
case CLOSE_EVENT: case CLOSE_EVENT:

View File

@ -143,7 +143,7 @@ export default defineComponent({
} }
const { share, isSupported: shareIsSupported } = useShare(); const { share, isSupported: shareIsSupported } = useShare();
const { copy } = useClipboard(); const { copy, copied, isSupported } = useClipboard();
function getRecipeText() { function getRecipeText() {
return i18n.t("recipe.share-recipe-message", [props.name]); return i18n.t("recipe.share-recipe-message", [props.name]);
@ -154,8 +154,18 @@ export default defineComponent({
} }
async function copyTokenLink(token: string) { async function copyTokenLink(token: string) {
await copy(getTokenLink(token)); if (isSupported.value) {
alert.success(i18n.t("recipe-share.recipe-link-copied-message") as string); await copy(getTokenLink(token));
if (copied.value) {
alert.success(i18n.t("recipe-share.recipe-link-copied-message") as string);
}
else {
alert.error(i18n.t("general.clipboard-copy-failure") as string);
}
}
else {
alert.error(i18n.t("general.clipboard-not-supported") as string);
}
} }
async function shareRecipe(token: string) { async function shareRecipe(token: string) {

View File

@ -1,390 +0,0 @@
<template>
<v-container
v-if="recipe && recipe.slug && recipe.settings && recipe.recipeIngredient"
:class="{
'pa-0': $vuetify.breakpoint.smAndDown,
}"
>
<BannerExperimental />
<div v-if="loading">
<v-spacer />
<v-progress-circular indeterminate class="" color="primary"> </v-progress-circular>
{{ loadingText }}
<v-spacer />
</div>
<v-row v-if="!loading">
<v-col cols="12" sm="7" md="7" lg="7">
<RecipeOcrEditorPageCanvas
:image="canvasImage"
:tsv="tsv"
@setText="canvasSetText"
@update-recipe="updateRecipe"
@close-editor="closeEditor"
@text-selected="updateSelectedText"
>
</RecipeOcrEditorPageCanvas>
<RecipeOcrEditorPageHelp />
</v-col>
<v-col cols="12" sm="5" md="5" lg="5">
<v-tabs v-model="tab" fixed-tabs>
<v-tab key="header">
{{ $t("general.recipe") }}
</v-tab>
<v-tab key="ingredients">
{{ $t("recipe.ingredients") }}
</v-tab>
<v-tab key="instructions">
{{ $t("recipe.instructions") }}
</v-tab>
</v-tabs>
<v-tabs-items v-model="tab">
<v-tab-item key="header">
<v-text-field
v-model="recipe.name"
class="my-3"
:label="$t('recipe.recipe-name')"
:rules="[validators.required]"
@focus="selectedRecipeField = 'name'"
>
</v-text-field>
<div class="d-flex flex-wrap">
<v-text-field
v-model="recipe.totalTime"
class="mx-2"
:label="$t('recipe.total-time')"
@click="selectedRecipeField = 'totalTime'"
></v-text-field>
<v-text-field
v-model="recipe.prepTime"
class="mx-2"
:label="$t('recipe.prep-time')"
@click="selectedRecipeField = 'prepTime'"
></v-text-field>
<v-text-field
v-model="recipe.performTime"
class="mx-2"
:label="$t('recipe.perform-time')"
@click="selectedRecipeField = 'performTime'"
></v-text-field>
</div>
<v-textarea
v-model="recipe.description"
auto-grow
min-height="100"
:label="$t('recipe.description')"
@click="selectedRecipeField = 'description'"
>
</v-textarea>
<v-text-field
v-model="recipe.recipeYield"
dense
:label="$t('recipe.servings')"
@click="selectedRecipeField = 'recipeYield'"
>
</v-text-field>
</v-tab-item>
<v-tab-item key="ingredients">
<div class="d-flex justify-end mt-2">
<RecipeDialogBulkAdd class="ml-1 mr-1" :input-text-prop="canvasSelectedText" @bulk-data="addIngredient" />
<BaseButton @click="addIngredient"> {{ $t("general.new") }} </BaseButton>
</div>
<draggable
v-if="recipe.recipeIngredient.length > 0"
v-model="recipe.recipeIngredient"
handle=".handle"
v-bind="{
animation: 200,
group: 'description',
disabled: false,
ghostClass: 'ghost',
}"
@start="drag = true"
@end="drag = false"
>
<TransitionGroup type="transition" :name="!drag ? 'flip-list' : ''">
<RecipeIngredientEditor
v-for="(ingredient, index) in recipe.recipeIngredient"
:key="ingredient.referenceId"
v-model="recipe.recipeIngredient[index]"
class="list-group-item"
:disable-amount="recipe.settings.disableAmount"
@delete="recipe.recipeIngredient.splice(index, 1)"
@clickIngredientField="setSingleIngredient($event, index)"
/>
</TransitionGroup>
</draggable>
</v-tab-item>
<v-tab-item key="instructions">
<div class="d-flex justify-end mt-2">
<RecipeDialogBulkAdd class="ml-1 mr-1" :input-text-prop="canvasSelectedText" @bulk-data="addStep" />
<BaseButton @click="addStep()"> {{ $t("general.new") }}</BaseButton>
</div>
<RecipePageInstructions
v-model="recipe.recipeInstructions"
:ingredients="recipe.recipeIngredient"
:disable-amount="recipe.settings.disableAmount"
:edit="true"
:recipe="recipe"
:assets.sync="recipe.assets"
@click-instruction-field="setSingleStep"
/>
</v-tab-item>
</v-tabs-items>
</v-col>
</v-row>
</v-container>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, reactive, toRefs, useContext, useRouter, computed, useRoute } from "@nuxtjs/composition-api";
import { until } from "@vueuse/core";
import { invoke } from "@vueuse/shared";
import draggable from "vuedraggable";
import RecipePageInstructions from "~/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageInstructions.vue";
import { useUserApi, useStaticRoutes } from "~/composables/api";
import { OcrTsvResponse as NullableOcrTsvResponse } from "~/lib/api/types/ocr";
import { validators } from "~/composables/use-validators";
import { Recipe, RecipeIngredient, RecipeStep } from "~/lib/api/types/recipe";
import { Paths, Leaves, SelectedRecipeLeaves } from "~/types/ocr-types";
import BannerExperimental from "~/components/global/BannerExperimental.vue";
import RecipeDialogBulkAdd from "~/components/Domain/Recipe/RecipeDialogBulkAdd.vue";
import RecipeIngredientEditor from "~/components/Domain/Recipe/RecipeIngredientEditor.vue";
import RecipeOcrEditorPageCanvas from "~/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue";
import RecipeOcrEditorPageHelp from "~/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue";
import { uuid4 } from "~/composables/use-utils";
import { NoUndefinedField } from "~/lib/api/types/non-generated";
// Temporary Shim until we have a better solution
// https://github.com/phillipdupuis/pydantic-to-typescript/issues/28
type OcrTsvResponse = NoUndefinedField<NullableOcrTsvResponse>;
export default defineComponent({
components: {
RecipeIngredientEditor,
draggable,
BannerExperimental,
RecipeDialogBulkAdd,
RecipePageInstructions,
RecipeOcrEditorPageCanvas,
RecipeOcrEditorPageHelp,
},
props: {
recipe: {
type: Object as () => NoUndefinedField<Recipe>,
required: true,
},
},
setup(props) {
const { $auth } = useContext();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const router = useRouter();
const api = useUserApi();
const tsv = ref<OcrTsvResponse[]>([]);
const drag = ref(false);
const { i18n } = useContext();
const { recipeAssetPath } = useStaticRoutes();
function assetURL(assetName: string) {
return recipeAssetPath(props.recipe.id, assetName);
}
const state = reactive({
loading: true,
loadingText: i18n.tc("general.loading-recipe"),
tab: null,
selectedRecipeField: "" as SelectedRecipeLeaves | "",
canvasSelectedText: "",
canvasImage: new Image(),
});
const setPropertyValueByPath = function <T extends Recipe>(object: T, path: Paths<T>, value: any) {
const a = path.split(".");
let nextProperty: any = object;
for (let i = 0, n = a.length - 1; i < n; ++i) {
const k = a[i];
if (k in nextProperty) {
nextProperty = nextProperty[k];
} else {
return;
}
}
nextProperty[a[a.length - 1]] = value;
};
/**
* This function will find the title of a recipe with the assumption that the title
* has the biggest ratio of surface area / number of words on the image.
* @return Returns the text parts of the block with the highest score.
*/
function findRecipeTitle() {
const filtered = tsv.value.filter((element) => element.level === 2 || element.level === 5);
const blocks = [[]] as OcrTsvResponse[][];
let blockNum = 1;
filtered.forEach((element, index, array) => {
if (index !== 0 && array[index - 1].blockNum !== element.blockNum) {
blocks.push([]);
blockNum = element.blockNum;
}
blocks[blockNum - 1].push(element);
});
let bestScore = 0;
let bestBlock = blocks[0];
blocks.forEach((element) => {
// element[0] is the block declaration line containing the blocks total dimensions
// element.length is the number of words (+ 2) contained in that block
const elementScore = (element[0].height * element[0].width) / element.length; // Prettier is adding useless parenthesis for a mysterious reason
const elementText = element.map((element) => element.text).join(""); // Identify empty blocks and don't count them
if (elementScore > bestScore && elementText !== "") {
bestBlock = element;
bestScore = elementScore;
}
});
return bestBlock
.filter((element) => element.level === 5 && element.conf >= 40)
.map((element) => {
return element.text.trim();
})
.join(" ");
}
onMounted(() => {
invoke(async () => {
await until(props.recipe).not.toBeNull();
state.loadingText = i18n.tc("general.loading-ocr-data");
const assetName = props.recipe.assets[0].fileName;
const imagesrc = assetURL(assetName);
state.canvasImage.src = imagesrc;
const res = await api.ocr.assetToTsv(props.recipe.slug, assetName);
tsv.value = res.data as OcrTsvResponse[];
state.loading = false;
if (props.recipe.name.match(/New\sOCR\sRecipe(\s\([0-9]+\))?/g)) {
props.recipe.name = findRecipeTitle();
}
});
});
function addIngredient(ingredients: Array<string> | null = null) {
if (ingredients?.length) {
const newIngredients = ingredients.map((x) => {
return {
referenceId: uuid4(),
title: "",
note: x,
unit: undefined,
food: undefined,
disableAmount: true,
quantity: 1,
originalText: "",
};
});
if (newIngredients) {
// @ts-expect-error - prop can be null-type by NoUndefinedField type forces it to be set
props.recipe.recipeIngredient.push(...newIngredients);
}
} else {
props.recipe.recipeIngredient.push({
referenceId: uuid4(),
title: "",
note: "",
// @ts-expect-error - prop can be null-type by NoUndefinedField type forces it to be set
unit: undefined,
// @ts-expect-error - prop can be null-type by NoUndefinedField type forces it to be set
food: undefined,
disableAmount: true,
quantity: 1,
});
}
}
function addStep(steps: Array<string> | null = null) {
if (!props.recipe.recipeInstructions) {
return;
}
if (steps) {
const cleanedSteps = steps.map((step) => {
return { id: uuid4(), text: step, title: "", ingredientReferences: [] };
});
props.recipe.recipeInstructions.push(...cleanedSteps);
} else {
props.recipe.recipeInstructions.push({ id: uuid4(), text: "", title: "", ingredientReferences: [] });
}
}
// EVENT HANDLERS
// Canvas component event handlers
async function updateRecipe() {
const { data } = await api.recipes.updateOne(props.recipe.slug, props.recipe);
if (data?.slug) {
router.push(`/g/${groupSlug.value}/r/${data.slug}`);
}
}
function closeEditor() {
router.push(`/g/${groupSlug.value}/r/${props.recipe.slug}`);
}
const canvasSetText = function () {
if (state.selectedRecipeField !== "") {
setPropertyValueByPath<Recipe>(props.recipe, state.selectedRecipeField, state.canvasSelectedText);
}
};
function updateSelectedText(value: string) {
state.canvasSelectedText = value;
}
// Recipe field selection event handlers
function setSingleIngredient(f: keyof RecipeIngredient, index: number) {
state.selectedRecipeField = `recipeIngredient.${index}.${f}` as SelectedRecipeLeaves;
}
// Leaves<RecipeStep[]> will return some function types making eslint very unhappy
type RecipeStepsLeaves = `${number}.${Leaves<RecipeStep>}`;
function setSingleStep(path: RecipeStepsLeaves) {
state.selectedRecipeField = `recipeInstructions.${path}` as SelectedRecipeLeaves;
}
return {
...toRefs(state),
addIngredient,
addStep,
drag,
assetURL,
updateRecipe,
closeEditor,
updateSelectedText,
tsv,
validators,
setSingleIngredient,
setSingleStep,
canvasSetText,
};
},
});
</script>
<style lang="css">
.ghost {
opacity: 0.5;
}
</style>

View File

@ -1,488 +0,0 @@
<template>
<v-card flat tile>
<v-toolbar v-for="(section, idx) in toolbarIcons" :key="section.sectionTitle" dense style="float: left">
<v-toolbar-title bottom>
{{ section.sectionTitle }}
</v-toolbar-title>
<v-tooltip v-for="icon in section.icons" :key="icon.name" bottom>
<template #activator="{ on, attrs }">
<v-btn icon @click="section.eventHandler(icon.name)">
<v-icon :color="section.highlight === icon.name ? 'primary' : 'default'" v-bind="attrs" v-on="on">
{{ icon.icon }}
</v-icon>
</v-btn>
</template>
<span>{{ icon.tooltip }}</span>
</v-tooltip>
<v-divider v-if="idx != toolbarIcons.length - 1" vertical class="mx-2" />
</v-toolbar>
<v-toolbar dense style="float: right">
<BaseButton class="ml-1 mr-1" save @click="updateRecipe()">
{{ $t("general.save") }}
</BaseButton>
<BaseButton cancel @click="closeEditor()">
{{ $t("general.close") }}
</BaseButton>
</v-toolbar>
<canvas
ref="canvas"
@mousedown="handleMouseDown"
@mouseup="handleMouseUp"
@mousemove="handleMouseMove"
@wheel="handleMouseScroll"
>
</canvas>
<span style="white-space: pre-wrap">
{{ selectedText.trim() }}
</span>
</v-card>
</template>
<script lang="ts">
import { defineComponent, reactive, useContext, ref, toRefs, watch, onMounted } from "@nuxtjs/composition-api";
import { NoUndefinedField } from "~/lib/api/types/non-generated";
import { OcrTsvResponse as NullableOcrTsvResponse } from "~/lib/api/types/ocr";
import { CanvasModes, SelectedTextSplitModes, ImagePosition, Mouse, CanvasRect, ToolbarIcons } from "~/types/ocr-types";
// Temporary Shim until we have a better solution
// https://github.com/phillipdupuis/pydantic-to-typescript/issues/28
type OcrTsvResponse = NoUndefinedField<NullableOcrTsvResponse>;
export default defineComponent({
props: {
image: {
type: HTMLImageElement,
required: true,
},
tsv: {
type: Array as () => OcrTsvResponse[],
required: true,
},
},
setup(props, context) {
const state = reactive({
canvas: null as HTMLCanvasElement | null,
ctx: null as CanvasRenderingContext2D | null,
canvasRect: null as DOMRect | null,
rect: {
startX: 0,
startY: 0,
w: 0,
h: 0,
},
mouse: {
current: {
x: 0,
y: 0,
},
down: false,
},
selectedText: "",
canvasMode: "selection" as CanvasModes,
imagePosition: {
sx: 0,
sy: 0,
sWidth: 0,
sHeight: 0,
dx: 0,
dy: 0,
dWidth: 0,
dHeight: 0,
scale: 1,
panStartPoint: {
x: 0,
y: 0,
},
} as ImagePosition,
isImageSmallerThanCanvas: false,
selectedTextSplitMode: "lineNum" as SelectedTextSplitModes,
});
watch(
() => state.selectedText,
(value) => {
context.emit("text-selected", value);
}
);
onMounted(() => {
if (state.canvas === null) return; // never happens because the ref "canvas" is in the template
state.ctx = state.canvas.getContext("2d") as CanvasRenderingContext2D;
state.ctx.imageSmoothingEnabled = false;
state.canvasRect = state.canvas.getBoundingClientRect();
state.canvas.width = state.canvasRect.width;
if (props.image.width < state.canvas.width) {
state.isImageSmallerThanCanvas = true;
}
state.imagePosition.dWidth = state.canvas.width;
updateImageScale();
state.canvas.height = Math.min(props.image.height * state.imagePosition.scale, 700); // Max height of 700px
state.imagePosition.sWidth = props.image.width;
state.imagePosition.sHeight = props.image.height;
state.imagePosition.dWidth = state.canvas.width;
drawImage(state.ctx);
drawWordBoxesOnCanvas(props.tsv);
});
function handleMouseDown(event: MouseEvent) {
if (state.canvasRect === null || state.canvas === null || state.ctx === null) return;
state.mouse.down = true;
updateMousePos(event);
if (state.canvasMode === "selection") {
if (isMouseInRect(state.mouse, state.rect)) {
context.emit("setText", state.selectedText);
} else {
state.ctx.fillStyle = "rgb(255, 255, 255)";
state.ctx.fillRect(0, 0, state.canvas.width, state.canvas.height);
drawImage(state.ctx);
state.rect.startX = state.mouse.current.x;
state.rect.startY = state.mouse.current.y;
resetSelection();
}
return;
}
if (state.canvasMode === "panAndZoom") {
state.imagePosition.panStartPoint.x = state.mouse.current.x - state.imagePosition.dx;
state.imagePosition.panStartPoint.y = state.mouse.current.y - state.imagePosition.dy;
resetSelection();
}
}
function handleMouseUp(_event: MouseEvent) {
if (state.canvasRect === null) return;
state.mouse.down = false;
state.selectedText = getWordsInSelection(props.tsv, state.rect);
}
function handleMouseMove(event: MouseEvent) {
if (state.canvasRect === null || state.canvas === null || state.ctx === null) return;
updateMousePos(event);
if (state.mouse.down) {
if (state.canvasMode === "selection") {
state.rect.w = state.mouse.current.x - state.rect.startX;
state.rect.h = state.mouse.current.y - state.rect.startY;
draw();
return;
}
if (state.canvasMode === "panAndZoom") {
state.canvas.style.cursor = "move";
state.imagePosition.dx = state.mouse.current.x - state.imagePosition.panStartPoint.x;
state.imagePosition.dy = state.mouse.current.y - state.imagePosition.panStartPoint.y;
keepImageInCanvas();
state.ctx.fillStyle = "rgb(255, 255, 255)";
state.ctx.fillRect(0, 0, state.canvas.width, state.canvas.height);
drawImage(state.ctx);
return;
}
}
if (isMouseInRect(state.mouse, state.rect) && state.canvasMode === "selection") {
state.canvas.style.cursor = "pointer";
} else {
state.canvas.style.cursor = "default";
}
}
const scrollSensitivity = 0.05;
function handleMouseScroll(event: WheelEvent) {
if (state.isImageSmallerThanCanvas) return;
if (state.canvasRect === null || state.canvas === null || state.ctx === null) return;
if (state.canvasMode === "panAndZoom") {
event.preventDefault();
updateMousePos(event);
const m = Math.sign(event.deltaY);
const ndx = state.imagePosition.dx + m * state.imagePosition.dWidth * scrollSensitivity;
const ndy = state.imagePosition.dy + m * state.imagePosition.dHeight * scrollSensitivity;
const ndw = state.imagePosition.dWidth + -m * state.imagePosition.dWidth * scrollSensitivity * 2;
const ndh = state.imagePosition.dHeight + -m * state.imagePosition.dHeight * scrollSensitivity * 2;
if (ndw < props.image.width) {
state.imagePosition.dx = ndx;
state.imagePosition.dy = ndy;
state.imagePosition.dWidth = ndw;
state.imagePosition.dHeight = ndh;
}
keepImageInCanvas();
updateImageScale();
state.ctx.fillStyle = "rgb(255, 255, 255)";
state.ctx.fillRect(0, 0, state.canvas.width, state.canvas.height);
drawImage(state.ctx);
}
}
function draw() {
if (state.canvasRect === null || state.canvas === null || state.ctx === null) return;
if (state.mouse.down) {
state.ctx.imageSmoothingEnabled = false;
state.ctx.fillStyle = "rgb(255, 255, 255)";
state.ctx.fillRect(0, 0, state.canvas.width, state.canvas.height);
drawImage(state.ctx);
state.ctx.fillStyle = "rgba(255, 255, 255, 0.1)";
state.ctx.setLineDash([6]);
state.ctx.fillRect(state.rect.startX, state.rect.startY, state.rect.w, state.rect.h);
state.ctx.strokeRect(state.rect.startX, state.rect.startY, state.rect.w, state.rect.h);
}
}
function drawImage(ctx: CanvasRenderingContext2D) {
ctx.drawImage(
props.image,
state.imagePosition.sx,
state.imagePosition.sy,
state.imagePosition.sWidth,
state.imagePosition.sHeight,
state.imagePosition.dx,
state.imagePosition.dy,
state.imagePosition.dWidth,
state.imagePosition.dHeight
);
}
function keepImageInCanvas() {
if (state.canvasRect === null || state.canvas === null) return;
// Prevent image from being smaller than the canvas width
if (state.imagePosition.dWidth - state.canvas.width < 0) {
state.imagePosition.dWidth = state.canvas.width;
}
// Prevent image from being smaller than the canvas height
if (state.imagePosition.dHeight - state.canvas.height < 0) {
state.imagePosition.dHeight = props.image.height * state.imagePosition.scale;
}
// Prevent to move the image too much to the left
if (state.canvas.width - state.imagePosition.dx - state.imagePosition.dWidth > 0) {
state.imagePosition.dx = state.canvas.width - state.imagePosition.dWidth;
}
// Prevent to move the image too much to the top
if (state.canvas.height - state.imagePosition.dy - state.imagePosition.dHeight > 0) {
state.imagePosition.dy = state.canvas.height - state.imagePosition.dHeight;
}
// Prevent to move the image too much to the right
if (state.imagePosition.dx > 0) {
state.imagePosition.dx = 0;
}
// Prevent to move the image too much to the bottom
if (state.imagePosition.dy > 0) {
state.imagePosition.dy = 0;
}
}
function updateImageScale() {
state.imagePosition.scale = state.imagePosition.dWidth / props.image.width;
// force the original ratio to be respected
state.imagePosition.dHeight = props.image.height * state.imagePosition.scale;
// Don't let images bigger than the canvas be zoomed in more than 1:1 scale
// Meaning only let images smaller than the canvas to have a scale > 1
if (!state.isImageSmallerThanCanvas && state.imagePosition.scale > 1) {
state.imagePosition.scale = 1;
}
}
function resetSelection() {
if (state.canvasRect === null) return;
state.rect.w = 0;
state.rect.h = 0;
state.selectedText = "";
}
function updateMousePos<T extends MouseEvent>(event: T) {
if (state.canvas === null) return;
state.canvasRect = state.canvas.getBoundingClientRect();
state.mouse.current = {
x: event.clientX - state.canvasRect.left,
y: event.clientY - state.canvasRect.top,
};
}
function isMouseInRect(mouse: Mouse, rect: CanvasRect) {
if (state.canvasRect === null) return;
const correctRect = correctRectCoordinates(rect);
return (
mouse.current.x > correctRect.startX &&
mouse.current.x < correctRect.startX + correctRect.w &&
mouse.current.y > correctRect.startY &&
mouse.current.y < correctRect.startY + correctRect.h
);
}
/**
* Returns rectangle coordinates with positive dimensions
* @param rect A rectangle
* @returns An equivalent rectangle with width and height > 0
*/
function correctRectCoordinates(rect: CanvasRect) {
if (rect.w < 0) {
rect.startX = rect.startX + rect.w;
rect.w = -rect.w;
}
if (rect.h < 0) {
rect.startY = rect.startY + rect.h;
rect.h = -rect.h;
}
return rect;
}
function drawWordBoxesOnCanvas(tsv: OcrTsvResponse[]) {
if (state.canvasRect === null || state.canvas === null || state.ctx === null) return;
state.ctx.fillStyle = "rgb(255, 255, 255, 0.3)";
tsv
.filter((element) => element.level === 5)
.forEach((element) => {
if (state.canvasRect === null || state.canvas === null || state.ctx === null) return;
state.ctx.fillRect(
element.left * state.imagePosition.scale,
element.top * state.imagePosition.scale,
element.width * state.imagePosition.scale,
element.height * state.imagePosition.scale
);
});
}
// Event emitters
const updateRecipe = function () {
context.emit("update-recipe");
};
const closeEditor = function () {
context.emit("close-editor");
};
// TOOLBAR STUFF
const { $globals, i18n } = useContext();
const toolbarIcons = ref<ToolbarIcons<CanvasModes | SelectedTextSplitModes>>([
{
sectionTitle: i18n.tc("ocr-editor.toolbar"),
eventHandler: switchCanvasMode,
highlight: state.canvasMode,
icons: [
{
name: "selection",
icon: $globals.icons.selectMode,
tooltip: i18n.tc("ocr-editor.selection-mode"),
},
{
name: "panAndZoom",
icon: $globals.icons.panAndZoom,
tooltip: i18n.tc("ocr-editor.pan-and-zoom-picture"),
},
],
},
{
sectionTitle: i18n.tc("ocr-editor.split-text"),
eventHandler: switchSplitTextMode,
highlight: state.selectedTextSplitMode,
icons: [
{
name: "lineNum",
icon: $globals.icons.preserveLines,
tooltip: i18n.tc("ocr-editor.preserve-line-breaks"),
},
{
name: "blockNum",
icon: $globals.icons.preserveBlocks,
tooltip: i18n.tc("ocr-editor.split-by-block"),
},
{
name: "flatten",
icon: $globals.icons.flatten,
tooltip: i18n.tc("ocr-editor.flatten"),
},
],
},
]);
function switchCanvasMode(mode: CanvasModes) {
if (state.canvasRect === null || state.canvas === null) return;
state.canvasMode = mode;
toolbarIcons.value[0].highlight = mode;
if (mode === "panAndZoom") {
state.canvas.style.cursor = "pointer";
} else {
state.canvas.style.cursor = "default";
}
}
function switchSplitTextMode(mode: SelectedTextSplitModes) {
if (state.canvasRect === null) return;
state.selectedTextSplitMode = mode;
toolbarIcons.value[1].highlight = mode;
state.selectedText = getWordsInSelection(props.tsv, state.rect);
}
/**
* Using rectangle coordinates, filters the tsv to get text elements contained
* inside the rectangle
* Additionaly adds newlines depending on the current "text split" mode
* @param tsv An Object containing tesseracts tsv fields
* @param rect Coordinates of a rectangle
* @returns Text from tsv contained in the rectangle
*/
function getWordsInSelection(tsv: OcrTsvResponse[], rect: CanvasRect) {
const correctedRect = correctRectCoordinates(rect);
return tsv
.filter(
(element) =>
element.level === 5 &&
correctedRect.startY - state.imagePosition.dy < element.top * state.imagePosition.scale &&
correctedRect.startX - state.imagePosition.dx < element.left * state.imagePosition.scale &&
correctedRect.startX + correctedRect.w >
(element.left + element.width) * state.imagePosition.scale + state.imagePosition.dx &&
correctedRect.startY + correctedRect.h >
(element.top + element.height) * state.imagePosition.scale + state.imagePosition.dy
)
.map((element, index, array) => {
let separator = " ";
if (
state.selectedTextSplitMode !== "flatten" &&
index !== array.length - 1 &&
element[state.selectedTextSplitMode] !== array[index + 1][state.selectedTextSplitMode]
) {
separator = "\n";
}
return element.text + separator;
})
.join("");
}
return {
...toRefs(state),
handleMouseDown,
handleMouseUp,
handleMouseMove,
handleMouseScroll,
toolbarIcons,
updateRecipe,
closeEditor,
};
},
});
</script>

View File

@ -1,54 +0,0 @@
<template>
<v-card>
<v-app-bar dense dark color="primary" class="mb-2">
<v-icon large left>
{{ $globals.icons.help }}
</v-icon>
<v-toolbar-title class="headline"> {{ $t("ocr-editor.help.help") }} </v-toolbar-title>
<v-spacer></v-spacer>
</v-app-bar>
<v-card-text>
<h1> {{ $t("ocr-editor.help.mouse-modes") }}</h1>
<v-divider class="mb-2 mt-1" />
<h2 class="my-2">
<v-icon> {{ $globals.icons.selectMode }} </v-icon>{{ $t("ocr-editor.help.selection-mode") }}
</h2>
<p class="my-1">{{ $t("ocr-editor.help.selection-mode") }}</p>
<ol>
<li>{{ $t("ocr-editor.help.selection-mode-steps.draw") }}</li>
<li>{{ $t("ocr-editor.help.selection-mode-steps.click") }}</li>
<li>{{ $t("ocr-editor.help.selection-mode-steps.result") }}</li>
</ol>
<h2 class="my-2">
<v-icon> {{ $globals.icons.panAndZoom }} </v-icon>{{ $t("ocr-editor.help.pan-and-zoom-mode") }}
</h2>
{{ $t("ocr-editor.help.pan-and-zoom-desc") }}
<h1 class="mt-5">{{ $t("ocr-editor.help.split-text-mode") }}</h1>
<v-divider class="mb-2 mt-1" />
<h2 class="my-2">
<v-icon> {{ $globals.icons.preserveLines }} </v-icon>
{{ $t("ocr-editor.help.split-modes.line-mode") }}
</h2>
<p>
{{ $t("ocr-editor.help.split-modes.line-mode-desc") }}
</p>
<h2 class="my-2">
<v-icon> {{ $globals.icons.preserveBlocks }} </v-icon>
{{ $t("ocr-editor.help.split-modes.block-mode") }}
</h2>
<p>
{{ $t("ocr-editor.help.split-modes.block-mode-desc") }}
</p>
<h2 class="my-2">
<v-icon> {{ $globals.icons.flatten }} </v-icon> {{ $t("ocr-editor.help.split-modes.flat-mode") }}
</h2>
<p>{{ $t("ocr-editor.help.split-modes.flat-mode-desc") }}</p>
</v-card-text>
</v-card>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api";
export default defineComponent({});
</script>

View File

@ -1,3 +0,0 @@
import RecipeOcrEditorPage from "./RecipeOcrEditorPage.vue";
export default RecipeOcrEditorPage;

View File

@ -50,7 +50,6 @@
:logged-in="isOwnGroup" :logged-in="isOwnGroup"
:open="isEditMode" :open="isEditMode"
:recipe-id="recipe.id" :recipe-id="recipe.id"
:show-ocr-button="recipe.isOcrRecipe"
class="ml-auto mt-n8 pb-4" class="ml-auto mt-n8 pb-4"
@close="setMode(PageMode.VIEW)" @close="setMode(PageMode.VIEW)"
@json="toggleEditMode()" @json="toggleEditMode()"
@ -58,13 +57,12 @@
@save="$emit('save')" @save="$emit('save')"
@delete="$emit('delete')" @delete="$emit('delete')"
@print="printRecipe" @print="printRecipe"
@ocr="goToOcrEditor"
/> />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, useContext, computed, ref, watch, useRouter, useRoute } from "@nuxtjs/composition-api"; import { defineComponent, useContext, computed, ref, watch } from "@nuxtjs/composition-api";
import { useLoggedInState } from "~/composables/use-logged-in-state"; import { useLoggedInState } from "~/composables/use-logged-in-state";
import RecipeRating from "~/components/Domain/Recipe/RecipeRating.vue"; import RecipeRating from "~/components/Domain/Recipe/RecipeRating.vue";
import RecipeLastMade from "~/components/Domain/Recipe/RecipeLastMade.vue"; import RecipeLastMade from "~/components/Domain/Recipe/RecipeLastMade.vue";
@ -96,16 +94,12 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const { $auth, $vuetify } = useContext(); const { $vuetify } = useContext();
const { recipeImage } = useStaticRoutes(); const { recipeImage } = useStaticRoutes();
const { imageKey, pageMode, editMode, setMode, toggleEditMode, isEditMode } = usePageState(props.recipe.slug); const { imageKey, pageMode, editMode, setMode, toggleEditMode, isEditMode } = usePageState(props.recipe.slug);
const { user } = usePageUser(); const { user } = usePageUser();
const { isOwnGroup } = useLoggedInState(); const { isOwnGroup } = useLoggedInState();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const router = useRouter();
function printRecipe() { function printRecipe() {
window.print(); window.print();
} }
@ -119,10 +113,6 @@ export default defineComponent({
return recipeImage(props.recipe.id, props.recipe.image, imageKey.value); return recipeImage(props.recipe.id, props.recipe.image, imageKey.value);
}); });
function goToOcrEditor() {
router.push(`/g/${groupSlug.value}/r/${props.recipe.slug}/ocr-editor`);
}
watch( watch(
() => recipeImageUrl.value, () => recipeImageUrl.value,
() => { () => {
@ -146,7 +136,6 @@ export default defineComponent({
hideImage, hideImage,
isEditMode, isEditMode,
recipeImageUrl, recipeImageUrl,
goToOcrEditor,
}; };
}, },
}); });

View File

@ -2,7 +2,7 @@
<v-tooltip <v-tooltip
ref="copyToolTip" ref="copyToolTip"
v-model="show" v-model="show"
color="success lighten-1" :color="copied? 'success lighten-1' : 'red lighten-1'"
top top
:open-on-hover="false" :open-on-hover="false"
:open-on-click="true" :open-on-click="true"
@ -29,12 +29,14 @@
<v-icon left dark> <v-icon left dark>
{{ $globals.icons.clipboardCheck }} {{ $globals.icons.clipboardCheck }}
</v-icon> </v-icon>
<slot> {{ $t("general.copied_message") }} </slot> <slot v-if="!isSupported"> {{ $t("general.your-browser-does-not-support-clipboard") }} </slot>
<slot v-else> {{ copied ? $t("general.copied_message") : $t("general.clipboard-copy-failure") }} </slot>
</span> </span>
</v-tooltip> </v-tooltip>
</template> </template>
<script lang="ts"> <script lang="ts">
import { useClipboard } from "@vueuse/core"
import { defineComponent, ref } from "@nuxtjs/composition-api"; import { defineComponent, ref } from "@nuxtjs/composition-api";
import { VTooltip } from "~/types/vuetify"; import { VTooltip } from "~/types/vuetify";
@ -58,6 +60,7 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const { copy, copied, isSupported } = useClipboard()
const show = ref(false); const show = ref(false);
const copyToolTip = ref<VTooltip | null>(null); const copyToolTip = ref<VTooltip | null>(null);
@ -65,13 +68,21 @@ export default defineComponent({
copyToolTip.value?.deactivate(); copyToolTip.value?.deactivate();
} }
function textToClipboard() { async function textToClipboard() {
if (isSupported.value) {
await copy(props.copyText);
if (copied.value) {
console.log(`Copied\n${props.copyText}`)
}
else {
console.warn("Copy failed: ", copied.value);
}
}
else {
console.warn("Clipboard is currently not supported by your browser. Ensure you're on a secure (https) site.");
}
show.value = true; show.value = true;
const copyText = props.copyText;
navigator.clipboard.writeText(copyText).then(
() => console.log(`Copied\n${copyText}`),
() => console.log(`Copied Failed\n${copyText}`)
);
setTimeout(() => { setTimeout(() => {
toggleBlur(); toggleBlur();
}, 500); }, 500);
@ -81,6 +92,8 @@ export default defineComponent({
show, show,
copyToolTip, copyToolTip,
textToClipboard, textToClipboard,
copied,
isSupported,
}; };
}, },
}); });

View File

@ -7,23 +7,30 @@ export function useCopy() {
const { i18n } = useContext(); const { i18n } = useContext();
function copyText(text: string) { function copyText(text: string) {
if (!isSupported) { if (!isSupported.value) {
alert.error(i18n.tc("general.clipboard-not-supported")); alert.error(i18n.tc("general.clipboard-not-supported"));
return; return;
} }
copy(text); copy(text).then(() => {
alert.success(i18n.tc("general.copied-to-clipboard")); // Verify copy success as no error is thrown on failure.
if (copied.value) {
alert.success(i18n.tc("general.copied-to-clipboard"));
}
else {
alert.error(i18n.tc("general.clipboard-copy-failure"));
}
});
} }
return { copyText, copied }; return { copyText, copied };
} }
export function useCopyList() { export function useCopyList() {
const { copy, isSupported } = useClipboard(); const { copy, isSupported, copied } = useClipboard();
const { i18n } = useContext(); const { i18n } = useContext();
function checkClipboard() { function checkClipboard() {
if (!isSupported) { if (!isSupported.value) {
alert.error(i18n.tc("general.your-browser-does-not-support-clipboard")); alert.error(i18n.tc("general.your-browser-does-not-support-clipboard"));
return false; return false;
} }
@ -54,7 +61,13 @@ export function useCopyList() {
function copyText(text: string, len: number) { function copyText(text: string, len: number) {
copy(text).then(() => { copy(text).then(() => {
alert.success(i18n.tc("general.copied-items-to-clipboard", len)); // Verify copy success as no error is thrown on failure.
if (copied.value) {
alert.success(i18n.tc("general.copied-items-to-clipboard", len));
}
else {
alert.error(i18n.tc("general.clipboard-copy-failure"));
}
}); });
} }

View File

@ -198,7 +198,8 @@
"refresh": "Verfris", "refresh": "Verfris",
"upload-file": "Laai dokument op", "upload-file": "Laai dokument op",
"created-on-date": "Geskep op: {0}", "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." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Is jy seker jy wil <b>{groupName}<b/> uitvee?", "are-you-sure-you-want-to-delete-the-group": "Is jy seker jy wil <b>{groupName}<b/> uitvee?",

View File

@ -198,7 +198,8 @@
"refresh": "تحديث", "refresh": "تحديث",
"upload-file": "تحميل الملف", "upload-file": "تحميل الملف",
"created-on-date": "تم الإنشاء في {0}", "created-on-date": "تم الإنشاء في {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "هل انت متأكد من رغبتك في حذف <b>{groupName}<b/>؟", "are-you-sure-you-want-to-delete-the-group": "هل انت متأكد من رغبتك في حذف <b>{groupName}<b/>؟",

View File

@ -198,7 +198,8 @@
"refresh": "Опресни", "refresh": "Опресни",
"upload-file": "Качване на файл", "upload-file": "Качване на файл",
"created-on-date": "Създадено на {0}", "created-on-date": "Създадено на {0}",
"unsaved-changes": "Имате незапазени промени. Желаете ли да ги запазите преди да излезете? Натиснете Ок за запазване и Отказ за отхвърляне на промените." "unsaved-changes": "Имате незапазени промени. Желаете ли да ги запазите преди да излезете? Натиснете Ок за запазване и Отказ за отхвърляне на промените.",
"clipboard-copy-failure": "Failed to copy to the clipboard."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Сигурни ли сте, че искате да изтриете <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Сигурни ли сте, че искате да изтриете <b>{groupName}<b/>?",
@ -510,7 +511,7 @@
"how-did-it-turn-out": "Как се получи?", "how-did-it-turn-out": "Как се получи?",
"user-made-this": "{user} направи това", "user-made-this": "{user} направи това",
"last-made-date": "Последно приготвена на {date}", "last-made-date": "Последно приготвена на {date}",
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.", "api-extras-description": "Екстрите за рецепти са ключова характеристика на Mealie API. Те Ви позволяват да създавате персонализирани JSON двойки ключ/стойност в рамките на рецепта, за да ги препращате към други приложения. Можете да използвате тези ключове, за да предоставите информация за задействане на автоматизация или персонализирани съобщения, за препращане към желаното от Вас устройство.",
"message-key": "Ключ на съобщението", "message-key": "Ключ на съобщението",
"parse": "Анализирай", "parse": "Анализирай",
"attach-images-hint": "Прикачете снимки като ги влачете и пуснете в редактора", "attach-images-hint": "Прикачете снимки като ги влачете и пуснете в редактора",

View File

@ -198,7 +198,8 @@
"refresh": "Actualitza", "refresh": "Actualitza",
"upload-file": "Puja un fitxer", "upload-file": "Puja un fitxer",
"created-on-date": "Creat el: {0}", "created-on-date": "Creat el: {0}",
"unsaved-changes": "Tens canvis que no estan guardats. Vols guardar-los abans de sortir? Clica d'acord per guardar-los o cancel·lar per descartar els canvis." "unsaved-changes": "Tens canvis que no estan guardats. Vols guardar-los abans de sortir? Clica d'acord per guardar-los o cancel·lar per descartar els canvis.",
"clipboard-copy-failure": "Failed to copy to the clipboard."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Esteu segur de voler suprimir el grup <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Esteu segur de voler suprimir el grup <b>{groupName}<b/>?",
@ -510,7 +511,7 @@
"how-did-it-turn-out": "Com ha sortit?", "how-did-it-turn-out": "Com ha sortit?",
"user-made-this": "{user} ha fet això", "user-made-this": "{user} ha fet això",
"last-made-date": "Última vegada feta {date}", "last-made-date": "Última vegada feta {date}",
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom json key/value pairs within a recipe to reference from 3rd part applications. You can use these keys to contain information to trigger automation or custom messages to relay to your desired device.", "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", "message-key": "Message Key",
"parse": "Analitzar", "parse": "Analitzar",
"attach-images-hint": "Afegeix imatges arrossegant i deixant anar la imatge a l'editor", "attach-images-hint": "Afegeix imatges arrossegant i deixant anar la imatge a l'editor",

View File

@ -198,7 +198,8 @@
"refresh": "Obnovit", "refresh": "Obnovit",
"upload-file": "Nahrát soubor", "upload-file": "Nahrát soubor",
"created-on-date": "Vytvořeno dne: {0}", "created-on-date": "Vytvořeno dne: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Jste si jisti, že chcete smazat <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Jste si jisti, že chcete smazat <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Opdater", "refresh": "Opdater",
"upload-file": "Upload Fil", "upload-file": "Upload Fil",
"created-on-date": "Oprettet den: {0}", "created-on-date": "Oprettet den: {0}",
"unsaved-changes": "Du har ændringer som ikke er gemt. Vil du gemme før du forlader? Vælg \"Okay\" for at gemme, eller \"Annullér\" for at kassere ændringer." "unsaved-changes": "Du har ændringer som ikke er gemt. Vil du gemme før du forlader? Vælg \"Okay\" for at gemme, eller \"Annullér\" for at kassere ændringer.",
"clipboard-copy-failure": "Failed to copy to the clipboard."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Er du sikker på, du vil slette <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Er du sikker på, du vil slette <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Aktualisieren", "refresh": "Aktualisieren",
"upload-file": "Datei hochladen", "upload-file": "Datei hochladen",
"created-on-date": "Erstellt am: {0}", "created-on-date": "Erstellt am: {0}",
"unsaved-changes": "Du hast ungespeicherte Änderungen. Möchtest du vor dem Verlassen speichern? OK um zu speichern, Cancel um Änderungen zu verwerfen." "unsaved-changes": "Du hast ungespeicherte Änderungen. Möchtest du vor dem Verlassen speichern? OK um zu speichern, Cancel um Änderungen zu verwerfen.",
"clipboard-copy-failure": "Fehler beim Kopieren in die Zwischenablage."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Bist du dir sicher, dass du die Gruppe <b>{groupName}<b/> löschen möchtest?", "are-you-sure-you-want-to-delete-the-group": "Bist du dir sicher, dass du die Gruppe <b>{groupName}<b/> löschen möchtest?",

View File

@ -198,7 +198,8 @@
"refresh": "Ανανέωση", "refresh": "Ανανέωση",
"upload-file": "Μεταφόρτωση αρχείου", "upload-file": "Μεταφόρτωση αρχείου",
"created-on-date": "Δημιουργήθηκε στις: {0}", "created-on-date": "Δημιουργήθηκε στις: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό τον ασφαλή σύνδεσμο <b>{groupName}<b/>;", "are-you-sure-you-want-to-delete-the-group": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό τον ασφαλή σύνδεσμο <b>{groupName}<b/>;",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "upload-file": "Upload File",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "upload-file": "Upload File",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Actualizar", "refresh": "Actualizar",
"upload-file": "Subir Archivo", "upload-file": "Subir Archivo",
"created-on-date": "Creado el {0}", "created-on-date": "Creado el {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Por favor, confirma que deseas eliminar <b>{groupName}<b/>", "are-you-sure-you-want-to-delete-the-group": "Por favor, confirma que deseas eliminar <b>{groupName}<b/>",

View File

@ -198,7 +198,8 @@
"refresh": "Päivitä", "refresh": "Päivitä",
"upload-file": "Tuo tiedosto", "upload-file": "Tuo tiedosto",
"created-on-date": "Luotu {0}", "created-on-date": "Luotu {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Haluatko varmasti poistaa ryhmän <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Haluatko varmasti poistaa ryhmän <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Actualiser", "refresh": "Actualiser",
"upload-file": "Transférer un fichier", "upload-file": "Transférer un fichier",
"created-on-date": "Créé le {0}", "created-on-date": "Créé le {0}",
"unsaved-changes": "Vous avez des modifications non enregistrées. Voulez-vous enregistrer avant de partir? OK pour enregistrer, Annuler pour ignorer les modifications." "unsaved-changes": "Vous avez des modifications non enregistrées. Voulez-vous enregistrer avant de partir? OK pour enregistrer, Annuler pour ignorer les modifications.",
"clipboard-copy-failure": "Failed to copy to the clipboard."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Êtes-vous certain de vouloir supprimer <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Êtes-vous certain de vouloir supprimer <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Actualiser", "refresh": "Actualiser",
"upload-file": "Transférer un fichier", "upload-file": "Transférer un fichier",
"created-on-date": "Créé le {0}", "created-on-date": "Créé le {0}",
"unsaved-changes": "Vous avez des modifications non enregistrées. Voulez-vous enregistrer avant de partir? OK pour enregistrer, Annuler pour ignorer les modifications." "unsaved-changes": "Vous avez des modifications non enregistrées. Voulez-vous enregistrer avant de partir? OK pour enregistrer, Annuler pour ignorer les modifications.",
"clipboard-copy-failure": "Échec de la copie dans le presse-papiers."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Voulez-vous vraiment supprimer <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Voulez-vous vraiment supprimer <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "upload-file": "Upload File",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",

View File

@ -77,7 +77,7 @@
"tag-events": "אירועי תגיות", "tag-events": "אירועי תגיות",
"category-events": "אירועי קטגוריות", "category-events": "אירועי קטגוריות",
"when-a-new-user-joins-your-group": "כאשר משתמש חדש מצטרף לקבוצה", "when-a-new-user-joins-your-group": "כאשר משתמש חדש מצטרף לקבוצה",
"recipe-events": "Recipe Events" "recipe-events": "אירועי מתכון"
}, },
"general": { "general": {
"cancel": "ביטול", "cancel": "ביטול",
@ -114,10 +114,10 @@
"json": "JSON", "json": "JSON",
"keyword": "מילת מפתח", "keyword": "מילת מפתח",
"link-copied": "קישור הועתק", "link-copied": "קישור הועתק",
"loading": "Loading", "loading": "טעינה",
"loading-events": "טוען", "loading-events": "טוען",
"loading-recipe": "Loading recipe...", "loading-recipe": "טוען מתכון...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "טוען נתוני OCR...",
"loading-recipes": "מתכונים בטעינה", "loading-recipes": "מתכונים בטעינה",
"message": "הודעה", "message": "הודעה",
"monday": "שני", "monday": "שני",
@ -128,7 +128,7 @@
"no-recipe-found": "לא נמצא מתכון", "no-recipe-found": "לא נמצא מתכון",
"ok": "אישור", "ok": "אישור",
"options": "אפשרויות:", "options": "אפשרויות:",
"plural-name": "Plural Name", "plural-name": "שם ברבים",
"print": "הדפסה", "print": "הדפסה",
"print-preferences": "העדפות הדפסה", "print-preferences": "העדפות הדפסה",
"random": "אקראי", "random": "אקראי",
@ -198,7 +198,8 @@
"refresh": "רענן", "refresh": "רענן",
"upload-file": "העלאת קבצים", "upload-file": "העלאת קבצים",
"created-on-date": "נוצר ב-{0}", "created-on-date": "נוצר ב-{0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "unsaved-changes": "יש שינויים שלא נשמרו. לצאת לפני שמירה? אשר לשמירה, בטל למחיקת שינויים.",
"clipboard-copy-failure": "כשלון בהעתקה ללוח ההדבקה."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "האם את/ה בטוח/ה שברצונך למחוק את <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "האם את/ה בטוח/ה שברצונך למחוק את <b>{groupName}<b/>?",
@ -213,7 +214,7 @@
"group-id-with-value": "מזהה קבוצה: {groupID}", "group-id-with-value": "מזהה קבוצה: {groupID}",
"group-name": "שם קבוצה", "group-name": "שם קבוצה",
"group-not-found": "קבוצה לא נמצאה", "group-not-found": "קבוצה לא נמצאה",
"group-token": "Group Token", "group-token": "טוקן קבוצתי",
"group-with-value": "קבוצה: {groupID}", "group-with-value": "קבוצה: {groupID}",
"groups": "קבוצות", "groups": "קבוצות",
"manage-groups": "ניהול קבוצות", "manage-groups": "ניהול קבוצות",
@ -249,7 +250,7 @@
"general-preferences": "העדפות כלליות", "general-preferences": "העדפות כלליות",
"group-recipe-preferences": "העדפות קבוצה", "group-recipe-preferences": "העדפות קבוצה",
"report": "דיווח", "report": "דיווח",
"report-with-id": "Report ID: {id}", "report-with-id": "מספר דוח: {id}",
"group-management": "ניהול קבוצה", "group-management": "ניהול קבוצה",
"admin-group-management": "ניהול קבוצת מנהל", "admin-group-management": "ניהול קבוצת מנהל",
"admin-group-management-text": "השינויים לקבוצה זו יתבצעו מיידית.", "admin-group-management-text": "השינויים לקבוצה זו יתבצעו מיידית.",
@ -470,9 +471,9 @@
"add-to-plan": "הוספה לתכנית", "add-to-plan": "הוספה לתכנית",
"add-to-timeline": "הוסף לציר הזמן", "add-to-timeline": "הוסף לציר הזמן",
"recipe-added-to-list": "מתכון נוסף לרשימה", "recipe-added-to-list": "מתכון נוסף לרשימה",
"recipes-added-to-list": "Recipes added to list", "recipes-added-to-list": "מתכונים הוספו לרשימה",
"recipe-added-to-mealplan": "מתכון נוסף לתכנון ארוחות", "recipe-added-to-mealplan": "מתכון נוסף לתכנון ארוחות",
"failed-to-add-recipes-to-list": "Failed to add recipe to list", "failed-to-add-recipes-to-list": "כשלון בהוספת מתכון לרשימה",
"failed-to-add-recipe-to-mealplan": "הוספת מתכון לתכנון ארוחות נכשלה", "failed-to-add-recipe-to-mealplan": "הוספת מתכון לתכנון ארוחות נכשלה",
"yield": "תשואה", "yield": "תשואה",
"quantity": "כמות", "quantity": "כמות",
@ -514,7 +515,7 @@
"message-key": "מפתח הודעה", "message-key": "מפתח הודעה",
"parse": "ניתוח", "parse": "ניתוח",
"attach-images-hint": "הוסף תמונות ע\"י גרירה ושחרור אל תוך העורך", "attach-images-hint": "הוסף תמונות ע\"י גרירה ושחרור אל תוך העורך",
"drop-image": "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": "חילוץ רכיבים",
@ -573,16 +574,16 @@
"search-hint": "לחץ '/'", "search-hint": "לחץ '/'",
"advanced": "מתקדם", "advanced": "מתקדם",
"auto-search": "חיפוש אוטומטי", "auto-search": "חיפוש אוטומטי",
"no-results": "No results found" "no-results": "לא נמצאו תוצאות"
}, },
"settings": { "settings": {
"add-a-new-theme": "הוסף ערכת נושא חדשה", "add-a-new-theme": "הוסף ערכת נושא חדשה",
"admin-settings": "הגדרות מנהל", "admin-settings": "הגדרות מנהל",
"backup": { "backup": {
"backup-created": "Backup created successfully", "backup-created": "הגיבוי בוצע בהצלחה",
"backup-created-at-response-export_path": "גיבוי נוצר ב {path}", "backup-created-at-response-export_path": "גיבוי נוצר ב {path}",
"backup-deleted": "גיבוי נמחק", "backup-deleted": "גיבוי נמחק",
"restore-success": "Restore successful", "restore-success": "השחזור הצליח",
"backup-tag": "תגית גיבוי", "backup-tag": "תגית גיבוי",
"create-heading": "Create a Backup", "create-heading": "Create a Backup",
"delete-backup": "מחיקת גיבוי", "delete-backup": "מחיקת גיבוי",
@ -691,13 +692,13 @@
"configuration": "הגדרות", "configuration": "הגדרות",
"docker-volume": "Docker Volume", "docker-volume": "Docker Volume",
"docker-volume-help": "מילי דורשת שקונטיינר הקצה הקדמי והקצה האחורי חולקים את באותו כונן / שטח אחסון בדוקר.\nכל זאת כל מנת לוודא שלקונטיינר תהיה גישה לתמונות הגיבוי או לנכסים בדיסק.", "docker-volume-help": "מילי דורשת שקונטיינר הקצה הקדמי והקצה האחורי חולקים את באותו כונן / שטח אחסון בדוקר.\nכל זאת כל מנת לוודא שלקונטיינר תהיה גישה לתמונות הגיבוי או לנכסים בדיסק.",
"volumes-are-misconfigured": "Volumes are misconfigured.", "volumes-are-misconfigured": "כוננים אינם מוגדרים בצורה תקינה.",
"volumes-are-configured-correctly": "ה-Volumeים מוגדרים תקין.", "volumes-are-configured-correctly": "ה-Volumeים מוגדרים תקין.",
"status-unknown-try-running-a-validation": "מצב לא ידוע. נסה להריץ אימות.", "status-unknown-try-running-a-validation": "מצב לא ידוע. נסה להריץ אימות.",
"validate": "אימות", "validate": "אימות",
"email-configuration-status": "מצב הגדרות דוא״ל", "email-configuration-status": "מצב הגדרות דוא״ל",
"email-configured": "Email Configured", "email-configured": "דואר אלקטרוני הוגדר",
"email-test-results": "Email Test Results", "email-test-results": "תוצאות בדיקת דואר אלקטרוני",
"ready": "מוכן", "ready": "מוכן",
"not-ready": "לא מוכן - בדוק משתני סביבה", "not-ready": "לא מוכן - בדוק משתני סביבה",
"succeeded": "הצליח", "succeeded": "הצליח",
@ -832,7 +833,7 @@
"password-updated": "הסיסמה עודכנה", "password-updated": "הסיסמה עודכנה",
"password": "סיסמה", "password": "סיסמה",
"password-strength": "חוזק הסיסמה {strength}", "password-strength": "חוזק הסיסמה {strength}",
"please-enter-password": "Please enter your new password.", "please-enter-password": "אנא הזן סיסמה חדשה.",
"register": "הרשמה", "register": "הרשמה",
"reset-password": "איפוס סיסמה", "reset-password": "איפוס סיסמה",
"sign-in": "התחברות", "sign-in": "התחברות",
@ -853,7 +854,7 @@
"username": "שם משתמש", "username": "שם משתמש",
"users-header": "משתמשים", "users-header": "משתמשים",
"users": "משתמשים", "users": "משתמשים",
"user-not-found": "User not found", "user-not-found": "משתמש לא נמצא",
"webhook-time": "זמן Webhook", "webhook-time": "זמן Webhook",
"webhooks-enabled": "הפעלת Webhooks", "webhooks-enabled": "הפעלת Webhooks",
"you-are-not-allowed-to-create-a-user": "אין הרשאה ליצור משתמש", "you-are-not-allowed-to-create-a-user": "אין הרשאה ליצור משתמש",
@ -876,7 +877,7 @@
"user-management": "ניהול משתמשים", "user-management": "ניהול משתמשים",
"reset-locked-users": "אתחל משתמשים נעולים", "reset-locked-users": "אתחל משתמשים נעולים",
"admin-user-creation": "יצירת משתמש אדמין", "admin-user-creation": "יצירת משתמש אדמין",
"admin-user-management": "Admin User Management", "admin-user-management": "ניהול משתמשים",
"user-details": "פרטי משתמש", "user-details": "פרטי משתמש",
"user-name": "שם משתמש", "user-name": "שם משתמש",
"authentication-method": "שיטת אימות", "authentication-method": "שיטת אימות",
@ -887,9 +888,9 @@
"user-can-manage-group": "משתמש יכול לנהל קבוצה", "user-can-manage-group": "משתמש יכול לנהל קבוצה",
"user-can-organize-group-data": "משתמש יכול לשנות מידע של קבוצה", "user-can-organize-group-data": "משתמש יכול לשנות מידע של קבוצה",
"enable-advanced-features": "אפשר אפשרויות מתקדמות", "enable-advanced-features": "אפשר אפשרויות מתקדמות",
"it-looks-like-this-is-your-first-time-logging-in": "It looks like this is your first time logging in.", "it-looks-like-this-is-your-first-time-logging-in": "נראה שזו ההתחברות הראשונה שלך.",
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!", "dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!",
"forgot-password": "Forgot Password", "forgot-password": "שכחתי סיסמא",
"forgot-password-text": "Please enter your email address and we will send you a link to reset your password.", "forgot-password-text": "Please enter your email address and we will send you a link to reset your password.",
"changes-reflected-immediately": "Changes to this user will be reflected immediately." "changes-reflected-immediately": "Changes to this user will be reflected immediately."
}, },
@ -965,8 +966,8 @@
"delete-recipes": "מחיקת מתכונים", "delete-recipes": "מחיקת מתכונים",
"source-unit-will-be-deleted": "יחידת המקור תמחק" "source-unit-will-be-deleted": "יחידת המקור תמחק"
}, },
"create-alias": "Create Alias", "create-alias": "יצירת שם נרדף",
"manage-aliases": "Manage Aliases", "manage-aliases": "נהל שמות נרדפים",
"seed-data": "אכלס נתונים", "seed-data": "אכלס נתונים",
"seed": "אכלס", "seed": "אכלס",
"data-management": "ניהול מידע", "data-management": "ניהול מידע",
@ -976,24 +977,24 @@
"columns": "עמודות", "columns": "עמודות",
"combine": "שילוב", "combine": "שילוב",
"categories": { "categories": {
"edit-category": "Edit Category", "edit-category": "ערוך קטגוריה",
"new-category": "New Category", "new-category": "קטגוריה חדשה",
"category-data": "Category Data" "category-data": "נתוני קטגוריה"
}, },
"tags": { "tags": {
"new-tag": "New Tag", "new-tag": "טאג חדש",
"edit-tag": "Edit Tag", "edit-tag": "ערוך טאג",
"tag-data": "Tag Data" "tag-data": "נתוני טאגים"
}, },
"tools": { "tools": {
"new-tool": "New Tool", "new-tool": "כלי חדש",
"edit-tool": "Edit Tool", "edit-tool": "ערוך כלי",
"tool-data": "Tool Data" "tool-data": "נתוני כלים"
} }
}, },
"user-registration": { "user-registration": {
"user-registration": "רישום משתמשים", "user-registration": "רישום משתמשים",
"registration-success": "Registration Success", "registration-success": "ההרשמה הושלמה",
"join-a-group": "הצטרפות לקבוצה", "join-a-group": "הצטרפות לקבוצה",
"create-a-new-group": "יצירת קבוצה חדשה", "create-a-new-group": "יצירת קבוצה חדשה",
"provide-registration-token-description": "ספק בבקשה את טוקן הרישום המשוייך לקבוצה אליה ברצונך להצטרף. בכדי לקבל אותו יהיה צורך להשיג אותו מאחד מחברה הקבוצה הקיימים.", "provide-registration-token-description": "ספק בבקשה את טוקן הרישום המשוייך לקבוצה אליה ברצונך להצטרף. בכדי לקבל אותו יהיה צורך להשיג אותו מאחד מחברה הקבוצה הקיימים.",
@ -1040,7 +1041,7 @@
}, },
"ocr-editor": { "ocr-editor": {
"ocr-editor": "עורך סריקת תווים", "ocr-editor": "עורך סריקת תווים",
"toolbar": "Toolbar", "toolbar": "סרגל כלים",
"selection-mode": "מצב בחירה", "selection-mode": "מצב בחירה",
"pan-and-zoom-picture": "סובב והגדל תמונה", "pan-and-zoom-picture": "סובב והגדל תמונה",
"split-text": "פיצול טקסט", "split-text": "פיצול טקסט",
@ -1048,8 +1049,8 @@
"split-by-block": "פצל לפי מבנה המלל", "split-by-block": "פצל לפי מבנה המלל",
"flatten": "שטח בלי קשר למבנה המקורי", "flatten": "שטח בלי קשר למבנה המקורי",
"help": { "help": {
"help": "Help", "help": "עזרה",
"mouse-modes": "Mouse modes", "mouse-modes": "מצבי עכבר",
"selection-mode": "מצב בחירה (ברירת מחדל)", "selection-mode": "מצב בחירה (ברירת מחדל)",
"selection-mode-desc": "מצב בחירה זה הינו הראשי אשר ישמש להכנסת מידע:", "selection-mode-desc": "מצב בחירה זה הינו הראשי אשר ישמש להכנסת מידע:",
"selection-mode-steps": { "selection-mode-steps": {

View File

@ -198,7 +198,8 @@
"refresh": "Osvježi", "refresh": "Osvježi",
"upload-file": "Prenesi Datoteku", "upload-file": "Prenesi Datoteku",
"created-on-date": "Kreirano dana: {0}", "created-on-date": "Kreirano dana: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Jeste li sigurni da želite izbrisati <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Jeste li sigurni da želite izbrisati <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Frissít", "refresh": "Frissít",
"upload-file": "Fájl feltöltése", "upload-file": "Fájl feltöltése",
"created-on-date": "Létrehozva: {0}", "created-on-date": "Létrehozva: {0}",
"unsaved-changes": "El nem mentett módosításai vannak. Szeretné elmenteni, mielőtt kilép? A mentéshez kattintson az Ok, a módosítások elvetéséhez a Mégsem gombra." "unsaved-changes": "El nem mentett módosításai vannak. Szeretné elmenteni, mielőtt kilép? A mentéshez kattintson az Ok, a módosítások elvetéséhez a Mégsem gombra.",
"clipboard-copy-failure": "Nem sikerült a vágólapra másolás."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Biztosan törölni szeretnéd ezt: <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Biztosan törölni szeretnéd ezt: <b>{groupName}<b/>?",
@ -1113,7 +1114,7 @@
"brute": "Brute", "brute": "Brute",
"show-individual-confidence": "", "show-individual-confidence": "",
"ingredient-text": "Hozzávaló szöveg", "ingredient-text": "Hozzávaló szöveg",
"average-confident": "{0} Confident", "average-confident": "{0}-os bizonyosság",
"try-an-example": "Próbáljon ki egy példát", "try-an-example": "Próbáljon ki egy példát",
"parser": "Szintaxis elemző", "parser": "Szintaxis elemző",
"background-tasks": "Háttér folyamatok", "background-tasks": "Háttér folyamatok",

View File

@ -77,7 +77,7 @@
"tag-events": "Tag Eventi", "tag-events": "Tag Eventi",
"category-events": "Categoria Eventi", "category-events": "Categoria Eventi",
"when-a-new-user-joins-your-group": "Quando un nuovo utente entra nel tuo gruppo", "when-a-new-user-joins-your-group": "Quando un nuovo utente entra nel tuo gruppo",
"recipe-events": "Recipe Events" "recipe-events": "Eventi di ricette"
}, },
"general": { "general": {
"cancel": "Cancella", "cancel": "Cancella",
@ -114,10 +114,10 @@
"json": "JSON", "json": "JSON",
"keyword": "Parola chiave", "keyword": "Parola chiave",
"link-copied": "Link Copiato", "link-copied": "Link Copiato",
"loading": "Loading", "loading": "Caricamento in corso",
"loading-events": "Caricamento eventi", "loading-events": "Caricamento eventi",
"loading-recipe": "Loading recipe...", "loading-recipe": "Caricamento della ricetta...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Caricamento dati OCR...",
"loading-recipes": "Caricamento Ricette", "loading-recipes": "Caricamento Ricette",
"message": "Messaggio", "message": "Messaggio",
"monday": "Lunedì", "monday": "Lunedì",
@ -128,7 +128,7 @@
"no-recipe-found": "Nessuna Ricetta Trovata", "no-recipe-found": "Nessuna Ricetta Trovata",
"ok": "OK", "ok": "OK",
"options": "Opzioni:", "options": "Opzioni:",
"plural-name": "Plural Name", "plural-name": "Nome Plurale",
"print": "Stampa", "print": "Stampa",
"print-preferences": "Preferenze Di Stampa", "print-preferences": "Preferenze Di Stampa",
"random": "Casuale", "random": "Casuale",
@ -198,7 +198,8 @@
"refresh": "Ricarica", "refresh": "Ricarica",
"upload-file": "Carica file", "upload-file": "Carica file",
"created-on-date": "Creato il: {0}", "created-on-date": "Creato il: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "unsaved-changes": "Sono state apportate modifiche non salvate. Salvare prima di uscire? Premi Ok per salvare, Annulla per scartare le modifiche.",
"clipboard-copy-failure": "Impossibile copiare negli appunti."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Sei sicuro di volerlo eliminare <b>{groupName}<b/>'?", "are-you-sure-you-want-to-delete-the-group": "Sei sicuro di volerlo eliminare <b>{groupName}<b/>'?",
@ -213,7 +214,7 @@
"group-id-with-value": "ID Gruppo:{groupID}", "group-id-with-value": "ID Gruppo:{groupID}",
"group-name": "Nome Gruppo", "group-name": "Nome Gruppo",
"group-not-found": "Gruppo non trovato", "group-not-found": "Gruppo non trovato",
"group-token": "Group Token", "group-token": "Token del gruppo",
"group-with-value": "Gruppo: {groupID}", "group-with-value": "Gruppo: {groupID}",
"groups": "Gruppi", "groups": "Gruppi",
"manage-groups": "Gestisci Gruppi", "manage-groups": "Gestisci Gruppi",
@ -249,7 +250,7 @@
"general-preferences": "Impostazioni Generali", "general-preferences": "Impostazioni Generali",
"group-recipe-preferences": "Impostazioni per le ricette del gruppo", "group-recipe-preferences": "Impostazioni per le ricette del gruppo",
"report": "Report", "report": "Report",
"report-with-id": "Report ID: {id}", "report-with-id": "ID Report: {id}",
"group-management": "Gestione Gruppo", "group-management": "Gestione Gruppo",
"admin-group-management": "Gestione Gruppo Amministratore", "admin-group-management": "Gestione Gruppo Amministratore",
"admin-group-management-text": "Le modifiche a questo gruppo si rifletteranno immediatamente.", "admin-group-management-text": "Le modifiche a questo gruppo si rifletteranno immediatamente.",
@ -304,7 +305,7 @@
"for-type-meal-types": "per {0} tipi di pasto", "for-type-meal-types": "per {0} tipi di pasto",
"meal-plan-rules": "Regole del piano alimentare", "meal-plan-rules": "Regole del piano alimentare",
"new-rule": "Nuova regola", "new-rule": "Nuova regola",
"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 categories of the rules will be merged. In practice, it's unnecessary to create duplicate rules, but it's possible to do so.", "meal-plan-rules-description": "Puoi creare regole per la selezione automatica delle ricette per i tuoi piani alimentari. Queste regole vengono utilizzate dal server per determinare le ricette da selezionare durante la creazione dei piani alimentari. Tieni presente che se le regole hanno gli stessi vincoli di giorno/tipo, le categorie delle regole verranno unite. In pratica non è necessario creare regole duplicate, ma è possibile farlo.",
"new-rule-description": "Quando si crea una nuova regola per un piano alimentare è possibile limitare la sua applicazione ad un giorno specifico della settimana e/o un tipo specifico di pasto. Per applicare una regola a tutti i giorni o a tutti i tipi di pasto, è possibile impostare la regola a \"Qualsiasi\", applicandola a tutti i possibili valori per il tipo di giorno e/o di pasto.", "new-rule-description": "Quando si crea una nuova regola per un piano alimentare è possibile limitare la sua applicazione ad un giorno specifico della settimana e/o un tipo specifico di pasto. Per applicare una regola a tutti i giorni o a tutti i tipi di pasto, è possibile impostare la regola a \"Qualsiasi\", applicandola a tutti i possibili valori per il tipo di giorno e/o di pasto.",
"recipe-rules": "Regole per le ricette", "recipe-rules": "Regole per le ricette",
"applies-to-all-days": "Si applica a ogni giorno", "applies-to-all-days": "Si applica a ogni giorno",
@ -356,7 +357,7 @@
"mealie-text": "Mealie può importare ricette dall'applicazione Mealie da un versione pre v1.0. Esporta le tue ricette dalla tua vecchia istanza e carica il file zip qui sotto. Nota che solo le ricette possono essere importate dall'esportazione.", "mealie-text": "Mealie può importare ricette dall'applicazione Mealie da un versione pre v1.0. Esporta le tue ricette dalla tua vecchia istanza e carica il file zip qui sotto. Nota che solo le ricette possono essere importate dall'esportazione.",
"plantoeat": { "plantoeat": {
"title": "Plan to Eat", "title": "Plan to Eat",
"description-long": "Mealie can import recipies from Plan to Eat." "description-long": "Mealie può importare le ricette da Plan to Eat."
} }
}, },
"new-recipe": { "new-recipe": {
@ -468,11 +469,11 @@
"date-format-hint-yyyy-mm-dd": "Formato YYYY-MM-DD", "date-format-hint-yyyy-mm-dd": "Formato YYYY-MM-DD",
"add-to-list": "Aggiungi alla lista", "add-to-list": "Aggiungi alla lista",
"add-to-plan": "Aggiungi al piano giornaliero", "add-to-plan": "Aggiungi al piano giornaliero",
"add-to-timeline": "Add to Timeline", "add-to-timeline": "Aggiungi alla linea temporale",
"recipe-added-to-list": "Ricetta aggiunta alla lista", "recipe-added-to-list": "Ricetta aggiunta alla lista",
"recipes-added-to-list": "Recipes added to list", "recipes-added-to-list": "Ricette aggiunte alla lista",
"recipe-added-to-mealplan": "Ricetta aggiunta al piano alimentare", "recipe-added-to-mealplan": "Ricetta aggiunta al piano alimentare",
"failed-to-add-recipes-to-list": "Failed to add recipe to list", "failed-to-add-recipes-to-list": "Impossibile aggiungere la ricetta alla lista",
"failed-to-add-recipe-to-mealplan": "Impossibile aggiungere la ricetta al piano alimentare", "failed-to-add-recipe-to-mealplan": "Impossibile aggiungere la ricetta al piano alimentare",
"yield": "Porzioni", "yield": "Porzioni",
"quantity": "Quantità", "quantity": "Quantità",
@ -495,26 +496,26 @@
"locked": "Bloccato", "locked": "Bloccato",
"public-link": "Link Pubblico", "public-link": "Link Pubblico",
"timer": { "timer": {
"kitchen-timer": "Kitchen Timer", "kitchen-timer": "Contaminuti da cucina",
"start-timer": "Start Timer", "start-timer": "Avvia timer",
"pause-timer": "Pause Timer", "pause-timer": "Metti in pausa il contaminuti",
"resume-timer": "Resume Timer", "resume-timer": "Riprendi il contaminuti",
"stop-timer": "Stop Timer" "stop-timer": "Arresta il Timer"
}, },
"edit-timeline-event": "Modifica Evento Timeline", "edit-timeline-event": "Modifica evento sulla linea temporale",
"timeline": "Timeline", "timeline": "Linea temporale",
"timeline-is-empty": "Niente sulla timeline. Prova a fare questa ricetta!", "timeline-is-empty": "Niente sulla linea temporale. Prova a fare questa ricetta!",
"group-global-timeline": "{groupName} Sequenza Temporale Globale", "group-global-timeline": "{groupName} Linea temporale globale",
"open-timeline": "Apri la Timeline", "open-timeline": "Apri la linea temporale",
"made-this": "L'Ho Preparato", "made-this": "L'Ho Preparato",
"how-did-it-turn-out": "Come è venuto?", "how-did-it-turn-out": "Come è venuto?",
"user-made-this": "{user} l'ha preparato", "user-made-this": "{user} l'ha preparato",
"last-made-date": "Ultima Preparazione {date}", "last-made-date": "Ultima Preparazione {date}",
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.", "api-extras-description": "Le opzioni extra delle ricette sono una caratteristica fondamentale dell'API Mealie. Consentono di creare json personalizzati con coppie di chiavi/valore all'interno di una ricetta a cui fare riferimento tramite applicazioni terze. È possibile utilizzare queste chiavi per inserire informazioni, per esempio per attivare automazioni oppure per inoltrare messaggi personalizzati al dispositivo desiderato.",
"message-key": "Chiave Messaggio", "message-key": "Chiave Messaggio",
"parse": "Analizza", "parse": "Analizza",
"attach-images-hint": "Allega immagini trascinandole nell'editor", "attach-images-hint": "Allega immagini trascinandole nell'editor",
"drop-image": "Drop image", "drop-image": "Trascina l'immagine",
"enable-ingredient-amounts-to-use-this-feature": "Abilita le quantità degli ingredienti per utilizzare questa funzione", "enable-ingredient-amounts-to-use-this-feature": "Abilita le quantità degli ingredienti per utilizzare questa funzione",
"recipes-with-units-or-foods-defined-cannot-be-parsed": "Le ricette con unità o alimenti definiti non possono essere analizzate.", "recipes-with-units-or-foods-defined-cannot-be-parsed": "Le ricette con unità o alimenti definiti non possono essere analizzate.",
"parse-ingredients": "Analizza ingredienti", "parse-ingredients": "Analizza ingredienti",
@ -553,8 +554,8 @@
"recipe-yield": "Resa Ricetta", "recipe-yield": "Resa Ricetta",
"unit": "Unità", "unit": "Unità",
"upload-image": "Carica immagine", "upload-image": "Carica immagine",
"screen-awake": "Keep Screen Awake", "screen-awake": "Mantieni lo schermo acceso",
"remove-image": "Remove image" "remove-image": "Rimuovi immagine"
}, },
"search": { "search": {
"advanced-search": "Ricerca Avanzata", "advanced-search": "Ricerca Avanzata",
@ -573,16 +574,16 @@
"search-hint": "Premi '/'", "search-hint": "Premi '/'",
"advanced": "Ricerca Avanzata", "advanced": "Ricerca Avanzata",
"auto-search": "Ricerca automatica", "auto-search": "Ricerca automatica",
"no-results": "No results found" "no-results": "Nessun risultato trovato"
}, },
"settings": { "settings": {
"add-a-new-theme": "Aggiungi un Nuovo Tema", "add-a-new-theme": "Aggiungi un Nuovo Tema",
"admin-settings": "Impostazioni Amministratore", "admin-settings": "Impostazioni Amministratore",
"backup": { "backup": {
"backup-created": "Backup created successfully", "backup-created": "Backup creato con successo",
"backup-created-at-response-export_path": "Backup Creato in {path}", "backup-created-at-response-export_path": "Backup Creato in {path}",
"backup-deleted": "Backup eliminato", "backup-deleted": "Backup eliminato",
"restore-success": "Restore successful", "restore-success": "Ripristino riuscito",
"backup-tag": "Tag Backup", "backup-tag": "Tag Backup",
"create-heading": "Crea un Backup", "create-heading": "Crea un Backup",
"delete-backup": "Elimina Backup", "delete-backup": "Elimina Backup",
@ -691,13 +692,13 @@
"configuration": "Configurazione", "configuration": "Configurazione",
"docker-volume": "Docker Volume", "docker-volume": "Docker Volume",
"docker-volume-help": "Mealie richiede che il frontend e il backend condividano lo stesso volume docker o archiviazione. Ciò assicura che il frontend possa accedere correttamente alle immagini e alle risorse memorizzate sul disco.", "docker-volume-help": "Mealie richiede che il frontend e il backend condividano lo stesso volume docker o archiviazione. Ciò assicura che il frontend possa accedere correttamente alle immagini e alle risorse memorizzate sul disco.",
"volumes-are-misconfigured": "Volumes are misconfigured.", "volumes-are-misconfigured": "I volumi sono configurati male.",
"volumes-are-configured-correctly": "I volumi sono stati configurati correttamente.", "volumes-are-configured-correctly": "I volumi sono stati configurati correttamente.",
"status-unknown-try-running-a-validation": "Stato sconosciuto. Prova ad eseguire una convalida.", "status-unknown-try-running-a-validation": "Stato sconosciuto. Prova ad eseguire una convalida.",
"validate": "Convalida", "validate": "Convalida",
"email-configuration-status": "Configurazione e-mail", "email-configuration-status": "Configurazione e-mail",
"email-configured": "Email Configured", "email-configured": "Email configurata",
"email-test-results": "Email Test Results", "email-test-results": "Risultati del test email",
"ready": "Pronto", "ready": "Pronto",
"not-ready": "Non Pronto - Verifica Variabili Di Ambiente", "not-ready": "Non Pronto - Verifica Variabili Di Ambiente",
"succeeded": "Operazione riuscita", "succeeded": "Operazione riuscita",
@ -832,7 +833,7 @@
"password-updated": "Password aggiornata", "password-updated": "Password aggiornata",
"password": "Password", "password": "Password",
"password-strength": "La password è {strength}", "password-strength": "La password è {strength}",
"please-enter-password": "Please enter your new password.", "please-enter-password": "Si prega di inserire la nuova password.",
"register": "Registrati", "register": "Registrati",
"reset-password": "Reimposta Password", "reset-password": "Reimposta Password",
"sign-in": "Accedi", "sign-in": "Accedi",
@ -853,7 +854,7 @@
"username": "Nome Utente", "username": "Nome Utente",
"users-header": "UTENTI", "users-header": "UTENTI",
"users": "Utenti", "users": "Utenti",
"user-not-found": "User not found", "user-not-found": "Utente non trovato",
"webhook-time": "Ora Webhook", "webhook-time": "Ora Webhook",
"webhooks-enabled": "Webhooks Abilitati", "webhooks-enabled": "Webhooks Abilitati",
"you-are-not-allowed-to-create-a-user": "Non sei autorizzato per la creazione di utenti", "you-are-not-allowed-to-create-a-user": "Non sei autorizzato per la creazione di utenti",
@ -876,7 +877,7 @@
"user-management": "Gestione Utenti", "user-management": "Gestione Utenti",
"reset-locked-users": "Ripristina Utenti Bloccati", "reset-locked-users": "Ripristina Utenti Bloccati",
"admin-user-creation": "Creazione Utente Amministratore", "admin-user-creation": "Creazione Utente Amministratore",
"admin-user-management": "Admin User Management", "admin-user-management": "Gestione Utente Amministratore",
"user-details": "Dettagli Utente", "user-details": "Dettagli Utente",
"user-name": "Nome Utente", "user-name": "Nome Utente",
"authentication-method": "Metodo di autenticazione", "authentication-method": "Metodo di autenticazione",
@ -887,11 +888,11 @@
"user-can-manage-group": "L'utente può gestire il gruppo", "user-can-manage-group": "L'utente può gestire il gruppo",
"user-can-organize-group-data": "L'utente può organizzare i dati del gruppo", "user-can-organize-group-data": "L'utente può organizzare i dati del gruppo",
"enable-advanced-features": "Abilita funzionalità avanzate", "enable-advanced-features": "Abilita funzionalità avanzate",
"it-looks-like-this-is-your-first-time-logging-in": "It looks like this is your first time logging in.", "it-looks-like-this-is-your-first-time-logging-in": "Sembra che questa sia la tua prima volta che accedi.",
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!", "dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Non vuoi più vederlo? Assicurati di modificare la tua email nelle impostazioni utente!",
"forgot-password": "Forgot Password", "forgot-password": "Password Dimenticata",
"forgot-password-text": "Please enter your email address and we will send you a link to reset your password.", "forgot-password-text": "Inserisci il tuo indirizzo email e ti invieremo un collegamento per reimpostare la tua password.",
"changes-reflected-immediately": "Changes to this user will be reflected immediately." "changes-reflected-immediately": "Le modifiche a questo utente diventeranno immediatamente effettive."
}, },
"language-dialog": { "language-dialog": {
"translated": "tradotto", "translated": "tradotto",
@ -913,8 +914,8 @@
"food-label": "Etichetta Alimento", "food-label": "Etichetta Alimento",
"edit-food": "Modifica Alimento", "edit-food": "Modifica Alimento",
"food-data": "Dati Alimento", "food-data": "Dati Alimento",
"example-food-singular": "ex: Onion", "example-food-singular": "esempio: Cipolla",
"example-food-plural": "ex: Onions" "example-food-plural": "esempio: Cipolle"
}, },
"units": { "units": {
"seed-dialog-text": "Riempie il database con unità comuni basate sulla lingua.", "seed-dialog-text": "Riempie il database con unità comuni basate sulla lingua.",
@ -925,7 +926,7 @@
"merging-unit-into-unit": "Unione di {0} in {1}", "merging-unit-into-unit": "Unione di {0} in {1}",
"create-unit": "Crea Unità", "create-unit": "Crea Unità",
"abbreviation": "Abbreviazione", "abbreviation": "Abbreviazione",
"plural-abbreviation": "Plural Abbreviation", "plural-abbreviation": "Abbreviazione Plurale",
"description": "Descrizione", "description": "Descrizione",
"display-as-fraction": "Mostra come Frazione", "display-as-fraction": "Mostra come Frazione",
"use-abbreviation": "Usa Abbreviazione", "use-abbreviation": "Usa Abbreviazione",
@ -933,10 +934,10 @@
"unit-data": "Dati Unità", "unit-data": "Dati Unità",
"use-abbv": "Utilizzare Abbrev.", "use-abbv": "Utilizzare Abbrev.",
"fraction": "Frazione", "fraction": "Frazione",
"example-unit-singular": "ex: Tablespoon", "example-unit-singular": "esempio: Cucchiaino",
"example-unit-plural": "ex: Tablespoons", "example-unit-plural": "esempio: Cucchiaini",
"example-unit-abbreviation-singular": "ex: Tbsp", "example-unit-abbreviation-singular": "esempio: Ccno",
"example-unit-abbreviation-plural": "ex: Tbsps" "example-unit-abbreviation-plural": "esempio: Ccni"
}, },
"labels": { "labels": {
"seed-dialog-text": "Riempie il database con etichette comuni basate sulla lingua.", "seed-dialog-text": "Riempie il database con etichette comuni basate sulla lingua.",
@ -965,8 +966,8 @@
"delete-recipes": "Elimina Ricette", "delete-recipes": "Elimina Ricette",
"source-unit-will-be-deleted": "L'unità di origine verrà eliminata" "source-unit-will-be-deleted": "L'unità di origine verrà eliminata"
}, },
"create-alias": "Create Alias", "create-alias": "Crea Alias",
"manage-aliases": "Manage Aliases", "manage-aliases": "Gestisci Alias",
"seed-data": "Dati Predefiniti", "seed-data": "Dati Predefiniti",
"seed": "Inizializza", "seed": "Inizializza",
"data-management": "Gestione Dati", "data-management": "Gestione Dati",
@ -976,24 +977,24 @@
"columns": "Colonne", "columns": "Colonne",
"combine": "Unisci", "combine": "Unisci",
"categories": { "categories": {
"edit-category": "Edit Category", "edit-category": "Modifica categoria",
"new-category": "New Category", "new-category": "Nuova categoria",
"category-data": "Category Data" "category-data": "Categoria Dati"
}, },
"tags": { "tags": {
"new-tag": "New Tag", "new-tag": "Nuovo Tag",
"edit-tag": "Edit Tag", "edit-tag": "Modifica Tag",
"tag-data": "Tag Data" "tag-data": "Dati del Tag"
}, },
"tools": { "tools": {
"new-tool": "New Tool", "new-tool": "Nuovo strumento",
"edit-tool": "Edit Tool", "edit-tool": "Modifica Strumento",
"tool-data": "Tool Data" "tool-data": "Dati dello Strumento"
} }
}, },
"user-registration": { "user-registration": {
"user-registration": "Registrazione Utente", "user-registration": "Registrazione Utente",
"registration-success": "Registration Success", "registration-success": "Registrazione completata",
"join-a-group": "Unisciti a un Gruppo", "join-a-group": "Unisciti a un Gruppo",
"create-a-new-group": "Crea un Nuovo Gruppo", "create-a-new-group": "Crea un Nuovo Gruppo",
"provide-registration-token-description": "Fornisci il token di registrazione associato al gruppo a cui desideri partecipare. Dovrai ottenerlo da un membro di gruppo esistente.", "provide-registration-token-description": "Fornisci il token di registrazione associato al gruppo a cui desideri partecipare. Dovrai ottenerlo da un membro di gruppo esistente.",
@ -1040,7 +1041,7 @@
}, },
"ocr-editor": { "ocr-editor": {
"ocr-editor": "Editor Ocr", "ocr-editor": "Editor Ocr",
"toolbar": "Toolbar", "toolbar": "Barra degli strumenti",
"selection-mode": "Modalità di selezione", "selection-mode": "Modalità di selezione",
"pan-and-zoom-picture": "Sposta e Ingrandisci l'immagine", "pan-and-zoom-picture": "Sposta e Ingrandisci l'immagine",
"split-text": "Dividi testo", "split-text": "Dividi testo",
@ -1048,8 +1049,8 @@
"split-by-block": "Dividi per blocco di testo", "split-by-block": "Dividi per blocco di testo",
"flatten": "Appiattire indipendentemente dalla formattazione originale", "flatten": "Appiattire indipendentemente dalla formattazione originale",
"help": { "help": {
"help": "Help", "help": "Aiuto",
"mouse-modes": "Mouse modes", "mouse-modes": "Modalità Mouse",
"selection-mode": "Modalità di Selezione (Predefinito)", "selection-mode": "Modalità di Selezione (Predefinito)",
"selection-mode-desc": "La modalità di selezione è la modalità principale per inserire i dati:", "selection-mode-desc": "La modalità di selezione è la modalità principale per inserire i dati:",
"selection-mode-steps": { "selection-mode-steps": {
@ -1106,26 +1107,26 @@
"mainentance": { "mainentance": {
"actions-title": "Azioni" "actions-title": "Azioni"
}, },
"ingredients-natural-language-processor": "Ingredients Natural Language Processor", "ingredients-natural-language-processor": "Processore Di Lingua Naturale degli Ingredienti",
"ingredients-natural-language-processor-explanation": "Mealie utilizza campi casuali condizionali (CRFs) per l'analisi e la lavorazione di ingredienti. Il modello utilizzato per gli ingredienti è basato su una serie di dati di oltre 100.000 ingredienti da un set di dati compilato dal New York Times. Si noti che poiché il modello è addestrato solo in inglese, si possono avere risultati vari quando si utilizza il modello in altre lingue. Questa pagina è un campo di gioco per testare il modello.", "ingredients-natural-language-processor-explanation": "Mealie utilizza campi casuali condizionali (CRFs) per l'analisi e la lavorazione di ingredienti. Il modello utilizzato per gli ingredienti è basato su una serie di dati di oltre 100.000 ingredienti da un set di dati compilato dal New York Times. Si noti che poiché il modello è addestrato solo in inglese, si possono avere risultati vari quando si utilizza il modello in altre lingue. Questa pagina è un campo di gioco per testare il modello.",
"ingredients-natural-language-processor-explanation-2": "It's not perfect, but it yields great results in general and is a good starting point for manually parsing ingredients into individual fields. Alternatively, you can also use the \"Brute\" processor that uses a pattern matching technique to identify ingredients.", "ingredients-natural-language-processor-explanation-2": "Non è perfetto, ma produce ottimi risultati in generale ed è un buon punto di partenza per separare manualmente gli ingredienti in singoli campi. In alternativa, è anche possibile utilizzare il processore \"Bruto\" che utilizza una tecnica di corrispondenza di modello per identificare gli ingredienti.",
"nlp": "NLP", "nlp": "NLP",
"brute": "Brute", "brute": "Bruto",
"show-individual-confidence": "Show individual confidence", "show-individual-confidence": "Mostra fiducia individuale",
"ingredient-text": "Ingredient Text", "ingredient-text": "Testo Ingrediente",
"average-confident": "{0} Confident", "average-confident": "{0} Fiducia",
"try-an-example": "Try an example", "try-an-example": "Prova un esempio",
"parser": "Parser", "parser": "Analizzatore",
"background-tasks": "Attività in Background", "background-tasks": "Attività in Background",
"background-tasks-description": "Qui puoi visualizzare tutte le attività in background in esecuzione e il loro stato", "background-tasks-description": "Qui puoi visualizzare tutte le attività in background in esecuzione e il loro stato",
"no-logs-found": "Nessun Log Trovato", "no-logs-found": "Nessun Log Trovato",
"tasks": "Tasks" "tasks": "Compiti"
}, },
"profile": { "profile": {
"welcome-user": "👋 Benvenuto, {0}", "welcome-user": "👋 Benvenuto, {0}",
"description": "Gestisci il tuo profilo, le ricette e le impostazioni di gruppo.", "description": "Gestisci il tuo profilo, le ricette e le impostazioni di gruppo.",
"get-invite-link": "Ottieni Link Di Invito", "get-invite-link": "Ottieni Link Di Invito",
"get-public-link": "Get Public Link", "get-public-link": "Ottieni link pubblico",
"account-summary": "Riepilogo Account", "account-summary": "Riepilogo Account",
"account-summary-description": "Ecco un riepilogo delle informazioni del tuo gruppo", "account-summary-description": "Ecco un riepilogo delle informazioni del tuo gruppo",
"group-statistics": "Statistiche Gruppo", "group-statistics": "Statistiche Gruppo",
@ -1157,13 +1158,13 @@
"show-advanced-description": "Mostra funzionalità avanzate (Chiavi API, Webhook e Gestione dati)", "show-advanced-description": "Mostra funzionalità avanzate (Chiavi API, Webhook e Gestione dati)",
"back-to-profile": "Torna al Profilo", "back-to-profile": "Torna al Profilo",
"looking-for-privacy-settings": "Stai cercando le Impostazioni Della Privacy?", "looking-for-privacy-settings": "Stai cercando le Impostazioni Della Privacy?",
"manage-your-api-tokens": "Manage Your API Tokens", "manage-your-api-tokens": "Gestisci i tuoi Token Api",
"manage-user-profile": "Manage User Profile", "manage-user-profile": "Gestisci Profilo Utente",
"manage-cookbooks": "Manage Cookbooks", "manage-cookbooks": "Gestisci Libri Di Cucina",
"manage-members": "Manage Members", "manage-members": "Gestisci i membri",
"manage-webhooks": "Manage Webhooks", "manage-webhooks": "Gestisci i Webhook",
"manage-notifiers": "Manage Notifiers", "manage-notifiers": "Gestisci Notifiche",
"manage-data-migrations": "Manage Data Migrations" "manage-data-migrations": "Gestione Migrazioni Dei Dati"
}, },
"cookbook": { "cookbook": {
"cookbooks": "Ricettari", "cookbooks": "Ricettari",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "ファイルのアップロード", "upload-file": "ファイルのアップロード",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "<b>{groupName}<b/> を削除しますか?", "are-you-sure-you-want-to-delete-the-group": "<b>{groupName}<b/> を削除しますか?",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "upload-file": "Upload File",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Atnaujinti", "refresh": "Atnaujinti",
"upload-file": "Įkelti failą", "upload-file": "Įkelti failą",
"created-on-date": "Sukurta: {0}", "created-on-date": "Sukurta: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Ar tikrai norite ištrinti <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Ar tikrai norite ištrinti <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "upload-file": "Upload File",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Verversen", "refresh": "Verversen",
"upload-file": "Bestand uploaden", "upload-file": "Bestand uploaden",
"created-on-date": "Gemaakt op {0}", "created-on-date": "Gemaakt op {0}",
"unsaved-changes": "Er zijn niet-opgeslagen wijzigingen. Wil je eerst opslaan voordat je vertrekt? Okay om op te slaan, Annuleren om wijzigingen ongedaan te maken." "unsaved-changes": "Er zijn niet-opgeslagen wijzigingen. Wil je eerst opslaan voordat je vertrekt? Okay om op te slaan, Annuleren om wijzigingen ongedaan te maken.",
"clipboard-copy-failure": "Kopiëren naar klembord mislukt."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Weet je zeker dat je <b>{groupName}<b/> wil verwijderen?", "are-you-sure-you-want-to-delete-the-group": "Weet je zeker dat je <b>{groupName}<b/> wil verwijderen?",

View File

@ -6,7 +6,7 @@
"api-port": "API-port", "api-port": "API-port",
"application-mode": "Programmodus", "application-mode": "Programmodus",
"database-type": "Databasetype", "database-type": "Databasetype",
"database-url": "Database-URL", "database-url": "URL til database",
"default-group": "Standardgruppe", "default-group": "Standardgruppe",
"demo": "Demo", "demo": "Demo",
"demo-status": "Demostatus", "demo-status": "Demostatus",
@ -46,7 +46,7 @@
"category-updated": "Kategori oppdatert", "category-updated": "Kategori oppdatert",
"uncategorized-count": "Ukategorisert {count}", "uncategorized-count": "Ukategorisert {count}",
"create-a-category": "Opprett en kategori", "create-a-category": "Opprett en kategori",
"category-name": "Katergorinavn", "category-name": "Navn på kategori",
"category": "Kategori" "category": "Kategori"
}, },
"events": { "events": {
@ -65,10 +65,10 @@
"subscribed-events": "Abonnerte hendelser", "subscribed-events": "Abonnerte hendelser",
"test-message-sent": "Testmelding sendt", "test-message-sent": "Testmelding sendt",
"new-notification": "Ny varsel", "new-notification": "Ny varsel",
"event-notifiers": "Hendelsesvarslere", "event-notifiers": "Hendelsesvarsler",
"apprise-url-skipped-if-blank": "Apprise URL (hoppes over hvis tom)", "apprise-url-skipped-if-blank": "Apprise URL (hoppes over hvis tom)",
"enable-notifier": "Aktiver varsleren", "enable-notifier": "Aktiver varslingsagenten",
"what-events": "Hvilke hendelser denne varsleren abonnere på?", "what-events": "Hvilke hendelser skal denne varslingsagenten abonnere på?",
"user-events": "Brukerhendelser", "user-events": "Brukerhendelser",
"mealplan-events": "Måltidsplanleggerhendelser", "mealplan-events": "Måltidsplanleggerhendelser",
"when-a-user-in-your-group-creates-a-new-mealplan": "Når en bruker i gruppen din oppretter en ny måltidsplan", "when-a-user-in-your-group-creates-a-new-mealplan": "Når en bruker i gruppen din oppretter en ny måltidsplan",
@ -122,13 +122,13 @@
"message": "Melding", "message": "Melding",
"monday": "Mandag", "monday": "Mandag",
"name": "Navn", "name": "Navn",
"new": "Ny", "new": "Legg til",
"never": "Aldri", "never": "Aldri",
"no": "Nei", "no": "Nei",
"no-recipe-found": "Ingen oppskrift funnet", "no-recipe-found": "Ingen oppskrift funnet",
"ok": "OK", "ok": "OK",
"options": "Alternativer:", "options": "Alternativer:",
"plural-name": "Flertallsnavn", "plural-name": "Navn på flertallsform",
"print": "Skriv ut", "print": "Skriv ut",
"print-preferences": "Skriv ut innstillinger", "print-preferences": "Skriv ut innstillinger",
"random": "Tilfeldig", "random": "Tilfeldig",
@ -180,7 +180,7 @@
"delete-with-name": "Slett {name}", "delete-with-name": "Slett {name}",
"confirm-delete-generic-with-name": "Er du sikker på at du vil slette denne {name}?", "confirm-delete-generic-with-name": "Er du sikker på at du vil slette denne {name}?",
"confirm-delete-own-admin-account": "Vær oppmerksom på at du holder på å slette din egen administrator-konto! Dette kan ikke angres og vil slette kontoen din permanent!", "confirm-delete-own-admin-account": "Vær oppmerksom på at du holder på å slette din egen administrator-konto! Dette kan ikke angres og vil slette kontoen din permanent!",
"organizer": "Planlegger", "organizer": "Organisator",
"transfer": "Overfør", "transfer": "Overfør",
"copy": "Kopiér", "copy": "Kopiér",
"color": "Farge", "color": "Farge",
@ -188,7 +188,7 @@
"last-made": "Sist laget", "last-made": "Sist laget",
"learn-more": "Lær mer", "learn-more": "Lær mer",
"this-feature-is-currently-inactive": "Denne funksjonen er for øyeblikket deaktivert", "this-feature-is-currently-inactive": "Denne funksjonen er for øyeblikket deaktivert",
"clipboard-not-supported": "Utklippstavlen støttes ikke", "clipboard-not-supported": "Utklippstavle støttes ikke",
"copied-to-clipboard": "Kopiert til utklippstavle", "copied-to-clipboard": "Kopiert til utklippstavle",
"your-browser-does-not-support-clipboard": "Nettleseren din støtter ikke kopiering til utklippstavle", "your-browser-does-not-support-clipboard": "Nettleseren din støtter ikke kopiering til utklippstavle",
"copied-items-to-clipboard": "Ingen elementer kopiert til utklippstavlen|Ett element kopiert til utklippstavlen|{count} elementer til kopiert til utklippstavlen", "copied-items-to-clipboard": "Ingen elementer kopiert til utklippstavlen|Ett element kopiert til utklippstavlen|{count} elementer til kopiert til utklippstavlen",
@ -198,7 +198,8 @@
"refresh": "Oppdater", "refresh": "Oppdater",
"upload-file": "Last opp fil", "upload-file": "Last opp fil",
"created-on-date": "Opprettet: {0}", "created-on-date": "Opprettet: {0}",
"unsaved-changes": "Du har ulagrede endringer. Ønsker du å lagre før du forlater? Trykk 'OK' for å lagre, 'Avbryt' for å forkaste endringene." "unsaved-changes": "Du har ulagrede endringer. Ønsker du å lagre før du forlater? Trykk 'OK' for å lagre, 'Avbryt' for å forkaste endringene.",
"clipboard-copy-failure": "Kunne ikke kopiere til utklippstavlen."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Er du sikker på at du vil slette <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Er du sikker på at du vil slette <b>{groupName}<b/>?",
@ -225,25 +226,25 @@
"keep-my-recipes-private-description": "Setter gruppen din og alle oppskrifter som standard til privat. Du kan alltids endre dette senere." "keep-my-recipes-private-description": "Setter gruppen din og alle oppskrifter som standard til privat. Du kan alltids endre dette senere."
}, },
"manage-members": "Administrer medlemmer", "manage-members": "Administrer medlemmer",
"manage-members-description": "Administrere rettighetene til medlemmene i dine grupper. {manage} gir brukeren tilgang til data-administrasjonssiden {invite} mulighet til å generere invitasjonslenker for andre brukere. Gruppeeiere kan ikke endre egne tillatelser.", "manage-members-description": "Administrer rettighetene til medlemmene i gruppene dine. {manage} lar brukeren få tilgang til dataadministrasjonssiden. {invite} lar brukeren generere invitasjonslenker for andre brukere. Gruppeeiere kan ikke endre egne tillatelser.",
"manage": "Administrer", "manage": "Administrer",
"invite": "Inviter", "invite": "Inviter",
"looking-to-update-your-profile": "Ønsker du å oppdatere profilen din?", "looking-to-update-your-profile": "Ønsker du å oppdatere profilen din?",
"default-recipe-preferences-description": "Dette er standardinnstillingene når en ny oppskrift blir opprettet i gruppen din. Disse kan endres for individuelle oppskrifter i oppskriftsmenyen.", "default-recipe-preferences-description": "Dette er standardinnstillingene når en ny oppskrift blir opprettet i gruppen din. Disse kan endres for individuelle oppskrifter i oppskriftsmenyen.",
"default-recipe-preferences": "Standard Oppskriftsinnstillinger", "default-recipe-preferences": "Standard oppskriftsinnstillinger",
"group-preferences": "Gruppeinnstillinger", "group-preferences": "Gruppeinnstillinger",
"private-group": "Privat gruppe", "private-group": "Privat gruppe",
"private-group-description": "Hvis din gruppe settes til privat, vil alle instillinger setter til standard. Dette overstyrer en individuell oppskrifter offentlige innstillinger.", "private-group-description": "Når du setter gruppen din til privat, vil alle offentlige visningsalternativer tilbakestilles til standardverdiene. Dette overskriver individuelle oppskrifters offentlige visningsinnstillinger.",
"allow-users-outside-of-your-group-to-see-your-recipes": "Tillat brukere utenfor gruppen å se oppskriftene dine", "allow-users-outside-of-your-group-to-see-your-recipes": "Tillat brukere utenfor gruppen å se oppskriftene dine",
"allow-users-outside-of-your-group-to-see-your-recipes-description": "Når aktivert kan du bruke en lenke for offentlig deling til å dele bestemte oppskrifter uten å autorisere brukeren. Når deaktivert kan du bare dele oppskrifter med brukere i gruppen din eller med en forhåndsgenerert privat link", "allow-users-outside-of-your-group-to-see-your-recipes-description": "Når aktivert, kan du bruke en offentlig lenke for å dele spesifikke oppskrifter uten å autorisere brukeren. Når deaktivert, kan du kun dele oppskrifter med brukere som er i gruppen din eller med en forhåndsgenerert privat lenke",
"show-nutrition-information": "Vis ernæringsinformasjon", "show-nutrition-information": "Vis ernæringsinformasjon",
"show-nutrition-information-description": "Når aktivert vil ernæringsinformasjonen bli vist på oppskriften hvis tilgjengelig. Hvis det ikke finnes noen ernæringsinformasjon tilgjengelig vil ikke ernæringsinformasjonen vises", "show-nutrition-information-description": "Når aktivert vil ernæringsinformasjonen bli vist på oppskriften hvis tilgjengelig. Hvis det ikke finnes noen ernæringsinformasjon tilgjengelig vil ikke ernæringsinformasjonen vises",
"show-recipe-assets": "Vis oppskriftsressurser", "show-recipe-assets": "Vis oppskriftsressurser",
"show-recipe-assets-description": "Når aktivert, vil oppskriftsressurser bli vist på oppskriften hvis de er tilgjengelige", "show-recipe-assets-description": "Når aktivert, vil oppskriftsressurser bli vist på oppskriften hvis de er tilgjengelige",
"default-to-landscape-view": "Standard liggende visning", "default-to-landscape-view": "Sett landskapsvisning som standard",
"default-to-landscape-view-description": "Når aktivert, vil oppskriftsoverskriften vises i landskapsvisning", "default-to-landscape-view-description": "Når aktivert, vil oppskriftsoverskriften vises i landskapsvisning",
"disable-users-from-commenting-on-recipes": "Deaktiver brukere fra å kommentere på oppskrifter", "disable-users-from-commenting-on-recipes": "Deaktiver muligheten for at brukere kan kommentere på oppskrifter",
"disable-users-from-commenting-on-recipes-description": "Skjuler kommentarfeltet på oppskriftssiden og deaktiverer kommentarer", "disable-users-from-commenting-on-recipes-description": "Skjuler kommentarfeltet på oppskriftssiden og deaktiverer kommentering",
"disable-organizing-recipe-ingredients-by-units-and-food": "Deaktiver organisering av oppskriftsingredienser ved enheter og matvarer", "disable-organizing-recipe-ingredients-by-units-and-food": "Deaktiver organisering av oppskriftsingredienser ved enheter og matvarer",
"disable-organizing-recipe-ingredients-by-units-and-food-description": "Skjuler matvare-, enhet- og mengdefelt for ingredienser og behandler ingredienser som rene tekstfelt.", "disable-organizing-recipe-ingredients-by-units-and-food-description": "Skjuler matvare-, enhet- og mengdefelt for ingredienser og behandler ingredienser som rene tekstfelt.",
"general-preferences": "Generelle innstillinger", "general-preferences": "Generelle innstillinger",
@ -251,8 +252,8 @@
"report": "Rapport", "report": "Rapport",
"report-with-id": "Rapport-ID: {id}", "report-with-id": "Rapport-ID: {id}",
"group-management": "Gruppeadministrasjon", "group-management": "Gruppeadministrasjon",
"admin-group-management": "Admin gruppeadministrasjon", "admin-group-management": "Gruppeadministrasjon",
"admin-group-management-text": "Endringer i denne gruppen vil umiddelbart bli reflektert.", "admin-group-management-text": "Endringer i denne gruppen vil gjenspeiles umiddelbart.",
"group-id-value": "Gruppe-ID: {0}" "group-id-value": "Gruppe-ID: {0}"
}, },
"meal-plan": { "meal-plan": {
@ -264,12 +265,12 @@
"end-date": "Sluttdato", "end-date": "Sluttdato",
"group": "Gruppe (Beta)", "group": "Gruppe (Beta)",
"main": "Hovedrett", "main": "Hovedrett",
"meal-planner": "Planlegg måltid", "meal-planner": "Måltidsplanlegger",
"meal-plans": "Måltidsplaner", "meal-plans": "Måltidsplaner",
"mealplan-categories": "MÅLTIDSPLANKATEGORIER", "mealplan-categories": "MÅLTIDSPLANKATEGORIER",
"mealplan-created": "Måltidsplan opprettet", "mealplan-created": "Måltidsplan opprettet",
"mealplan-creation-failed": "Opprettelse av måltidsplan mislyktes", "mealplan-creation-failed": "Opprettelse av måltidsplan mislyktes",
"mealplan-deleted": "Måltidsplan Slettet", "mealplan-deleted": "Måltidsplan slettet",
"mealplan-deletion-failed": "Sletting av måltidsplan mislyktes", "mealplan-deletion-failed": "Sletting av måltidsplan mislyktes",
"mealplan-settings": "Måltidsplaninnstillinger", "mealplan-settings": "Måltidsplaninnstillinger",
"mealplan-update-failed": "Oppdatering av måltidsplan mislyktes", "mealplan-update-failed": "Oppdatering av måltidsplan mislyktes",
@ -282,81 +283,81 @@
"side": "Tilbehør", "side": "Tilbehør",
"sides": "Tilbehør", "sides": "Tilbehør",
"start-date": "Startdato", "start-date": "Startdato",
"rule-day": "Regeldag", "rule-day": "Regel for dager",
"meal-type": "Type måltid", "meal-type": "Type måltid",
"breakfast": "Frokost", "breakfast": "Frokost",
"lunch": "Lunsj", "lunch": "Lunsj",
"dinner": "Middag", "dinner": "Middag",
"type-any": "Enhver", "type-any": "Enhver",
"day-any": "Enhver", "day-any": "Enhver",
"editor": "Redigering", "editor": "Redigeringsverktøy",
"meal-recipe": "Måltid oppskrift", "meal-recipe": "Oppskrift på måltid",
"meal-title": "Navn på måltid", "meal-title": "Tittel på måltid",
"meal-note": "Måltid Notat", "meal-note": "Notat for måltid",
"note-only": "Kun notat", "note-only": "Kun notat",
"random-meal": "Tilfeldig måltid", "random-meal": "Tilfeldig måltid",
"random-dinner": "Tilfeldig Middag", "random-dinner": "Tilfeldig middag",
"random-side": "Tilfeldig Tilbehør", "random-side": "Tilfeldig tilbehør",
"this-rule-will-apply": "Denne regelen vil gjelde for {dayCriteria} {mealTypeCriteria}.", "this-rule-will-apply": "Denne regelen vil gjelde for {dayCriteria} {mealTypeCriteria}.",
"to-all-days": "til alle dager", "to-all-days": "til alle dager",
"on-days": "på {0}s", "on-days": "på {0}er",
"for-all-meal-types": "for alle måltidstyper", "for-all-meal-types": "for alle måltidstyper",
"for-type-meal-types": "for {0} måltidstyper", "for-type-meal-types": "for {0} måltidstyper",
"meal-plan-rules": "Regler for måltidsplan", "meal-plan-rules": "Regler for måltidsplan",
"new-rule": "Ny regel", "new-rule": "Ny regel",
"meal-plan-rules-description": "Du kan opprette regler for automatisk valg av oppskrifter for dine måltidsplaner. Disse reglene brukes av serveren til å bestemme det tilfeldige utvalget av oppskrifter som skal velges fra når det opprettes måltidsplaner. Vær oppmerksom på at hvis regler har de samme begrensningene for dag/type, vil kategoriene til reglene bli slått sammen. I praksis er det unødvendig å opprette duplikater av regler, men det er mulig å gjøre det.", "meal-plan-rules-description": "Du kan opprette regler for automatisk valg av oppskrifter for dine måltidsplaner. Disse reglene brukes av serveren til å bestemme det tilfeldige utvalget av oppskrifter som skal velges fra når det opprettes måltidsplaner. Vær oppmerksom på at hvis regler har de samme begrensningene for dag/type, vil kategoriene til reglene bli slått sammen. I praksis er det unødvendig å opprette duplikater av regler, men det er mulig å gjøre det.",
"new-rule-description": "Ved opprettelse av en ny regel for en måltidsplan kan du begrense regelen til å gjelde for en bestemt ukedag og/eller en bestemt type måltid. For å ta i bruk en regen alle dager eller alle måltider kan du sette regelen til \"Enhver\" som gjelder for alle mulige verdier for dag- og/eller måltidstyper.", "new-rule-description": "Ved opprettelse av en ny regel for en måltidsplan kan du begrense regelen til å gjelde for en bestemt ukedag og/eller en bestemt type måltid. For å ta i bruk en regen alle dager eller alle måltider kan du sette regelen til \"Enhver\" som gjelder for alle mulige verdier for dag- og/eller måltidstyper.",
"recipe-rules": "Oppskrift Regler", "recipe-rules": "Regler for oppskrifter",
"applies-to-all-days": "Gjelder for alle dager", "applies-to-all-days": "Gjelder for alle dager",
"applies-on-days": "Gjelder på {0}s", "applies-on-days": "Gjelder på {0}er",
"meal-plan-settings": "Innstillinger for måltidsplan" "meal-plan-settings": "Innstillinger for måltidsplan"
}, },
"migration": { "migration": {
"migration-data-removed": "Migrasjonsdata er fjernet", "migration-data-removed": "Overføringsdata er fjernet",
"new-migration": "Ny migrering", "new-migration": "Ny overføring",
"no-file-selected": "Ingen fil valgt", "no-file-selected": "Ingen fil valgt",
"no-migration-data-available": "Ingen migrasjonsdata tilgjengelig", "no-migration-data-available": "Ingen overføringsdata tilgjengelig",
"previous-migrations": "Tidligere migreringer", "previous-migrations": "Tidligere overføringer",
"recipe-migration": "Oppskriftsmigrering", "recipe-migration": "Oppskriftsoverføring",
"chowdown": { "chowdown": {
"description": "Overfør data fra Chowdown", "description": "Overfør data fra Chowdown",
"description-long": "Mealie nativt støtter chowdown depotet. Last ned kodelageret som en .zip-fil og last det opp nedenfor.", "description-long": "Mealie støtter Chowdown-arkivformatet. Last ned kodearkivet som en .zip-fil og last den opp nedenfor.",
"title": "Chowdown" "title": "Chowdown"
}, },
"nextcloud": { "nextcloud": {
"description": "Migrer data fra en Nextcloud Cookbook instans", "description": "Overfør data fra en Nextcloud Cookbook-instans",
"description-long": "Nextcloud oppskrifter kan importeres fra en zip-fil som inneholder dataene lagret i Nextcloud. Se mappestrukturen for eksempel nedenfor for å sikre at oppskriftene kan importeres.", "description-long": "Oppskrifter fra Nextcloud kan importeres fra en zip-fil som inneholder dataene lagret i Nextcloud. Se eksempelet på mappestrukture nedenfor for å sikre at oppskriftene kan importeres.",
"title": "Nextcloud Cookbook" "title": "Nextcloud Cookbook"
}, },
"copymethat": { "copymethat": {
"description-long": "Mealie kan importere oppskrifter fra Copy Me. Eksporter oppskrifter i HTML-format, deretter last opp .zip-filen under.", "description-long": "Mealie kan importere oppskrifter fra Copy Me That. Eksporter oppskrifter i HTML-format, last deretter opp .zip-filen under.",
"title": "Copy Me That oppskriftsbehandlingen" "title": "Copy Me That Recipe Manager"
}, },
"paprika": { "paprika": {
"description-long": "Mealie kan importere oppskrifter fra Paprika. Eksporter oppskriftene fra Paprika, endre filnavnutvidelsen til .zip og last den opp nedenfor.", "description-long": "Mealie kan importere oppskrifter fra Paprika. Eksporter oppskriftene fra Paprika, endre filnavnutvidelsen til .zip og last den opp nedenfor.",
"title": "Paprika Oppskriftsbehandler" "title": "Paprika Recipe Manager"
}, },
"mealie-pre-v1": { "mealie-pre-v1": {
"description-long": "Mealie kan importere oppskrifter fra Mealie fra versjoner eldre enn v1.0. Eksporter oppskriftene fra din gamle versjon og last opp zip-filen under. Merk at bare oppskrifter kan importeres fra eksporten.", "description-long": "Mealie kan importere oppskrifter fra Mealie fra versjoner eldre enn v1.0. Eksporter oppskriftene fra din gamle versjon og last opp zip-filen under. Merk at bare oppskrifter kan importeres fra eksporten.",
"title": "Mealie Pre v1.0" "title": "Mealie Pre v1.0"
}, },
"tandoor": { "tandoor": {
"description-long": "Mealie kan importere oppskrifter fra Tandoor. Eksporter dataene i \"Standard\"-formatet, deretter last opp .zip-formatet nedenfor.", "description-long": "Mealie kan importere oppskrifter fra Tandoor. Eksporter dataene i \"Standard\"-formatet, last deretter opp zip-filen nedenfor.",
"title": "Tandoor oppskrifter" "title": "Tandoor Recipes"
}, },
"recipe-data-migrations": "Oppskriftsmigrering", "recipe-data-migrations": "Overføring av oppskrifter",
"recipe-data-migrations-explanation": "Oppskrifter kan overføres fra et annet støttet program til Mealie. Dette er en flott måte å komme i gang med Mealie på.", "recipe-data-migrations-explanation": "Oppskrifter kan overføres fra et annet støttet program til Mealie. Dette er en flott måte å komme i gang med Mealie på.",
"choose-migration-type": "Velg migrasjonstype", "choose-migration-type": "Velg type overføring",
"tag-all-recipes": "Merk alle oppskrifter med {tag-name}-emneord", "tag-all-recipes": "Merk alle oppskrifter med {tag-name}-emneord",
"nextcloud-text": "Nextcloud oppskrifter kan importeres fra en zip-fil som inneholder dataene lagret i Nextcloud. Se mappestrukturen for eksempel nedenfor for å sikre at oppskriftene kan importeres.", "nextcloud-text": "Oppskrifter fra Nextcloud kan importeres fra en zip-fil som inneholder dataene lagret i Nextcloud. Se eksempelet på mappestrukture nedenfor for å sikre at oppskriftene kan importeres.",
"chowdown-text": "Mealie nativt støtter chowdown depotet. Last ned kodelageret som en .zip-fil og last det opp nedenfor", "chowdown-text": "Mealie støtter Chowdown-arkivformatet. Last ned kodearkivet som en .zip-fil og last den opp nedenfor",
"recipe-1": "Oppskrift 1", "recipe-1": "Oppskrift 1",
"recipe-2": "Oppskrift 2", "recipe-2": "Oppskrift 2",
"paprika-text": "Mealie kan importere oppskrifter fra Paprika. Eksporter oppskriftene fra Paprika, endre filnavnutvidelsen til .zip og last den opp nedenfor.", "paprika-text": "Mealie kan importere oppskrifter fra Paprika. Eksporter oppskriftene fra Paprika, endre filnavnutvidelsen til .zip og last den opp nedenfor.",
"mealie-text": "Mealie kan importere oppskrifter fra Mealie fra versjoner eldre enn v1.0. Eksporter oppskriftene fra din gamle versjon og last opp zip-filen under. Merk at bare oppskrifter kan importeres fra eksporten.", "mealie-text": "Mealie kan importere oppskrifter fra Mealie fra versjoner eldre enn v1.0. Eksporter oppskriftene fra din gamle versjon og last opp zip-filen under. Merk at bare oppskrifter kan importeres fra eksporten.",
"plantoeat": { "plantoeat": {
"title": "Planlegg å spise", "title": "Plan to Eat",
"description-long": "Mealie kan importere oppskrifter fra plan å spise." "description-long": "Mealie kan importere oppskrifter fra Plan to Eat."
} }
}, },
"new-recipe": { "new-recipe": {
@ -366,18 +367,18 @@
"from-url": "Importer en oppskrift", "from-url": "Importer en oppskrift",
"github-issues": "GitHub-problemer", "github-issues": "GitHub-problemer",
"google-ld-json-info": "Google ld+json-informasjon", "google-ld-json-info": "Google ld+json-informasjon",
"must-be-a-valid-url": "Må være en gyldig URL-adresse", "must-be-a-valid-url": "Må være en gyldig nettadresse",
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Lim inn oppskriftsdataene. Hver linje blir behandlet som et element i en liste", "paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Lim inn oppskriftsdataene. Hver linje blir behandlet som et element i en liste",
"recipe-markup-specification": "Spesifikasjon for oppskriftsmerking", "recipe-markup-specification": "Spesifikasjon for oppskriftsmerking",
"recipe-url": "Oppskrifts-URL", "recipe-url": "Nettadresse til oppskrift",
"upload-a-recipe": "Last opp oppskrift", "upload-a-recipe": "Last opp oppskrift",
"upload-individual-zip-file": "Last opp en individuell .zip-fil eksportert fra en annen Mealie-instans.", "upload-individual-zip-file": "Last opp en individuell .zip-fil eksportert fra en annen Mealie-instans.",
"url-form-hint": "Kopier og lim inn en link fra favorittoppskriftsnettstedet ditt", "url-form-hint": "Kopier og lim inn en lenke fra nettstedet med favorittoppskriftene dine",
"view-scraped-data": "Vis skrapte data", "view-scraped-data": "Vis skrapte data",
"trim-whitespace-description": "Trim innledende og etterfølgende mellomrom i tillegg til tomme linjer", "trim-whitespace-description": "Fjern innledende og etterfølgende mellomrom i tillegg til tomme linjer",
"trim-prefix-description": "Fjern første tegn fra hver linje", "trim-prefix-description": "Fjern første tegn fra hver linje",
"split-by-numbered-line-description": "Forsøk å dele et avsnitt ved å matche mønsteret '1)' eller '1.'", "split-by-numbered-line-description": "Forsøk å dele opp et avsnitt ved å matche mønsteret '1)' eller '1.'",
"import-by-url": "Importer en oppskrift via URL", "import-by-url": "Importer en oppskrift via nettadresse",
"create-manually": "Opprett en oppskrift manuelt", "create-manually": "Opprett en oppskrift manuelt",
"make-recipe-image": "Bruk dette som oppskriftsbilde" "make-recipe-image": "Bruk dette som oppskriftsbilde"
}, },
@ -412,7 +413,7 @@
"description": "Beskrivelse", "description": "Beskrivelse",
"disable-amount": "Deaktiver ingrediensmengde", "disable-amount": "Deaktiver ingrediensmengde",
"disable-comments": "Deaktiver kommentarer", "disable-comments": "Deaktiver kommentarer",
"duplicate": "Duplikat-oppskrift", "duplicate": "Dupliser oppskrift",
"duplicate-name": "Navn på den nye oppskriften", "duplicate-name": "Navn på den nye oppskriften",
"edit-scale": "Rediger skala", "edit-scale": "Rediger skala",
"fat-content": "Fett", "fat-content": "Fett",
@ -423,7 +424,7 @@
"insert-ingredient": "Sett inn ingrediens", "insert-ingredient": "Sett inn ingrediens",
"insert-section": "Sett inn avsnitt", "insert-section": "Sett inn avsnitt",
"instructions": "Instruksjoner", "instructions": "Instruksjoner",
"key-name-required": "Nøkkelnavn påkrevd", "key-name-required": "Navn på nøkkel er påkrevd",
"landscape-view-coming-soon": "Landskapsvisning", "landscape-view-coming-soon": "Landskapsvisning",
"milligrams": "mg", "milligrams": "mg",
"new-key-name": "Nytt nøkkelnavn", "new-key-name": "Nytt nøkkelnavn",
@ -432,7 +433,7 @@
"nutrition": "Ernæring", "nutrition": "Ernæring",
"object-key": "Objektnøkkel", "object-key": "Objektnøkkel",
"object-value": "Objektverdi", "object-value": "Objektverdi",
"original-url": "Opprinnlig URL", "original-url": "Nettadresse til oppskrift",
"perform-time": "Koketid", "perform-time": "Koketid",
"prep-time": "Forberedelsestid", "prep-time": "Forberedelsestid",
"protein-content": "Protein", "protein-content": "Protein",
@ -465,10 +466,10 @@
"add-recipe-to-mealplan": "Legg til oppskrift i måltidsplan", "add-recipe-to-mealplan": "Legg til oppskrift i måltidsplan",
"entry-type": "Oppføringstype", "entry-type": "Oppføringstype",
"date-format-hint": "MM/DD/ÅÅÅÅ-format", "date-format-hint": "MM/DD/ÅÅÅÅ-format",
"date-format-hint-yyyy-mm-dd": "ÅÅÅÅ-MM-DD format", "date-format-hint-yyyy-mm-dd": "ÅÅÅÅ-MM-DD-format",
"add-to-list": "Legg til i liste", "add-to-list": "Legg til i liste",
"add-to-plan": "Legg til i plan", "add-to-plan": "Legg til i plan",
"add-to-timeline": "Legg til tidslinjen", "add-to-timeline": "Legg til tidslinje",
"recipe-added-to-list": "Oppskrift er lagt til i liste", "recipe-added-to-list": "Oppskrift er lagt til i liste",
"recipes-added-to-list": "Oppskrifter lagt til listen", "recipes-added-to-list": "Oppskrifter lagt til listen",
"recipe-added-to-mealplan": "Oppskrift er lagt til i måltidsplan", "recipe-added-to-mealplan": "Oppskrift er lagt til i måltidsplan",
@ -483,11 +484,11 @@
"toggle-section": "Legg til seksjon", "toggle-section": "Legg til seksjon",
"see-original-text": "Se opprinnelig tekst", "see-original-text": "Se opprinnelig tekst",
"original-text-with-value": "Opprinnelig tekst: {originalText}", "original-text-with-value": "Opprinnelig tekst: {originalText}",
"ingredient-linker": "Ingredienskobler", "ingredient-linker": "Tilknytt ingredienser",
"linked-to-other-step": "Koblet til et annet trinn", "linked-to-other-step": "Tilknyttet et annet steg",
"auto": "Automatisk", "auto": "Automatisk",
"cook-mode": "Tilberedelsesmodus", "cook-mode": "Tilberedelsesmodus",
"link-ingredients": "Koble på ingredienser", "link-ingredients": "Tilknytt ingredienser",
"merge-above": "Slå sammen med steget over", "merge-above": "Slå sammen med steget over",
"reset-scale": "Nullstill skala", "reset-scale": "Nullstill skala",
"decrease-scale-label": "Reduser skala med 1", "decrease-scale-label": "Reduser skala med 1",
@ -497,23 +498,23 @@
"timer": { "timer": {
"kitchen-timer": "Kjøkkentimer", "kitchen-timer": "Kjøkkentimer",
"start-timer": "Start nedtelling", "start-timer": "Start nedtelling",
"pause-timer": "Pause nedtellingen", "pause-timer": "Pause nedtelling",
"resume-timer": "Fortsett nedtellingen", "resume-timer": "Fortsett nedtelling",
"stop-timer": "Stopp nedtellingen" "stop-timer": "Stopp nedtelling"
}, },
"edit-timeline-event": "Endre hendelsestidslinjen", "edit-timeline-event": "Endre tidslinjehendelser",
"timeline": "Tidslinje", "timeline": "Tidslinje",
"timeline-is-empty": "Ingenting på tidslinjen ennå. Prøv å lage denne oppskriften!", "timeline-is-empty": "Ingenting på tidslinjen ennå. Prøv å lage denne oppskriften!",
"group-global-timeline": "{groupName} Global tidslinje", "group-global-timeline": "{groupName} Global tidslinje",
"open-timeline": "Åpne tidslinje", "open-timeline": "Åpne tidslinje",
"made-this": "Jeg har lagd dette", "made-this": "Jeg har laget denne",
"how-did-it-turn-out": "Hvordan ble det?", "how-did-it-turn-out": "Hvordan ble den?",
"user-made-this": "{user} har lagd denne", "user-made-this": "{user} har laget denne",
"last-made-date": "Sist lagd {date}", "last-made-date": "Sist laget: {date}",
"api-extras-description": "Ekstramaterialer til oppskrifter er en viktig funksjon i Mealie API-en. De lar deg opprette egendefinerte JSON-nøkkel/verdi-par innenfor en oppskrift for å referere fra tredjepartsapplikasjoner. Du kan bruke disse nøklene til å gi informasjon for eksempel for å utløse automatiseringer eller egendefinerte meldinger som skal videreformidles til ønsket enhet.", "api-extras-description": "Ekstramaterialer til oppskrifter er en viktig funksjon i Mealie API-en. De lar deg opprette egendefinerte JSON-nøkkel/verdi-par innenfor en oppskrift for å referere fra tredjepartsapplikasjoner. Du kan bruke disse nøklene til å gi informasjon for eksempel for å utløse automatiseringer eller egendefinerte meldinger som skal videreformidles til ønsket enhet.",
"message-key": "Meldingsnøkkel", "message-key": "Meldingsnøkkel",
"parse": "Del opp", "parse": "Analyser",
"attach-images-hint": "Legg til bilder ved å dra og slippe dem i editoren", "attach-images-hint": "Fest bilder ved å dra og slippe dem inn i redigereringsverktøyet",
"drop-image": "Slipp bilde", "drop-image": "Slipp bilde",
"enable-ingredient-amounts-to-use-this-feature": "Aktiver ingrediensmengder for å bruke denne funksjonen", "enable-ingredient-amounts-to-use-this-feature": "Aktiver ingrediensmengder for å bruke denne funksjonen",
"recipes-with-units-or-foods-defined-cannot-be-parsed": "Oppskrifter med enheter eller matvarer som er definert kan ikke tolkes.", "recipes-with-units-or-foods-defined-cannot-be-parsed": "Oppskrifter med enheter eller matvarer som er definert kan ikke tolkes.",
@ -521,39 +522,39 @@
"edit-markdown": "Rediger Markdown", "edit-markdown": "Rediger Markdown",
"recipe-creation": "Opprett oppskrift", "recipe-creation": "Opprett oppskrift",
"select-one-of-the-various-ways-to-create-a-recipe": "Velg en av de ulike måtene å opprette en oppskrift", "select-one-of-the-various-ways-to-create-a-recipe": "Velg en av de ulike måtene å opprette en oppskrift",
"looking-for-migrations": "Ser du etter migrasjoner?", "looking-for-migrations": "Ser du etter overføringer?",
"import-with-url": "Importer med URL", "import-with-url": "Importer via nettadresse",
"create-recipe": "Opprett oppskrift", "create-recipe": "Opprett oppskrift",
"import-with-zip": "Importer med .zip", "import-with-zip": "Importer fra .zip-fil",
"create-recipe-from-an-image": "Opprett oppskrift fra et bilde", "create-recipe-from-an-image": "Opprett oppskrift fra et bilde",
"bulk-url-import": "Importer flere URL'er", "bulk-url-import": "Importer flere nettadresser",
"debug-scraper": "Feilsøk skraper", "debug-scraper": "Feilsøk skraper",
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Opprett en oppskrift ved å angi navnet. Alle oppskrifter må ha unike navn.", "create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Opprett en oppskrift ved å angi navnet. Alle oppskrifter må ha unike navn.",
"new-recipe-names-must-be-unique": "Oppskriftsnavn må være unike", "new-recipe-names-must-be-unique": "Navn på oppskrift må være unike",
"scrape-recipe": "Hent oppskrift", "scrape-recipe": "Skrap oppskrift",
"scrape-recipe-description": "Scrape en oppskrift ved url. Angi Url-adressen for nettstedet du vil skrape, Og Mealie vil forsøke å skrape oppskriften fra det området og legge den til i samlingen din.", "scrape-recipe-description": "Skrap en oppskrift ved bruk av nettadresse. Oppgi nettadressen til nettstedet du vil skrape, så vil Mealie forsøke å skrape oppskriften fra den siden og legge den til i samlingen din.",
"import-original-keywords-as-tags": "Importer originale søkeord som emneord", "import-original-keywords-as-tags": "Importer originale søkeord som emneord",
"stay-in-edit-mode": "Bli i skrivemodus", "stay-in-edit-mode": "Forbli i redigeringsmodus",
"import-from-zip": "Importer fra Zip", "import-from-zip": "Importer fra zip-fil",
"import-from-zip-description": "Importer en enkelt oppskrift som ble eksportert fra en annen Mealie-instans.", "import-from-zip-description": "Importer en enkelt oppskrift som ble eksportert fra en annen Mealie-instans.",
"zip-files-must-have-been-exported-from-mealie": ".zip-filer må ha blitt eksportert fra Mealie", "zip-files-must-have-been-exported-from-mealie": ".zip-filer må ha blitt eksportert fra Mealie",
"create-a-recipe-by-uploading-a-scan": "Lag en oppskrift ved å laste opp en skanning.", "create-a-recipe-by-uploading-a-scan": "Opprett en oppskrift ved å laste opp en skanning.",
"upload-a-png-image-from-a-recipe-book": "Last opp et png bilde fra en oppskriftsbok", "upload-a-png-image-from-a-recipe-book": "Last opp et png-bilde fra en oppskriftsbok",
"recipe-bulk-importer": "Oppskrift masse-import", "recipe-bulk-importer": "Masseimport av oppskrifter",
"recipe-bulk-importer-description": "Masse-oppskriftsimporten lar deg importere flere oppskrifter samtidig ved å sette i kø på kontrollstedene på bakgrunnen og kjøre oppgaven i bakgrunnen. Dette kan være nyttig ved først å migrere til Mealie, eller når du vil importere et stort antall oppskrifter.", "recipe-bulk-importer-description": "Masseimport av oppskrifter lar deg importere flere oppskrifter samtidig ved å sette opp nettstedene i kø på serveren og kjøre oppgaven i bakgrunnen. Dette kan være nyttig når du først migrerer til Mealie, eller når du ønsker å importere et stort antall oppskrifter.",
"set-categories-and-tags": "Sett kategorier og emneord", "set-categories-and-tags": "Angi kategorier og emneord",
"bulk-imports": "Masseimport", "bulk-imports": "Masseimport",
"bulk-import-process-has-started": "Masseimport har startet", "bulk-import-process-has-started": "Masseimport har startet",
"bulk-import-process-has-failed": "Masseimport mislyktes", "bulk-import-process-has-failed": "Masseimport mislyktes",
"report-deletion-failed": "Raport sletting feilet", "report-deletion-failed": "Sletting av rapport mislyktes",
"recipe-debugger": "Oppskrift Feilsøking", "recipe-debugger": "Oppskriftsfeilsøker",
"recipe-debugger-description": "Hent URL-adressen til oppskriften du vil feilsøke og lim den inn her. URL-adressen vil bli skrapt av oppskrifts-skraperen og resultatene vil bli vist. Hvis du ikke ser noen data returnert, er ikke nettstedet du prøver å skrape støttet av Mealie eller skraper-biblioteket.", "recipe-debugger-description": "Hent nettadressen til oppskriften du vil feilsøke og lim den inn her. Nettsiden vil bli skrapt og resultatene vil bli vist. Hvis du ikke ser noen data returnert, er ikke nettstedet du prøver å skrape støttet av Mealie eller skraper-biblioteket.",
"debug": "Feilsøk", "debug": "Feilsøk",
"tree-view": "Trevisning", "tree-view": "Trevisning",
"recipe-yield": "Oppskrift uttak", "recipe-yield": "Utbytte av oppskrift",
"unit": "Enhet", "unit": "Enhet",
"upload-image": "Last opp bilde", "upload-image": "Last opp bilde",
"screen-awake": "Hold skjerm på", "screen-awake": "Hold skjermen på",
"remove-image": "Slett bilde" "remove-image": "Slett bilde"
}, },
"search": { "search": {
@ -592,13 +593,13 @@
"partial-backup": "Delvis sikkerhetskopi", "partial-backup": "Delvis sikkerhetskopi",
"unable-to-delete-backup": "Kan ikke slette sikkerhetskopi.", "unable-to-delete-backup": "Kan ikke slette sikkerhetskopi.",
"experimental-description": "Sikkerhetskopier er komplette øyeblikksbilder av databasen og datamappen til nettstedet. Dette inkluderer all data og kan ikke settes til å ekskludere delsett av data. Du kan tenke på dette som et øyeblikksbilde av Mealie på et bestemt tidspunkt. Disse fungerer som en databasesystemuavhengig måte å eksportere og importere data på, eller sikkerhetskopiere nettstedet til en ekstern plassering.", "experimental-description": "Sikkerhetskopier er komplette øyeblikksbilder av databasen og datamappen til nettstedet. Dette inkluderer all data og kan ikke settes til å ekskludere delsett av data. Du kan tenke på dette som et øyeblikksbilde av Mealie på et bestemt tidspunkt. Disse fungerer som en databasesystemuavhengig måte å eksportere og importere data på, eller sikkerhetskopiere nettstedet til en ekstern plassering.",
"backup-restore": "Sikkerhetskopiering / gjenoppretting", "backup-restore": "Gjenoppretting av sikkerhetskopi",
"back-restore-description": "Gjenoppretting av denne sikkerhetskopien vil overskrive alle gjeldende data i databasen og i datamappen og erstatte dem med innholdet i denne sikkerhetskopien. {cannot-be-undone} Hvis gjenopprettingen er vellykket, vil du bli logget ut.", "back-restore-description": "Gjenoppretting av denne sikkerhetskopien vil overskrive alle gjeldende data i databasen og i datamappen og erstatte dem med innholdet i denne sikkerhetskopien. {cannot-be-undone} Hvis gjenopprettingen er vellykket, vil du bli logget ut.",
"cannot-be-undone": "Denne handlingen kan ikke angres brukes med forsiktighet.", "cannot-be-undone": "Denne handlingen kan ikke angres bruk med forsiktighet.",
"postgresql-note": "Hvis du bruker PostGreSQL, vennligst gå igjennom {backup-restore-process} før du gjenoppretter.", "postgresql-note": "Hvis du bruker PostGreSQL, vennligst gå igjennom {backup-restore-process} før du gjenoppretter.",
"backup-restore-process-in-the-documentation": "sikkerhetskopiering/gjenoppretting prosess i dokumentasjonen", "backup-restore-process-in-the-documentation": "sikkerhetskopiering/gjenoppretting prosess i dokumentasjonen",
"irreversible-acknowledgment": "Jeg forstår at dette er irreversibel, destruktiv og kan føre til tap av data", "irreversible-acknowledgment": "Jeg forstår at denne handlingen er irreversibel, destruktiv og kan føre til tap av data",
"restore-backup": "Gjenopprett sikkerhetskopien" "restore-backup": "Gjenopprett sikkerhetskopi"
}, },
"backup-and-exports": "Sikkerhetskopier", "backup-and-exports": "Sikkerhetskopier",
"change-password": "Endre passord", "change-password": "Endre passord",
@ -623,7 +624,7 @@
"new-page": "Ny side", "new-page": "Ny side",
"notify": "Varsle", "notify": "Varsle",
"organize": "Organiser", "organize": "Organiser",
"page-name": "Sidenavn", "page-name": "Navn på side",
"pages": "Sider", "pages": "Sider",
"profile": "Profil", "profile": "Profil",
"remove-existing-entries-matching-imported-entries": "Fjern eksisterende oppføringer som samsvarer med de importerte oppføringene", "remove-existing-entries-matching-imported-entries": "Fjern eksisterende oppføringer som samsvarer med de importerte oppføringene",
@ -632,9 +633,9 @@
"settings-updated": "Innstillinger oppdatert", "settings-updated": "Innstillinger oppdatert",
"site-settings": "Sideinnstillinger", "site-settings": "Sideinnstillinger",
"theme": { "theme": {
"accent": "Utheving", "accent": "Uthevet",
"dark": "Mørk", "dark": "Mørk",
"default-to-system": "Standard", "default-to-system": "Systemstandard",
"error": "Feil", "error": "Feil",
"error-creating-theme-see-log-file": "Feil under oppretting av tema. Se loggfil.", "error-creating-theme-see-log-file": "Feil under oppretting av tema. Se loggfil.",
"error-deleting-theme": "Feil ved sletting av tema", "error-deleting-theme": "Feil ved sletting av tema",
@ -643,17 +644,17 @@
"light": "Lys", "light": "Lys",
"primary": "Primær", "primary": "Primær",
"secondary": "Sekundær", "secondary": "Sekundær",
"success": "Fullført", "success": "Suksess",
"switch-to-dark-mode": "Bytt til mørk modus", "switch-to-dark-mode": "Bytt til mørk modus",
"switch-to-light-mode": "Bytt til lys modus", "switch-to-light-mode": "Bytt til lys modus",
"theme-deleted": "Tema slettet", "theme-deleted": "Tema slettet",
"theme-name": "Temanavn", "theme-name": "Navn på tema",
"theme-name-is-required": "Navn på tema er påkrevd.", "theme-name-is-required": "Navn på tema er påkrevd.",
"theme-saved": "Tema lagret", "theme-saved": "Tema lagret",
"theme-updated": "Tema oppdatert", "theme-updated": "Tema oppdatert",
"warning": "Advarsel", "warning": "Advarsel",
"light-mode": "Lys modus", "light-mode": "Lys modus",
"dark-mode": "Mørkemodus" "dark-mode": "Mørk modus"
}, },
"token": { "token": {
"active-tokens": "AKTIVE TOKENS", "active-tokens": "AKTIVE TOKENS",
@ -661,13 +662,13 @@
"api-tokens": "API-tokener", "api-tokens": "API-tokener",
"copy-this-token-for-use-with-an-external-application-this-token-will-not-be-viewable-again": "Kopier dette tokenet til bruk med et eksternt program. Dette tokenet vil ikke kunne ses igjen.", "copy-this-token-for-use-with-an-external-application-this-token-will-not-be-viewable-again": "Kopier dette tokenet til bruk med et eksternt program. Dette tokenet vil ikke kunne ses igjen.",
"create-an-api-token": "Opprett et API-token", "create-an-api-token": "Opprett et API-token",
"token-name": "Tokennavn", "token-name": "Navn på token",
"generate": "Opprett", "generate": "Opprett",
"you-have-token-count": "Du har ingen aktive token.|Du har ett aktivt token.|Du har {count} aktive tokener." "you-have-token-count": "Du har ingen aktive token.|Du har ett aktivt token.|Du har {count} aktive tokener."
}, },
"toolbox": { "toolbox": {
"assign-all": "Tildel alle", "assign-all": "Tildel alle",
"bulk-assign": "Tilordne flere", "bulk-assign": "Tildel flere",
"new-name": "Nytt navn", "new-name": "Nytt navn",
"no-unused-items": "Ingen ubrukte elementer", "no-unused-items": "Ingen ubrukte elementer",
"recipes-affected": "Ingen oppskrifter påvirket|En oppskrift påvirket|{count} Oppskrifter påvirket", "recipes-affected": "Ingen oppskrifter påvirket|En oppskrift påvirket|{count} Oppskrifter påvirket",
@ -677,29 +678,29 @@
"unorganized": "Uorganisert" "unorganized": "Uorganisert"
}, },
"webhooks": { "webhooks": {
"test-webhooks": "Test Webhooks", "test-webhooks": "Test webhooks",
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "URL-adressene som er oppført nedenfor vil motta webhooks med oppskriftsdata for måltidsplanen på dens planlagte dag. For øyeblikket vil webhooks utføres på", "the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "URL-adressene som er oppført nedenfor vil motta webhooks med oppskriftsdata for måltidsplanen på dens planlagte dag. For øyeblikket vil webhooks utføres på",
"webhook-url": "Webhook-URL", "webhook-url": "Webhook-URL",
"webhooks-caps": "WEBHOOKS", "webhooks-caps": "WEBHOOKS",
"webhooks": "Webhooks", "webhooks": "Webhooks",
"webhook-name": "Webhook navn", "webhook-name": "Navn på webhook",
"description": "Webhooks definert nedenfor vil utføres når et måltid defineres for dagen. På det planlagte tidspunktet blir webhook sendt med data fra oppskriften som er planlagt for dagen. Merke at av tidspunktet ikke er nøyaktig, webhooks utføres med et intervall på 5 minutter, dette betyr at webhooks utføres innen +/- 5 minutter etter planlagt tidspunkt." "description": "Webhooks definert nedenfor vil utføres når et måltid defineres for dagen. På det planlagte tidspunktet blir webhook sendt med data fra oppskriften som er planlagt for dagen. Merk at tidspunktet ikke er nøyaktig og webhooks utføres med et intervall på 5 minutter. Dette betyr at webhooks utføres innenfor +/- 5 minutter etter planlagt tidspunkt."
}, },
"bug-report": "Feilrapport", "bug-report": "Feilrapport",
"bug-report-information": "Bruk denne informasjonen til å rapportere en feil. Å gi detaljer om installasjonen din til utviklerne er den beste måten å få løst problemene dine raskt på.", "bug-report-information": "Bruk denne informasjonen til å rapportere en feil. Å gi detaljer om installasjonen din til utviklerne er den beste måten å få løst problemene dine raskt på.",
"tracker": "Sporingsagent", "tracker": "Sporingsagent",
"configuration": "Konfigurasjon", "configuration": "Konfigurasjon",
"docker-volume": "Docker volum", "docker-volume": "Docker-volum",
"docker-volume-help": "Mealie krever at frontend- og backend-konteinerene deler samme docker-volum eller lagringssted. Dette sikrer at frontend-kontaineren får tilgang til bilder og ressurser lagret på harddisken.", "docker-volume-help": "Mealie krever at frontend- og backend-konteinerene deler samme docker-volum eller lagringssted. Dette sikrer at frontend-kontaineren får tilgang til bilder og ressurser lagret på harddisken.",
"volumes-are-misconfigured": "Volumene er feilkonfigurert.", "volumes-are-misconfigured": "Volumene er konfigurert feil.",
"volumes-are-configured-correctly": "Volumene er riktig konfigurert.", "volumes-are-configured-correctly": "Volumene er riktig konfigurert.",
"status-unknown-try-running-a-validation": "Statusen er ukjent. Prøv å validere.", "status-unknown-try-running-a-validation": "Statusen er ukjent. Prøv å kjør en validering.",
"validate": "Valider", "validate": "Valider",
"email-configuration-status": "E-postkonfigurasjonsstatus", "email-configuration-status": "Status på konfigurasjon av e-post",
"email-configured": "E-post konfigurert", "email-configured": "E-post konfigurert",
"email-test-results": "Email Test Results", "email-test-results": "Testresultater for e-post",
"ready": "Klar", "ready": "Klar",
"not-ready": "Ikke klar - sjekk miljøvariabler", "not-ready": "Ikke klar - kontroller konfigurasjonen",
"succeeded": "Lyktes", "succeeded": "Lyktes",
"failed": "Mislyktes", "failed": "Mislyktes",
"general-about": "Generelt om", "general-about": "Generelt om",
@ -708,15 +709,15 @@
"mealie-is-up-to-date": "Mealie er oppdatert", "mealie-is-up-to-date": "Mealie er oppdatert",
"secure-site": "Sikkert nettsted", "secure-site": "Sikkert nettsted",
"secure-site-error-text": "Server via localhost eller sikre med https. Utklippstavle og ytterlige nettleser-API-er vil muligens ikke fungere.", "secure-site-error-text": "Server via localhost eller sikre med https. Utklippstavle og ytterlige nettleser-API-er vil muligens ikke fungere.",
"secure-site-success-text": "Tjenesten er tilgjengelig localhost eller https", "secure-site-success-text": "Tjenesten er tilgjengelig via localhost eller https",
"server-side-base-url": "Serverens sidebase URL", "server-side-base-url": "Serverens URL",
"server-side-base-url-error-text": "`BASE_URL` er fortsatt standardverdien på API-serveren. Dette vil forårsake problemer med varslingslenker som genereres på serveren for e-post osv.", "server-side-base-url-error-text": "`BASE_URL` er fortsatt standardverdien på API-serveren. Dette vil forårsake problemer med varslingslenker som genereres på serveren for e-post osv.",
"server-side-base-url-success-text": "Serverside-URL samsvarer ikke med standard", "server-side-base-url-success-text": "Serverside-URL samsvarer ikke med standard",
"ldap-ready": "LDAP klar", "ldap-ready": "LDAP klar",
"ldap-ready-error-text": "Ikke alle LDAP-verdier er konfigurert. Dette kan ignoreres hvis du ikke bruker LDAP-autentisering.", "ldap-ready-error-text": "Ikke alle LDAP-verdier er konfigurert. Dette kan ignoreres hvis du ikke bruker LDAP-autentisering.",
"ldap-ready-success-text": "Alle obligratoriske LDAP-variabler er satt.", "ldap-ready-success-text": "Alle obligratoriske LDAP-variabler er satt.",
"build": "Bygg", "build": "Build",
"recipe-scraper-version": "OppskriftsScraper versjon" "recipe-scraper-version": "Versjon på oppskrift-scraper"
}, },
"shopping-list": { "shopping-list": {
"all-lists": "Alle lister", "all-lists": "Alle lister",
@ -736,15 +737,15 @@
"are-you-sure-you-want-to-delete-this-item": "Er du sikker på at du vil slette dette elementet?", "are-you-sure-you-want-to-delete-this-item": "Er du sikker på at du vil slette dette elementet?",
"copy-as-text": "Kopier som tekst", "copy-as-text": "Kopier som tekst",
"copy-as-markdown": "Kopier som Markdown", "copy-as-markdown": "Kopier som Markdown",
"delete-checked": "Slett avkrysset", "delete-checked": "Fjern markerte elementer",
"toggle-label-sort": "Bytt etikettsortering", "toggle-label-sort": "Bytt etikettsortering",
"reorder-labels": "Omorganiser etiketter", "reorder-labels": "Omorganiser etiketter",
"uncheck-all-items": "Fjern merking av alle elementer", "uncheck-all-items": "Fjern markering av alle elementer",
"check-all-items": "Velg alle elementer", "check-all-items": "Marker alle elementer",
"linked-recipes-count": "Ingen lenkede oppskrifter|En lenket oppskrift|{count} Lenkede oppskrifter", "linked-recipes-count": "Ingen tilknyttede oppskrifter|En tilknyttet oppskrift|{count} tilknyttede oppskrifter",
"items-checked-count": "Ingen elementer krysset av|Ett element krysset av|{count} elementer krysset av", "items-checked-count": "Ingen elementer krysset av|Ett element krysset av|{count} elementer krysset av",
"no-label": "Ingen etikett", "no-label": "Ingen etikett",
"completed-on": "Fullført {date}" "completed-on": "Fullført den {date}"
}, },
"sidebar": { "sidebar": {
"all-recipes": "Alle oppskrifter", "all-recipes": "Alle oppskrifter",
@ -791,24 +792,24 @@
"tag-name": "Navn på emneord" "tag-name": "Navn på emneord"
}, },
"tool": { "tool": {
"tools": "Utstyr", "tools": "Kjøkkenredskap",
"on-hand": "Tillgjengelig", "on-hand": "Tillgjengelig",
"create-a-tool": "Opprett utstyr", "create-a-tool": "Opprett kjøkkenredskap",
"tool-name": "Navn på utstyr", "tool-name": "Navn på kjøkkenredskap",
"create-new-tool": "Opprett nytt utstyr", "create-new-tool": "Opprett nytt kjøkkenredskap",
"on-hand-checkbox-label": "Vis som tilgjengelig (avmerket)", "on-hand-checkbox-label": "Vis som tilgjengelig (avmerket)",
"required-tools": "Påkrevd utstyr" "required-tools": "Påkrevde kjøkkenredskaper"
}, },
"user": { "user": {
"admin": "Administrator", "admin": "Administrator",
"are-you-sure-you-want-to-delete-the-link": "Er du sikker på at du vil slette lenken <b>{link}<b/>?", "are-you-sure-you-want-to-delete-the-link": "Er du sikker på at du vil slette lenken <b>{link}<b/>?",
"are-you-sure-you-want-to-delete-the-user": "Er du sikker på at du vil slette brukeren <b>{activeName} ID: {activeId}<b/>?", "are-you-sure-you-want-to-delete-the-user": "Er du sikker på at du vil slette brukeren <b>{activeName} ID: {activeId}<b/>?",
"auth-method": "Autentisering metode", "auth-method": "Autentiseringsmetode",
"confirm-link-deletion": "Bekreft sletting av lenke", "confirm-link-deletion": "Bekreft sletting av lenke",
"confirm-password": "Bekreft passord", "confirm-password": "Bekreft passord",
"confirm-user-deletion": "Bekreft sletting av bruker", "confirm-user-deletion": "Bekreft sletting av bruker",
"could-not-validate-credentials": "Kunne ikke validere påloggingsinformasjon", "could-not-validate-credentials": "Kunne ikke validere påloggingsinformasjon",
"create-link": "Opprett link", "create-link": "Opprett lenke",
"create-user": "Opprett bruker", "create-user": "Opprett bruker",
"current-password": "Gjeldende passord", "current-password": "Gjeldende passord",
"e-mail-must-be-valid": "E-post må være gyldig", "e-mail-must-be-valid": "E-post må være gyldig",
@ -817,10 +818,10 @@
"error-cannot-delete-super-user": "Feil! Kan ikke slette superbruker", "error-cannot-delete-super-user": "Feil! Kan ikke slette superbruker",
"existing-password-does-not-match": "Eksisterende passord samsvarer ikke", "existing-password-does-not-match": "Eksisterende passord samsvarer ikke",
"full-name": "Fullt navn", "full-name": "Fullt navn",
"generate-password-reset-link": "Generer kobling for tilbakestilling av passord", "generate-password-reset-link": "Generer lenke for tilbakestilling av passord",
"invite-only": "Kun inviterte", "invite-only": "Kun inviterte",
"link-id": "Lenke-ID", "link-id": "Lenke-ID",
"link-name": "Lenkenavn", "link-name": "Navn på lenke",
"login": "Logg på", "login": "Logg på",
"logout": "Logg ut", "logout": "Logg ut",
"manage-users": "Administrer brukere", "manage-users": "Administrer brukere",
@ -832,7 +833,7 @@
"password-updated": "Passord oppdatert", "password-updated": "Passord oppdatert",
"password": "Passord", "password": "Passord",
"password-strength": "Passordet er {strength}", "password-strength": "Passordet er {strength}",
"please-enter-password": "Angi nytt passord.", "please-enter-password": "Vennligst angi nytt passord.",
"register": "Registrér", "register": "Registrér",
"reset-password": "Tilbakestill passord", "reset-password": "Tilbakestill passord",
"sign-in": "Logg inn", "sign-in": "Logg inn",
@ -854,7 +855,7 @@
"users-header": "BRUKERE", "users-header": "BRUKERE",
"users": "Brukere", "users": "Brukere",
"user-not-found": "Bruker ikke funnet", "user-not-found": "Bruker ikke funnet",
"webhook-time": "Webhooks Tidsbruk", "webhook-time": "Webhook-tid",
"webhooks-enabled": "Webhooks aktivert", "webhooks-enabled": "Webhooks aktivert",
"you-are-not-allowed-to-create-a-user": "Du har ikke rettigheter til å opprette en bruker", "you-are-not-allowed-to-create-a-user": "Du har ikke rettigheter til å opprette en bruker",
"you-are-not-allowed-to-delete-this-user": "Du har ikke rettigheter til å slette denne brukeren", "you-are-not-allowed-to-delete-this-user": "Du har ikke rettigheter til å slette denne brukeren",
@ -863,7 +864,7 @@
"favorite-recipes": "Favorittoppskrifter", "favorite-recipes": "Favorittoppskrifter",
"email-or-username": "E-post eller brukernavn", "email-or-username": "E-post eller brukernavn",
"remember-me": "Husk meg", "remember-me": "Husk meg",
"please-enter-your-email-and-password": "Vennligst angi brukernavnet og passordet ditt", "please-enter-your-email-and-password": "Vennligst angi ditt brukernavn og passord",
"invalid-credentials": "Ugyldig brukerinformasjon", "invalid-credentials": "Ugyldig brukerinformasjon",
"account-locked-please-try-again-later": "Kontoen er låst. Prøv igjen senere", "account-locked-please-try-again-later": "Kontoen er låst. Prøv igjen senere",
"user-favorites": "Brukerfavoritter", "user-favorites": "Brukerfavoritter",
@ -874,14 +875,14 @@
"very-strong": "Veldig sterkt" "very-strong": "Veldig sterkt"
}, },
"user-management": "Brukeradministrasjon", "user-management": "Brukeradministrasjon",
"reset-locked-users": "Tilbakestille låste brukere", "reset-locked-users": "Tilbakestill låste brukere",
"admin-user-creation": "Admin bruker oppretting", "admin-user-creation": "Opprett administratorkonto",
"admin-user-management": "Admin User Management", "admin-user-management": "Brukeradministrasjon",
"user-details": "Brukerdetaljer", "user-details": "Brukerdetaljer",
"user-name": "Brukernavn", "user-name": "Brukernavn",
"authentication-method": "Autentiseringsmetode", "authentication-method": "Autentiseringsmetode",
"authentication-method-hint": "This specifies how a user will authenticate with Mealie. If you're not sure, choose 'Mealie", "authentication-method-hint": "This specifies how a user will authenticate with Mealie. If you're not sure, choose 'Mealie",
"permissions": "Tillatelser", "permissions": "Rettigheter",
"administrator": "Administrator", "administrator": "Administrator",
"user-can-invite-other-to-group": "Brukeren kan invitere andre til gruppe", "user-can-invite-other-to-group": "Brukeren kan invitere andre til gruppe",
"user-can-manage-group": "Brukeren kan administrere gruppe", "user-can-manage-group": "Brukeren kan administrere gruppe",
@ -902,7 +903,7 @@
}, },
"data-pages": { "data-pages": {
"foods": { "foods": {
"merge-dialog-text": "Ved å kombinere de valgte matvarene, vil de bli slått sammen til én matvare. Den første matvaren vil bli slettet, og alle referanser til denne vil bli oppdatert til å peke til den nye matvaren.", "merge-dialog-text": "Ved å kombinere de valgte matvarene vil de bli slått sammen til én matvare. Den første matvaren vil bli slettet, og alle referanser til denne vil bli oppdatert til å peke til den nye matvaren.",
"merge-food-example": "Slår sammen {food1} til {food2}", "merge-food-example": "Slår sammen {food1} til {food2}",
"seed-dialog-text": "Legg til matvarer i databasen basert på ditt lokale språk. Dette vil opprette 200+ vanlige matvarer som kan brukes til å organisere databasen din. Matvarene oversettes via en fellesinnsats fra samfunnet.", "seed-dialog-text": "Legg til matvarer i databasen basert på ditt lokale språk. Dette vil opprette 200+ vanlige matvarer som kan brukes til å organisere databasen din. Matvarene oversettes via en fellesinnsats fra samfunnet.",
"seed-dialog-warning": "Du har allerede noen elementer i databasen din. Denne handlingen vil ikke forene duplikater, du må håndtere dem manuelt.", "seed-dialog-warning": "Du har allerede noen elementer i databasen din. Denne handlingen vil ikke forene duplikater, du må håndtere dem manuelt.",
@ -913,30 +914,30 @@
"food-label": "Matvareetikett", "food-label": "Matvareetikett",
"edit-food": "Rediger matvare", "edit-food": "Rediger matvare",
"food-data": "Matvaredata", "food-data": "Matvaredata",
"example-food-singular": "f. eks. løk", "example-food-singular": "f.eks: tomat",
"example-food-plural": "f. eks. løk" "example-food-plural": "f.eks: tomater"
}, },
"units": { "units": {
"seed-dialog-text": "Tilfør typiske enheter i databasen basert på ditt lokale språk.", "seed-dialog-text": "Tilfør typiske enheter i databasen basert på ditt lokale språk.",
"combine-unit-description": "Ved å kombinere de valgte enhetene vil kildeenheten og målenheten slås sammen i en enkelt enhet. {source-unit-will-be-deleted} og alle referansene til kildeenheten vil bli oppdatert til å peke til målenheten.", "combine-unit-description": "Ved å kombinere de valgte enhetene, vil de bli slått sammen til én enkelt enhet. {source-unit-will-be-deleted} og alle referanser til denne vil bli oppdatert til å peke til den nye enheten.",
"combine-unit": "Kombiner enhet", "combine-unit": "Kombiner enhet",
"source-unit": "Kildeenhet", "source-unit": "Kildeenhet",
"target-unit": "Målenhet", "target-unit": "Målenhet",
"merging-unit-into-unit": "Slår sammen {0} til {1}", "merging-unit-into-unit": "Slår sammen {0} til {1}",
"create-unit": "Opprett enhet", "create-unit": "Opprett enhet",
"abbreviation": "Forkortelse", "abbreviation": "Forkortelse",
"plural-abbreviation": "Flertallsforkortelse", "plural-abbreviation": "Forkortet flertallsform",
"description": "Beskrivelse", "description": "Beskrivelse",
"display-as-fraction": "Vis som brøkdel", "display-as-fraction": "Vis som brøk",
"use-abbreviation": "Bruk forkortelse", "use-abbreviation": "Bruk forkortelse",
"edit-unit": "Rediger enhet", "edit-unit": "Rediger enhet",
"unit-data": "Enhetsdata", "unit-data": "Enhetsdata",
"use-abbv": "Bruk forkortelse.", "use-abbv": "Bruk forkortelse",
"fraction": "Brøk", "fraction": "Brøk",
"example-unit-singular": "Feks: Spiseskje", "example-unit-singular": "f.eks: spiseskje",
"example-unit-plural": "Feks: Spiseskjeer", "example-unit-plural": "f.eks: spiseskjeer",
"example-unit-abbreviation-singular": "Feks: SS", "example-unit-abbreviation-singular": "f.eks: ss",
"example-unit-abbreviation-plural": "Feks: SS" "example-unit-abbreviation-plural": "f.eks: ss"
}, },
"labels": { "labels": {
"seed-dialog-text": "Tilfør typiske etiketter i databasen basert på ditt lokale språk.", "seed-dialog-text": "Tilfør typiske etiketter i databasen basert på ditt lokale språk.",
@ -946,16 +947,16 @@
}, },
"recipes": { "recipes": {
"purge-exports": "Fjern eksporter", "purge-exports": "Fjern eksporter",
"are-you-sure-you-want-to-delete-all-export-data": "Er du sikker på at du vil slette all historikk?", "are-you-sure-you-want-to-delete-all-export-data": "Er du sikker på at du vil slette alle eksporterte data?",
"confirm-delete-recipes": "Er du sikker på at du vil slette denne oppskriften? Denne handlingen kan ikke angres.", "confirm-delete-recipes": "Er du sikker på at du vil slette følgende oppskrifter? Denne handlingen kan ikke angres.",
"the-following-recipes-selected-length-will-be-exported": "Følgende oppskrifter ({0}) vil bli eksportert.", "the-following-recipes-selected-length-will-be-exported": "Følgende oppskrifter ({0}) vil bli eksportert.",
"settings-chosen-explanation": "Innstillinger valgt her, bortsett fra det låste alternativet, vil bli brukt på alle valgte oppskrifter.", "settings-chosen-explanation": "Innstillinger som valgt her, bortsett fra det låste alternativet, vil bli brukt på alle valgte oppskrifter.",
"selected-length-recipe-s-settings-will-be-updated": "Innstillingene til {count} oppskrift(er) vil bli oppdatert.", "selected-length-recipe-s-settings-will-be-updated": "Innstillingene til {count} oppskrift(er) vil bli oppdatert.",
"recipe-data": "Oppskriftsdata", "recipe-data": "Oppskriftsdata",
"recipe-data-description": "Bruk denne delen til å administrere dataene knyttet til oppskriftene dine. Du kan utføre flere massehandlinger på oppskriftene dine, inkludert eksportering, sletting, merking og tildeling av kategorier.", "recipe-data-description": "Bruk denne delen til å administrere dataene knyttet til oppskriftene dine. Du kan utføre flere massehandlinger på oppskriftene dine, inkludert eksportering, sletting, merking og tildeling av kategorier.",
"recipe-columns": "Oppskriftskolonner", "recipe-columns": "Oppskriftskolonner",
"data-exports-description": "Dette avsnittet gir lenker til tilgjengelige eksportfiler som er klare til nedlasting. Disse eksportfilene utløper, så sørg for å laste dem ned mens de fortsatt er tilgjengelige.", "data-exports-description": "Her finner du lenker til tilgjengelige eksportfiler som er klare til nedlasting. Disse eksportfilene utløper, så sørg for å laste dem ned mens de fortsatt er tilgjengelige.",
"data-exports": "Data eksport", "data-exports": "Dataeksport",
"tag": "Emneord", "tag": "Emneord",
"categorize": "Kategoriser", "categorize": "Kategoriser",
"update-settings": "Oppdater innstillinger", "update-settings": "Oppdater innstillinger",
@ -968,16 +969,16 @@
"create-alias": "Opprett alias", "create-alias": "Opprett alias",
"manage-aliases": "Administrer aliaser", "manage-aliases": "Administrer aliaser",
"seed-data": "Tilføringsdata", "seed-data": "Tilføringsdata",
"seed": "Nøkkel", "seed": "Tilfør",
"data-management": "Databehandling", "data-management": "Databehandling",
"data-management-description": "Velg hvilke data du vil gjøre endringer i.", "data-management-description": "Velg hvilke data du vil gjøre endringer .",
"select-data": "Velg data", "select-data": "Velg data",
"select-language": "Velg språk", "select-language": "Velg språk",
"columns": "Kolonner", "columns": "Kolonner",
"combine": "Kombiner", "combine": "Kombiner",
"categories": { "categories": {
"edit-category": "Rediger kategori", "edit-category": "Rediger kategori",
"new-category": "Ny Kategori", "new-category": "Ny kategori",
"category-data": "Kategoridata" "category-data": "Kategoridata"
}, },
"tags": { "tags": {
@ -986,9 +987,9 @@
"tag-data": "Emneorddata" "tag-data": "Emneorddata"
}, },
"tools": { "tools": {
"new-tool": "Nytt utstyr", "new-tool": "Nytt kjøkkenredskap",
"edit-tool": "Rediger utstyr", "edit-tool": "Rediger kjøkkenredskap",
"tool-data": "Utstyrsdata" "tool-data": "Kjøkkenredskapsdata"
} }
}, },
"user-registration": { "user-registration": {
@ -1020,12 +1021,12 @@
"share-recipe": "Del oppskrift", "share-recipe": "Del oppskrift",
"default-30-days": "Standard 30 dager", "default-30-days": "Standard 30 dager",
"expires-at": "Utløper den", "expires-at": "Utløper den",
"recipe-link-copied-message": "Lenke kopiert til utklippstavle" "recipe-link-copied-message": "Oppskriftslenke kopiert til utklippstavle"
}, },
"banner-experimental": { "banner-experimental": {
"title": "Eksperimentelle Funksjoner", "title": "Eksperimentelle funksjoner",
"description": "Denne siden inneholder eksperimentelle og uferdige funksjoner. Beklager rotet.", "description": "Denne siden inneholder eksperimentelle og uferdige funksjoner. Beklager rotet.",
"issue-link-text": "Følg fremgangen din her" "issue-link-text": "Følg vår fremgang her"
}, },
"form": { "form": {
"quantity-label-abbreviated": "Ant" "quantity-label-abbreviated": "Ant"
@ -1039,34 +1040,34 @@
"demo_password": "Passord: {password}" "demo_password": "Passord: {password}"
}, },
"ocr-editor": { "ocr-editor": {
"ocr-editor": "redigere OCR", "ocr-editor": "OCR-redigering",
"toolbar": "Verktøylinje", "toolbar": "Verktøylinje",
"selection-mode": "Velg modus", "selection-mode": "Markeringsmodus",
"pan-and-zoom-picture": "Panorer og zoom bilde", "pan-and-zoom-picture": "Panorer og zoom bilde",
"split-text": "Splitt tekst", "split-text": "Splitt tekst",
"preserve-line-breaks": "Behold opprinnelige linjeskift", "preserve-line-breaks": "Bevar opprinnelig linjeskift",
"split-by-block": "Del tekstblokk", "split-by-block": "Del etter tekstblokk",
"flatten": "Flat ut, uavhengig av orginalformatering.", "flatten": "Flat ut uavhengig av orginalformatering",
"help": { "help": {
"help": "Hjelp", "help": "Hjelp",
"mouse-modes": "Musemodus", "mouse-modes": "Musemoduser",
"selection-mode": "Valgmodus (standard)", "selection-mode": "Markeringsmodus (standard)",
"selection-mode-desc": "Utvalgsmodus er hovedmodus som kan brukes til å legge inn data:", "selection-mode-desc": "Markeringsmodusen er hovedmodusen som kan brukes til å legge inn data:",
"selection-mode-steps": { "selection-mode-steps": {
"draw": "Tegn et rektangel på teksten du vil velge.", "draw": "Tegn en firkant på teksten du vil velge.",
"click": "Klikk på valgfritt felt til høyre, deretter klikk tilbake på firkanten over bildet.", "click": "Klikk på valgfritt felt til høyre, deretter klikk tilbake på firkanten over bildet.",
"result": "Den markerte teksten vil bli lagt inn i det tidligere valgte feltet." "result": "Den markerte teksten vil bli lagt inn i det tidligere valgte feltet."
}, },
"pan-and-zoom-mode": "Panér og Zoom modus", "pan-and-zoom-mode": "Panorer- og zoommodus",
"pan-and-zoom-desc": "Velg pan og zoom ved å klikke ikonet. Denne modusen gjør det lettere å bruke store bilder, ved at du kan zoome og flytte rundt på bildet.", "pan-and-zoom-desc": "Velg panorer og zoom ved å klikke ikonet. Denne modusen gjør det lettere å bruke store bilder ved at du kan zoome og flytte rundt på bildet.",
"split-text-mode": "Splitt tekstmodus", "split-text-mode": "Splitt-tekst-moduser",
"split-modes": { "split-modes": {
"line-mode": "Linjemodus (standard)", "line-mode": "Linjemodus (standard)",
"line-mode-desc": "I linjemodus, vil teksten bli oppdelt ut i fra de orginale linjeskiftene. Denne modusen er nytting når man legger til ingredienslister i bulk der hver ingrediens er på egen linje.", "line-mode-desc": "I linjemodus vil teksten bli oppdelt ut i fra de orginale linjeskiftene. Denne modusen er nyttig når man legger til ingredienslister i bulk der hver ingrediens er på egen linje.",
"block-mode": "Blokk modus", "block-mode": "Blokkmodus",
"block-mode-desc": "I blokkmodus vil teksten bli delt i blokker. Denne modusen er nyttig når man legger inn istruksjoner i bulk, som vanligvis er skrevet i avsnitt.", "block-mode-desc": "I blokkmodus vil teksten bli delt inn i blokker. Denne modusen er nyttig når du legger til instruksjoner i bulk som vanligvis er skrevet i avsnitt.",
"flat-mode": "Flat modus", "flat-mode": "Flat modus",
"flat-mode-desc": "I flat modus vil teksten bli lagt til i det valgte oppskriftsfeltet uten noen linjeskift." "flat-mode-desc": "I flat modus vil teksten bli lagt til i det valgte oppskriftsfeltet uten linjeskift."
} }
} }
}, },
@ -1078,9 +1079,9 @@
"button-label-get-summary": "Hent sammendrag", "button-label-get-summary": "Hent sammendrag",
"button-label-open-details": "Detaljer", "button-label-open-details": "Detaljer",
"info-description-data-dir-size": "Størrelse på datamappe", "info-description-data-dir-size": "Størrelse på datamappe",
"info-description-log-file-size": "Loggfil størrelse", "info-description-log-file-size": "Størrelse på loggfil",
"info-description-cleanable-directories": "Rensbare kataloger", "info-description-cleanable-directories": "Mapper som kan ryddes i",
"info-description-cleanable-images": "Rydbare bilder", "info-description-cleanable-images": "Ryddbare bilder",
"storage": { "storage": {
"title-temporary-directory": "Midlertidig mappe (.temp)", "title-temporary-directory": "Midlertidig mappe (.temp)",
"title-backups-directory": "Mappe for sikkerhetskopier (backups)", "title-backups-directory": "Mappe for sikkerhetskopier (backups)",
@ -1091,7 +1092,7 @@
"action-delete-log-files-name": "Slett loggfiler", "action-delete-log-files-name": "Slett loggfiler",
"action-delete-log-files-description": "Sletter alle loggfilene", "action-delete-log-files-description": "Sletter alle loggfilene",
"action-clean-directories-name": "Fjern kataloger", "action-clean-directories-name": "Fjern kataloger",
"action-clean-directories-description": "Fjerner alle oppskriftsmapper som ikke er gyldige UUIDer", "action-clean-directories-description": "Fjerner alle oppskriftsmapper som ikke er gyldige UUID-er",
"action-clean-temporary-files-name": "Fjern midlertidige filer", "action-clean-temporary-files-name": "Fjern midlertidige filer",
"action-clean-temporary-files-description": "Fjerner alle filer og mapper i .temp-mappen", "action-clean-temporary-files-description": "Fjerner alle filer og mapper i .temp-mappen",
"action-clean-images-name": "Fjern bilder", "action-clean-images-name": "Fjern bilder",
@ -1100,70 +1101,70 @@
"actions-description-destructive": "destruktiv", "actions-description-destructive": "destruktiv",
"actions-description-irreversible": "irreversibel", "actions-description-irreversible": "irreversibel",
"logs-action-refresh": "Oppdater logger", "logs-action-refresh": "Oppdater logger",
"logs-page-title": "Mealie Log", "logs-page-title": "Mealie log",
"logs-tail-lines-label": "Siste linjer" "logs-tail-lines-label": "Siste linjer"
}, },
"mainentance": { "mainentance": {
"actions-title": "Handlinger" "actions-title": "Handlinger"
}, },
"ingredients-natural-language-processor": "Ingredients Natural Language Processor", "ingredients-natural-language-processor": "Naturlig språkprossesering for ingredienser",
"ingredients-natural-language-processor-explanation": "Mealie bruker Conditional Random Fields (CRFs) for å analysere og behandle ingredienser. Modellen som brukes til ingredienser, er basert på et datasett med over 100 000 ingredienser satt sammen av New York Times. Vær oppmerksom på at siden modellen kun er trent på engelsk, kan resultatene variere når du bruker modellen på andre språk. Denne siden er en lekeplass for å teste modellen.", "ingredients-natural-language-processor-explanation": "Mealie bruker Conditional Random Fields (CRFs) for å analysere og behandle ingredienser. Modellen som brukes til ingredienser er basert på et datasett med over 100 000 ingredienser satt sammen av New York Times. Vær oppmerksom på at siden modellen kun er trent på engelsk, kan resultatene variere når du bruker modellen på andre språk. På denne siden kan du teste modellen.",
"ingredients-natural-language-processor-explanation-2": "Modellen er ikke perfekt, men det gir generelt sett gode resultater og er et godt utgangspunkt for å manuelt analysere ingredienser i individuelle felt. Alternativt kan du også bruke 'Brute'-prosessoren som bruker mønstergjenkjennelsesteknikker for å identifisere ingredienser.", "ingredients-natural-language-processor-explanation-2": "Modellen er ikke perfekt, men det gir generelt sett gode resultater og er et godt utgangspunkt for å manuelt analysere ingredienser i individuelle felt. Alternativt kan du også bruke 'Brute'-prosessoren som bruker mønstergjenkjennelsesteknikker for å identifisere ingredienser.",
"nlp": "NLP", "nlp": "NLP",
"brute": "Brute", "brute": "Brute",
"show-individual-confidence": "Vis individuell tillit", "show-individual-confidence": "Vis individuell konfidens",
"ingredient-text": "Ingredient tekst", "ingredient-text": "Ingredienstekst",
"average-confident": "{0} Troverdig", "average-confident": "{0} Troverdig",
"try-an-example": "Prøv et eksempel", "try-an-example": "Prøv et eksempel",
"parser": "Parser", "parser": "Parser",
"background-tasks": "Bakgrunnsoppgaver", "background-tasks": "Bakgrunnsoppgaver",
"background-tasks-description": "Her kan du se alle aktive bakgrunnsoppgaver og deres status", "background-tasks-description": "Her kan du se alle de aktive bakgrunnsoppgavene og statusen deres",
"no-logs-found": "Ingen logger funnet", "no-logs-found": "Ingen logger funnet",
"tasks": "Oppgaver" "tasks": "Oppgaver"
}, },
"profile": { "profile": {
"welcome-user": "👋 Velkommen, {0}", "welcome-user": "👋 Velkommen, {0}",
"description": "Behandle din profil, oppskrifter og gruppeinnstillinger.", "description": "Administrer din profil, oppskrifter og gruppeinnstillinger.",
"get-invite-link": "Få invitasjonslink", "get-invite-link": "Få invitasjonslenke",
"get-public-link": "Få offentlig lenke", "get-public-link": "Få offentlig lenke",
"account-summary": "Kontosammendrag", "account-summary": "Kontosammendrag",
"account-summary-description": "Her er en oppsummering av gruppens informasjon", "account-summary-description": "Her er en oppsummering av informasjonen til gruppen din",
"group-statistics": "Gruppestatistikk", "group-statistics": "Gruppestatistikk",
"group-statistics-description": "Gruppestatistikken din gir deg et innblikk i hvordan du bruker Mealie.", "group-statistics-description": "Gruppestatistikken din gir deg et innblikk i hvordan du bruker Mealie.",
"storage-capacity": "Lagringskapasitet", "storage-capacity": "Lagringskapasitet",
"storage-capacity-description": "Lagringskapasiteten er en beregning av bildene og ressursene du har lastet opp.", "storage-capacity-description": "Lagringskapasiteten er en beregning av bildene og ressursene du har lastet opp.",
"personal": "Personlig", "personal": "Personlig",
"personal-description": "Dette er innstillingene som er personlige for deg. Endringer her påvirker ikke andre brukere", "personal-description": "Dette er innstillingene som er personlige for deg. Endringer gjort her påvirker ikke andre brukere",
"user-settings": "Brukerinnstillinger", "user-settings": "Brukerinnstillinger",
"user-settings-description": "Administrer innstillingene, endre passordet og oppdater e-postadressen din", "user-settings-description": "Administrer innstillingene, endre passordet og oppdater e-postadressen din",
"api-tokens-description": "Håndter dine API-tokens for tilgang fra eksterne programmer", "api-tokens-description": "Administrer dine API-tokens for tilgang fra eksterne programmer",
"group-description": "Disse elementene deles innad i gruppen din. Å redigere ett av dem vil endre det for hele gruppen!", "group-description": "Disse elementene deles innad i gruppen din. Redigering av elementenee vil føre til endringer for hele gruppen!",
"group-settings": "Gruppeinnstillinger", "group-settings": "Gruppeinnstillinger",
"group-settings-description": "Administrer felles gruppeinnstillinger som måltidsplan- og personverninnstillinger.", "group-settings-description": "Administrer felles gruppeinnstillinger som innstillinger for måltidsplaner og personvern.",
"cookbooks-description": "Administrer en samling av oppskriftskategorier og generer sider for dem.", "cookbooks-description": "Administrer en samling av oppskriftskategorier og generer sider for dem.",
"members": "Medlemmer", "members": "Medlemmer",
"members-description": "Se hvem som er i gruppen din og adminstrer deres tillatelser.", "members-description": "Se hvem som er medlem av gruppen din og adminstrer deres rettigheter.",
"webhooks-description": "Setup webhooks that trigger on days that you have have mealplan scheduled.", "webhooks-description": "Sett opp webhooks som utløses på dager du har planlagt måltidsplaner.",
"notifiers": "Varslere", "notifiers": "Varslingsagenter",
"notifiers-description": "Sett opp e-post- og pushvarsler som utløses av spesifikke hendelser.", "notifiers-description": "Sett opp e-post- og pushvarsler som utløses av spesifikke hendelser.",
"manage-data": "Administrer data", "manage-data": "Administrer data",
"manage-data-description": "Administrer dine matvarer og enheter (flere alternativer kommer snart)", "manage-data-description": "Administrer dine matvarer og enheter (flere alternativer kommer snart)",
"data-migrations": "Datamigrering", "data-migrations": "Dataoverføringer",
"data-migrations-description": "Overfør eksisterende data fra andre programmer som Nextcloud Recipes og Chowdown", "data-migrations-description": "Overfør eksisterende data fra andre programmer som Nextcloud Recipes og Chowdown",
"email-sent": "Epost sendt", "email-sent": "E-post sendt",
"error-sending-email": "Feil ved sending av e-post", "error-sending-email": "Feil ved sending av e-post",
"personal-information": "Personlig Informasjon", "personal-information": "Personlig informasjon",
"preferences": "Preferanser", "preferences": "Preferanser",
"show-advanced-description": "Vis avanserte funksjoner (API-nøkler, webhooks og databehandling)", "show-advanced-description": "Vis avanserte funksjoner (API-nøkler, webhooks og databehandling)",
"back-to-profile": "Tilbake til profil", "back-to-profile": "Tilbake til profil",
"looking-for-privacy-settings": "Leter du etter personverninnstillinger?", "looking-for-privacy-settings": "Leter du etter personverninnstillinger?",
"manage-your-api-tokens": "Håndter dine API-tokens", "manage-your-api-tokens": "Administrer dine API-tokens",
"manage-user-profile": "Administrer brukerprofil", "manage-user-profile": "Administrer brukerprofil",
"manage-cookbooks": "Administrere kokebøker", "manage-cookbooks": "Administrer kokebøker",
"manage-members": "Administrer medlemmer", "manage-members": "Administrer medlemmer",
"manage-webhooks": "Administrer webhooks", "manage-webhooks": "Administrer webhooks",
"manage-notifiers": "Behandle varslere", "manage-notifiers": "Administrer varslingsagenter",
"manage-data-migrations": "Håndter datamigreringer" "manage-data-migrations": "Administrer dataoverføringer"
}, },
"cookbook": { "cookbook": {
"cookbooks": "Kokebøker", "cookbooks": "Kokebøker",
@ -1174,7 +1175,7 @@
"filter-options-description": "Når krev alle er valgt, vil kokeboken bare inkludere oppskrifter som har alle de valgte elementene. Dette gjelder for hvert delsett av valgene og ikke et tverrsnitt av de valgte elementene.", "filter-options-description": "Når krev alle er valgt, vil kokeboken bare inkludere oppskrifter som har alle de valgte elementene. Dette gjelder for hvert delsett av valgene og ikke et tverrsnitt av de valgte elementene.",
"require-all-categories": "Krev alle kategorier", "require-all-categories": "Krev alle kategorier",
"require-all-tags": "Krev alle emneord", "require-all-tags": "Krev alle emneord",
"require-all-tools": "Krev alt utstyr", "require-all-tools": "Krev alle kjøkkenredskaper",
"cookbook-name": "Navn på kokebok", "cookbook-name": "Navn på kokebok",
"cookbook-with-name": "Kokebok {0}" "cookbook-with-name": "Kokebok {0}"
} }

View File

@ -114,9 +114,9 @@
"json": "JSON", "json": "JSON",
"keyword": "Słowo kluczowe", "keyword": "Słowo kluczowe",
"link-copied": "Odnośnik skopiowany", "link-copied": "Odnośnik skopiowany",
"loading": "Loading", "loading": "Ładowanie",
"loading-events": "Ładowanie wydarzeń", "loading-events": "Ładowanie wydarzeń",
"loading-recipe": "Loading recipe...", "loading-recipe": "Ładowanie przepisów...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Loading OCR data...",
"loading-recipes": "Ładowanie przepisów", "loading-recipes": "Ładowanie przepisów",
"message": "Wiadomość", "message": "Wiadomość",
@ -128,7 +128,7 @@
"no-recipe-found": "Nie znaleziono przepisu", "no-recipe-found": "Nie znaleziono przepisu",
"ok": "OK", "ok": "OK",
"options": "Opcje:", "options": "Opcje:",
"plural-name": "Plural Name", "plural-name": "Nazwa w liczbie mnogiej",
"print": "Drukuj", "print": "Drukuj",
"print-preferences": "Właściwości drukowania", "print-preferences": "Właściwości drukowania",
"random": "Losowa", "random": "Losowa",
@ -198,7 +198,8 @@
"refresh": "Odśwież", "refresh": "Odśwież",
"upload-file": "Prześlij plik", "upload-file": "Prześlij plik",
"created-on-date": "Utworzono dnia: {0}", "created-on-date": "Utworzono dnia: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Czy na pewno chcesz usunąć <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Czy na pewno chcesz usunąć <b>{groupName}<b/>?",
@ -213,7 +214,7 @@
"group-id-with-value": "ID grupy: {groupID}", "group-id-with-value": "ID grupy: {groupID}",
"group-name": "Nazwa grupy", "group-name": "Nazwa grupy",
"group-not-found": "Nie znaleziono grupy", "group-not-found": "Nie znaleziono grupy",
"group-token": "Group Token", "group-token": "Token grupy",
"group-with-value": "Grupa: {groupID}", "group-with-value": "Grupa: {groupID}",
"groups": "Grupy", "groups": "Grupy",
"manage-groups": "Zarządzaj grupami", "manage-groups": "Zarządzaj grupami",
@ -249,7 +250,7 @@
"general-preferences": "Ustawienia ogólne", "general-preferences": "Ustawienia ogólne",
"group-recipe-preferences": "Ustawienia grupy przepisów", "group-recipe-preferences": "Ustawienia grupy przepisów",
"report": "Zgłoś", "report": "Zgłoś",
"report-with-id": "Report ID: {id}", "report-with-id": "ID zgłoszenia: {id}",
"group-management": "Zarządzanie grupą", "group-management": "Zarządzanie grupą",
"admin-group-management": "Administracja Zarządzanie Grupami", "admin-group-management": "Administracja Zarządzanie Grupami",
"admin-group-management-text": "Zmiany w tej grupie zostaną natychmiast odzwierciedlone.", "admin-group-management-text": "Zmiany w tej grupie zostaną natychmiast odzwierciedlone.",
@ -304,7 +305,7 @@
"for-type-meal-types": "dla {0} rodzajów posiłków", "for-type-meal-types": "dla {0} rodzajów posiłków",
"meal-plan-rules": "Zasady planu posiłków", "meal-plan-rules": "Zasady planu posiłków",
"new-rule": "Nowa reguła", "new-rule": "Nowa reguła",
"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 categories of the rules will be merged. In practice, it's unnecessary to create duplicate rules, but it's possible to do so.", "meal-plan-rules-description": "Możesz tworzyć reguły automatycznego wyboru przepisów dla planów posiłkowych. Te reguły są używane przez serwer do określenia losowej puli przepisów do wyboru podczas tworzenia planów posiłków. Zauważ, że jeśli reguły mają ograniczenia tego samego dnia/typu, kategorie reguł zostaną połączone. W praktyce tworzenie duplikatów reguł jest zbędne, ale jest to możliwe.",
"new-rule-description": "Przy tworzeniu nowej reguły dotyczącej planu posiłków można ograniczyć regułę, tak aby miała zastosowanie do określonego dnia tygodnia i/lub określonego rodzaju posiłku. Aby zastosować regułę do wszystkich dni lub wszystkich rodzajów posiłków można ustawić regułę na \"Dowolny\", co będzie miało zastosowanie do wszystkich możliwych wartości dla dnia i/lub typu posiłku.", "new-rule-description": "Przy tworzeniu nowej reguły dotyczącej planu posiłków można ograniczyć regułę, tak aby miała zastosowanie do określonego dnia tygodnia i/lub określonego rodzaju posiłku. Aby zastosować regułę do wszystkich dni lub wszystkich rodzajów posiłków można ustawić regułę na \"Dowolny\", co będzie miało zastosowanie do wszystkich możliwych wartości dla dnia i/lub typu posiłku.",
"recipe-rules": "Reguły przepisów", "recipe-rules": "Reguły przepisów",
"applies-to-all-days": "Dotyczy wszystkich dni", "applies-to-all-days": "Dotyczy wszystkich dni",
@ -341,8 +342,8 @@
"title": "Mealie Pre v1.0" "title": "Mealie Pre v1.0"
}, },
"tandoor": { "tandoor": {
"description-long": "Mealie can import recipes from Tandoor. Export your data in the \"Default\" format, then upload the .zip below.", "description-long": "Mealie może zaimportować przepisy z Tandoor. Wyeksportuj swoje przepisy w formacie HTML, a następnie prześlij plik .zip poniżej.",
"title": "Tandoor Recipes" "title": "Przepisy Tandoor"
}, },
"recipe-data-migrations": "Migracja danych przepisów", "recipe-data-migrations": "Migracja danych przepisów",
"recipe-data-migrations-explanation": "Receptury mogą być przeniesione z innej wspieranej aplikacji na Mealie. To świetny sposób na rozpoczęcie z Mealie.", "recipe-data-migrations-explanation": "Receptury mogą być przeniesione z innej wspieranej aplikacji na Mealie. To świetny sposób na rozpoczęcie z Mealie.",
@ -355,8 +356,8 @@
"paprika-text": "Mealie może importować przepisy z aplikacji Paprika. Eksportuj swoje przepisy z papriki, zmień nazwę rozszerzenia eksportu na .zip i prześlij je poniżej.", "paprika-text": "Mealie może importować przepisy z aplikacji Paprika. Eksportuj swoje przepisy z papriki, zmień nazwę rozszerzenia eksportu na .zip i prześlij je poniżej.",
"mealie-text": "Mealie może importować receptury z aplikacji Mealie z wersji przed v1.0. Wyeksportuj swoje przepisy ze starej instancji i prześlij plik zip poniżej. Pamiętaj, że tylko receptury mogą być zaimportowane z eksportu.", "mealie-text": "Mealie może importować receptury z aplikacji Mealie z wersji przed v1.0. Wyeksportuj swoje przepisy ze starej instancji i prześlij plik zip poniżej. Pamiętaj, że tylko receptury mogą być zaimportowane z eksportu.",
"plantoeat": { "plantoeat": {
"title": "Plan to Eat", "title": "Zaplanuj jedzenie",
"description-long": "Mealie can import recipies from Plan to Eat." "description-long": "Mealie może importować przepisy z Plan to Eat."
} }
}, },
"new-recipe": { "new-recipe": {
@ -468,11 +469,11 @@
"date-format-hint-yyyy-mm-dd": "Format RRRR-MM-DD", "date-format-hint-yyyy-mm-dd": "Format RRRR-MM-DD",
"add-to-list": "Dodaj do listy", "add-to-list": "Dodaj do listy",
"add-to-plan": "Dodaj do planu", "add-to-plan": "Dodaj do planu",
"add-to-timeline": "Add to Timeline", "add-to-timeline": "Dodaj do osi czasu",
"recipe-added-to-list": "Przepis dodany do listy", "recipe-added-to-list": "Przepis dodany do listy",
"recipes-added-to-list": "Przepisy dodane do listy", "recipes-added-to-list": "Przepisy dodane do listy",
"recipe-added-to-mealplan": "Przepis dodany do planu posiłków", "recipe-added-to-mealplan": "Przepis dodany do planu posiłków",
"failed-to-add-recipes-to-list": "Failed to add recipe to list", "failed-to-add-recipes-to-list": "Nie udało się dodać przepisu do listy",
"failed-to-add-recipe-to-mealplan": "Nie udało się dodać przepisu do planu posiłków", "failed-to-add-recipe-to-mealplan": "Nie udało się dodać przepisu do planu posiłków",
"yield": "Wydajność", "yield": "Wydajność",
"quantity": "Ilość", "quantity": "Ilość",
@ -495,10 +496,10 @@
"locked": "Zablokowany", "locked": "Zablokowany",
"public-link": "Link publiczny", "public-link": "Link publiczny",
"timer": { "timer": {
"kitchen-timer": "Kitchen Timer", "kitchen-timer": "Minutnik",
"start-timer": "Włącz minutnik", "start-timer": "Włącz minutnik",
"pause-timer": "Pause Timer", "pause-timer": "Zatrzymaj minutnik",
"resume-timer": "Resume Timer", "resume-timer": "Wznów minutnik",
"stop-timer": "Zatrzymaj minutnik" "stop-timer": "Zatrzymaj minutnik"
}, },
"edit-timeline-event": "Edytuj zdarzenie osi czasu", "edit-timeline-event": "Edytuj zdarzenie osi czasu",
@ -510,11 +511,11 @@
"how-did-it-turn-out": "Jak się to udało?", "how-did-it-turn-out": "Jak się to udało?",
"user-made-this": "{user} ugotował(a) to", "user-made-this": "{user} ugotował(a) to",
"last-made-date": "Ostatnio ugotowano {date}", "last-made-date": "Ostatnio ugotowano {date}",
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.", "api-extras-description": "Dodatki w przepisach są kluczową cechą API Mealie. Pozwalają na tworzenie niestandardowych par kluczy/wartości JSON w przepisie do odwoływania się przez zewnętrzne aplikacje. Możesz użyć tych kluczy do wyzwalania automatyzacji lub przekazywania niestandardowych wiadomości do twoich wybranych urządzeń.",
"message-key": "Klucz Wiadomości", "message-key": "Klucz Wiadomości",
"parse": "Analizuj", "parse": "Analizuj",
"attach-images-hint": "Dołącz obrazy przeciągając i upuszczając je do edytora", "attach-images-hint": "Dołącz obrazy przeciągając i upuszczając je do edytora",
"drop-image": "Drop image", "drop-image": "Upuść zdjęcie",
"enable-ingredient-amounts-to-use-this-feature": "Włącz ilości składników, aby użyć tej funkcji", "enable-ingredient-amounts-to-use-this-feature": "Włącz ilości składników, aby użyć tej funkcji",
"recipes-with-units-or-foods-defined-cannot-be-parsed": "Nie można przeanalizować przepisów z już zdefiniowanymi jednostkami lub żywnością.", "recipes-with-units-or-foods-defined-cannot-be-parsed": "Nie można przeanalizować przepisów z już zdefiniowanymi jednostkami lub żywnością.",
"parse-ingredients": "Analizuj tekst składników", "parse-ingredients": "Analizuj tekst składników",
@ -553,7 +554,7 @@
"recipe-yield": "Wydajność przepisu", "recipe-yield": "Wydajność przepisu",
"unit": "Jednostka", "unit": "Jednostka",
"upload-image": "Prześlij obraz", "upload-image": "Prześlij obraz",
"screen-awake": "Keep Screen Awake", "screen-awake": "Pozostaw ekran włączony",
"remove-image": "Usuń obraz" "remove-image": "Usuń obraz"
}, },
"search": { "search": {
@ -573,7 +574,7 @@
"search-hint": "Naciśnij '/'", "search-hint": "Naciśnij '/'",
"advanced": "Zaawansowane", "advanced": "Zaawansowane",
"auto-search": "Auto wyszukiwanie", "auto-search": "Auto wyszukiwanie",
"no-results": "No results found" "no-results": "Nie znaleziono wyników"
}, },
"settings": { "settings": {
"add-a-new-theme": "Dodaj nowy motyw", "add-a-new-theme": "Dodaj nowy motyw",
@ -582,7 +583,7 @@
"backup-created": "Kopia zapasowa utworzona pomyślnie", "backup-created": "Kopia zapasowa utworzona pomyślnie",
"backup-created-at-response-export_path": "Kopia zapasowa została utworzona w {path}", "backup-created-at-response-export_path": "Kopia zapasowa została utworzona w {path}",
"backup-deleted": "Kopia zapasowa została usunięta", "backup-deleted": "Kopia zapasowa została usunięta",
"restore-success": "Restore successful", "restore-success": "Przywracanie zakończone sukcesem",
"backup-tag": "Etykieta kopii zapasowej", "backup-tag": "Etykieta kopii zapasowej",
"create-heading": "Utwórz kopię zapasową", "create-heading": "Utwórz kopię zapasową",
"delete-backup": "Usuń kopię zapasową", "delete-backup": "Usuń kopię zapasową",
@ -691,13 +692,13 @@
"configuration": "Konfiguracja", "configuration": "Konfiguracja",
"docker-volume": "Docker Volume", "docker-volume": "Docker Volume",
"docker-volume-help": "Mealie wymaga, aby kontener frontendu i backendu współdzieliły ten sam wolumen docker lub pamięć. Zapewnia to prawidłowy dostęp do zdjęć i zasobów przechowywanych na dysku.", "docker-volume-help": "Mealie wymaga, aby kontener frontendu i backendu współdzieliły ten sam wolumen docker lub pamięć. Zapewnia to prawidłowy dostęp do zdjęć i zasobów przechowywanych na dysku.",
"volumes-are-misconfigured": "Volumes are misconfigured.", "volumes-are-misconfigured": "Woluminy są skonfigurowane nieprawidłowo.",
"volumes-are-configured-correctly": "Wolumeny są skonfigurowane poprawnie.", "volumes-are-configured-correctly": "Wolumeny są skonfigurowane poprawnie.",
"status-unknown-try-running-a-validation": "Status nieznany. Spróbuj wykonać walidację.", "status-unknown-try-running-a-validation": "Status nieznany. Spróbuj wykonać walidację.",
"validate": "Sprawdź", "validate": "Sprawdź",
"email-configuration-status": "Status konfiguracji Email", "email-configuration-status": "Status konfiguracji Email",
"email-configured": "Email Configured", "email-configured": "E-mail skonfigurowany",
"email-test-results": "Email Test Results", "email-test-results": "Wyniki testu e-mail",
"ready": "Gotowe", "ready": "Gotowe",
"not-ready": "Niegotowy - Sprawdź zmienne środowiskowe", "not-ready": "Niegotowy - Sprawdź zmienne środowiskowe",
"succeeded": "Powiodło się", "succeeded": "Powiodło się",
@ -876,7 +877,7 @@
"user-management": "Zarządzanie użytkownikami", "user-management": "Zarządzanie użytkownikami",
"reset-locked-users": "Zresetuj zablokowanych użytkowników", "reset-locked-users": "Zresetuj zablokowanych użytkowników",
"admin-user-creation": "Administracja Tworzenie Użytkownika", "admin-user-creation": "Administracja Tworzenie Użytkownika",
"admin-user-management": "Admin User Management", "admin-user-management": "Zarządzanie użytkownikami",
"user-details": "Dane użytkownika", "user-details": "Dane użytkownika",
"user-name": "Nazwa użytkownika", "user-name": "Nazwa użytkownika",
"authentication-method": "Sposób uwierzytelniania", "authentication-method": "Sposób uwierzytelniania",
@ -887,11 +888,11 @@
"user-can-manage-group": "Użytkownik może zarządzać grupą", "user-can-manage-group": "Użytkownik może zarządzać grupą",
"user-can-organize-group-data": "Użytkownik może organizować dane grupy", "user-can-organize-group-data": "Użytkownik może organizować dane grupy",
"enable-advanced-features": "Włącz zaawansowane funkcje", "enable-advanced-features": "Włącz zaawansowane funkcje",
"it-looks-like-this-is-your-first-time-logging-in": "It looks like this is your first time logging in.", "it-looks-like-this-is-your-first-time-logging-in": "Wygląda na to, że to jest twoje pierwsze logowanie.",
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!", "dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Nie chcesz już tego widzieć? Pamiętaj, aby zmienić swój adres e-mail w ustawieniach użytkownika!",
"forgot-password": "Forgot Password", "forgot-password": "Nie pamiętam hasła",
"forgot-password-text": "Please enter your email address and we will send you a link to reset your password.", "forgot-password-text": "Podaj adres e-mail konta, do którego chcesz odzyskać hasło.",
"changes-reflected-immediately": "Changes to this user will be reflected immediately." "changes-reflected-immediately": "Zmiany dla tego użytkownika będą zastosowane natychmiastowo."
}, },
"language-dialog": { "language-dialog": {
"translated": "przetłumaczone", "translated": "przetłumaczone",
@ -913,8 +914,8 @@
"food-label": "Etykieta Żywności", "food-label": "Etykieta Żywności",
"edit-food": "Edytuj Żywność", "edit-food": "Edytuj Żywność",
"food-data": "Dane Żywności", "food-data": "Dane Żywności",
"example-food-singular": "ex: Onion", "example-food-singular": "np. Cebula",
"example-food-plural": "ex: Onions" "example-food-plural": "np. Cebule"
}, },
"units": { "units": {
"seed-dialog-text": "Wypełnij bazę zwyczajowymi jednostkami dla wybranego języka.", "seed-dialog-text": "Wypełnij bazę zwyczajowymi jednostkami dla wybranego języka.",
@ -933,8 +934,8 @@
"unit-data": "Dane Jednostki", "unit-data": "Dane Jednostki",
"use-abbv": "Użyj Skr.", "use-abbv": "Użyj Skr.",
"fraction": "Ułamki", "fraction": "Ułamki",
"example-unit-singular": "ex: Tablespoon", "example-unit-singular": "np. Łyżka stołowa",
"example-unit-plural": "ex: Tablespoons", "example-unit-plural": "np. Łyżki stołowe",
"example-unit-abbreviation-singular": "ex: Tbsp", "example-unit-abbreviation-singular": "ex: Tbsp",
"example-unit-abbreviation-plural": "ex: Tbsps" "example-unit-abbreviation-plural": "ex: Tbsps"
}, },
@ -965,8 +966,8 @@
"delete-recipes": "Usuń Przepisy", "delete-recipes": "Usuń Przepisy",
"source-unit-will-be-deleted": "Jednostka źródłowa zostanie usunięta" "source-unit-will-be-deleted": "Jednostka źródłowa zostanie usunięta"
}, },
"create-alias": "Create Alias", "create-alias": "Utwórz alias",
"manage-aliases": "Manage Aliases", "manage-aliases": "Zarządzaj aliasami",
"seed-data": "Dane przykładowe", "seed-data": "Dane przykładowe",
"seed": "Seed", "seed": "Seed",
"data-management": "Zarządzanie Danymi", "data-management": "Zarządzanie Danymi",
@ -982,18 +983,18 @@
}, },
"tags": { "tags": {
"new-tag": "Nowy Tag", "new-tag": "Nowy Tag",
"edit-tag": "Edit Tag", "edit-tag": "Edytuj tag",
"tag-data": "Tag Data" "tag-data": "Dane tagu"
}, },
"tools": { "tools": {
"new-tool": "New Tool", "new-tool": "Nowe Narzędzie",
"edit-tool": "Edit Tool", "edit-tool": "Edytuj Narzędzie",
"tool-data": "Tool Data" "tool-data": "Dane narzędzia"
} }
}, },
"user-registration": { "user-registration": {
"user-registration": "Rejestracja użytkownika", "user-registration": "Rejestracja użytkownika",
"registration-success": "Registration Success", "registration-success": "Rejestracja przebiegła pomyślnie",
"join-a-group": "Dołącz do grupy", "join-a-group": "Dołącz do grupy",
"create-a-new-group": "Stwórz nową grupę", "create-a-new-group": "Stwórz nową grupę",
"provide-registration-token-description": "Podaj kod rejestracyjny powiązany z grupą do której chcesz dołączyć. Taki kod uzyskać możesz od użytkownika który przynależy już do owej grupy.", "provide-registration-token-description": "Podaj kod rejestracyjny powiązany z grupą do której chcesz dołączyć. Taki kod uzyskać możesz od użytkownika który przynależy już do owej grupy.",
@ -1040,7 +1041,7 @@
}, },
"ocr-editor": { "ocr-editor": {
"ocr-editor": "Edytor OCR", "ocr-editor": "Edytor OCR",
"toolbar": "Toolbar", "toolbar": "Pasek narzędzi",
"selection-mode": "Tryb wyboru", "selection-mode": "Tryb wyboru",
"pan-and-zoom-picture": "Przesuwanie i powiększanie obrazu", "pan-and-zoom-picture": "Przesuwanie i powiększanie obrazu",
"split-text": "Podziel tekst", "split-text": "Podziel tekst",
@ -1048,8 +1049,8 @@
"split-by-block": "Podziel według bloku tekstowego", "split-by-block": "Podziel według bloku tekstowego",
"flatten": "Wyrównaj niezależnie od oryginalnego formatowania", "flatten": "Wyrównaj niezależnie od oryginalnego formatowania",
"help": { "help": {
"help": "Help", "help": "Pomoc",
"mouse-modes": "Mouse modes", "mouse-modes": "Tryb myszy",
"selection-mode": "Tryb wyboru (domyślny)", "selection-mode": "Tryb wyboru (domyślny)",
"selection-mode-desc": "Tryb wyboru jest głównym trybem, który służy do wprowadzenia danych:", "selection-mode-desc": "Tryb wyboru jest głównym trybem, który służy do wprowadzenia danych:",
"selection-mode-steps": { "selection-mode-steps": {
@ -1125,7 +1126,7 @@
"welcome-user": "👋 Witaj, {0}", "welcome-user": "👋 Witaj, {0}",
"description": "Zarządzaj swoim profilem, przepisami i ustawieniami grupy.", "description": "Zarządzaj swoim profilem, przepisami i ustawieniami grupy.",
"get-invite-link": "Uzyskaj link z zaproszeniem", "get-invite-link": "Uzyskaj link z zaproszeniem",
"get-public-link": "Get Public Link", "get-public-link": "Uzyskaj link publiczny",
"account-summary": "Podsumowanie konta", "account-summary": "Podsumowanie konta",
"account-summary-description": "Oto podsumowanie informacji o Twojej grupie", "account-summary-description": "Oto podsumowanie informacji o Twojej grupie",
"group-statistics": "Statystyki Grupy", "group-statistics": "Statystyki Grupy",

View File

@ -198,7 +198,8 @@
"refresh": "Recarregar", "refresh": "Recarregar",
"upload-file": "Enviar arquivo", "upload-file": "Enviar arquivo",
"created-on-date": "Criado em {0}", "created-on-date": "Criado em {0}",
"unsaved-changes": "Você possui alterações não salvas. Deseja salvar antes de sair? Ok para salvar, Cancelar para descartar alterações." "unsaved-changes": "Você possui alterações não salvas. Deseja salvar antes de sair? Ok para salvar, Cancelar para descartar alterações.",
"clipboard-copy-failure": "Failed to copy to the clipboard."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Tem certeza que deseja excluir o grupo <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Tem certeza que deseja excluir o grupo <b>{groupName}<b/>?",

View File

@ -114,7 +114,7 @@
"json": "JSON", "json": "JSON",
"keyword": "Palavra-chave", "keyword": "Palavra-chave",
"link-copied": "Ligação copiada", "link-copied": "Ligação copiada",
"loading": "Loading", "loading": "A carregar",
"loading-events": "A carregar Eventos", "loading-events": "A carregar Eventos",
"loading-recipe": "A carregar receita...", "loading-recipe": "A carregar receita...",
"loading-ocr-data": "A carregar dados OCR...", "loading-ocr-data": "A carregar dados OCR...",
@ -198,7 +198,8 @@
"refresh": "Atualizar", "refresh": "Atualizar",
"upload-file": "Carregar ficheiro", "upload-file": "Carregar ficheiro",
"created-on-date": "Criado em: {0}", "created-on-date": "Criado em: {0}",
"unsaved-changes": "Tem alterações por gravar. Quer gravar antes de sair? OK para gravar, Cancelar para descartar alterações." "unsaved-changes": "Tem alterações por gravar. Quer gravar antes de sair? OK para gravar, Cancelar para descartar alterações.",
"clipboard-copy-failure": "Erro ao copiar para a área de transferência."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Tem a certeza que quer eliminar <b>{groupName}</b>?", "are-you-sure-you-want-to-delete-the-group": "Tem a certeza que quer eliminar <b>{groupName}</b>?",
@ -510,7 +511,7 @@
"how-did-it-turn-out": "Que tal ficou?", "how-did-it-turn-out": "Que tal ficou?",
"user-made-this": "{user} fez isto", "user-made-this": "{user} fez isto",
"last-made-date": "Última vez {date}", "last-made-date": "Última vez {date}",
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.", "api-extras-description": "Extras para receitas são funcionalidades chave da API Mealie. Estas permitem criar, dentro de uma receita, pares personalizados de chave/valor em JSON, para referência a partir de aplicações de terceiros. Pode usar essas chaves para fornecer informações, por exemplo, para acionar automações ou mensagens personalizadas para transmitir a um determinado dispositivo.",
"message-key": "Chave de Mensagem", "message-key": "Chave de Mensagem",
"parse": "Interpretar", "parse": "Interpretar",
"attach-images-hint": "Anexe imagens arrastando e soltando-as no editor", "attach-images-hint": "Anexe imagens arrastando e soltando-as no editor",

View File

@ -198,7 +198,8 @@
"refresh": "Reîncarcă", "refresh": "Reîncarcă",
"upload-file": "Încărcă fișier", "upload-file": "Încărcă fișier",
"created-on-date": "Creat pe {0}", "created-on-date": "Creat pe {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Sunteți sigur că doriți să ștergeți <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Sunteți sigur că doriți să ștergeți <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Обновить", "refresh": "Обновить",
"upload-file": "Загрузить файл", "upload-file": "Загрузить файл",
"created-on-date": "Создано: {0}", "created-on-date": "Создано: {0}",
"unsaved-changes": "У вас есть несохраненные изменения. Вы хотите сохранить их перед выходом?" "unsaved-changes": "У вас есть несохраненные изменения. Вы хотите сохранить их перед выходом?",
"clipboard-copy-failure": "Failed to copy to the clipboard."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Вы действительно хотите удалить <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Вы действительно хотите удалить <b>{groupName}<b/>?",

View File

@ -114,10 +114,10 @@
"json": "JSON", "json": "JSON",
"keyword": "Kľučové slovo", "keyword": "Kľučové slovo",
"link-copied": "Odkaz bol skopírovaný", "link-copied": "Odkaz bol skopírovaný",
"loading": "Loading", "loading": "Načítavam",
"loading-events": "Načítanie udalostí", "loading-events": "Načítanie udalostí",
"loading-recipe": "Loading recipe...", "loading-recipe": "Načítavam recept...",
"loading-ocr-data": "Loading OCR data...", "loading-ocr-data": "Načítavam OCR dáta...",
"loading-recipes": "Nahrávanie receptu", "loading-recipes": "Nahrávanie receptu",
"message": "Správa", "message": "Správa",
"monday": "Pondelok", "monday": "Pondelok",
@ -128,7 +128,7 @@
"no-recipe-found": "Žiadny recept nenájdený", "no-recipe-found": "Žiadny recept nenájdený",
"ok": "OK", "ok": "OK",
"options": "Možnosti:", "options": "Možnosti:",
"plural-name": "Plural Name", "plural-name": "Meno v množnom čísle",
"print": "Tlačiť", "print": "Tlačiť",
"print-preferences": "Nastavenia tlače", "print-preferences": "Nastavenia tlače",
"random": "Náhodné", "random": "Náhodné",
@ -198,7 +198,8 @@
"refresh": "Obnoviť", "refresh": "Obnoviť",
"upload-file": "Nahrať súbor", "upload-file": "Nahrať súbor",
"created-on-date": "Vytvorené: {0}", "created-on-date": "Vytvorené: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Naozaj chcete odstrániť <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Naozaj chcete odstrániť <b>{groupName}<b/>?",
@ -495,11 +496,11 @@
"locked": "Zamknuté", "locked": "Zamknuté",
"public-link": "Verejný odkaz", "public-link": "Verejný odkaz",
"timer": { "timer": {
"kitchen-timer": "Kitchen Timer", "kitchen-timer": "Kuchynský časovač",
"start-timer": "Start Timer", "start-timer": "Spustiť časovač",
"pause-timer": "Pause Timer", "pause-timer": "Pozastaviť časovač",
"resume-timer": "Resume Timer", "resume-timer": "Znova spustiť časovač",
"stop-timer": "Stop Timer" "stop-timer": "Zastaviť časovač"
}, },
"edit-timeline-event": "Upraviť udalosť na časovej osi", "edit-timeline-event": "Upraviť udalosť na časovej osi",
"timeline": "Časová os", "timeline": "Časová os",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "upload-file": "Upload File",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Ste prepričani, da želite izbrisati <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Ste prepričani, da želite izbrisati <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Освежи", "refresh": "Освежи",
"upload-file": "Учитај датотеку", "upload-file": "Учитај датотеку",
"created-on-date": "Крерирано: {0}", "created-on-date": "Крерирано: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Да ли сте сигурни да желите да обришете <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Да ли сте сигурни да желите да обришете <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Uppdatera", "refresh": "Uppdatera",
"upload-file": "Ladda upp fil", "upload-file": "Ladda upp fil",
"created-on-date": "Skapad {0}", "created-on-date": "Skapad {0}",
"unsaved-changes": "Du har osparade ändringar. Vill du spara innan du lämnar? Tryck Okej att spara, Avbryt för att ignorera ändringar." "unsaved-changes": "Du har osparade ändringar. Vill du spara innan du lämnar? Tryck Okej att spara, Avbryt för att ignorera ändringar.",
"clipboard-copy-failure": "Det gick inte att kopiera till urklipp."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Är du säker på att du vill radera <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Är du säker på att du vill radera <b>{groupName}<b/>?",
@ -249,7 +250,7 @@
"general-preferences": "Generella inställningar", "general-preferences": "Generella inställningar",
"group-recipe-preferences": "Inställningar för receptgrupper", "group-recipe-preferences": "Inställningar för receptgrupper",
"report": "Rapport", "report": "Rapport",
"report-with-id": "Report ID: {id}", "report-with-id": "RapportID: {id}",
"group-management": "Grupphantering", "group-management": "Grupphantering",
"admin-group-management": "Hantering av administratörsgrupp", "admin-group-management": "Hantering av administratörsgrupp",
"admin-group-management-text": "Ändringar i denna grupp kommer att återspeglas omedelbart.", "admin-group-management-text": "Ändringar i denna grupp kommer att återspeglas omedelbart.",
@ -355,7 +356,7 @@
"paprika-text": "Mealie kan importera recept från Paprika-applikationen. Exportera dina recept från Paprika, byt namn på filnamnstillägget på exporten till .zip och ladda upp det nedan.", "paprika-text": "Mealie kan importera recept från Paprika-applikationen. Exportera dina recept från Paprika, byt namn på filnamnstillägget på exporten till .zip och ladda upp det nedan.",
"mealie-text": "Mealie kan importera recept från Mealieapplikationen från en före v1.0 version. Exportera dina recept från din gamla instans, och ladda upp zip-filen nedan. Observera att endast recept kan importeras från exporten.", "mealie-text": "Mealie kan importera recept från Mealieapplikationen från en före v1.0 version. Exportera dina recept från din gamla instans, och ladda upp zip-filen nedan. Observera att endast recept kan importeras från exporten.",
"plantoeat": { "plantoeat": {
"title": "Plan to Eat", "title": "Planera att äta",
"description-long": "Mealie kan importera recept från Plan to Eat." "description-long": "Mealie kan importera recept från Plan to Eat."
} }
}, },
@ -510,7 +511,7 @@
"how-did-it-turn-out": "Hur blev rätten?", "how-did-it-turn-out": "Hur blev rätten?",
"user-made-this": "{user} lagade detta", "user-made-this": "{user} lagade detta",
"last-made-date": "Senast lagad {date}", "last-made-date": "Senast lagad {date}",
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.", "api-extras-description": "Recept extras är en viktig funktion i Mealie's API. Med hjälp av dem kan du skapa anpassade JSON-nyckel/värdepar i ett recept, som du kan referera till från tredjepartsapplikationer. Du kan använda dessa nycklar för att tillhandahålla information, till exempel för att trigga automatiseringar eller anpassade meddelanden som ska vidarebefordras till önskad enhet.",
"message-key": "Meddelandenyckel", "message-key": "Meddelandenyckel",
"parse": "Läs in", "parse": "Läs in",
"attach-images-hint": "Bifoga bilder genom att dra och släppa dem i redigeraren", "attach-images-hint": "Bifoga bilder genom att dra och släppa dem i redigeraren",
@ -596,7 +597,7 @@
"back-restore-description": "Återställning av den här backuppen kommer att skriva över all information i databasen och datakatalogen och ersätta allt med innehållet i nackuppen. {cannot-be-undone} Om återställningen går bra kommer du att loggas ut.", "back-restore-description": "Återställning av den här backuppen kommer att skriva över all information i databasen och datakatalogen och ersätta allt med innehållet i nackuppen. {cannot-be-undone} Om återställningen går bra kommer du att loggas ut.",
"cannot-be-undone": "Denna åtgärd kan inte ångras - använd med försiktighet.", "cannot-be-undone": "Denna åtgärd kan inte ångras - använd med försiktighet.",
"postgresql-note": "Om du använder PostGreSQL, vänligen granska {backup-restore-process} innan du återställer.", "postgresql-note": "Om du använder PostGreSQL, vänligen granska {backup-restore-process} innan du återställer.",
"backup-restore-process-in-the-documentation": "backup/restore process in the documentation", "backup-restore-process-in-the-documentation": "säkerhetskopiering/återställning i dokumentationen",
"irreversible-acknowledgment": "Jag förstår att denna åtgärd är oåterkallelig, destruktiv och kan orsaka dataförlust", "irreversible-acknowledgment": "Jag förstår att denna åtgärd är oåterkallelig, destruktiv och kan orsaka dataförlust",
"restore-backup": "Återställ säkerhetskopia" "restore-backup": "Återställ säkerhetskopia"
}, },
@ -683,21 +684,21 @@
"webhooks-caps": "WEBHOOKS", "webhooks-caps": "WEBHOOKS",
"webhooks": "Webhooks", "webhooks": "Webhooks",
"webhook-name": "Namn på webhook", "webhook-name": "Namn på webhook",
"description": "The webhooks defined below will be executed when a meal is defined for the day. At the scheduled time the webhooks will be sent with the data from the recipe that is scheduled for the day. Note that webhook execution is not exact. The webhooks are executed on a 5 minutes interval so the webhooks will be executed within 5 +/- minutes of the scheduled." "description": "De webhooks som definieras nedan kommer att exekveras när en måltid definieras för dagen. Vid den schemalagda tiden skickas webhooks med data från receptet som är schemalagt för dagen. Observera att exekveringen av webhooks inte är exakt. Webhooks exekveras med ett 5 minuters intervall så att webhooks kommer att exekveras inom 5 +/- minuter från den schemalagda tiden."
}, },
"bug-report": "Buggrapport", "bug-report": "Buggrapport",
"bug-report-information": "Use this information to report a bug. Providing details of your instance to developers is the best way to get your issues resolved quickly.", "bug-report-information": "Använd denna information för att rapportera ett fel. Att ge utvecklarna information om din installation är det bästa sättet att få dina problem lösta snabbt.",
"tracker": "Spårare", "tracker": "Spårare",
"configuration": "Konfiguration", "configuration": "Konfiguration",
"docker-volume": "Docker volym", "docker-volume": "Docker volym",
"docker-volume-help": "Mealie requires that the frontend container and the backend share the same docker volume or storage. This ensures that the frontend container can properly access the images and assets stored on disk.", "docker-volume-help": "Mealie kräver att frontend behållare och backend dela samma docker volym eller lagring. Detta säkerställer att frontend-behållaren på rätt sätt kan komma åt bilder och tillgångar som lagras på disken.",
"volumes-are-misconfigured": "Volumes are misconfigured.", "volumes-are-misconfigured": "Volymer är felkonfigurerade.",
"volumes-are-configured-correctly": "Volumes are configured correctly.", "volumes-are-configured-correctly": "Volymer är konfigurerade korrekt.",
"status-unknown-try-running-a-validation": "Status Unknown. Try running a validation.", "status-unknown-try-running-a-validation": "Status okänd. Försök köra en validering.",
"validate": "Validera", "validate": "Validera",
"email-configuration-status": "Email Configuration Status", "email-configuration-status": "E-post konfigurationsstatus",
"email-configured": "Email Configured", "email-configured": "E-post konfigurerad",
"email-test-results": "Email Test Results", "email-test-results": "Testresultat för e-post",
"ready": "Redo", "ready": "Redo",
"not-ready": "Inte redo - Kontrollera miljövariabler", "not-ready": "Inte redo - Kontrollera miljövariabler",
"succeeded": "Lyckades", "succeeded": "Lyckades",
@ -707,16 +708,16 @@
"application-version-error-text": "Din nuvarande version ({0}) matchar inte den senaste utgåvan. Överväg att uppdatera till den senaste versionen ({1}).", "application-version-error-text": "Din nuvarande version ({0}) matchar inte den senaste utgåvan. Överväg att uppdatera till den senaste versionen ({1}).",
"mealie-is-up-to-date": "Mealie är uppdaterad", "mealie-is-up-to-date": "Mealie är uppdaterad",
"secure-site": "Säker webbplats", "secure-site": "Säker webbplats",
"secure-site-error-text": "Serve via localhost or secure with https. Clipboard and additional browser APIs may not work.", "secure-site-error-text": "Servera via localhost eller säker med https. Urklipp och ytterligare webbläsare API: er kanske inte fungerar.",
"secure-site-success-text": "Webbplatsen nås av localhost eller https", "secure-site-success-text": "Webbplatsen nås av localhost eller https",
"server-side-base-url": "Serverns bas-URL", "server-side-base-url": "Serverns bas-URL",
"server-side-base-url-error-text": "`BASE_URL` is still the default value on API Server. This will cause issues with notifications links generated on the server for emails, etc.", "server-side-base-url-error-text": "`BASE_URL` är fortfarande standardvärdet på API-servern. Detta kommer att orsaka problem med meddelanden som genereras på servern för e-postmeddelanden, etc.",
"server-side-base-url-success-text": "Server Side URL does not match the default", "server-side-base-url-success-text": "Serversidans URL matchar inte standard",
"ldap-ready": "LDAP Redo", "ldap-ready": "LDAP Redo",
"ldap-ready-error-text": "Not all LDAP Values are configured. This can be ignored if you are not using LDAP Authentication.", "ldap-ready-error-text": "Alla LDAP-värden är inte konfigurerade. Detta kan ignoreras om du inte använder LDAP-autentisering.",
"ldap-ready-success-text": "Required LDAP variables are all set.", "ldap-ready-success-text": "Alla obligatoriska LDAP-variabler är satta.",
"build": "Bygg", "build": "Bygg",
"recipe-scraper-version": "Recipe Scraper Version" "recipe-scraper-version": "Version av Recept-scraper"
}, },
"shopping-list": { "shopping-list": {
"all-lists": "Visa alla listor", "all-lists": "Visa alla listor",
@ -730,19 +731,19 @@
"food": "Mat", "food": "Mat",
"note": "Anteckning", "note": "Anteckning",
"label": "Etikett", "label": "Etikett",
"linked-item-warning": "This item is linked to one or more recipe. Adjusting the units or foods will yield unexpected results when adding or removing the recipe from this list.", "linked-item-warning": "Denna artikel är länkad till ett eller flera recept. Justering av enheter eller livsmedel ger oväntade resultat när du lägger till eller tar bort receptet från denna lista.",
"toggle-food": "Växla mat", "toggle-food": "Växla mat",
"manage-labels": "Hantera etiketter", "manage-labels": "Hantera etiketter",
"are-you-sure-you-want-to-delete-this-item": "Är du säker på att du vill ta bort detta objekt?", "are-you-sure-you-want-to-delete-this-item": "Är du säker på att du vill ta bort detta objekt?",
"copy-as-text": "Kopiera som text", "copy-as-text": "Kopiera som text",
"copy-as-markdown": "Kopiera som Markdown", "copy-as-markdown": "Kopiera som Markdown",
"delete-checked": "Ta bort markerade", "delete-checked": "Ta bort markerade",
"toggle-label-sort": "Toggle Label Sort", "toggle-label-sort": "Växla etikettsortering",
"reorder-labels": "Ordna om etiketter", "reorder-labels": "Ordna om etiketter",
"uncheck-all-items": "Avmarkera alla objekt", "uncheck-all-items": "Avmarkera alla objekt",
"check-all-items": "Markera alla objekt", "check-all-items": "Markera alla objekt",
"linked-recipes-count": "No Linked Recipes|One Linked Recipe|{count} Linked Recipes", "linked-recipes-count": "Inga länkade recept|Ett länkat recept|{count} länkade recept",
"items-checked-count": "No items checked|One item checked|{count} items checked", "items-checked-count": "Inga artiklar markerade|En artikel markerad|{count} artiklar markerade",
"no-label": "Ingen etikett", "no-label": "Ingen etikett",
"completed-on": "Slutförd på {date}" "completed-on": "Slutförd på {date}"
}, },
@ -876,7 +877,7 @@
"user-management": "Användarhantering", "user-management": "Användarhantering",
"reset-locked-users": "Återställ låsta användare", "reset-locked-users": "Återställ låsta användare",
"admin-user-creation": "Skapande av adminanvändare", "admin-user-creation": "Skapande av adminanvändare",
"admin-user-management": "Admin User Management", "admin-user-management": "Användarhantering",
"user-details": "Användarinformation", "user-details": "Användarinformation",
"user-name": "Användarnamn", "user-name": "Användarnamn",
"authentication-method": "Autentiseringsmetod", "authentication-method": "Autentiseringsmetod",
@ -907,8 +908,8 @@
"seed-dialog-text": "Fyll databasen med livsmedel baserade på ditt språk. Detta kommer att skapa 200+ vanliga livsmedel som kan användas för att organisera din databas. Livsmedlen översätts via ett gemenskapsinsats.", "seed-dialog-text": "Fyll databasen med livsmedel baserade på ditt språk. Detta kommer att skapa 200+ vanliga livsmedel som kan användas för att organisera din databas. Livsmedlen översätts via ett gemenskapsinsats.",
"seed-dialog-warning": "Du har redan några objekt i din databas. Denna åtgärd kommer inte att förena dubbletter, du kommer att behöva hantera dem manuellt.", "seed-dialog-warning": "Du har redan några objekt i din databas. Denna åtgärd kommer inte att förena dubbletter, du kommer att behöva hantera dem manuellt.",
"combine-food": "Kombinera mat", "combine-food": "Kombinera mat",
"source-food": "Source Food", "source-food": "Matens källa",
"target-food": "Target Food", "target-food": "Matens mål",
"create-food": "Skapa mat", "create-food": "Skapa mat",
"food-label": "Mat etikett", "food-label": "Mat etikett",
"edit-food": "Redigera mat", "edit-food": "Redigera mat",
@ -918,7 +919,7 @@
}, },
"units": { "units": {
"seed-dialog-text": "Fyll databasen med vanliga enheter baserade på ditt språk.", "seed-dialog-text": "Fyll databasen med vanliga enheter baserade på ditt språk.",
"combine-unit-description": "Combining the selected units will merge the Source Unit and Target Unit into a single unit. The {source-unit-will-be-deleted} and all of the references to the Source Unit will be updated to point to the Target Unit.", "combine-unit-description": "Genom att kombinera de valda enheterna slås källenheten och målenheten samman till en enda enhet. {source-unit-will-be-deleted} och alla referenser till enhetens källa kommer att uppdateras så att de pekar på enhetens mål.",
"combine-unit": "Kombinera enhet", "combine-unit": "Kombinera enhet",
"source-unit": "Källenhet", "source-unit": "Källenhet",
"target-unit": "Målenhet", "target-unit": "Målenhet",
@ -954,7 +955,7 @@
"recipe-data": "Recept data", "recipe-data": "Recept data",
"recipe-data-description": "Använd det här avsnittet för att hantera data som är kopplade till dina recept. Du kan utföra flera massåtgärder på dina recept, inklusive export, radering, taggning och tilldelning av kategorier.", "recipe-data-description": "Använd det här avsnittet för att hantera data som är kopplade till dina recept. Du kan utföra flera massåtgärder på dina recept, inklusive export, radering, taggning och tilldelning av kategorier.",
"recipe-columns": "Receptkolumner", "recipe-columns": "Receptkolumner",
"data-exports-description": "This section provides links to available exports that are ready to download. These exports do expire, so be sure to grab them while they're still available.", "data-exports-description": "I det här avsnittet finns länkar till tillgängliga exporter som är redo att laddas ner. Dessa exporter upphör att gälla, så se till att hämta dem medan de fortfarande är tillgängliga.",
"data-exports": "Dataexport", "data-exports": "Dataexport",
"tag": "Tagg", "tag": "Tagg",
"categorize": "Kategorisera", "categorize": "Kategorisera",
@ -963,14 +964,14 @@
"categorize-recipes": "Kategorisera recept", "categorize-recipes": "Kategorisera recept",
"export-recipes": "Exportera recept", "export-recipes": "Exportera recept",
"delete-recipes": "Radera recept", "delete-recipes": "Radera recept",
"source-unit-will-be-deleted": "Source Unit will be deleted" "source-unit-will-be-deleted": "Källenheten kommer att raderas"
}, },
"create-alias": "Skapa alias", "create-alias": "Skapa alias",
"manage-aliases": "Manage Aliases", "manage-aliases": "Hantera alias",
"seed-data": "Exempeldata", "seed-data": "Exempeldata",
"seed": "Seed", "seed": "Frö",
"data-management": "Datahantering", "data-management": "Datahantering",
"data-management-description": "Select which data set you want to make changes to.", "data-management-description": "Välj vilken data du vill göra ändringar i.",
"select-data": "Välj data", "select-data": "Välj data",
"select-language": "Välj språk", "select-language": "Välj språk",
"columns": "Kolumner", "columns": "Kolumner",
@ -978,7 +979,7 @@
"categories": { "categories": {
"edit-category": "Redigera kategori", "edit-category": "Redigera kategori",
"new-category": "Ny kategori", "new-category": "Ny kategori",
"category-data": "Category Data" "category-data": "Kategoridata"
}, },
"tags": { "tags": {
"new-tag": "Ny Tag", "new-tag": "Ny Tag",
@ -988,7 +989,7 @@
"tools": { "tools": {
"new-tool": "Nytt verktyg", "new-tool": "Nytt verktyg",
"edit-tool": "Lägg till/ta bort verktyg", "edit-tool": "Lägg till/ta bort verktyg",
"tool-data": "Tool Data" "tool-data": "Verktygsdata"
} }
}, },
"user-registration": { "user-registration": {
@ -1039,52 +1040,52 @@
"demo_password": "Lösenord: {password}" "demo_password": "Lösenord: {password}"
}, },
"ocr-editor": { "ocr-editor": {
"ocr-editor": "Ocr editor", "ocr-editor": "Ocr redigerare",
"toolbar": "Toolbar", "toolbar": "Verktygsfält",
"selection-mode": "Markeringsläge", "selection-mode": "Markeringsläge",
"pan-and-zoom-picture": "Pan and zoom picture", "pan-and-zoom-picture": "Panorera och zooma bild",
"split-text": "Dela text", "split-text": "Dela text",
"preserve-line-breaks": "Preserve original line breaks", "preserve-line-breaks": "Bevara ursprungliga radbrytningar",
"split-by-block": "Split by text block", "split-by-block": "Dela med textblock",
"flatten": "Flatten regardless of original formating", "flatten": "Platta till oavsett ursprunglig formatering",
"help": { "help": {
"help": "Hjälp", "help": "Hjälp",
"mouse-modes": "Mouse modes", "mouse-modes": "Musläge",
"selection-mode": "Markeringsläge (standard)", "selection-mode": "Markeringsläge (standard)",
"selection-mode-desc": "The selection mode is the main mode that can be used to enter data:", "selection-mode-desc": "Urvalsläget är det huvudsakliga läget som kan användas för att mata in data:",
"selection-mode-steps": { "selection-mode-steps": {
"draw": "Draw a rectangle on the text you want to select.", "draw": "Rita en rektangel på den text du vill markera.",
"click": "Click on any field on the right and then click back on the rectangle above the image.", "click": "Klicka på valfritt fält till höger och klicka sedan tillbaka på rektangeln ovanför bilden.",
"result": "The selected text will appear inside the previously selected field." "result": "Den markerade texten visas i det tidigare markerade fältet."
}, },
"pan-and-zoom-mode": "Pan and Zoom Mode", "pan-and-zoom-mode": "Panorerings- och zoomläge",
"pan-and-zoom-desc": "Select pan and zoom by clicking the icon. This mode allows to zoom inside the image and move around to make using big images easier.", "pan-and-zoom-desc": "Välj panorera och zooma genom att klicka på ikonen. I det här läget kan du zooma in i bilden och flytta runt den för att göra det enklare att använda stora bilder.",
"split-text-mode": "Split Text modes", "split-text-mode": "Dela upp textlägen",
"split-modes": { "split-modes": {
"line-mode": "Line mode (default)", "line-mode": "Radläge (standard)",
"line-mode-desc": "In line mode, the text will be propagated by keeping the original line breaks. This mode is useful when using bulk add on a list of ingredients where one ingredient is one line.", "line-mode-desc": "I radläget kommer texten att spridas genom att behålla de ursprungliga radbrytningarna. Detta läge är användbart när du använder bulk add på en lista med ingredienser där en ingrediens är en rad.",
"block-mode": "Block mode", "block-mode": "Block läge",
"block-mode-desc": "In block mode, the text will be split in blocks. This mode is useful when bulk adding instructions that are usually written in paragraphs.", "block-mode-desc": "I blockläget kommer texten att delas upp i block. Detta läge är användbart när du lägger till instruktioner som vanligtvis är skrivna i stycken.",
"flat-mode": "Flat mode", "flat-mode": "Platt läge",
"flat-mode-desc": "In flat mode, the text will be added to the selected recipe field with no line breaks." "flat-mode-desc": "I platt läge läggs texten till i det valda receptfältet utan radbrytningar."
} }
} }
}, },
"admin": { "admin": {
"maintenance": { "maintenance": {
"storage-details": "Storage Details", "storage-details": "Lagringsdetaljer",
"page-title": "Site Maintenance", "page-title": "Underhåll av webbplatsen",
"summary-title": "Summary", "summary-title": "Sammanfattning",
"button-label-get-summary": "Get Summary", "button-label-get-summary": "Hämta sammanfattning",
"button-label-open-details": "Details", "button-label-open-details": "Detaljer",
"info-description-data-dir-size": "Data Directory Size", "info-description-data-dir-size": "Datakatalogens storlek",
"info-description-log-file-size": "Storlek på loggfil", "info-description-log-file-size": "Storlek på loggfil",
"info-description-cleanable-directories": "Rensbara mappar", "info-description-cleanable-directories": "Rensbara mappar",
"info-description-cleanable-images": "Rensbara bilder", "info-description-cleanable-images": "Rensbara bilder",
"storage": { "storage": {
"title-temporary-directory": "Tillfällig mapp (.temp)", "title-temporary-directory": "Tillfällig mapp (.temp)",
"title-backups-directory": "Backups Directory (backups)", "title-backups-directory": "Katalog för säkerhetskopior (säkerhetskopior)",
"title-groups-directory": "Groups Directory (groups)", "title-groups-directory": "Gruppkatalog (grupper)",
"title-recipes-directory": "Recipes Directory (recipes)", "title-recipes-directory": "Recipes Directory (recipes)",
"title-user-directory": "User Directory (user)" "title-user-directory": "User Directory (user)"
}, },

View File

@ -198,7 +198,8 @@
"refresh": "Yenile", "refresh": "Yenile",
"upload-file": "Dosya Yükle", "upload-file": "Dosya Yükle",
"created-on-date": "{0} tarihinde oluşturuldu", "created-on-date": "{0} tarihinde oluşturuldu",
"unsaved-changes": "Kaydedilmemiş değişiklikleriniz mevcut. Ayrılmadan önce kaydetmek ister misiniz? Kaydetmek için Tamam'ı, değişiklikleri iptal etmek için İptal'i seçin." "unsaved-changes": "Kaydedilmemiş değişiklikleriniz mevcut. Ayrılmadan önce kaydetmek ister misiniz? Kaydetmek için Tamam'ı, değişiklikleri iptal etmek için İptal'i seçin.",
"clipboard-copy-failure": "Panoya kopyalanamadı."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "<b>{groupName}<b/>'i silmek istediğine emin misin?", "are-you-sure-you-want-to-delete-the-group": "<b>{groupName}<b/>'i silmek istediğine emin misin?",

View File

@ -198,7 +198,8 @@
"refresh": "Оновити", "refresh": "Оновити",
"upload-file": "Вивантажити файл", "upload-file": "Вивантажити файл",
"created-on-date": "Створено: {0}", "created-on-date": "Створено: {0}",
"unsaved-changes": "У вас є незбережені зміни. Ви хочете зберегти їх перед виходом? Гаразд, щоб зберегти, Скасувати, щоб скасувати." "unsaved-changes": "У вас є незбережені зміни. Ви хочете зберегти їх перед виходом? Гаразд, щоб зберегти, Скасувати, щоб скасувати.",
"clipboard-copy-failure": "Не вдалося скопіювати до буфера обміну."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Ви дійсно бажаєте видалити <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Ви дійсно бажаєте видалити <b>{groupName}<b/>?",

View File

@ -198,7 +198,8 @@
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "upload-file": "Upload File",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",

File diff suppressed because it is too large Load Diff

View File

@ -177,28 +177,29 @@
"run": "運行", "run": "運行",
"menu": "選單", "menu": "選單",
"a-name-is-required": "名稱必填", "a-name-is-required": "名稱必填",
"delete-with-name": "Delete {name}", "delete-with-name": "刪除 {name}",
"confirm-delete-generic-with-name": "Are you sure you want to delete this {name}?", "confirm-delete-generic-with-name": "Are you sure you want to delete this {name}?",
"confirm-delete-own-admin-account": "Please note that you are trying to delete your own admin account! This action cannot be undone and will permanently delete your account?", "confirm-delete-own-admin-account": "Please note that you are trying to delete your own admin account! This action cannot be undone and will permanently delete your account?",
"organizer": "Organizer", "organizer": "Organizer",
"transfer": "Transfer", "transfer": "Transfer",
"copy": "複製", "copy": "複製",
"color": "Color", "color": "色彩",
"timestamp": "時間戳", "timestamp": "時間戳",
"last-made": "最後製作的", "last-made": "最後製作的",
"learn-more": "Learn More", "learn-more": "學習更多",
"this-feature-is-currently-inactive": "該功能目前處於非活動狀態", "this-feature-is-currently-inactive": "該功能目前處於非活動狀態",
"clipboard-not-supported": "Clipboard not supported", "clipboard-not-supported": "Clipboard not supported",
"copied-to-clipboard": "Copied to clipboard", "copied-to-clipboard": "複製到剪貼簿",
"your-browser-does-not-support-clipboard": "Your browser does not support clipboard", "your-browser-does-not-support-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": "No item copied to clipboard|One item copied to clipboard|Copied {count} items to clipboard",
"actions": "Actions", "actions": "Actions",
"selected-count": "Selected: {count}", "selected-count": "Selected: {count}",
"export-all": "Export All", "export-all": "Export All",
"refresh": "Refresh", "refresh": "更新",
"upload-file": "上傳文件", "upload-file": "上傳文件",
"created-on-date": "Created on: {0}", "created-on-date": "Created on: {0}",
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." "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."
}, },
"group": { "group": {
"are-you-sure-you-want-to-delete-the-group": "確定要刪除<b>{groupName}<b/>", "are-you-sure-you-want-to-delete-the-group": "確定要刪除<b>{groupName}<b/>",
@ -224,7 +225,7 @@
"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-description": "Sets your group and all recipes defaults to private. You can always change this later."
}, },
"manage-members": "Manage Members", "manage-members": "管理成員",
"manage-members-description": "Manage the permissions of the members in your groups. {manage} allows the user to access the data-management page {invite} allows the user to generate invitation links for other users. Group owners cannot change their own permissions.", "manage-members-description": "Manage the permissions of the members in your groups. {manage} allows the user to access the data-management page {invite} allows the user to generate invitation links for other users. Group owners cannot change their own permissions.",
"manage": "Manage", "manage": "Manage",
"invite": "邀請", "invite": "邀請",

View File

@ -4,9 +4,7 @@
<v-banner v-if="isDemo" sticky> <v-banner v-if="isDemo" sticky>
<div class="text-center"> <div class="text-center">
<b> {{ $t("demo.info_message_with_version", { version: version }) }} </b> | <b> {{ $t("demo.info_message_with_version", { version: version }) }} </b>
{{ $t("demo.demo_username", { username: "changeme@example.com" }) }} |
{{ $t("demo.demo_password", { password: "demo" }) }}
</div> </div>
</v-banner> </v-banner>

View File

@ -23,7 +23,6 @@ import { MultiPurposeLabelsApi } from "./user/group-multiple-purpose-labels";
import { GroupEventNotifierApi } from "./user/group-event-notifier"; import { GroupEventNotifierApi } from "./user/group-event-notifier";
import { MealPlanRulesApi } from "./user/group-mealplan-rules"; import { MealPlanRulesApi } from "./user/group-mealplan-rules";
import { GroupDataSeederApi } from "./user/group-seeder"; import { GroupDataSeederApi } from "./user/group-seeder";
import { OcrAPI } from "./user/ocr";
import { ApiRequestInstance } from "~/lib/api/types/non-generated"; import { ApiRequestInstance } from "~/lib/api/types/non-generated";
export class UserApiClient { export class UserApiClient {
@ -52,7 +51,6 @@ export class UserApiClient {
public groupEventNotifier: GroupEventNotifierApi; public groupEventNotifier: GroupEventNotifierApi;
public upload: UploadFile; public upload: UploadFile;
public seeders: GroupDataSeederApi; public seeders: GroupDataSeederApi;
public ocr: OcrAPI;
constructor(requests: ApiRequestInstance) { constructor(requests: ApiRequestInstance) {
// Recipes // Recipes
@ -91,9 +89,6 @@ export class UserApiClient {
this.bulk = new BulkActionsAPI(requests); this.bulk = new BulkActionsAPI(requests);
this.groupEventNotifier = new GroupEventNotifierApi(requests); this.groupEventNotifier = new GroupEventNotifierApi(requests);
// ocr
this.ocr = new OcrAPI(requests);
Object.freeze(this); Object.freeze(this);
} }
} }

View File

@ -1,25 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
/* This file was automatically generated from pydantic models by running pydantic2ts.
/* Do not modify it by hand - just update the pydantic models and then re-run the script
*/
export interface OcrAssetReq {
recipeSlug: string;
assetName: string;
}
export interface OcrTsvResponse {
level?: number;
pageNum?: number;
blockNum?: number;
parNum?: number;
lineNum?: number;
wordNum?: number;
left?: number;
top?: number;
width?: number;
height?: number;
conf?: number;
text?: string;
}

View File

@ -244,7 +244,6 @@ export interface Recipe {
extras?: { extras?: {
[k: string]: unknown; [k: string]: unknown;
}; };
isOcrRecipe?: boolean;
comments?: RecipeCommentOut[]; comments?: RecipeCommentOut[];
} }
export interface RecipeTool { export interface RecipeTool {

View File

@ -1,16 +0,0 @@
import { BaseAPI } from "../base/base-clients";
const prefix = "/api";
export class OcrAPI extends BaseAPI {
// Currently unused in favor for the endpoint using asset names
async fileToTsv(file: File) {
const formData = new FormData();
formData.append("file", file);
return await this.requests.post(`${prefix}/ocr/file-to-tsv`, formData);
}
async assetToTsv(recipeSlug: string, assetName: string) {
return await this.requests.post(`${prefix}/ocr/asset-to-tsv`, { recipeSlug, assetName });
}
}

View File

@ -38,7 +38,6 @@ const routes = {
recipesCategory: `${prefix}/recipes/category`, recipesCategory: `${prefix}/recipes/category`,
recipesParseIngredient: `${prefix}/parser/ingredient`, recipesParseIngredient: `${prefix}/parser/ingredient`,
recipesParseIngredients: `${prefix}/parser/ingredients`, recipesParseIngredients: `${prefix}/parser/ingredients`,
recipesCreateFromOcr: `${prefix}/recipes/create-ocr`,
recipesTimelineEvent: `${prefix}/recipes/timeline/events`, recipesTimelineEvent: `${prefix}/recipes/timeline/events`,
recipesRecipeSlug: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}`, recipesRecipeSlug: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}`,
@ -159,15 +158,6 @@ export class RecipeAPI extends BaseCRUDAPI<CreateRecipe, Recipe, Recipe> {
return `${routes.recipesRecipeSlugExportZip(recipeSlug)}?token=${token}`; return `${routes.recipesRecipeSlugExportZip(recipeSlug)}?token=${token}`;
} }
async createFromOcr(file: File, makeFileRecipeImage: boolean) {
const formData = new FormData();
formData.append("file", file);
formData.append("extension", file.name.split(".").pop() ?? "");
formData.append("makefilerecipeimage", String(makeFileRecipeImage));
return await this.requests.post(routes.recipesCreateFromOcr, formData);
}
async updateLastMade(recipeSlug: string, timestamp: string) { async updateLastMade(recipeSlug: string, timestamp: string) {
return await this.requests.patch<Recipe, RecipeLastMade>(routes.recipesSlugLastMade(recipeSlug), { timestamp }) return await this.requests.patch<Recipe, RecipeLastMade>(routes.recipesSlugLastMade(recipeSlug), { timestamp })
} }

View File

@ -1,51 +0,0 @@
<template>
<div>
<RecipeOcrEditorPage v-if="recipe" :recipe="recipe" />
</div>
</template>
<script lang="ts">
import { defineComponent, useRoute } from "@nuxtjs/composition-api";
import RecipeOcrEditorPage from "~/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue";
import { useRecipe } from "~/composables/recipes";
export default defineComponent({
components: { RecipeOcrEditorPage },
setup() {
const route = useRoute();
const slug = route.value.params.slug;
const { recipe, loading } = useRecipe(slug);
return {
recipe,
loading,
};
},
});
</script>
<style lang="css">
.ghost {
opacity: 0.5;
}
body {
background: #eee;
}
canvas {
background: white;
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.2);
width: 100%;
image-rendering: optimizeQuality;
}
.box {
position: absolute;
border: 2px #90ee90 solid;
background-color: #90ee90;
z-index: 3;
}
</style>

View File

@ -52,11 +52,6 @@ export default defineComponent({
text: i18n.tc("recipe.import-with-zip"), text: i18n.tc("recipe.import-with-zip"),
value: "zip", value: "zip",
}, },
{
icon: $globals.icons.fileImage,
text: i18n.tc("recipe.create-recipe-from-an-image"),
value: "ocr",
},
{ {
icon: $globals.icons.link, icon: $globals.icons.link,
text: i18n.tc("recipe.bulk-url-import"), text: i18n.tc("recipe.bulk-url-import"),

View File

@ -1,85 +0,0 @@
<template>
<div>
<v-card-title class="headline"> {{ $t('recipe.create-recipe-from-an-image') }} </v-card-title>
<v-card-text>
{{ $t('recipe.create-a-recipe-by-uploading-a-scan') }}
<v-form ref="domCreateByOcr"> </v-form>
</v-card-text>
<v-card-actions class="justify-center">
<v-file-input
v-model="imageUpload"
accept=".png"
label="recipe.png"
filled
clearable
class="rounded-lg mt-2"
rounded
truncate-length="100"
:hint="$t('recipe.upload-a-png-image-from-a-recipe-book')"
persistent-hint
prepend-icon=""
:prepend-inner-icon="$globals.icons.fileImage"
/>
</v-card-actions>
<v-card-actions class="justify-center">
<v-checkbox v-model="makeFileRecipeImage" :label="$t('new-recipe.make-recipe-image')" />
</v-card-actions>
<v-card-actions class="justify-center">
<div style="width: 250px">
<BaseButton :disabled="imageUpload === null" large rounded block :loading="loading" @click="createByOcr" />
</div>
</v-card-actions>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, ref, useRouter, computed, useContext, useRoute } from "@nuxtjs/composition-api";
import { AxiosResponse } from "axios";
import { useUserApi } from "~/composables/api";
import { validators } from "~/composables/use-validators";
import { VForm } from "~/types/vuetify";
export default defineComponent({
setup() {
const state = reactive({
error: false,
loading: false,
makeFileRecipeImage: false,
});
const { $auth } = useContext();
const route = useRoute();
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
const api = useUserApi();
const router = useRouter();
const imageUpload = ref<File | null>(null);
function handleResponse(response: AxiosResponse<string> | null) {
if (response?.status !== 201) {
state.error = true;
state.loading = false;
return;
}
router.push(`/g/${groupSlug.value}/r/${response.data}/ocr-editor`);
}
const domCreateByOcr = ref<VForm | null>(null);
async function createByOcr() {
if (imageUpload.value === null) return; // Should never be true due to circumstances
state.loading = true;
const { response } = await api.recipes.createFromOcr(imageUpload.value, state.makeFileRecipeImage);
// @ts-ignore returns a string and not a full Recipe
handleResponse(response);
}
return {
domCreateByOcr,
createByOcr,
...toRefs(state),
validators,
imageUpload,
};
},
});
</script>

View File

@ -1,73 +0,0 @@
import { OcrTsvResponse } from "~/lib/api/types/ocr";
import { Recipe } from "~/lib/api/types/recipe";
export type CanvasRect = {
startX: number;
startY: number;
w: number;
h: number;
};
export type ImagePosition = {
sx: number;
sy: number;
sWidth: number;
sHeight: number;
dx: number;
dy: number;
dWidth: number;
dHeight: number;
scale: number;
panStartPoint: {
x: number;
y: number;
};
};
export type Mouse = {
current: {
x: number;
y: number;
};
down: boolean;
};
// https://stackoverflow.com/questions/58434389/export typescript-deep-keyof-of-a-nested-object/58436959#58436959
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];
type Join<K, P> = K extends string | number
? P extends string | number
? `${K}${"" extends P ? "" : "."}${P}`
: never
: never;
export type Leaves<T, D extends number = 10> = [D] extends [never]
? never
: T extends object
? { [K in keyof T]-?: Join<K, Leaves<T[K], Prev[D]>> }[keyof T]
: "";
export type Paths<T, D extends number = 10> = [D] extends [never]
? never
: T extends object
? {
[K in keyof T]-?: K extends string | number ? `${K}` | Join<K, Paths<T[K], Prev[D]>> : never;
}[keyof T]
: "";
export type SelectedRecipeLeaves = Leaves<Recipe>;
export type CanvasModes = "selection" | "panAndZoom";
export type SelectedTextSplitModes = keyof OcrTsvResponse | "flatten";
export type ToolbarIcons<T extends string> = {
sectionTitle: string;
eventHandler(mode: T): void;
highlight: T;
icons: {
name: T;
icon: string;
tooltip: string;
}[];
}[];

View File

@ -11,7 +11,7 @@
"user": { "user": {
"user-updated": "Bruker oppdatert", "user-updated": "Bruker oppdatert",
"password-updated": "Passord oppdatert", "password-updated": "Passord oppdatert",
"invalid-current-password": "Feil nåværende passord", "invalid-current-password": "Nåværende passord er feil",
"ldap-update-password-unavailable": "Kan ikke oppdatere passordet, brukeren kontrolleres av LDAP" "ldap-update-password-unavailable": "Kan ikke oppdatere passordet, brukeren kontrolleres av LDAP"
}, },
"group": { "group": {
@ -29,7 +29,7 @@
"generic-updated": "{name} ble oppdatert", "generic-updated": "{name} ble oppdatert",
"generic-created-with-url": "{name} har blitt opprettet, {url}", "generic-created-with-url": "{name} har blitt opprettet, {url}",
"generic-updated-with-url": "{name} har blitt oppdatert, {url}", "generic-updated-with-url": "{name} har blitt oppdatert, {url}",
"generic-duplicated": "Det er blitt laget kopi av {name}", "generic-duplicated": "{name} har blitt duplisert",
"generic-deleted": "{name} har blitt slettet" "generic-deleted": "{name} har blitt slettet"
} }
} }

View File

@ -23,7 +23,7 @@
"broccolini": "broccolini", "broccolini": "broccolini",
"broccoli-rabe": "broccoli rabe", "broccoli-rabe": "broccoli rabe",
"brussels-sprouts": "λαχανάκια Βρυξελλών", "brussels-sprouts": "λαχανάκια Βρυξελλών",
"cabbage": "cabbage", "cabbage": "λάχανο",
"cauliflower": "κουνουπίδι", "cauliflower": "κουνουπίδι",
"chinese-leaves": "κινέζικα φύλλα", "chinese-leaves": "κινέζικα φύλλα",
"collard-greens": "collard greens", "collard-greens": "collard greens",
@ -52,34 +52,34 @@
"chicory": "chicory", "chicory": "chicory",
"chilli-peppers": "chilli peppers", "chilli-peppers": "chilli peppers",
"chives": "chives", "chives": "chives",
"chocolate": "chocolate", "chocolate": "σοκολάτα",
"cilantro": "cilantro", "cilantro": "κόλιανδρος",
"cinnamon": "cinnamon", "cinnamon": "κανέλα",
"clarified-butter": "clarified butter", "clarified-butter": "clarified butter",
"coconut": "coconut", "coconut": "καρύδα",
"coconut-milk": "coconut milk", "coconut-milk": "γάλα καρύδας",
"coffee": "coffee", "coffee": "καφές",
"confectioners-sugar": "confectioners' sugar", "confectioners-sugar": "confectioners' sugar",
"coriander": "coriander", "coriander": "κόλιανδρος",
"corn": "corn", "corn": "καλαμπόκι",
"corn-syrup": "corn syrup", "corn-syrup": "corn syrup",
"cottonseed-oil": "cottonseed oil", "cottonseed-oil": "cottonseed oil",
"courgette": "courgette", "courgette": "courgette",
"cream-of-tartar": "cream of tartar", "cream-of-tartar": "cream of tartar",
"cucumber": "cucumber", "cucumber": "αγγούρι",
"cumin": "cumin", "cumin": "κύμινο",
"daikon": "daikon", "daikon": "daikon",
"dairy-products-and-dairy-substitutes": "dairy products and dairy substitutes", "dairy-products-and-dairy-substitutes": "dairy products and dairy substitutes",
"eggs": "eggs", "eggs": "αυγά",
"ghee": "ghee", "ghee": "ghee",
"milk": "milk", "milk": "γάλα",
"dandelion": "dandelion", "dandelion": "dandelion",
"demerara-sugar": "demerara sugar", "demerara-sugar": "demerara sugar",
"dough": "dough", "dough": "ζυμάρι",
"edible-cactus": "edible cactus", "edible-cactus": "edible cactus",
"eggplant": "eggplant", "eggplant": "μελιτζάνα",
"endive": "endive", "endive": "endive",
"fats": "fats", "fats": "λιπαρά",
"speck": "speck", "speck": "speck",
"fava-beans": "fava beans", "fava-beans": "fava beans",
"fiddlehead": "fiddlehead", "fiddlehead": "fiddlehead",

View File

@ -36,7 +36,7 @@
"butternut-pumpkin": "flaskegresskar", "butternut-pumpkin": "flaskegresskar",
"butternut-squash": "butternut squash", "butternut-squash": "butternut squash",
"cactus-edible": "kaktus, spiselig", "cactus-edible": "kaktus, spiselig",
"calabrese": "calabrese Fersk Pølse", "calabrese": "calabrese",
"cannabis": "cannabis", "cannabis": "cannabis",
"capsicum": "chilipepper", "capsicum": "chilipepper",
"caraway": "karve", "caraway": "karve",
@ -45,7 +45,7 @@
"cayenne-pepper": "kayenne pepper", "cayenne-pepper": "kayenne pepper",
"celeriac": "sellerirot", "celeriac": "sellerirot",
"celery": "selleri", "celery": "selleri",
"cereal-grains": "frokostblanding korn", "cereal-grains": "frokostblandingkorn",
"rice": "ris", "rice": "ris",
"chard": "bladbete", "chard": "bladbete",
"cheese": "ost", "cheese": "ost",

View File

@ -3,22 +3,22 @@
"name": "Produce" "name": "Produce"
}, },
{ {
"name": "Grains" "name": "Σιτηρά"
}, },
{ {
"name": "Fruits" "name": "Φρούτα"
}, },
{ {
"name": "Vegetables" "name": "Λαχανικά"
}, },
{ {
"name": "Meat" "name": "Κρέας"
}, },
{ {
"name": "Seafood" "name": "Θαλασσινά"
}, },
{ {
"name": "Beverages" "name": "Ποτά"
}, },
{ {
"name": "Baked Goods" "name": "Baked Goods"
@ -33,10 +33,10 @@
"name": "Confectionary" "name": "Confectionary"
}, },
{ {
"name": "Dairy Products" "name": "Γαλακτοκομικά"
}, },
{ {
"name": "Frozen Foods" "name": "Κατεψυγμένα Φαγητά"
}, },
{ {
"name": "Health Foods" "name": "Health Foods"
@ -48,18 +48,18 @@
"name": "Meat Products" "name": "Meat Products"
}, },
{ {
"name": "Snacks" "name": "Σνακ"
}, },
{ {
"name": "Spices" "name": "Μπαχαρικά"
}, },
{ {
"name": "Sweets" "name": "Γλυκά"
}, },
{ {
"name": "Alcohol" "name": "Αλκοόλ"
}, },
{ {
"name": "Other" "name": "Άλλα"
} }
] ]

View File

@ -1,6 +1,6 @@
[ [
{ {
"name": "Produce" "name": "农产品"
}, },
{ {
"name": "谷物" "name": "谷物"
@ -30,7 +30,7 @@
"name": "调味品" "name": "调味品"
}, },
{ {
"name": "Confectionary" "name": "糖果类"
}, },
{ {
"name": "乳制品" "name": "乳制品"
@ -54,7 +54,7 @@
"name": "调味品" "name": "调味品"
}, },
{ {
"name": "甜味剂" "name": "甜"
}, },
{ {
"name": "酒类" "name": "酒类"

View File

@ -2,17 +2,17 @@
"teaspoon": { "teaspoon": {
"name": "teaspoon", "name": "teaspoon",
"description": "", "description": "",
"abbreviation": "tsp" "abbreviation": "κ.γ."
}, },
"tablespoon": { "tablespoon": {
"name": "tablespoon", "name": "tablespoon",
"description": "", "description": "",
"abbreviation": "tbsp" "abbreviation": "κ.σ."
}, },
"cup": { "cup": {
"name": "cup", "name": "φλιτζάνι",
"description": "", "description": "",
"abbreviation": "cup" "abbreviation": "φλ."
}, },
"fluid-ounce": { "fluid-ounce": {
"name": "fluid ounce", "name": "fluid ounce",
@ -42,7 +42,7 @@
"liter": { "liter": {
"name": "λίτρο", "name": "λίτρο",
"description": "", "description": "",
"abbreviation": "λ" "abbreviation": "l"
}, },
"pound": { "pound": {
"name": "pound", "name": "pound",
@ -57,17 +57,17 @@
"gram": { "gram": {
"name": "γραμ", "name": "γραμ",
"description": "", "description": "",
"abbreviation": "γ" "abbreviation": "γρ."
}, },
"kilogram": { "kilogram": {
"name": "κιλό", "name": "κιλό",
"description": "", "description": "",
"abbreviation": "κιλ" "abbreviation": "kg"
}, },
"milligram": { "milligram": {
"name": "χιλιοστόγραμμο", "name": "χιλιοστόγραμμο",
"description": "", "description": "",
"abbreviation": "μιλιγκράμ" "abbreviation": "mg"
}, },
"splash": { "splash": {
"name": "splash", "name": "splash",

View File

@ -15,17 +15,17 @@
"abbreviation": "kopp" "abbreviation": "kopp"
}, },
"fluid-ounce": { "fluid-ounce": {
"name": "us væske unse", "name": "væskeunse",
"description": "", "description": "",
"abbreviation": "fl oz" "abbreviation": "fl oz"
}, },
"pint": { "pint": {
"name": "halvliter", "name": "pint",
"description": "", "description": "",
"abbreviation": "pt" "abbreviation": "pt"
}, },
"quart": { "quart": {
"name": "quart", "name": "kvart",
"description": "", "description": "",
"abbreviation": "qt" "abbreviation": "qt"
}, },
@ -60,27 +60,27 @@
"abbreviation": "g" "abbreviation": "g"
}, },
"kilogram": { "kilogram": {
"name": "kilo", "name": "kilogram",
"description": "", "description": "",
"abbreviation": "kg" "abbreviation": "kg"
}, },
"milligram": { "milligram": {
"name": "mg", "name": "milligram",
"description": "", "description": "",
"abbreviation": "mg" "abbreviation": "mg"
}, },
"splash": { "splash": {
"name": "splash", "name": "skvett",
"description": "", "description": "",
"abbreviation": "" "abbreviation": ""
}, },
"dash": { "dash": {
"name": "dash", "name": "klype",
"description": "", "description": "",
"abbreviation": "" "abbreviation": ""
}, },
"serving": { "serving": {
"name": "servering", "name": "porsjon",
"description": "", "description": "",
"abbreviation": "" "abbreviation": ""
}, },

View File

@ -7,7 +7,6 @@ from . import (
comments, comments,
explore, explore,
groups, groups,
ocr,
organizers, organizers,
parser, parser,
recipe, recipe,
@ -32,4 +31,3 @@ router.include_router(unit_and_foods.router)
router.include_router(admin.router) router.include_router(admin.router)
router.include_router(validators.router) router.include_router(validators.router)
router.include_router(explore.router) router.include_router(explore.router)
router.include_router(ocr.router)

View File

@ -1,7 +0,0 @@
from fastapi import APIRouter
from . import pytesseract
router = APIRouter(prefix="/ocr")
router.include_router(pytesseract.router)

View File

@ -1,37 +0,0 @@
from fastapi import APIRouter, File
from mealie.routes._base import BaseUserController, controller
from mealie.schema.ocr.ocr import OcrAssetReq, OcrTsvResponse
from mealie.services.ocr.pytesseract import OcrService
from mealie.services.recipe.recipe_data_service import RecipeDataService
from mealie.services.recipe.recipe_service import RecipeService
router = APIRouter()
@controller(router)
class OCRController(BaseUserController):
def __init__(self):
self.ocr_service = OcrService()
@router.post("/", response_model=str)
def image_to_string(self, file: bytes = File(...)):
return self.ocr_service.image_to_string(file)
@router.post("/file-to-tsv", response_model=list[OcrTsvResponse])
def file_to_tsv(self, file: bytes = File(...)):
tsv = self.ocr_service.image_to_tsv(file)
return self.ocr_service.format_tsv_output(tsv)
@router.post("/asset-to-tsv", response_model=list[OcrTsvResponse])
def asset_to_tsv(self, req: OcrAssetReq):
recipe_service = RecipeService(self.repos, self.user, self.group)
recipe = recipe_service._get_recipe(req.recipe_slug)
if recipe.id is None:
return []
data_service = RecipeDataService(recipe.id, recipe.group_id)
asset_path = data_service.dir_assets.joinpath(req.asset_name)
file = open(asset_path, "rb")
tsv = self.ocr_service.image_to_tsv(file.read())
return self.ocr_service.format_tsv_output(tsv)

View File

@ -1,7 +1,7 @@
from functools import cached_property from functools import cached_property
from pathlib import Path from pathlib import Path
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends, HTTPException
from mealie.core.dependencies.dependencies import temporary_zip_path from mealie.core.dependencies.dependencies import temporary_zip_path
from mealie.core.security import create_file_token from mealie.core.security import create_file_token
@ -50,6 +50,10 @@ class RecipeBulkActionsController(BaseUserController):
@router.get("/export/download") @router.get("/export/download")
def get_exported_data_token(self, path: Path): def get_exported_data_token(self, path: Path):
"""Returns a token to download a file""" """Returns a token to download a file"""
path = Path(path).resolve()
if not path.is_relative_to(self.folders.DATA_DIR):
raise HTTPException(400, "path must be relative to data directory")
return {"fileToken": create_file_token(path)} return {"fileToken": create_file_token(path)}

View File

@ -27,10 +27,7 @@ from mealie.schema.make_dependable import make_dependable
from mealie.schema.recipe import Recipe, RecipeImageTypes, ScrapeRecipe from mealie.schema.recipe import Recipe, RecipeImageTypes, ScrapeRecipe
from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipeLastMade, RecipeSummary from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipeLastMade, RecipeSummary
from mealie.schema.recipe.recipe_asset import RecipeAsset from mealie.schema.recipe.recipe_asset import RecipeAsset
from mealie.schema.recipe.recipe_ingredient import RecipeIngredient
from mealie.schema.recipe.recipe_scraper import ScrapeRecipeTest from mealie.schema.recipe.recipe_scraper import ScrapeRecipeTest
from mealie.schema.recipe.recipe_settings import RecipeSettings
from mealie.schema.recipe.recipe_step import RecipeStep
from mealie.schema.recipe.request_helpers import RecipeDuplicate, RecipeZipTokenResponse, UpdateImageResponse from mealie.schema.recipe.request_helpers import RecipeDuplicate, RecipeZipTokenResponse, UpdateImageResponse
from mealie.schema.response import PaginationBase, PaginationQuery from mealie.schema.response import PaginationBase, PaginationQuery
from mealie.schema.response.pagination import RecipeSearchQuery from mealie.schema.response.pagination import RecipeSearchQuery
@ -489,37 +486,3 @@ class RecipeController(BaseRecipeController):
self.mixins.update_one(recipe, slug) self.mixins.update_one(recipe, slug)
return asset_in return asset_in
# ==================================================================================================================
# OCR
@router.post("/create-ocr", status_code=201, response_model=str)
def create_recipe_ocr(
self, extension: str = Form(...), file: UploadFile = File(...), makefilerecipeimage: bool = Form(...)
):
"""Takes an image and creates a recipe based on the image"""
slug = self.service.create_one(
Recipe(
name="New OCR Recipe",
recipe_ingredient=[RecipeIngredient(note="", title=None, unit=None, food=None, original_text=None)],
recipe_instructions=[RecipeStep(text="")],
is_ocr_recipe=True,
settings=RecipeSettings(show_assets=True),
id=None,
image=None,
recipe_yield=None,
rating=None,
orgURL=None,
date_added=None,
date_updated=None,
created_at=None,
update_at=None,
nutrition=None,
)
).slug
RecipeController.upload_recipe_asset(self, slug, "Original recipe image", "", extension, file)
if makefilerecipeimage:
# Get the pointer to the beginning of the file to read it once more
file.file.seek(0)
self.update_recipe_image(slug, file.file.read(), extension)
return slug

View File

@ -3,6 +3,7 @@ from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from starlette.responses import FileResponse from starlette.responses import FileResponse
from mealie.core.config import get_app_dirs
from mealie.core.dependencies import validate_file_token from mealie.core.dependencies import validate_file_token
router = APIRouter(prefix="/api/utils", tags=["Utils"], include_in_schema=True) router = APIRouter(prefix="/api/utils", tags=["Utils"], include_in_schema=True)
@ -12,6 +13,14 @@ router = APIRouter(prefix="/api/utils", tags=["Utils"], include_in_schema=True)
async def download_file(file_path: Path = Depends(validate_file_token)): async def download_file(file_path: Path = Depends(validate_file_token)):
"""Uses a file token obtained by an active user to retrieve a file from the operating """Uses a file token obtained by an active user to retrieve a file from the operating
system.""" system."""
file_path = Path(file_path).resolve()
dirs = get_app_dirs()
if not file_path.is_relative_to(dirs.DATA_DIR):
raise HTTPException(status.HTTP_400_BAD_REQUEST)
if not file_path.is_file(): if not file_path.is_file():
raise HTTPException(status.HTTP_400_BAD_REQUEST) raise HTTPException(status.HTTP_400_BAD_REQUEST)

View File

@ -1,7 +0,0 @@
# This file is auto-generated by gen_schema_exports.py
from .ocr import OcrAssetReq, OcrTsvResponse
__all__ = [
"OcrAssetReq",
"OcrTsvResponse",
]

View File

@ -1,21 +0,0 @@
from mealie.schema._mealie import MealieModel
class OcrTsvResponse(MealieModel):
level: int = 0
page_num: int = 0
block_num: int = 0
par_num: int = 0
line_num: int = 0
word_num: int = 0
left: int = 0
top: int = 0
width: int = 0
height: int = 0
conf: float = 0.0
text: str = ""
class OcrAssetReq(MealieModel):
recipe_slug: str
asset_name: str

View File

@ -128,7 +128,6 @@ class Recipe(RecipeSummary):
assets: list[RecipeAsset] | None = [] assets: list[RecipeAsset] | None = []
notes: list[RecipeNote] | None = [] notes: list[RecipeNote] | None = []
extras: dict | None = {} extras: dict | None = {}
is_ocr_recipe: bool | None = False
comments: list[RecipeCommentOut] | None = [] comments: list[RecipeCommentOut] | None = []

View File

@ -1,56 +0,0 @@
from io import BytesIO
import pytesseract
from PIL import Image
from mealie.schema.ocr.ocr import OcrTsvResponse
from mealie.services._base_service import BaseService
class OcrService(BaseService):
"""
Class for ocr engines.
"""
def image_to_string(self, image_data):
"""
Returns a plain text translation of an image
"""
return pytesseract.image_to_string(Image.open(image_data))
def image_to_tsv(self, image_data, lang=None):
"""
Returns the pytesseract default tsv output
"""
if lang is not None:
return pytesseract.image_to_data(Image.open(BytesIO(image_data)), lang=lang)
return pytesseract.image_to_data(Image.open(BytesIO(image_data)))
def format_tsv_output(self, tsv: str) -> list[OcrTsvResponse]:
"""
Returns a OcrTsvResponse from a default pytesseract tsv output
"""
lines = tsv.split("\n")
titles = [t.strip() for t in lines[0].split("\t")]
response: list[OcrTsvResponse] = []
for i in range(1, len(lines)):
if lines[i] == "":
continue
line = OcrTsvResponse()
for key, value in zip(titles, lines[i].split("\t"), strict=False):
if key == "text":
setattr(line, key, value.strip())
elif key == "conf":
setattr(line, key, float(value.strip()))
elif key in OcrTsvResponse.__fields__:
setattr(line, key, int(value.strip()))
else:
continue
if isinstance(line, OcrTsvResponse):
response.append(line)
return response

47
poetry.lock generated
View File

@ -605,6 +605,7 @@ files = [
{file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"},
{file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"},
{file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"},
{file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d967650d3f56af314b72df7089d96cda1083a7fc2da05b375d2bc48c82ab3f3c"},
{file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"},
{file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"},
{file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"},
@ -613,6 +614,7 @@ files = [
{file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"},
{file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"},
{file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"},
{file = "greenlet-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d4606a527e30548153be1a9f155f4e283d109ffba663a15856089fb55f933e47"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"},
@ -642,6 +644,7 @@ files = [
{file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"},
{file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"},
{file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"},
{file = "greenlet-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1087300cf9700bbf455b1b97e24db18f2f77b55302a68272c56209d5587c12d1"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"},
@ -650,6 +653,7 @@ files = [
{file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"},
{file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"},
{file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"},
{file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8512a0c38cfd4e66a858ddd1b17705587900dd760c6003998e9472b77b56d417"},
{file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"},
{file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"},
{file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"},
@ -1862,21 +1866,6 @@ files = [
html5lib = "*" html5lib = "*"
rdflib = "*" rdflib = "*"
[[package]]
name = "pytesseract"
version = "0.3.10"
description = "Python-tesseract is a python wrapper for Google's Tesseract-OCR"
optional = false
python-versions = ">=3.7"
files = [
{file = "pytesseract-0.3.10-py3-none-any.whl", hash = "sha256:8f22cc98f765bf13517ead0c70effedb46c153540d25783e04014f28b55a5fc6"},
{file = "pytesseract-0.3.10.tar.gz", hash = "sha256:f1c3a8b0f07fd01a1085d451f5b8315be6eec1d5577a6796d46dc7a62bd4120f"},
]
[package.dependencies]
packaging = ">=21.3"
Pillow = ">=8.0.0"
[[package]] [[package]]
name = "pytest" name = "pytest"
version = "7.2.2" version = "7.2.2"
@ -2024,6 +2013,7 @@ files = [
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
@ -2031,8 +2021,15 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
@ -2049,6 +2046,7 @@ files = [
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
@ -2056,6 +2054,7 @@ files = [
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
@ -2205,13 +2204,13 @@ tests = ["html5lib", "pytest", "pytest-cov"]
[[package]] [[package]]
name = "recipe-scrapers" name = "recipe-scrapers"
version = "14.52.0" version = "14.53.0"
description = "Python package, scraping recipes from all over the internet" description = "Python package, scraping recipes from all over the internet"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "recipe_scrapers-14.52.0-py3-none-any.whl", hash = "sha256:3514048808c7b7de467bfa56bea3921ecff637441cde9085186345e3ce7cabdc"}, {file = "recipe_scrapers-14.53.0-py3-none-any.whl", hash = "sha256:330353dc824f9d77a089e4830722fef940a04259a1a59a6578a162378ed6bc72"},
{file = "recipe_scrapers-14.52.0.tar.gz", hash = "sha256:3d1d2cf7ad8c5fd73b5a0e921b3505daeddb42da705ef5c68523a465ccd8cd8f"}, {file = "recipe_scrapers-14.53.0.tar.gz", hash = "sha256:916e1182fb497b89df8ac29cb816a9566aafc6d2bba73f60462aef42fc1bba22"},
] ]
[package.dependencies] [package.dependencies]
@ -2972,6 +2971,16 @@ files = [
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"},
{file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"},
{file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"},
{file = "wrapt-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecee4132c6cd2ce5308e21672015ddfed1ff975ad0ac8d27168ea82e71413f55"},
{file = "wrapt-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2020f391008ef874c6d9e208b24f28e31bcb85ccff4f335f15a3251d222b92d9"},
{file = "wrapt-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2feecf86e1f7a86517cab34ae6c2f081fd2d0dac860cb0c0ded96d799d20b335"},
{file = "wrapt-1.14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:240b1686f38ae665d1b15475966fe0472f78e71b1b4903c143a842659c8e4cb9"},
{file = "wrapt-1.14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9008dad07d71f68487c91e96579c8567c98ca4c3881b9b113bc7b33e9fd78b8"},
{file = "wrapt-1.14.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6447e9f3ba72f8e2b985a1da758767698efa72723d5b59accefd716e9e8272bf"},
{file = "wrapt-1.14.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:acae32e13a4153809db37405f5eba5bac5fbe2e2ba61ab227926a22901051c0a"},
{file = "wrapt-1.14.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49ef582b7a1152ae2766557f0550a9fcbf7bbd76f43fbdc94dd3bf07cc7168be"},
{file = "wrapt-1.14.1-cp311-cp311-win32.whl", hash = "sha256:358fe87cc899c6bb0ddc185bf3dbfa4ba646f05b1b0b9b5a27c2cb92c2cea204"},
{file = "wrapt-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:26046cd03936ae745a502abf44dac702a5e6880b2b01c29aea8ddf3353b68224"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"},
@ -3025,4 +3034,4 @@ pgsql = ["psycopg2-binary"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.10" python-versions = "^3.10"
content-hash = "5e0cc403c1ec022e6a75a4969dd97c55ce312daafd7d2024a3617eca25b2129f" content-hash = "d7537958ae2ddbf8e2b350cb7b1189492a62b02becfe087efbc37a3b0115ff13"

View File

@ -29,7 +29,6 @@ passlib = "^1.7.4"
psycopg2-binary = { version = "^2.9.1", optional = true } psycopg2-binary = { version = "^2.9.1", optional = true }
pydantic = "^1.10.4" pydantic = "^1.10.4"
pyhumps = "^3.5.3" pyhumps = "^3.5.3"
pytesseract = "^0.3.9"
python = "^3.10" python = "^3.10"
python-dateutil = "^2.8.2" python-dateutil = "^2.8.2"
python-dotenv = "^1.0.0" python-dotenv = "^1.0.0"
@ -37,7 +36,7 @@ python-jose = "^3.3.0"
python-ldap = "^3.3.1" python-ldap = "^3.3.1"
python-multipart = "^0.0.6" python-multipart = "^0.0.6"
python-slugify = "^8.0.0" python-slugify = "^8.0.0"
recipe-scrapers = "^14.52.0" recipe-scrapers = "^14.53.0"
requests = "^2.31.0" requests = "^2.31.0"
tzdata = "^2022.7" tzdata = "^2022.7"
uvicorn = { extras = ["standard"], version = "^0.21.0" } uvicorn = { extras = ["standard"], version = "^0.21.0" }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,73 +0,0 @@
level page_num block_num par_num line_num word_num left top width height conf text
1 1 0 0 0 0 0 0 640 480 -1
2 1 1 0 0 0 36 92 582 269 -1
3 1 1 1 0 0 36 92 582 92 -1
4 1 1 1 1 0 36 92 544 30 -1
5 1 1 1 1 1 36 92 60 24 87.137558 This
5 1 1 1 1 2 109 92 20 24 87.137558 is
5 1 1 1 1 3 141 98 15 18 87.823906 a
5 1 1 1 1 4 169 92 32 24 87.823906 lot
5 1 1 1 1 5 212 92 28 24 92.965874 of
5 1 1 1 1 6 251 92 31 24 93.247513 12
5 1 1 1 1 7 296 92 68 30 92.734741 point
5 1 1 1 1 8 374 93 53 23 92.996040 text
5 1 1 1 1 9 437 93 26 23 93.160057 to
5 1 1 1 1 10 474 93 52 23 92.312637 test
5 1 1 1 1 11 536 92 44 24 92.312637 the
4 1 1 1 2 0 36 126 582 31 -1
5 1 1 1 2 1 36 132 45 18 90.505524 ocr
5 1 1 1 2 2 91 126 69 24 90.505524 code
5 1 1 1 2 3 172 126 51 24 91.169167 and
5 1 1 1 2 4 236 132 50 18 89.765854 see
5 1 1 1 2 5 299 126 15 24 85.827324 if
5 1 1 1 2 6 325 126 14 24 93.116241 it
5 1 1 1 2 7 348 126 85 24 92.394562 works
5 1 1 1 2 8 445 132 33 18 30.119690 on
5 1 1 1 2 9 500 126 29 24 30.119690 all
5 1 1 1 2 10 541 127 77 30 92.090988 types
4 1 1 1 3 0 36 160 187 24 -1
5 1 1 1 3 1 36 160 28 24 92.476135 of
5 1 1 1 3 2 72 160 41 24 90.919365 file
5 1 1 1 3 3 123 160 100 24 91.360367 format.
3 1 1 2 0 0 36 194 561 167 -1
4 1 1 2 1 0 36 194 549 31 -1
5 1 1 2 1 1 36 194 55 24 89.098892 The
5 1 1 2 1 2 102 194 75 30 89.098892 quick
5 1 1 2 1 3 189 194 85 24 91.415680 brown
5 1 1 2 1 4 287 194 52 31 91.943085 dog
5 1 1 2 1 5 348 194 108 31 92.167969 jumped
5 1 1 2 1 6 468 200 63 18 91.970985 over
5 1 1 2 1 7 540 194 45 24 92.843704 the
4 1 1 2 2 0 37 228 548 31 -1
5 1 1 2 2 1 37 228 55 31 92.262550 lazy
5 1 1 2 2 2 103 228 50 24 92.693161 fox.
5 1 1 2 2 3 165 228 55 24 92.947639 The
5 1 1 2 2 4 232 228 75 30 90.589806 quick
5 1 1 2 2 5 319 228 85 24 91.051247 brown
5 1 1 2 2 6 417 228 51 31 91.925011 dog
5 1 1 2 2 7 478 228 107 31 91.471077 jumped
4 1 1 2 3 0 36 262 561 31 -1
5 1 1 2 3 1 36 268 63 18 90.210129 over
5 1 1 2 3 2 109 262 44 24 90.210129 the
5 1 1 2 3 3 165 262 56 31 91.178192 lazy
5 1 1 2 3 4 231 262 50 24 92.794647 fox.
5 1 1 2 3 5 294 262 55 24 91.388016 The
5 1 1 2 3 6 360 262 75 30 92.525742 quick
5 1 1 2 3 7 447 262 85 24 90.425552 brown
5 1 1 2 3 8 545 262 52 31 90.425552 dog
4 1 1 2 4 0 43 296 518 31 -1
5 1 1 2 4 1 43 296 107 31 91.759590 jumped
5 1 1 2 4 2 162 302 64 18 92.923576 over
5 1 1 2 4 3 235 296 44 24 92.017929 the
5 1 1 2 4 4 292 296 55 31 91.558884 lazy
5 1 1 2 4 5 357 296 50 24 92.687485 fox.
5 1 1 2 4 6 420 296 55 24 91.922661 The
5 1 1 2 4 7 486 296 75 30 91.870224 quick
4 1 1 2 5 0 37 330 524 31 -1
5 1 1 2 5 1 37 330 85 24 92.923935 brown
5 1 1 2 5 2 135 330 52 31 91.468765 dog
5 1 1 2 5 3 196 330 108 31 91.425491 jumped
5 1 1 2 5 4 316 336 63 18 91.489830 over
5 1 1 2 5 5 388 330 45 24 91.740379 the
5 1 1 2 5 6 445 330 55 31 92.110054 lazy
5 1 1 2 5 7 511 330 50 24 93.180054 fox.
1 level page_num block_num par_num line_num word_num left top width height conf text
2 1 1 0 0 0 0 0 0 640 480 -1
3 2 1 1 0 0 0 36 92 582 269 -1
4 3 1 1 1 0 0 36 92 582 92 -1
5 4 1 1 1 1 0 36 92 544 30 -1
6 5 1 1 1 1 1 36 92 60 24 87.137558 This
7 5 1 1 1 1 2 109 92 20 24 87.137558 is
8 5 1 1 1 1 3 141 98 15 18 87.823906 a
9 5 1 1 1 1 4 169 92 32 24 87.823906 lot
10 5 1 1 1 1 5 212 92 28 24 92.965874 of
11 5 1 1 1 1 6 251 92 31 24 93.247513 12
12 5 1 1 1 1 7 296 92 68 30 92.734741 point
13 5 1 1 1 1 8 374 93 53 23 92.996040 text
14 5 1 1 1 1 9 437 93 26 23 93.160057 to
15 5 1 1 1 1 10 474 93 52 23 92.312637 test
16 5 1 1 1 1 11 536 92 44 24 92.312637 the
17 4 1 1 1 2 0 36 126 582 31 -1
18 5 1 1 1 2 1 36 132 45 18 90.505524 ocr
19 5 1 1 1 2 2 91 126 69 24 90.505524 code
20 5 1 1 1 2 3 172 126 51 24 91.169167 and
21 5 1 1 1 2 4 236 132 50 18 89.765854 see
22 5 1 1 1 2 5 299 126 15 24 85.827324 if
23 5 1 1 1 2 6 325 126 14 24 93.116241 it
24 5 1 1 1 2 7 348 126 85 24 92.394562 works
25 5 1 1 1 2 8 445 132 33 18 30.119690 on
26 5 1 1 1 2 9 500 126 29 24 30.119690 all
27 5 1 1 1 2 10 541 127 77 30 92.090988 types
28 4 1 1 1 3 0 36 160 187 24 -1
29 5 1 1 1 3 1 36 160 28 24 92.476135 of
30 5 1 1 1 3 2 72 160 41 24 90.919365 file
31 5 1 1 1 3 3 123 160 100 24 91.360367 format.
32 3 1 1 2 0 0 36 194 561 167 -1
33 4 1 1 2 1 0 36 194 549 31 -1
34 5 1 1 2 1 1 36 194 55 24 89.098892 The
35 5 1 1 2 1 2 102 194 75 30 89.098892 quick
36 5 1 1 2 1 3 189 194 85 24 91.415680 brown
37 5 1 1 2 1 4 287 194 52 31 91.943085 dog
38 5 1 1 2 1 5 348 194 108 31 92.167969 jumped
39 5 1 1 2 1 6 468 200 63 18 91.970985 over
40 5 1 1 2 1 7 540 194 45 24 92.843704 the
41 4 1 1 2 2 0 37 228 548 31 -1
42 5 1 1 2 2 1 37 228 55 31 92.262550 lazy
43 5 1 1 2 2 2 103 228 50 24 92.693161 fox.
44 5 1 1 2 2 3 165 228 55 24 92.947639 The
45 5 1 1 2 2 4 232 228 75 30 90.589806 quick
46 5 1 1 2 2 5 319 228 85 24 91.051247 brown
47 5 1 1 2 2 6 417 228 51 31 91.925011 dog
48 5 1 1 2 2 7 478 228 107 31 91.471077 jumped
49 4 1 1 2 3 0 36 262 561 31 -1
50 5 1 1 2 3 1 36 268 63 18 90.210129 over
51 5 1 1 2 3 2 109 262 44 24 90.210129 the
52 5 1 1 2 3 3 165 262 56 31 91.178192 lazy
53 5 1 1 2 3 4 231 262 50 24 92.794647 fox.
54 5 1 1 2 3 5 294 262 55 24 91.388016 The
55 5 1 1 2 3 6 360 262 75 30 92.525742 quick
56 5 1 1 2 3 7 447 262 85 24 90.425552 brown
57 5 1 1 2 3 8 545 262 52 31 90.425552 dog
58 4 1 1 2 4 0 43 296 518 31 -1
59 5 1 1 2 4 1 43 296 107 31 91.759590 jumped
60 5 1 1 2 4 2 162 302 64 18 92.923576 over
61 5 1 1 2 4 3 235 296 44 24 92.017929 the
62 5 1 1 2 4 4 292 296 55 31 91.558884 lazy
63 5 1 1 2 4 5 357 296 50 24 92.687485 fox.
64 5 1 1 2 4 6 420 296 55 24 91.922661 The
65 5 1 1 2 4 7 486 296 75 30 91.870224 quick
66 4 1 1 2 5 0 37 330 524 31 -1
67 5 1 1 2 5 1 37 330 85 24 92.923935 brown
68 5 1 1 2 5 2 135 330 52 31 91.468765 dog
69 5 1 1 2 5 3 196 330 108 31 91.425491 jumped
70 5 1 1 2 5 4 316 336 63 18 91.489830 over
71 5 1 1 2 5 5 388 330 45 24 91.740379 the
72 5 1 1 2 5 6 445 330 55 31 92.110054 lazy
73 5 1 1 2 5 7 511 330 50 24 93.180054 fox.

View File

@ -1,9 +0,0 @@
This is a lot of 12 point text to test the
ocr code and see if it works on all types
of file format.
The quick brown dog jumped over the
lazy fox. The quick brown dog jumped
over the lazy fox. The quick brown dog
jumped over the lazy fox. The quick
brown dog jumped over the lazy fox.

View File

@ -1,58 +0,0 @@
from pathlib import Path
import pytest
from mealie.services.ocr.pytesseract import OcrService
ocr_service = OcrService()
@pytest.mark.skip("Tesseract is not reliable between environments")
def test_image_to_string():
with open(Path("tests/data/images/test-ocr.png"), "rb") as image:
result = ocr_service.image_to_string(image)
with open(Path("tests/data/text/test-ocr.txt"), encoding="utf-8") as expected_result:
assert result == expected_result.read()
@pytest.mark.skip("Tesseract is not reliable between environments")
def test_image_to_tsv():
with open(Path("tests/data/images/test-ocr.png"), "rb") as image:
result = ocr_service.image_to_tsv(image.read())
with open(Path("tests/data/text/test-ocr.tsv"), encoding="utf-8") as expected_result:
assert result == expected_result.read()
def test_format_tsv_output():
tsv = " level\tpage_num\tblock_num\tpar_num\tline_num\tword_num\tleft\ttop\twidth\theight\tconf\ttext \n1\t1\t0\t0\t0\t0\t0\t0\t640\t480\t-1\t\n5\t1\t1\t1\t1\t1\t36\t92\t60\t24\t87.137558\tThis"
expected_result = [
{
"level": 1,
"page_num": 1,
"block_num": 0,
"par_num": 0,
"line_num": 0,
"word_num": 0,
"left": 0,
"top": 0,
"width": 640,
"height": 480,
"conf": -1.0,
"text": "",
},
{
"level": 5,
"page_num": 1,
"block_num": 1,
"par_num": 1,
"line_num": 1,
"word_num": 1,
"left": 36,
"top": 92,
"width": 60,
"height": 24,
"conf": 87.137558,
"text": "This",
},
]
assert ocr_service.format_tsv_output(tsv) == expected_result

View File

@ -113,12 +113,6 @@ groups_webhooks_rerun = "/api/groups/webhooks/rerun"
"""`/api/groups/webhooks/rerun`""" """`/api/groups/webhooks/rerun`"""
media_docker_validate_txt = "/api/media/docker/validate.txt" media_docker_validate_txt = "/api/media/docker/validate.txt"
"""`/api/media/docker/validate.txt`""" """`/api/media/docker/validate.txt`"""
ocr = "/api/ocr/"
"""`/api/ocr/`"""
ocr_asset_to_tsv = "/api/ocr/asset-to-tsv"
"""`/api/ocr/asset-to-tsv`"""
ocr_file_to_tsv = "/api/ocr/file-to-tsv"
"""`/api/ocr/file-to-tsv`"""
organizers_categories = "/api/organizers/categories" organizers_categories = "/api/organizers/categories"
"""`/api/organizers/categories`""" """`/api/organizers/categories`"""
organizers_categories_empty = "/api/organizers/categories/empty" organizers_categories_empty = "/api/organizers/categories/empty"
@ -151,8 +145,6 @@ recipes_bulk_actions_tag = "/api/recipes/bulk-actions/tag"
"""`/api/recipes/bulk-actions/tag`""" """`/api/recipes/bulk-actions/tag`"""
recipes_create_from_zip = "/api/recipes/create-from-zip" recipes_create_from_zip = "/api/recipes/create-from-zip"
"""`/api/recipes/create-from-zip`""" """`/api/recipes/create-from-zip`"""
recipes_create_ocr = "/api/recipes/create-ocr"
"""`/api/recipes/create-ocr`"""
recipes_create_url = "/api/recipes/create-url" recipes_create_url = "/api/recipes/create-url"
"""`/api/recipes/create-url`""" """`/api/recipes/create-url`"""
recipes_create_url_bulk = "/api/recipes/create-url/bulk" recipes_create_url_bulk = "/api/recipes/create-url/bulk"