feat: add product selection step before meal planning

Inserts a new PlanProductsSheet as step 1 of the planning flow.
Users see their current products as a multi-select checklist (all
selected by default) before choosing the planning mode and dates.

- Empty state explains the benefit and offers "Add products" CTA
  while always allowing "Plan without products" to skip
- Selected product IDs flow through PlanMenuSheet →
  PlanDatePickerSheet → MenuService.generateForDates → backend
- Backend: added ProductIDs field to generate-menu request body;
  uses ListForPromptByIDs when set, ListForPrompt otherwise
- Backend: added Repository.ListForPromptByIDs (filtered SQL query)
- All 12 ARB locale files updated with planProducts* keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
dbastrikin
2026-03-23 16:07:28 +02:00
parent b6c75a3488
commit b38190ff5b
33 changed files with 1007 additions and 77 deletions

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "لم يتم العثور على نتائج لـ \"{query}\"",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "حصص",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "وضع علامة كمأكول",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "سيقوم الذكاء الاصطناعي بإنشاء قائمة طعام تشمل الإفطار والغداء والعشاء لكامل الأسبوع",
"generatingMenu": "جارٍ إنشاء القائمة...",
"dayPlannedLabel": "تم تخطيط اليوم",
"planMenuButton": "تخطيط الوجبات",
"planMenuTitle": "ماذا تريد تخطيطه؟",
"planOptionSingleMeal": "وجبة واحدة",
@@ -151,6 +154,16 @@
"planSelectMealType": "نوع الوجبة",
"planSelectRange": "اختر الفترة",
"planGenerateButton": "تخطيط",
"planGenerating": "جارٍ إنشاء الخطة\u2026",
"planSuccess": "تم تخطيط القائمة!"
"planGenerating": "جارٍ إنشاء الخطة",
"planSuccess": "تم تخطيط القائمة!",
"planProductsTitle": "مكونات القائمة",
"planProductsSubtitle": "سيأخذ الذكاء الاصطناعي المكونات المختارة بعين الاعتبار عند إنشاء الوصفات",
"planProductsEmpty": "لم يتم إضافة منتجات",
"planProductsEmptyMessage": "أضف المنتجات الموجودة لديك في المنزل — سيقترح الذكاء الاصطناعي وصفات مما لديك بالفعل",
"planProductsAddProducts": "إضافة منتجات",
"planProductsContinue": "متابعة",
"planProductsSkip": "تخطي اختيار المنتجات",
"planProductsSkipNoProducts": "التخطيط بدون منتجات",
"planProductsSelectAll": "تحديد الكل",
"planProductsDeselectAll": "إلغاء تحديد الكل"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "Keine Ergebnisse für \"{query}\"",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "Portionen",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "Als gegessen markieren",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "KI erstellt einen Menüplan mit Frühstück, Mittagessen und Abendessen für die ganze Woche",
"generatingMenu": "Menü wird erstellt...",
"dayPlannedLabel": "Tag geplant",
"planMenuButton": "Mahlzeiten planen",
"planMenuTitle": "Was planen?",
"planOptionSingleMeal": "Einzelne Mahlzeit",
@@ -151,6 +154,16 @@
"planSelectMealType": "Mahlzeittyp",
"planSelectRange": "Zeitraum wählen",
"planGenerateButton": "Planen",
"planGenerating": "Plan wird erstellt\u2026",
"planSuccess": "Menü geplant!"
"planGenerating": "Plan wird erstellt",
"planSuccess": "Menü geplant!",
"planProductsTitle": "Zutaten für den Speiseplan",
"planProductsSubtitle": "Die KI berücksichtigt die ausgewählten Produkte bei der Rezeptgenerierung",
"planProductsEmpty": "Keine Produkte hinzugefügt",
"planProductsEmptyMessage": "Füge Produkte hinzu, die du zu Hause hast — die KI schlägt Rezepte aus deinen Vorräten vor",
"planProductsAddProducts": "Produkte hinzufügen",
"planProductsContinue": "Weiter",
"planProductsSkip": "Produktauswahl überspringen",
"planProductsSkipNoProducts": "Ohne Produkte planen",
"planProductsSelectAll": "Alle auswählen",
"planProductsDeselectAll": "Alle abwählen"
}

