Add comprehensive base recipe system allowing recipes to reference other recipes dynamically. References can include custom items before/after the base recipe content and render as unified lists.
Features:
- Mark recipes as base recipes with isBaseRecipe flag
- Insert base recipe references at any position in ingredients/instructions
- Add custom items before/after referenced content (itemsBefore/itemsAfter, stepsBefore/stepsAfter)
- Combined rendering displays all items in single unified lists
- Full edit/remove functionality for additional items with modal reuse
- Empty item validation prevents accidental blank entries
- HTML rendering in section titles for proper <wbr> and ­ support
- Reference links in section headings with multiplier preservation
- Subtle hover effects (2% scale) on add buttons
- Translation support for all reference fields
- Deletion handling expands references before removing base recipes
Add new page at /rezepte/untranslated for recipe admins to view and manage recipes without approved English translations. Includes translation status tracking, statistics dashboard, and visual badges.
Changes:
- Add API endpoint to fetch recipes without approved translations
- Create untranslated recipes page with auth checks for rezepte_users group
- Add translation status badges to Card component (pending, needs_update, none)
- Add database index on translations.en.translationStatus for performance
- Create layout for /rezepte route with header navigation
- Add "Unübersetzt" link to navigation for authorized users
Add content-based hashing to recipe images for proper cache invalidation
while maintaining graceful degradation through dual file storage.
Changes:
- Add imageHash utility with SHA-256 content hashing (8-char)
- Update Recipe model to store hashed filenames in images[0].mediapath
- Modify image upload endpoint to save both hashed and unhashed versions
- Update frontend components to use images[0].mediapath with fallback
- Add migration endpoint to hash existing images (production-only)
- Update image delete/rename endpoints to handle both file versions
Images are now stored as:
- recipe.a1b2c3d4.webp (hashed, cached forever)
- recipe.webp (unhashed, graceful degradation fallback)
Database stores hashed filename for cache busting, while unhashed
version remains on disk for backward compatibility and manual uploads.
Add comprehensive translation support for previously untranslatable fields:
- Portions (serving sizes)
- Time fields (preparation, cooking, total_time)
- Baking properties (temperature, length, mode)
- Fermentation times (bulk, final)
- Ingredient units (EL→tbsp, TL→tsp, etc.)
Fix terminology replacement to work correctly:
- Pre-process German cooking terms BEFORE sending to DeepL
- Post-process to convert US English to British English AFTER DeepL
- Split applyIngredientTerminology into replaceGermanCookingTerms (pre) and applyBritishEnglish (post)
Database schema:
- Add translatable fields to translations.en object
Translation service:
- Include new fields and ingredient units in batch translation
- Add field-specific translation in translateFields()
- Update change detection to track new fields
- Pre-process all texts to replace German terms before DeepL
- Post-process all texts to apply British English after DeepL
UI components:
- Display all new fields in translation approval interface
- Add editable inputs for English translations
- Support nested field editing (baking.temperature, fermentation.bulk, etc.)
Fix changed fields detection:
- Only show changed fields when editing existing translations
- Don't show false warnings for first-time translations
- Add embedded translations schema to Recipe model with English support
- Create DeepL translation service with batch translation and change detection
- Build translation approval UI with side-by-side editing for all recipe fields
- Integrate translation workflow into add/edit pages with field comparison
- Create complete English recipe routes at /recipes/* mirroring German structure
- Add language switcher component with hreflang SEO tags
- Support image loading from German short_name for English recipes
- Add English API endpoints for all recipe filters (category, tag, icon, season)
- Include layout with English navigation header for all recipe subroutes