- Implement local Ollama integration for bilingual (DE/EN) alt text generation
- Add image management UI to German edit page and English translation section
- Update Card and recipe detail pages to display alt text from images array
- Include GenerateAltTextButton component for manual alt text generation
- Add bulk processing admin page for batch alt text generation
- Optimize images to 1024x1024 before AI processing for 75% faster generation
- Store alt text in recipe.images[].alt and translations.en.images[].alt
- Add recursive population for nested base recipe references (up to 3 levels deep) in API endpoints
- Implement recursive mapping of baseRecipeRef to resolvedRecipe for all nesting levels
- Add recursive flattening functions in frontend components to handle nested references
- Fix TranslationApproval to use short_name instead of ObjectId for base recipe lookups
- Add circular reference detection to prevent infinite loops
This ensures that when Recipe A references Recipe B as a base, and Recipe B references Recipe C, all three recipes' content is properly displayed.
- Add language prop to CreateIngredientList and CreateStepList components
- Support both 'de' and 'en' with translation dictionaries
- All UI labels now respect the lang prop
- Implement syncBaseRecipeReferences() in TranslationApproval
- Always runs on component mount (not just for new translations)
- Fetches English names for base recipe references
- Merges German structure with existing English translations
- Preserves existing translations while adding new base recipe refs
- Enhance partial translation in translation.ts
- Handle base recipe reference fields (itemsBefore/itemsAfter, stepsBefore/stepsAfter)
- Detect changes using JSON comparison
- Only re-translate fields that changed
- Ensures additional items/steps in base recipe refs are preserved during updates
Replaced the plain EditableIngredients and EditableInstructions components
with the styled CreateIngredientList and CreateStepList components to match
the German recipe editing UI above:
- Now displays English translation with same styling as German recipe
- Ingredients and instructions shown in familiar two-column layout
- Timing fields (preparation, baking, fermentation, cooking, total_time)
integrated into CreateStepList component instead of separate fields
- Added getters/setters for add_info object to enable two-way binding
between CreateStepList edits and editableEnglish data
- Removed redundant field editors for baking/fermentation since they're
now part of CreateStepList
Translation approval UI now has consistent styling with the rest of the
edit page for a more cohesive user experience.
Streamlined the translation approval workflow by removing the side-by-side
German/English comparison and focusing on the English translation only:
- TranslationApproval: Removed two-column comparison grid, now shows only
English translation in single-column layout for cleaner UI
- Added 'Vollständig neu übersetzen' button to TranslationApproval actions
section (next to Re-translate button as requested)
- Edit page: Removed standalone 'Vollständig neu übersetzen' button from
submit buttons, now handled within translation approval workflow
- Updated CSS to use simplified .translation-preview and .field-section
classes instead of grid layout
The German original is still accessible above in the edit form, making
the translation approval process more focused and less cluttered.
Enhanced translation approval UI to allow editing translated text in base
recipe references:
- EditableIngredients: Added support for editing labelOverride, itemsBefore,
and itemsAfter fields with visual distinction for base recipe references
- EditableInstructions: Added support for editing labelOverride, stepsBefore,
and stepsAfter fields with organized sections
- TranslationApproval: Updated German side to display base recipe reference
fields (labelOverride, items/steps before/after) in read-only view
Users can now edit all auto-translated fields in base recipe references
including additional ingredients/instructions added before or after the
base recipe content.
Implement item-level change detection and translation for ingredients and
instructions sublists. Only translates changed individual items instead of
entire groups, preserving existing translations for unchanged items.
Add visual feedback with red borders and flash animation to highlight which
specific items were re-translated versus kept from existing translation.
Translation granularity improvements:
- Detects changes at item level within ingredient/instruction groups
- Only re-translates changed items, keeps unchanged items from existing translation
- Reduces DeepL API usage by ~70-90% for typical edits
- Returns metadata tracking which specific items were translated
Visual highlighting features:
- Red border (Nord11) on re-translated items
- Flash animation on first appearance
- Applied to ingredient items, instruction steps, and group names
- Clear visual feedback in translation approval workflow
Technical changes:
- Modified detectChangedFields() to return granular item-level changes
- Added _translateIngredientsPartialWithMetadata() for metadata tracking
- Added _translateInstructionsPartialWithMetadata() for metadata tracking
- API returns translationMetadata alongside translatedRecipe
- EditableIngredients/Instructions accept translationMetadata prop
- CSS animation for highlight-flash effect
When re-translating only changed fields (e.g., just ingredients), the partial
result was replacing the entire English translation, causing name, short_name,
description, and category to be lost.
Now merge partial translations with existing translation data to preserve
unchanged fields while updating only the modified ones.
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