View File

@@ -150,5 +150,15 @@
"planSelectRange": "Select period",
"planGenerateButton": "Plan",
"planGenerating": "Generating plan\u2026",
"planSuccess": "Menu planned!"
"planSuccess": "Menu planned!",
"planProductsTitle": "Products for the menu",
"planProductsSubtitle": "AI will take the selected products into account when generating recipes",
"planProductsEmpty": "No products added",
"planProductsEmptyMessage": "Add products you have at home \u2014 AI will suggest recipes from what you already have",
"planProductsAddProducts": "Add products",
"planProductsContinue": "Continue",
"planProductsSkip": "Skip product selection",
"planProductsSkipNoProducts": "Plan without products",
"planProductsSelectAll": "Select all",
"planProductsDeselectAll": "Deselect all"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "Nada encontrado para \"{query}\"",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "Porciones",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "Marcar como comido",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "La IA creará un menú con desayuno, comida y cena para toda la semana",
"generatingMenu": "Generando menú...",
"dayPlannedLabel": "Día planificado",
"planMenuButton": "Planificar comidas",
"planMenuTitle": "¿Qué planificar?",
"planOptionSingleMeal": "Una comida",
@@ -151,6 +154,16 @@
"planSelectMealType": "Tipo de comida",
"planSelectRange": "Seleccionar período",
"planGenerateButton": "Planificar",
"planGenerating": "Generando plan\u2026",
"planSuccess": "¡Menú planificado!"
"planGenerating": "Generando plan",
"planSuccess": "¡Menú planificado!",
"planProductsTitle": "Productos para el menú",
"planProductsSubtitle": "La IA tendrá en cuenta los productos seleccionados al generar recetas",
"planProductsEmpty": "No hay productos añadidos",
"planProductsEmptyMessage": "Añade productos que tengas en casa — la IA sugerirá recetas con lo que ya tienes",
"planProductsAddProducts": "Añadir productos",
"planProductsContinue": "Continuar",
"planProductsSkip": "Omitir selección de productos",
"planProductsSkipNoProducts": "Planificar sin productos",
"planProductsSelectAll": "Seleccionar todo",
"planProductsDeselectAll": "Deseleccionar todo"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "Rien trouvé pour \"{query}\"",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "Portions",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "Marquer comme mangé",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "L'IA créera un menu avec petit-déjeuner, déjeuner et dîner pour toute la semaine",
"generatingMenu": "Génération du menu...",
"dayPlannedLabel": "Jour planifié",
"planMenuButton": "Planifier les repas",
"planMenuTitle": "Que planifier ?",
"planOptionSingleMeal": "Un repas",
@@ -151,6 +154,16 @@
"planSelectMealType": "Type de repas",
"planSelectRange": "Choisir la période",
"planGenerateButton": "Planifier",
"planGenerating": "Génération du plan\u2026",
"planSuccess": "Menu planifié !"
"planGenerating": "Génération du plan",
"planSuccess": "Menu planifié !",
"planProductsTitle": "Produits pour le menu",
"planProductsSubtitle": "L'IA tiendra compte des produits sélectionnés lors de la génération des recettes",
"planProductsEmpty": "Aucun produit ajouté",
"planProductsEmptyMessage": "Ajoutez des produits que vous avez à la maison — l'IA suggérera des recettes à partir de ce que vous avez déjà",
"planProductsAddProducts": "Ajouter des produits",
"planProductsContinue": "Continuer",
"planProductsSkip": "Ignorer la sélection des produits",
"planProductsSkipNoProducts": "Planifier sans produits",
"planProductsSelectAll": "Tout sélectionner",
"planProductsDeselectAll": "Tout désélectionner"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "\"{query}\" के लिए कुछ नहीं मिला",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "सर्विंग",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "खाया हुआ चिह्नित करें",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "AI पूरे सप्ताह के लिए नाश्ता, दोपहर का खाना और रात के खाने के साथ मेनू बनाएगा",
"generatingMenu": "मेनू बना रहे हैं...",
"dayPlannedLabel": "दिन की योजना बनाई गई",
"planMenuButton": "भोजन की योजना बनाएं",
"planMenuTitle": "क्या योजना बनानी है?",
"planOptionSingleMeal": "एक भोजन",
@@ -151,6 +154,16 @@
"planSelectMealType": "भोजन का प्रकार",
"planSelectRange": "अवधि चुनें",
"planGenerateButton": "योजना बनाएं",
"planGenerating": "योजना बना रहे हैं\u2026",
"planSuccess": "मेनू की योजना बनाई गई!"
"planGenerating": "योजना बना रहे हैं",
"planSuccess": "मेनू की योजना बनाई गई!",
"planProductsTitle": "मेनू के लिए उत्पाद",
"planProductsSubtitle": "AI रेसिपी बनाते समय चुने हुए उत्पादों को ध्यान में रखेगा",
"planProductsEmpty": "कोई उत्पाद नहीं जोड़ा गया",
"planProductsEmptyMessage": "घर पर उपलब्ध उत्पाद जोड़ें — AI आपके पास पहले से मौजूद चीज़ों से रेसिपी सुझाएगा",
"planProductsAddProducts": "उत्पाद जोड़ें",
"planProductsContinue": "जारी रखें",
"planProductsSkip": "उत्पाद चयन छोड़ें",
"planProductsSkipNoProducts": "उत्पादों के बिना योजना बनाएं",
"planProductsSelectAll": "सभी चुनें",
"planProductsDeselectAll": "सभी हटाएं"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "Nessun risultato per \"{query}\"",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "Porzioni",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "Segna come mangiato",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "L'AI creerà un menu con colazione, pranzo e cena per tutta la settimana",
"generatingMenu": "Generazione menu...",
"dayPlannedLabel": "Giorno pianificato",
"planMenuButton": "Pianifica i pasti",
"planMenuTitle": "Cosa pianificare?",
"planOptionSingleMeal": "Un pasto",
@@ -151,6 +154,16 @@
"planSelectMealType": "Tipo di pasto",
"planSelectRange": "Seleziona periodo",
"planGenerateButton": "Pianifica",
"planGenerating": "Generazione piano\u2026",
"planSuccess": "Menu pianificato!"
"planGenerating": "Generazione piano",
"planSuccess": "Menu pianificato!",
"planProductsTitle": "Prodotti per il menu",
"planProductsSubtitle": "L'AI terrà conto dei prodotti selezionati nella generazione delle ricette",
"planProductsEmpty": "Nessun prodotto aggiunto",
"planProductsEmptyMessage": "Aggiungi prodotti che hai in casa — l'AI suggerirà ricette con quello che hai già",
"planProductsAddProducts": "Aggiungi prodotti",
"planProductsContinue": "Continua",
"planProductsSkip": "Salta la selezione dei prodotti",
"planProductsSkipNoProducts": "Pianifica senza prodotti",
"planProductsSelectAll": "Seleziona tutto",
"planProductsDeselectAll": "Deseleziona tutto"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "「{query}」の検索結果はありません",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "人前",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "食べた印をつける",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "AIが一週間の朝食・昼食・夕食のメニューを作成します",
"generatingMenu": "メニューを生成中...",
"dayPlannedLabel": "日の計画済み",
"planMenuButton": "食事を計画する",
"planMenuTitle": "何を計画する?",
"planOptionSingleMeal": "1食",
@@ -151,6 +154,16 @@
"planSelectMealType": "食事タイプ",
"planSelectRange": "期間を選択",
"planGenerateButton": "計画する",
"planGenerating": "プランを生成中\u2026",
"planSuccess": "メニューが計画されました!"
"planGenerating": "プランを生成中",
"planSuccess": "メニューが計画されました!",
"planProductsTitle": "メニューの食材",
"planProductsSubtitle": "AIはレシピ生成時に選択した食材を考慮します",
"planProductsEmpty": "食材が追加されていません",
"planProductsEmptyMessage": "家にある食材を追加してください — AIが手持ちの食材でレシピを提案します",
"planProductsAddProducts": "食材を追加",
"planProductsContinue": "続ける",
"planProductsSkip": "食材選択をスキップ",
"planProductsSkipNoProducts": "食材なしでプランニング",
"planProductsSelectAll": "すべて選択",
"planProductsDeselectAll": "すべて解除"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "\"{query}\"에 대한 결과 없음",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "인분",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "먹은 것으로 표시",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "AI가 한 주 동안 아침, 점심, 저녁 식사 메뉴를 만들어 드립니다",
"generatingMenu": "메뉴 생성 중...",
"dayPlannedLabel": "일일 계획 완료",
"planMenuButton": "식사 계획하기",
"planMenuTitle": "무엇을 계획하시겠어요?",
"planOptionSingleMeal": "식사 1회",
@@ -151,6 +154,16 @@
"planSelectMealType": "식사 유형",
"planSelectRange": "기간 선택",
"planGenerateButton": "계획하기",
"planGenerating": "플랜 생성 중\u2026",
"planSuccess": "메뉴가 계획되었습니다!"
"planGenerating": "플랜 생성 중",
"planSuccess": "메뉴가 계획되었습니다!",
"planProductsTitle": "메뉴 재료",
"planProductsSubtitle": "AI가 레시피 생성 시 선택한 재료를 고려합니다",
"planProductsEmpty": "추가된 재료가 없습니다",
"planProductsEmptyMessage": "집에 있는 재료를 추가하세요 — AI가 이미 있는 재료로 레시피를 제안합니다",
"planProductsAddProducts": "재료 추가",
"planProductsContinue": "계속",
"planProductsSkip": "재료 선택 건너뛰기",
"planProductsSkipNoProducts": "재료 없이 계획하기",
"planProductsSelectAll": "모두 선택",
"planProductsDeselectAll": "모두 해제"
}

