diff --git a/docs/docs/contributors/developers-guide/code-contributions.md b/docs/docs/contributors/developers-guide/code-contributions.md
index 6b12973b1..9d5385e09 100644
--- a/docs/docs/contributors/developers-guide/code-contributions.md
+++ b/docs/docs/contributors/developers-guide/code-contributions.md
@@ -12,7 +12,7 @@ We use github to host code, to track issues and feature requests, as well as acc
Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
1. Fork the repo and create your branch from `dev`.
-2. Read the page in in [dev/dev-notes.md](https://github.com/hay-kot/mealie/blob/0.1.0/dev/dev-notes.md) to get an idea on where the project is at.
+2. Read the page in in [dev/dev-notes.md](https://github.com/hay-kot/mealie/blob/master/dev/dev-notes.md) to get an idea on where the project is at.
3. If you're interested on working on major changes please get in touch on discord and coordinate with other developers. No sense in doubling up on work if someones already on it.
4. If you've changed APIs, update the documentation.
5. Issue that pull request!
diff --git a/frontend/src/locales/sv.json b/frontend/src/locales/sv.json
new file mode 100644
index 000000000..6d27c144f
--- /dev/null
+++ b/frontend/src/locales/sv.json
@@ -0,0 +1,136 @@
+{
+ "404": {
+ "page-not-found": "404 sidan kan inte hittas",
+ "take-me-home": "Ta mig hem"
+ },
+ "new-recipe": {
+ "from-url": "Från länk",
+ "recipe-url": "Recept URL",
+ "error-message": "Ett fel uppstod när receptet skulle läsas in. Undersök loggen och debug/last_recipe.json för att felsöka problemet.",
+ "bulk-add": "Lägg till flera",
+ "paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Klistra in din receptdata, varje rad kommer att hanteras som ett listelement"
+ },
+ "general": {
+ "submit": "Skicka",
+ "name": "Namn",
+ "settings": "Inställningar",
+ "cancel": "Avbryt",
+ "close": "Stäng",
+ "create": "Skapa",
+ "delete": "Ta bort",
+ "edit": "Redigera",
+ "enabled": "Aktiverad",
+ "image-file": "Bildfil",
+ "new": "Ny",
+ "ok": "Ok",
+ "random": "Slumpa",
+ "save": "Spara",
+ "select": "Välj",
+ "update": "Uppdatera",
+ "delete-data": "Radera data",
+ "download": "Ladda ner",
+ "import": "Importera"
+ },
+ "login": {
+ "email": "E-mail",
+ "password": "Lösenord",
+ "sign-in": "Logga in",
+ "sign-up": "Logga ut",
+ "stay-logged-in": "Kom ihåg mig"
+ },
+ "meal-plan": {
+ "dinner-this-week": "Veckans middagar",
+ "dinner-today": "Middag idag",
+ "planner": "Planeringkalender",
+ "choose-a-recipe": "Välj ett recept",
+ "create-a-new-meal-plan": "Skapa en ny måltidsplan",
+ "edit-meal-plan": "Redigera måltidsplan",
+ "end-date": "Slutdatum",
+ "meal-plans": "Måltidsplaner",
+ "start-date": "Startdatum"
+ },
+ "recipe": {
+ "description": "Beskrivning",
+ "categories": "Kategorier",
+ "ingredient": "Ingrediens",
+ "ingredients": "Ingredienser",
+ "instructions": "Instruktioner",
+ "note": "Anteckning",
+ "notes": "Anteckningar",
+ "original-recipe": "Originalrecept",
+ "recipe-name": "Receptets namn",
+ "servings": "Portioner",
+ "step-index": "Steg: {step}",
+ "tags": "Taggar",
+ "view-recipe": "Visa recept"
+ },
+ "search": {
+ "search-for-a-recipe": "Sök efter recept",
+ "search-for-your-favorite-recipe": "Sök efter Favoritrecept"
+ },
+ "settings": {
+ "color": "Färg",
+ "swatches": "Färgrutor",
+ "add-a-new-theme": "Lägg till ett nytt tema",
+ "set-new-time": "Välj ny tid",
+ "current": "Version:",
+ "latest": "Senaste",
+ "explore-the-docs": "Utforska dokumentationen",
+ "contribute": "Bidra",
+ "backup-and-exports": "Backups",
+ "backup-info": "Säkerhetskopior exporteras i JSON-format tillsammans med de bilder som finns i systemet. I din mapp för säkerhetskopior finner du en zip-fil som innehåller alla recept i JSON samt bilder från databasen. Om du dessutom valde att exportera till markdown så hittas också de i samma zip-fil. För att importera en säkerhetskopia så måste den ligga i din backup-mapp. Automatisk säkerhetskopiering genomförs varje dag kl. 03:00.",
+ "backup-tag": "Backup tagg",
+ "markdown-template": "Markdown mall",
+ "backup-recipes": "Säkerhetskopiera recept",
+ "theme": {
+ "theme-settings": "Temainställningar",
+ "select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Välj ett tema från menyn eller skapa ett nytt. Standardtemat kommer att användas för alla användare som inte gjort något val.",
+ "dark-mode": "Mörkt läge",
+ "theme-is-required": "Tema krävs",
+ "primary": "Primär",
+ "secondary": "Sekundär",
+ "accent": "Accent",
+ "success": "Success",
+ "info": "Info",
+ "warning": "Varning",
+ "error": "Error",
+ "light": "Ljust",
+ "dark": "Mörkt",
+ "theme": "Tema",
+ "saved-color-theme": "Sparat färgschema",
+ "delete-theme": "Radera tema",
+ "are-you-sure-you-want-to-delete-this-theme": "Är du säker på att du vill radera temat?",
+ "save-colors-and-apply-theme": "Spara färgval och använd tema",
+ "choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "Välj hur Mealie ska se ut för dig. Låt Mealie följa dina systeminställningar, eller välj mörkt eller ljust tema."
+ },
+ "webhooks": {
+ "meal-planner-webhooks": "Webhooks för denna måltidsplan",
+ "the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "Följande URLer kommer att mottaga webhooks med receptdata för dagens planerade måltid. Datan kommer att skickas klockan { time }",
+ "test-webhooks": "Testa Webhooks",
+ "webhook-url": "Webhook URL",
+ "save-webhooks": "Spara Webhooks"
+ },
+ "new-version-available": "En ny version av Mealie finns tillgänglig, Besök repot ",
+ "backup": {
+ "import-recipes": "Importera recept",
+ "import-themes": "Importera färgscheman",
+ "import-settings": "Importera recept",
+ "create-heading": "Skapa en säkerhetskopia",
+ "backup-tag": "Backup tagg"
+ }
+ },
+ "migration": {
+ "recipe-migration": "Migrera recept",
+ "currently-chowdown-via-public-repo-url-is-the-only-supported-type-of-migration": "Chowdown kan för tillfället endast migreras via URL till ett publikt repo.",
+ "chowdown-repo-url": "Chowdown Repo URL",
+ "migrate": "Migrera",
+ "failed-recipes": "Misslyckad recept",
+ "failed-images": "Misslyckade bilder",
+ "you-can-import-recipes-from-either-a-zip-file-or-a-directory-located-in-the-app-data-migraiton-folder-please-review-the-documentation-to-ensure-your-directory-structure-matches-what-is-expected": "Du kan importera recept från antingen en zip.fil eller en mapp placerad i /app/data/migrations/. Läs dokumentationen för att försäkra dig om att din mappstruktur matchar det som förväntas.",
+ "nextcloud-data": "Nextcloud Data",
+ "delete-confirmation": "Är du säker på att du vill radera denna migrationsdata?",
+ "successfully-imported-from-nextcloud": "Import från Nextcloud lyckades",
+ "failed-imports": "Misslyckade importer",
+ "upload-an-archive": "Ladda upp arkiv"
+ }
+}
diff --git a/frontend/src/store/modules/language.js b/frontend/src/store/modules/language.js
index 6fff6d677..893976f10 100644
--- a/frontend/src/store/modules/language.js
+++ b/frontend/src/store/modules/language.js
@@ -8,13 +8,17 @@ const state = {
value: "en",
},
{
- name: "Dutch",
+ name: "Danish",
value: "da",
},
{
name: "French",
value: "fr",
},
+ {
+ name: "Swedish",
+ value: "sv",
+ }
],
};
diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js
index fbcf43f89..b0fd2d30f 100644
--- a/frontend/src/store/store.js
+++ b/frontend/src/store/store.js
@@ -81,9 +81,9 @@ const store = new Vuex.Store({
getters: {
//
- getSnackText: (state) => state.snackText,
- getSnackActive: (state) => state.snackActive,
- getSnackType: (state) => state.snackType,
+ getSnackText: state => state.snackText,
+ getSnackActive: state => state.snackActive,
+ getSnackType: state => state.snackType,
getRecentRecipes: (state) => state.recentRecipes,
getHomePageSettings: (state) => state.homePageSettings,
diff --git a/mealie/services/scrape_services.py b/mealie/services/scrape_services.py
index 1980384e2..8e70155af 100644
--- a/mealie/services/scrape_services.py
+++ b/mealie/services/scrape_services.py
@@ -5,6 +5,7 @@ from typing import List, Tuple
import extruct
import requests
import scrape_schema_recipe
+import html
from app_config import DEBUG_DIR
from slugify import slugify
from utils.logger import logger
@@ -32,17 +33,17 @@ def normalize_instructions(instructions) -> List[dict]:
# One long string split by (possibly multiple) new lines
if type(instructions) == str:
return [
- {"text": line.strip()} for line in filter(None, instructions.splitlines())
+ {"text": normalize_instruction(line)} for line in instructions.splitlines() if line
]
# Plain strings in a list
elif type(instructions) == list and type(instructions[0]) == str:
- return [{"text": step.strip()} for step in instructions]
+ return [{"text": normalize_instruction(step)} for step in instructions]
# Dictionaries (let's assume it's a HowToStep) in a list
elif type(instructions) == list and type(instructions[0]) == dict:
return [
- {"text": step["text"].strip()}
+ {"text": normalize_instruction(step["text"])}
for step in instructions
if step["@type"] == "HowToStep"
]
@@ -51,6 +52,14 @@ def normalize_instructions(instructions) -> List[dict]:
raise Exception(f"Unrecognised instruction format: {instructions}")
+def normalize_instruction(line) -> str:
+ l = line.strip()
+ # Some sites erroneously escape their strings on multiple levels
+ while not l == (l := html.unescape(l)):
+ pass
+ return l
+
+
def normalize_yield(yld) -> str:
if type(yld) == list:
return yld[-1]