feat: translate recommendations and menu dishes into user language
- Generate recipes in English (reverted prompt to English-only) - Add TranslateRecipes to OpenAI client (translate.go) — sends compact JSON payload of translatable fields, merges back into original recipes - recommendation/handler.go: translate recipes in-memory before response when lang != "en"; falls back to English on error - dish/repository.go: Create() now returns (dishID, recipeID, err) so callers can upsert dish_translations after saving - menu/handler.go: saveRecipes returns savedRecipeEntry slice with dishID; saveDishTranslations calls TranslateRecipes then UpsertTranslation for each dish when the request locale is not English - savedrecipe/repository.go: updated to ignore dishID from Create() - init.go: wire openaiClient as RecipeTranslator and dishRepository as DishTranslator for menu.NewHandler Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,6 @@ var goalNames = map[string]string{
|
||||
"gain": "muscle gain",
|
||||
}
|
||||
|
||||
|
||||
// GenerateRecipes generates recipes using the OpenAI API.
|
||||
// Retries up to maxRetries times only when the response is not valid JSON.
|
||||
// API-level errors (rate limits, auth, etc.) are returned immediately.
|
||||
@@ -62,11 +61,6 @@ func buildRecipePrompt(req ai.RecipeRequest) string {
|
||||
goal = "weight maintenance"
|
||||
}
|
||||
|
||||
targetLang := langNames[req.Lang]
|
||||
if targetLang == "" {
|
||||
targetLang = "English"
|
||||
}
|
||||
|
||||
restrictions := "none"
|
||||
if len(req.Restrictions) > 0 {
|
||||
restrictions = strings.Join(req.Restrictions, ", ")
|
||||
@@ -93,7 +87,7 @@ func buildRecipePrompt(req ai.RecipeRequest) string {
|
||||
strings.Join(req.AvailableProducts, "\n") + "\n"
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`You are a chef and nutritionist. Generate %d recipes in %s.
|
||||
return fmt.Sprintf(`You are a chef and nutritionist. Generate %d recipes in English.
|
||||
|
||||
User profile:
|
||||
- Goal: %s
|
||||
@@ -107,7 +101,7 @@ Requirements for each recipe:
|
||||
- Include approximate macros per serving
|
||||
|
||||
IMPORTANT:
|
||||
- All text fields (title, description, ingredient names, units, step descriptions, tags) MUST be in %s.
|
||||
- All text fields (title, description, ingredient names, units, step descriptions, tags) MUST be in English.
|
||||
- The "image_query" field MUST always be in English (it is used for stock-photo search).
|
||||
|
||||
Return ONLY a valid JSON array without markdown or extra text:
|
||||
@@ -124,7 +118,7 @@ Return ONLY a valid JSON array without markdown or extra text:
|
||||
"steps": [{"number": 1, "description": "...", "timer_seconds": null}],
|
||||
"tags": ["..."],
|
||||
"nutrition_per_serving": {"calories": 420, "protein_g": 48, "fat_g": 12, "carbs_g": 18}
|
||||
}]`, count, targetLang, goal, req.DailyCalories, restrictions, cuisines, productsSection, perMealCalories, targetLang)
|
||||
}]`, count, goal, req.DailyCalories, restrictions, cuisines, productsSection, perMealCalories)
|
||||
}
|
||||
|
||||
func parseRecipesJSON(text string) ([]ai.Recipe, error) {
|
||||
|
||||
Reference in New Issue
Block a user