View File

@@ -927,6 +927,66 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Menu planned!'**
String get planSuccess;
/// No description provided for @planProductsTitle.
///
/// In en, this message translates to:
/// **'Products for the menu'**
String get planProductsTitle;
/// No description provided for @planProductsSubtitle.
///
/// In en, this message translates to:
/// **'AI will take the selected products into account when generating recipes'**
String get planProductsSubtitle;
/// No description provided for @planProductsEmpty.
///
/// In en, this message translates to:
/// **'No products added'**
String get planProductsEmpty;
/// No description provided for @planProductsEmptyMessage.
///
/// In en, this message translates to:
/// **'Add products you have at home — AI will suggest recipes from what you already have'**
String get planProductsEmptyMessage;
/// No description provided for @planProductsAddProducts.
///
/// In en, this message translates to:
/// **'Add products'**
String get planProductsAddProducts;
/// No description provided for @planProductsContinue.
///
/// In en, this message translates to:
/// **'Continue'**
String get planProductsContinue;
/// No description provided for @planProductsSkip.
///
/// In en, this message translates to:
/// **'Skip product selection'**
String get planProductsSkip;
/// No description provided for @planProductsSkipNoProducts.
///
/// In en, this message translates to:
/// **'Plan without products'**
String get planProductsSkipNoProducts;
/// No description provided for @planProductsSelectAll.
///
/// In en, this message translates to:
/// **'Select all'**
String get planProductsSelectAll;
/// No description provided for @planProductsDeselectAll.
///
/// In en, this message translates to:
/// **'Deselect all'**
String get planProductsDeselectAll;
}
class _AppLocalizationsDelegate

