Compare commits

...

2 Commits

Author SHA1 Message Date
Michael Genson
3ae455539c fix: Ensure recipe ingredients have a valid reference_id (#7139) 2026-02-24 19:50:49 -06:00
Hayden
8fd7995681 chore(l10n): New Crowdin updates (#7136) 2026-02-24 19:51:38 +00:00
44 changed files with 393 additions and 368 deletions

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "يجب أن يكون عنوان URL صالحًا",
"no-whitespace": "لا يسمح باستخدام المسافات",
"min-length": "يجب أن يكون على الأقل {min} أحرف",
"max-length": "يجب أن يكون على الأكثر {max} أحرف"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Линкът трябва да е валиден",
"no-whitespace": "Не са позволени интервали",
"min-length": "Трябва да съдържа поне {min} знака",
"max-length": "Трябва да съдържа най-много {max} знака"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "La URL ha de ser vàlida",
"no-whitespace": "No es permeten espais en blanc",
"min-length": "Ha de tenir almenys {min} caràcters",
"max-length": "Ha de tenir com a màxim {max} caràcters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Musí být platná URL adresa",
"no-whitespace": "Mezery nejsou povoleny",
"min-length": "Musí být alespoň {min} znaků",
"max-length": "Musí být nejvíce {max} znaků"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "URL'en skal være gyldig",
"no-whitespace": "Mellemrum er ikke tilladt",
"min-length": "Der skal mindst være {min} tegn",
"max-length": "Der må højst være {max} tegn"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Muss eine gültige URL sein",
"no-whitespace": "Kein Leerzeichen erlaubt",
"min-length": "Muss mindestens {min} Zeichen haben",
"max-length": "Darf mindestens {max} Zeichen haben"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Πρέπει να είναι μια έγκυρη διεύθυνση URL",
"no-whitespace": "Δεν επιτρέπονται κενοί χαρακτήρες",
"min-length": "Πρέπει να αποτελείται από τουλάχιστον {min} χαρακτήρες",
"max-length": "Πρέπει να αποτελείται το πολύ από {max} χαρακτήρες"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Debe ser una URL válida",
"no-whitespace": "No se permiten espacios en blanco",
"min-length": "Debe ser como mínimo {min} caracteres",
"max-length": "Debe ser como máximo {max} caracteres"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "URL ei ole kelvollinen",
"no-whitespace": "Tekstissä ei saa olla välilyöntejä",
"min-length": "Vähimmäispituus on {min} merkkiä",
"max-length": "Enimmäispituus on {max} merkkiä"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Doit être une URL valide",
"no-whitespace": "Aucun espace n'est autorisé",
"min-length": "Doit contenir au moins {min} caractères",
"max-length": "Doit contenir au maximum {max} caractères"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1423,8 +1423,8 @@
"is-greater-than-or-equal-to": "est supérieur ou égal à",
"is-less-than": "est inférieure à",
"is-less-than-or-equal-to": "est inférieur ou égal à",
"is-older-than": "is older than",
"is-newer-than": "is newer than"
"is-older-than": "est plus ancien que",
"is-newer-than": "est plus récent que"
},
"relational-keywords": {
"is": "est",
@@ -1436,7 +1436,7 @@
"is-not-like": "n'est pas similaire à"
},
"dates": {
"days-ago": "days ago|day ago|days ago"
"days-ago": "jours|jour|jours"
}
},
"validators": {
@@ -1445,6 +1445,6 @@
"invalid-url": "Doit être une URL valide",
"no-whitespace": "Aucun espace n'est autorisé",
"min-length": "",
"max-length": "Doit contenir au maximum {max} caractères"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Doit être une URL valide",
"no-whitespace": "Aucun espace n'est autorisé",
"min-length": "Doit contenir au moins {min} caractères",
"max-length": "Doit contenir au maximum {max} caractères"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Érvényes URL-nek kell lennie",
"no-whitespace": "Szóközt nem tartalmazhat",
"min-length": "Legalább {min} karakter legyen",
"max-length": "Legfeljebb {max} karakter legyen"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Verður að vera gild vefslóð",
"no-whitespace": "Engin bil leyfð",
"min-length": "Verður að vera að lágmarki {min} stafir",
"max-length": "Má vera að hámarki {max} stafir"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Lo URL Deve Essere Valido",
"no-whitespace": "Gli Spazi Non Sono Ammessi",
"min-length": "Deve Essere Almeno {min} Caratteri",
"max-length": "Deve Essere Al Massimo {max} Caratteri"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "유효한 URL이어야 합니다.",
"no-whitespace": "공백 허용 안 됨",
"min-length": "최소 {min}자 이상이어야 합니다",
"max-length": "최대 {min}자 이하여야 합니다"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Moet een geldige URL zijn",
"no-whitespace": "Geen spaties toegestaan",
"min-length": "Moet minimaal {min} tekens bevatten",
"max-length": "Zorg dat je {max} tekens gebruikt"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Må være en gyldig nettadresse",
"no-whitespace": "Ingen mellomrom tillatt",
"min-length": "Må minst ha {min} tegn",
"max-length": "Kan maksimalt ha {max} tegn"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Musi być prawidłowym odnośnikiem",
"no-whitespace": "Niedozwolone są puste spacje",
"min-length": "Musi zawierać co najmniej {min} znaków",
"max-length": "Musi zawierać co najwyżej {max} znaków"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Precisa ser uma URL válida",
"no-whitespace": "Nenhum espaço em branco é permitido",
"min-length": "Precisa ter pelo menos {min} caracteres",
"max-length": "Pode ter até {max} caracteres"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "O URL deve ser válido",
"no-whitespace": "Não são permitidos espaços em branco",
"min-length": "Deve ter pelo menos {min} caracteres",
"max-length": "Deve ter no máximo {max} caracteres"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Trebuie Să Fie Un URL Valid",
"no-whitespace": "Niciun Spațiu Alb Permis",
"min-length": "Trebuie Să Aibă Cel Puțin {min} Caractere",
"max-length": "Trebuie Să Aibă Cel Mult {max} Caractere"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "Без пробелов",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Musí byť platná URL",
"no-whitespace": "Prázdne znaky nepovolené",
"min-length": "Musí mať aspoň {min} znakov",
"max-length": "Musí mať najviac {max} znakov"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "URL mora biti veljaven",
"no-whitespace": "Presledki niso dovoljeni",
"min-length": "Mora vsebovati vsaj {min} znakov",
"max-length": "Lahko je največ {max} znakov"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Мора бити валидан URL",
"no-whitespace": "Размак није дозвољен",
"min-length": "Мора бити најмање {min} карактера",
"max-length": "Мора бити највише {max} карактера"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Måste var en giltig länk",
"no-whitespace": "Ingen blanksteg tillåten",
"min-length": "Måste vara minst {min} tecken",
"max-length": "Måste vara som mest {max} tecken"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Geçerli Bir URL Olmalıdır",
"no-whitespace": "No Whitespace Allowed",
"min-length": "En Az {min} Karakter Olmalıdır",
"max-length": "En Fazla {max} Karakter Olmalıdır"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Має бути дійсною URL-адресою",
"no-whitespace": "Пробіли заборонені",
"min-length": "Повинно бути не менше ніж {min} символів ",
"max-length": "Повинно бути не більше ніж {max} символів"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

View File

@@ -1445,6 +1445,6 @@
"invalid-url": "Must Be A Valid URL",
"no-whitespace": "No Whitespace Allowed",
"min-length": "Must Be At Least {min} Characters",
"max-length": "Must Be At Most {max} Characters"
"max-length": "Must Be At Most {max} Character|Must Be At Most {max} Characters"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -303,6 +303,11 @@ class RecipeIngredient(RecipeIngredientBase):
reference_id: UUID = Field(default_factory=uuid4)
model_config = ConfigDict(from_attributes=True)
@field_validator("reference_id", mode="before")
@classmethod
def ensure_reference_id(cls, value) -> UUID:
return value or uuid4()
@field_validator("quantity", mode="before")
@classmethod
def validate_quantity(cls, value) -> NoneFloat:

View File

@@ -19,6 +19,7 @@ from recipe_scrapers._schemaorg import SchemaOrg
from recipe_scrapers.plugins import SchemaOrgFillPlugin
from slugify import slugify
from mealie.db.models.recipe import RecipeModel
from mealie.pkgs.safehttp.transport import AsyncSafeTransport
from mealie.schema.cookbook.cookbook import SaveCookBook
from mealie.schema.recipe.recipe import Recipe, RecipeCategory, RecipeSummary, RecipeTag
@@ -1252,6 +1253,25 @@ def test_get_recipe_by_slug_or_id(api_client: TestClient, unique_user: utils.Tes
assert recipe_data["id"] == recipe_id
def test_get_recipe_ingredient_missing_reference_id(api_client: TestClient, unique_user: utils.TestUser):
slug = random_string()
response = api_client.post(api_routes.recipes, json={"name": slug}, headers=unique_user.token)
assert response.status_code == 201
# Manually edit the database to remove the reference id from the ingredient
session = unique_user.repos.session
recipe = session.query(RecipeModel).filter(RecipeModel.slug == slug).first()
recipe.recipe_ingredient[0].reference_id = None
session.commit()
# Make sure we can fetch the recipe and generate a new reference id
response = api_client.get(api_routes.recipes_slug(slug), headers=unique_user.token)
assert response.status_code == 200
recipe_data = response.json()
assert len(recipe_data["recipeIngredient"]) == 1
assert recipe_data["recipeIngredient"][0].get("referenceId")
@pytest.mark.parametrize("organizer_type", ["tags", "categories", "tools"])
def test_get_recipes_organizer_filter(api_client: TestClient, unique_user: utils.TestUser, organizer_type: str):
database = unique_user.repos