View File

@@ -420,4 +420,36 @@ class AppLocalizationsAr extends AppLocalizations {
@override
String get planSuccess => 'تم تخطيط القائمة!';
@override
String get planProductsTitle => 'مكونات القائمة';
@override
String get planProductsSubtitle =>
'سيأخذ الذكاء الاصطناعي المكونات المختارة بعين الاعتبار عند إنشاء الوصفات';
@override
String get planProductsEmpty => 'لم يتم إضافة منتجات';
@override
String get planProductsEmptyMessage =>
'أضف المنتجات الموجودة لديك في المنزل — سيقترح الذكاء الاصطناعي وصفات مما لديك بالفعل';
@override
String get planProductsAddProducts => 'إضافة منتجات';
@override
String get planProductsContinue => 'متابعة';
@override
String get planProductsSkip => 'تخطي اختيار المنتجات';
@override
String get planProductsSkipNoProducts => 'التخطيط بدون منتجات';
@override
String get planProductsSelectAll => 'تحديد الكل';
@override
String get planProductsDeselectAll => 'إلغاء تحديد الكل';
}

View File

@@ -422,4 +422,36 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get planSuccess => 'Menü geplant!';
@override
String get planProductsTitle => 'Zutaten für den Speiseplan';
@override
String get planProductsSubtitle =>
'Die KI berücksichtigt die ausgewählten Produkte bei der Rezeptgenerierung';
@override
String get planProductsEmpty => 'Keine Produkte hinzugefügt';
@override
String get planProductsEmptyMessage =>
'Füge Produkte hinzu, die du zu Hause hast — die KI schlägt Rezepte aus deinen Vorräten vor';
@override
String get planProductsAddProducts => 'Produkte hinzufügen';
@override
String get planProductsContinue => 'Weiter';
@override
String get planProductsSkip => 'Produktauswahl überspringen';
@override
String get planProductsSkipNoProducts => 'Ohne Produkte planen';
@override
String get planProductsSelectAll => 'Alle auswählen';
@override
String get planProductsDeselectAll => 'Alle abwählen';
}

View File

@@ -420,4 +420,36 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get planSuccess => 'Menu planned!';
@override
String get planProductsTitle => 'Products for the menu';
@override
String get planProductsSubtitle =>
'AI will take the selected products into account when generating recipes';
@override
String get planProductsEmpty => 'No products added';
@override
String get planProductsEmptyMessage =>
'Add products you have at home — AI will suggest recipes from what you already have';
@override
String get planProductsAddProducts => 'Add products';
@override
String get planProductsContinue => 'Continue';
@override
String get planProductsSkip => 'Skip product selection';
@override
String get planProductsSkipNoProducts => 'Plan without products';
@override
String get planProductsSelectAll => 'Select all';
@override
String get planProductsDeselectAll => 'Deselect all';
}

View File

@@ -422,4 +422,36 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get planSuccess => '¡Menú planificado!';
@override
String get planProductsTitle => 'Productos para el menú';
@override
String get planProductsSubtitle =>
'La IA tendrá en cuenta los productos seleccionados al generar recetas';
@override
String get planProductsEmpty => 'No hay productos añadidos';
@override
String get planProductsEmptyMessage =>
'Añade productos que tengas en casa — la IA sugerirá recetas con lo que ya tienes';
@override
String get planProductsAddProducts => 'Añadir productos';
@override
String get planProductsContinue => 'Continuar';
@override
String get planProductsSkip => 'Omitir selección de productos';
@override
String get planProductsSkipNoProducts => 'Planificar sin productos';
@override
String get planProductsSelectAll => 'Seleccionar todo';
@override
String get planProductsDeselectAll => 'Deseleccionar todo';
}

View File

@@ -423,4 +423,36 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get planSuccess => 'Menu planifié !';
@override
String get planProductsTitle => 'Produits pour le menu';
@override
String get planProductsSubtitle =>
'L\'IA tiendra compte des produits sélectionnés lors de la génération des recettes';
@override
String get planProductsEmpty => 'Aucun produit ajouté';
@override
String get planProductsEmptyMessage =>
'Ajoutez des produits que vous avez à la maison — l\'IA suggérera des recettes à partir de ce que vous avez déjà';
@override
String get planProductsAddProducts => 'Ajouter des produits';
@override
String get planProductsContinue => 'Continuer';
@override
String get planProductsSkip => 'Ignorer la sélection des produits';
@override
String get planProductsSkipNoProducts => 'Planifier sans produits';
@override
String get planProductsSelectAll => 'Tout sélectionner';
@override
String get planProductsDeselectAll => 'Tout désélectionner';
}

View File

@@ -421,4 +421,36 @@ class AppLocalizationsHi extends AppLocalizations {
@override
String get planSuccess => 'मेनू की योजना बनाई गई!';
@override
String get planProductsTitle => 'मेनू के लिए उत्पाद';
@override
String get planProductsSubtitle =>
'AI रेसिपी बनाते समय चुने हुए उत्पादों को ध्यान में रखेगा';
@override
String get planProductsEmpty => 'कोई उत्पाद नहीं जोड़ा गया';
@override
String get planProductsEmptyMessage =>
'घर पर उपलब्ध उत्पाद जोड़ें — AI आपके पास पहले से मौजूद चीज़ों से रेसिपी सुझाएगा';
@override
String get planProductsAddProducts => 'उत्पाद जोड़ें';
@override
String get planProductsContinue => 'जारी रखें';
@override
String get planProductsSkip => 'उत्पाद चयन छोड़ें';
@override
String get planProductsSkipNoProducts => 'उत्पादों के बिना योजना बनाएं';
@override
String get planProductsSelectAll => 'सभी चुनें';
@override
String get planProductsDeselectAll => 'सभी हटाएं';
}

View File

@@ -422,4 +422,36 @@ class AppLocalizationsIt extends AppLocalizations {
@override
String get planSuccess => 'Menu pianificato!';
@override
String get planProductsTitle => 'Prodotti per il menu';
@override
String get planProductsSubtitle =>
'L\'AI terrà conto dei prodotti selezionati nella generazione delle ricette';
@override
String get planProductsEmpty => 'Nessun prodotto aggiunto';
@override
String get planProductsEmptyMessage =>
'Aggiungi prodotti che hai in casa — l\'AI suggerirà ricette con quello che hai già';
@override
String get planProductsAddProducts => 'Aggiungi prodotti';
@override
String get planProductsContinue => 'Continua';
@override
String get planProductsSkip => 'Salta la selezione dei prodotti';
@override
String get planProductsSkipNoProducts => 'Pianifica senza prodotti';
@override
String get planProductsSelectAll => 'Seleziona tutto';
@override
String get planProductsDeselectAll => 'Deseleziona tutto';
}

View File

@@ -418,4 +418,35 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get planSuccess => 'メニューが計画されました!';
@override
String get planProductsTitle => 'メニューの食材';
@override
String get planProductsSubtitle => 'AIはレシピ生成時に選択した食材を考慮します';
@override
String get planProductsEmpty => '食材が追加されていません';
@override
String get planProductsEmptyMessage =>
'家にある食材を追加してください — AIが手持ちの食材でレシピを提案します';
@override
String get planProductsAddProducts => '食材を追加';
@override
String get planProductsContinue => '続ける';
@override
String get planProductsSkip => '食材選択をスキップ';
@override
String get planProductsSkipNoProducts => '食材なしでプランニング';
@override
String get planProductsSelectAll => 'すべて選択';
@override
String get planProductsDeselectAll => 'すべて解除';
}

View File

@@ -418,4 +418,35 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get planSuccess => '메뉴가 계획되었습니다!';
@override
String get planProductsTitle => '메뉴 재료';
@override
String get planProductsSubtitle => 'AI가 레시피 생성 시 선택한 재료를 고려합니다';
@override
String get planProductsEmpty => '추가된 재료가 없습니다';
@override
String get planProductsEmptyMessage =>
'집에 있는 재료를 추가하세요 — AI가 이미 있는 재료로 레시피를 제안합니다';
@override
String get planProductsAddProducts => '재료 추가';
@override
String get planProductsContinue => '계속';
@override
String get planProductsSkip => '재료 선택 건너뛰기';
@override
String get planProductsSkipNoProducts => '재료 없이 계획하기';
@override
String get planProductsSelectAll => '모두 선택';
@override
String get planProductsDeselectAll => '모두 해제';
}

View File

@@ -422,4 +422,36 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get planSuccess => 'Menu planejado!';
@override
String get planProductsTitle => 'Produtos para o menu';
@override
String get planProductsSubtitle =>
'A IA levará em conta os produtos selecionados ao gerar receitas';
@override
String get planProductsEmpty => 'Nenhum produto adicionado';
@override
String get planProductsEmptyMessage =>
'Adicione produtos que você tem em casa — a IA sugerirá receitas com o que você já tem';
@override
String get planProductsAddProducts => 'Adicionar produtos';
@override
String get planProductsContinue => 'Continuar';
@override
String get planProductsSkip => 'Pular seleção de produtos';
@override
String get planProductsSkipNoProducts => 'Planejar sem produtos';
@override
String get planProductsSelectAll => 'Selecionar tudo';
@override
String get planProductsDeselectAll => 'Desmarcar tudo';
}

View File

@@ -420,4 +420,36 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get planSuccess => 'Меню запланировано!';
@override
String get planProductsTitle => 'Продукты для меню';
@override
String get planProductsSubtitle =>
'AI учтёт выбранные продукты при составлении рецептов';
@override
String get planProductsEmpty => 'Продукты не добавлены';
@override
String get planProductsEmptyMessage =>
'Добавьте продукты, которые есть у вас дома — AI подберёт рецепты из того, что уже есть';
@override
String get planProductsAddProducts => 'Добавить продукты';
@override
String get planProductsContinue => 'Продолжить';
@override
String get planProductsSkip => 'Пропустить выбор продуктов';
@override
String get planProductsSkipNoProducts => 'Планировать без продуктов';
@override
String get planProductsSelectAll => 'Выбрать все';
@override
String get planProductsDeselectAll => 'Снять всё';
}

View File

@@ -418,4 +418,34 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get planSuccess => '菜单已规划!';
@override
String get planProductsTitle => '菜单食材';
@override
String get planProductsSubtitle => 'AI在生成食谱时会考虑所选食材';
@override
String get planProductsEmpty => '尚未添加食材';
@override
String get planProductsEmptyMessage => '添加您家中的食材 — AI将根据您已有的食材推荐食谱';
@override
String get planProductsAddProducts => '添加食材';
@override
String get planProductsContinue => '继续';
@override
String get planProductsSkip => '跳过食材选择';
@override
String get planProductsSkipNoProducts => '不选食材直接规划';
@override
String get planProductsSelectAll => '全选';
@override
String get planProductsDeselectAll => '取消全选';
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "Nada encontrado para \"{query}\"",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "Porções",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "Marcar como comido",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "A IA criará um menu com café da manhã, almoço e jantar para a semana inteira",
"generatingMenu": "Gerando menu...",
"dayPlannedLabel": "Dia planejado",
"planMenuButton": "Planejar refeições",
"planMenuTitle": "O que planejar?",
"planOptionSingleMeal": "Uma refeição",
@@ -151,6 +154,16 @@
"planSelectMealType": "Tipo de refeição",
"planSelectRange": "Selecionar período",
"planGenerateButton": "Planejar",
"planGenerating": "Gerando plano\u2026",
"planSuccess": "Menu planejado!"
"planGenerating": "Gerando plano",
"planSuccess": "Menu planejado!",
"planProductsTitle": "Produtos para o menu",
"planProductsSubtitle": "A IA levará em conta os produtos selecionados ao gerar receitas",
"planProductsEmpty": "Nenhum produto adicionado",
"planProductsEmptyMessage": "Adicione produtos que você tem em casa — a IA sugerirá receitas com o que você já tem",
"planProductsAddProducts": "Adicionar produtos",
"planProductsContinue": "Continuar",
"planProductsSkip": "Pular seleção de produtos",
"planProductsSkipNoProducts": "Planejar sem produtos",
"planProductsSelectAll": "Selecionar tudo",
"planProductsDeselectAll": "Desmarcar tudo"
}

View File

@@ -28,7 +28,9 @@
"queuePosition": "Позиция {position}",
"@queuePosition": {
"placeholders": {
"position": { "type": "int" }
"position": {
"type": "int"
}
}
},
"processing": "Обрабатываем...",
@@ -116,7 +118,9 @@
"noResultsForQuery": "По запросу \"{query}\" ничего не найдено",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "Порций",
@@ -125,7 +129,9 @@
"planningForDate": "Планирование на {date}",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "Отметить как съеденное",
@@ -134,7 +140,6 @@
"generateWeekSubtitle": "AI составит меню с завтраком, обедом и ужином на всю неделю",
"generatingMenu": "Генерируем меню...",
"dayPlannedLabel": "День запланирован",
"planMenuButton": "Спланировать меню",
"planMenuTitle": "Что запланировать?",
"planOptionSingleMeal": "1 приём пищи",
@@ -149,6 +154,16 @@
"planSelectMealType": "Приём пищи",
"planSelectRange": "Выберите период",
"planGenerateButton": "Запланировать",
"planGenerating": "Генерирую план\u2026",
"planSuccess": "Меню запланировано!"
"planGenerating": "Генерирую план",
"planSuccess": "Меню запланировано!",
"planProductsTitle": "Продукты для меню",
"planProductsSubtitle": "AI учтёт выбранные продукты при составлении рецептов",
"planProductsEmpty": "Продукты не добавлены",
"planProductsEmptyMessage": "Добавьте продукты, которые есть у вас дома — AI подберёт рецепты из того, что уже есть",
"planProductsAddProducts": "Добавить продукты",
"planProductsContinue": "Продолжить",
"planProductsSkip": "Пропустить выбор продуктов",
"planProductsSkipNoProducts": "Планировать без продуктов",
"planProductsSelectAll": "Выбрать все",
"planProductsDeselectAll": "Снять всё"
}

View File

@@ -118,7 +118,9 @@
"noResultsForQuery": "未找到 \"{query}\" 的结果",
"@noResultsForQuery": {
"placeholders": {
"query": { "type": "String" }
"query": {
"type": "String"
}
}
},
"servingsLabel": "份数",
@@ -127,7 +129,9 @@
"planningForDate": "",
"@planningForDate": {
"placeholders": {
"date": { "type": "String" }
"date": {
"type": "String"
}
}
},
"markAsEaten": "标记为已吃",
@@ -136,7 +140,6 @@
"generateWeekSubtitle": "AI将为整周创建含早餐、午餐和晚餐的菜单",
"generatingMenu": "正在生成菜单...",
"dayPlannedLabel": "今日已规划",
"planMenuButton": "规划餐食",
"planMenuTitle": "规划什么?",
"planOptionSingleMeal": "单次餐食",
@@ -151,6 +154,16 @@
"planSelectMealType": "餐食类型",
"planSelectRange": "选择时间段",
"planGenerateButton": "规划",
"planGenerating": "正在生成计划\u2026",
"planSuccess": "菜单已规划!"
"planGenerating": "正在生成计划",
"planSuccess": "菜单已规划!",
"planProductsTitle": "菜单食材",
"planProductsSubtitle": "AI在生成食谱时会考虑所选食材",
"planProductsEmpty": "尚未添加食材",
"planProductsEmptyMessage": "添加您家中的食材 — AI将根据您已有的食材推荐食谱",
"planProductsAddProducts": "添加食材",
"planProductsContinue": "继续",
"planProductsSkip": "跳过食材选择",
"planProductsSkipNoProducts": "不选食材直接规划",
"planProductsSelectAll": "全选",
"planProductsDeselectAll": "取消全选"
}