feat: product search screen with catalog add and success feedback

- Add product search screen (/products/search) as primary add flow;
  "Add" button on products list opens search, manual entry remains as fallback
- Add to shelf bottom sheet with AnimatedSwitcher success view (green checkmark)
  and SnackBar confirmation on the search screen via onAdded callback
- Manual add (AddProductScreen) shows SnackBar on success before popping back
- Extend AddProductScreen with optional nutrition fields (calories, protein,
  fat, carbs, fiber); auto-fills from catalog selection and auto-expands section
- Auto-upsert catalog product on backend when nutrition data is provided
  without a primary_product_id, linking the user product to the catalog
- Add fiber_per_100g field to CatalogProduct model and CreateRequest
- Add 16 new L10n keys across all 12 locales (addProduct, addManually,
  searchProducts, quantity, storageDays, addToShelf, nutritionOptional,
  calories, protein, fat, carbs, fiber, productAddedToShelf, etc.)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
dbastrikin
2026-03-26 14:04:58 +02:00
parent 16d944c80e
commit 8d33a4eb30
40 changed files with 2167 additions and 74 deletions

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "إيصال",
"jobTypeProducts": "منتجات",
"scanSubmitting": "جارٍ الإرسال...",
"processingProducts": "جارٍ المعالجة..."
"processingProducts": "جارٍ المعالجة...",
"clearAllProducts": "مسح الكل",
"clearAllConfirmTitle": "مسح جميع المنتجات؟",
"clearAllConfirmMessage": "سيتم حذف جميع المنتجات نهائياً.",
"addManually": "يدويًا",
"scan": "مسح ضوئي",
"addProduct": "إضافة",
"searchProducts": "البحث عن المنتجات",
"searchProductsHint": "اكتب اسم المنتج أو أضف يدويًا",
"noSearchResults": "لا توجد نتائج لـ\"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "الكمية",
"storageDays": "أيام التخزين",
"addToShelf": "إضافة إلى المخزن",
"errorGeneric": "حدث خطأ ما",
"nutritionOptional": "القيم الغذائية لكل 100 جم (اختياري)",
"calories": "سعرات حرارية",
"protein": "بروتين",
"fat": "دهون",
"carbs": "كربوهيدرات",
"fiber": "ألياف",
"productAddedToShelf": "تمت الإضافة إلى المخزن"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "Kassenbon",
"jobTypeProducts": "Produkte",
"scanSubmitting": "Wird gesendet...",
"processingProducts": "Verarbeitung..."
"processingProducts": "Verarbeitung...",
"clearAllProducts": "Alles löschen",
"clearAllConfirmTitle": "Alle Produkte löschen?",
"clearAllConfirmMessage": "Alle Produkte werden dauerhaft gelöscht.",
"addManually": "Manuell",
"scan": "Scannen",
"addProduct": "Hinzufügen",
"searchProducts": "Produkte suchen",
"searchProductsHint": "Produktname eingeben oder manuell hinzufügen",
"noSearchResults": "Keine Ergebnisse für \"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "Menge",
"storageDays": "Lagertage",
"addToShelf": "Zum Vorrat hinzufügen",
"errorGeneric": "Etwas ist schiefgelaufen",
"nutritionOptional": "Nährwerte pro 100g (optional)",
"calories": "Kalorien",
"protein": "Eiweiß",
"fat": "Fett",
"carbs": "Kohlenhydrate",
"fiber": "Ballaststoffe",
"productAddedToShelf": "Zum Vorrat hinzugefügt"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "Receipt",
"jobTypeProducts": "Products",
"scanSubmitting": "Submitting...",
"processingProducts": "Processing..."
"processingProducts": "Processing...",
"clearAllProducts": "Clear all",
"clearAllConfirmTitle": "Clear all products?",
"clearAllConfirmMessage": "All products will be permanently deleted.",
"addManually": "Manually",
"scan": "Scan",
"addProduct": "Add",
"searchProducts": "Search products",
"searchProductsHint": "Type a product name to search or add manually",
"noSearchResults": "No results for \"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "Quantity",
"storageDays": "Storage days",
"addToShelf": "Add to pantry",
"errorGeneric": "Something went wrong",
"nutritionOptional": "Nutrition per 100g (optional)",
"calories": "Calories",
"protein": "Protein",
"fat": "Fat",
"carbs": "Carbohydrates",
"fiber": "Fiber",
"productAddedToShelf": "Added to pantry"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "Ticket",
"jobTypeProducts": "Productos",
"scanSubmitting": "Enviando...",
"processingProducts": "Procesando..."
"processingProducts": "Procesando...",
"clearAllProducts": "Borrar todo",
"clearAllConfirmTitle": "¿Borrar todos los productos?",
"clearAllConfirmMessage": "Todos los productos serán eliminados permanentemente.",
"addManually": "Manual",
"scan": "Escanear",
"addProduct": "Agregar",
"searchProducts": "Buscar productos",
"searchProductsHint": "Escribe el nombre del producto o agrega manualmente",
"noSearchResults": "Sin resultados para \"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "Cantidad",
"storageDays": "Días de almacenamiento",
"addToShelf": "Agregar a despensa",
"errorGeneric": "Algo salió mal",
"nutritionOptional": "Nutrición por 100g (opcional)",
"calories": "Calorías",
"protein": "Proteína",
"fat": "Grasas",
"carbs": "Carbohidratos",
"fiber": "Fibra",
"productAddedToShelf": "Agregado a la despensa"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "Reçu",
"jobTypeProducts": "Produits",
"scanSubmitting": "Envoi...",
"processingProducts": "Traitement..."
"processingProducts": "Traitement...",
"clearAllProducts": "Tout effacer",
"clearAllConfirmTitle": "Effacer tous les produits ?",
"clearAllConfirmMessage": "Tous les produits seront définitivement supprimés.",
"addManually": "Manuellement",
"scan": "Scanner",
"addProduct": "Ajouter",
"searchProducts": "Rechercher des produits",
"searchProductsHint": "Tapez un nom de produit ou ajoutez manuellement",
"noSearchResults": "Aucun résultat pour \"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "Quantité",
"storageDays": "Jours de conservation",
"addToShelf": "Ajouter au garde-manger",
"errorGeneric": "Une erreur est survenue",
"nutritionOptional": "Nutrition pour 100g (facultatif)",
"calories": "Calories",
"protein": "Protéines",
"fat": "Graisses",
"carbs": "Glucides",
"fiber": "Fibres",
"productAddedToShelf": "Ajouté au garde-manger"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "रसीद",
"jobTypeProducts": "उत्पाद",
"scanSubmitting": "सबमिट हो रहा है...",
"processingProducts": "प्रोसेस हो रहा है..."
"processingProducts": "प्रोसेस हो रहा है...",
"clearAllProducts": "सब साफ करें",
"clearAllConfirmTitle": "सभी उत्पाद साफ करें?",
"clearAllConfirmMessage": "सभी उत्पाद स्थायी रूप से हटा दिए जाएंगे।",
"addManually": "मैन्युअल",
"scan": "स्कैन करें",
"addProduct": "जोड़ें",
"searchProducts": "उत्पाद खोजें",
"searchProductsHint": "उत्पाद का नाम टाइप करें या मैन्युअल रूप से जोड़ें",
"noSearchResults": "\"{query}\" के लिए कोई परिणाम नहीं",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "मात्रा",
"storageDays": "भंडारण दिन",
"addToShelf": "पेंट्री में जोड़ें",
"errorGeneric": "कुछ गलत हो गया",
"nutritionOptional": "पोषण मूल्य प्रति 100 ग्राम (वैकल्पिक)",
"calories": "कैलोरी",
"protein": "प्रोटीन",
"fat": "वसा",
"carbs": "कार्बोहाइड्रेट",
"fiber": "फाइबर",
"productAddedToShelf": "पेंट्री में जोड़ा गया"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "Scontrino",
"jobTypeProducts": "Prodotti",
"scanSubmitting": "Invio...",
"processingProducts": "Elaborazione..."
"processingProducts": "Elaborazione...",
"clearAllProducts": "Cancella tutto",
"clearAllConfirmTitle": "Cancellare tutti i prodotti?",
"clearAllConfirmMessage": "Tutti i prodotti verranno eliminati definitivamente.",
"addManually": "Manualmente",
"scan": "Scansiona",
"addProduct": "Aggiungi",
"searchProducts": "Cerca prodotti",
"searchProductsHint": "Digita il nome del prodotto o aggiungi manualmente",
"noSearchResults": "Nessun risultato per \"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "Quantità",
"storageDays": "Giorni di conservazione",
"addToShelf": "Aggiungi alla dispensa",
"errorGeneric": "Qualcosa è andato storto",
"nutritionOptional": "Valori nutrizionali per 100g (opzionale)",
"calories": "Calorie",
"protein": "Proteine",
"fat": "Grassi",
"carbs": "Carboidrati",
"fiber": "Fibre",
"productAddedToShelf": "Aggiunto alla dispensa"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "レシート",
"jobTypeProducts": "商品",
"scanSubmitting": "送信中...",
"processingProducts": "処理中..."
"processingProducts": "処理中...",
"clearAllProducts": "すべてクリア",
"clearAllConfirmTitle": "すべての商品をクリアしますか?",
"clearAllConfirmMessage": "すべての商品が完全に削除されます。",
"addManually": "手動",
"scan": "スキャン",
"addProduct": "追加",
"searchProducts": "製品を検索",
"searchProductsHint": "製品名を入力するか手動で追加してください",
"noSearchResults": "「{query}」の検索結果はありません",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "数量",
"storageDays": "保存日数",
"addToShelf": "パントリーに追加",
"errorGeneric": "エラーが発生しました",
"nutritionOptional": "100gあたりの栄養素任意",
"calories": "カロリー",
"protein": "タンパク質",
"fat": "脂質",
"carbs": "炭水化物",
"fiber": "食物繊維",
"productAddedToShelf": "パントリーに追加しました"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "영수증",
"jobTypeProducts": "제품",
"scanSubmitting": "제출 중...",
"processingProducts": "처리 중..."
"processingProducts": "처리 중...",
"clearAllProducts": "모두 지우기",
"clearAllConfirmTitle": "모든 제품을 지울까요?",
"clearAllConfirmMessage": "모든 제품이 영구적으로 삭제됩니다.",
"addManually": "수동",
"scan": "스캔",
"addProduct": "추가",
"searchProducts": "제품 검색",
"searchProductsHint": "제품 이름을 입력하거나 수동으로 추가하세요",
"noSearchResults": "「{query}」에 대한 결과가 없습니다",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "수량",
"storageDays": "보관 일수",
"addToShelf": "저장실에 추가",
"errorGeneric": "오류가 발생했습니다",
"nutritionOptional": "100g당 영양성분 (선택사항)",
"calories": "칼로리",
"protein": "단백질",
"fat": "지방",
"carbs": "탄수화물",
"fiber": "식이섬유",
"productAddedToShelf": "저장실에 추가되었습니다"
}

View File

@@ -1029,6 +1029,126 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Processing...'**
String get processingProducts;
/// No description provided for @clearAllProducts.
///
/// In en, this message translates to:
/// **'Clear all'**
String get clearAllProducts;
/// No description provided for @clearAllConfirmTitle.
///
/// In en, this message translates to:
/// **'Clear all products?'**
String get clearAllConfirmTitle;
/// No description provided for @clearAllConfirmMessage.
///
/// In en, this message translates to:
/// **'All products will be permanently deleted.'**
String get clearAllConfirmMessage;
/// No description provided for @addManually.
///
/// In en, this message translates to:
/// **'Manually'**
String get addManually;
/// No description provided for @scan.
///
/// In en, this message translates to:
/// **'Scan'**
String get scan;
/// No description provided for @addProduct.
///
/// In en, this message translates to:
/// **'Add'**
String get addProduct;
/// No description provided for @searchProducts.
///
/// In en, this message translates to:
/// **'Search products'**
String get searchProducts;
/// No description provided for @searchProductsHint.
///
/// In en, this message translates to:
/// **'Type a product name to search or add manually'**
String get searchProductsHint;
/// No description provided for @noSearchResults.
///
/// In en, this message translates to:
/// **'No results for \"{query}\"'**
String noSearchResults(String query);
/// No description provided for @quantity.
///
/// In en, this message translates to:
/// **'Quantity'**
String get quantity;
/// No description provided for @storageDays.
///
/// In en, this message translates to:
/// **'Storage days'**
String get storageDays;
/// No description provided for @addToShelf.
///
/// In en, this message translates to:
/// **'Add to pantry'**
String get addToShelf;
/// No description provided for @errorGeneric.
///
/// In en, this message translates to:
/// **'Something went wrong'**
String get errorGeneric;
/// No description provided for @nutritionOptional.
///
/// In en, this message translates to:
/// **'Nutrition per 100g (optional)'**
String get nutritionOptional;
/// No description provided for @calories.
///
/// In en, this message translates to:
/// **'Calories'**
String get calories;
/// No description provided for @protein.
///
/// In en, this message translates to:
/// **'Protein'**
String get protein;
/// No description provided for @fat.
///
/// In en, this message translates to:
/// **'Fat'**
String get fat;
/// No description provided for @carbs.
///
/// In en, this message translates to:
/// **'Carbohydrates'**
String get carbs;
/// No description provided for @fiber.
///
/// In en, this message translates to:
/// **'Fiber'**
String get fiber;
/// No description provided for @productAddedToShelf.
///
/// In en, this message translates to:
/// **'Added to pantry'**
String get productAddedToShelf;
}
class _AppLocalizationsDelegate

View File

@@ -473,4 +473,66 @@ class AppLocalizationsAr extends AppLocalizations {
@override
String get processingProducts => 'جارٍ المعالجة...';
@override
String get clearAllProducts => 'مسح الكل';
@override
String get clearAllConfirmTitle => 'مسح جميع المنتجات؟';
@override
String get clearAllConfirmMessage => 'سيتم حذف جميع المنتجات نهائياً.';
@override
String get addManually => 'يدويًا';
@override
String get scan => 'مسح ضوئي';
@override
String get addProduct => 'إضافة';
@override
String get searchProducts => 'البحث عن المنتجات';
@override
String get searchProductsHint => 'اكتب اسم المنتج أو أضف يدويًا';
@override
String noSearchResults(String query) {
return 'لا توجد نتائج لـ\"$query\"';
}
@override
String get quantity => 'الكمية';
@override
String get storageDays => 'أيام التخزين';
@override
String get addToShelf => 'إضافة إلى المخزن';
@override
String get errorGeneric => 'حدث خطأ ما';
@override
String get nutritionOptional => 'القيم الغذائية لكل 100 جم (اختياري)';
@override
String get calories => 'سعرات حرارية';
@override
String get protein => 'بروتين';
@override
String get fat => 'دهون';
@override
String get carbs => 'كربوهيدرات';
@override
String get fiber => 'ألياف';
@override
String get productAddedToShelf => 'تمت الإضافة إلى المخزن';
}

View File

@@ -475,4 +475,68 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get processingProducts => 'Verarbeitung...';
@override
String get clearAllProducts => 'Alles löschen';
@override
String get clearAllConfirmTitle => 'Alle Produkte löschen?';
@override
String get clearAllConfirmMessage =>
'Alle Produkte werden dauerhaft gelöscht.';
@override
String get addManually => 'Manuell';
@override
String get scan => 'Scannen';
@override
String get addProduct => 'Hinzufügen';
@override
String get searchProducts => 'Produkte suchen';
@override
String get searchProductsHint =>
'Produktname eingeben oder manuell hinzufügen';
@override
String noSearchResults(String query) {
return 'Keine Ergebnisse für \"$query\"';
}
@override
String get quantity => 'Menge';
@override
String get storageDays => 'Lagertage';
@override
String get addToShelf => 'Zum Vorrat hinzufügen';
@override
String get errorGeneric => 'Etwas ist schiefgelaufen';
@override
String get nutritionOptional => 'Nährwerte pro 100g (optional)';
@override
String get calories => 'Kalorien';
@override
String get protein => 'Eiweiß';
@override
String get fat => 'Fett';
@override
String get carbs => 'Kohlenhydrate';
@override
String get fiber => 'Ballaststoffe';
@override
String get productAddedToShelf => 'Zum Vorrat hinzugefügt';
}

View File

@@ -473,4 +473,68 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get processingProducts => 'Processing...';
@override
String get clearAllProducts => 'Clear all';
@override
String get clearAllConfirmTitle => 'Clear all products?';
@override
String get clearAllConfirmMessage =>
'All products will be permanently deleted.';
@override
String get addManually => 'Manually';
@override
String get scan => 'Scan';
@override
String get addProduct => 'Add';
@override
String get searchProducts => 'Search products';
@override
String get searchProductsHint =>
'Type a product name to search or add manually';
@override
String noSearchResults(String query) {
return 'No results for \"$query\"';
}
@override
String get quantity => 'Quantity';
@override
String get storageDays => 'Storage days';
@override
String get addToShelf => 'Add to pantry';
@override
String get errorGeneric => 'Something went wrong';
@override
String get nutritionOptional => 'Nutrition per 100g (optional)';
@override
String get calories => 'Calories';
@override
String get protein => 'Protein';
@override
String get fat => 'Fat';
@override
String get carbs => 'Carbohydrates';
@override
String get fiber => 'Fiber';
@override
String get productAddedToShelf => 'Added to pantry';
}

View File

@@ -475,4 +475,68 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get processingProducts => 'Procesando...';
@override
String get clearAllProducts => 'Borrar todo';
@override
String get clearAllConfirmTitle => '¿Borrar todos los productos?';
@override
String get clearAllConfirmMessage =>
'Todos los productos serán eliminados permanentemente.';
@override
String get addManually => 'Manual';
@override
String get scan => 'Escanear';
@override
String get addProduct => 'Agregar';
@override
String get searchProducts => 'Buscar productos';
@override
String get searchProductsHint =>
'Escribe el nombre del producto o agrega manualmente';
@override
String noSearchResults(String query) {
return 'Sin resultados para \"$query\"';
}
@override
String get quantity => 'Cantidad';
@override
String get storageDays => 'Días de almacenamiento';
@override
String get addToShelf => 'Agregar a despensa';
@override
String get errorGeneric => 'Algo salió mal';
@override
String get nutritionOptional => 'Nutrición por 100g (opcional)';
@override
String get calories => 'Calorías';
@override
String get protein => 'Proteína';
@override
String get fat => 'Grasas';
@override
String get carbs => 'Carbohidratos';
@override
String get fiber => 'Fibra';
@override
String get productAddedToShelf => 'Agregado a la despensa';
}

View File

@@ -476,4 +476,68 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get processingProducts => 'Traitement...';
@override
String get clearAllProducts => 'Tout effacer';
@override
String get clearAllConfirmTitle => 'Effacer tous les produits ?';
@override
String get clearAllConfirmMessage =>
'Tous les produits seront définitivement supprimés.';
@override
String get addManually => 'Manuellement';
@override
String get scan => 'Scanner';
@override
String get addProduct => 'Ajouter';
@override
String get searchProducts => 'Rechercher des produits';
@override
String get searchProductsHint =>
'Tapez un nom de produit ou ajoutez manuellement';
@override
String noSearchResults(String query) {
return 'Aucun résultat pour \"$query\"';
}
@override
String get quantity => 'Quantité';
@override
String get storageDays => 'Jours de conservation';
@override
String get addToShelf => 'Ajouter au garde-manger';
@override
String get errorGeneric => 'Une erreur est survenue';
@override
String get nutritionOptional => 'Nutrition pour 100g (facultatif)';
@override
String get calories => 'Calories';
@override
String get protein => 'Protéines';
@override
String get fat => 'Graisses';
@override
String get carbs => 'Glucides';
@override
String get fiber => 'Fibres';
@override
String get productAddedToShelf => 'Ajouté au garde-manger';
}

View File

@@ -474,4 +474,68 @@ class AppLocalizationsHi extends AppLocalizations {
@override
String get processingProducts => 'प्रोसेस हो रहा है...';
@override
String get clearAllProducts => 'सब साफ करें';
@override
String get clearAllConfirmTitle => 'सभी उत्पाद साफ करें?';
@override
String get clearAllConfirmMessage =>
'सभी उत्पाद स्थायी रूप से हटा दिए जाएंगे।';
@override
String get addManually => 'मैन्युअल';
@override
String get scan => 'स्कैन करें';
@override
String get addProduct => 'जोड़ें';
@override
String get searchProducts => 'उत्पाद खोजें';
@override
String get searchProductsHint =>
'उत्पाद का नाम टाइप करें या मैन्युअल रूप से जोड़ें';
@override
String noSearchResults(String query) {
return '\"$query\" के लिए कोई परिणाम नहीं';
}
@override
String get quantity => 'मात्रा';
@override
String get storageDays => 'भंडारण दिन';
@override
String get addToShelf => 'पेंट्री में जोड़ें';
@override
String get errorGeneric => 'कुछ गलत हो गया';
@override
String get nutritionOptional => 'पोषण मूल्य प्रति 100 ग्राम (वैकल्पिक)';
@override
String get calories => 'कैलोरी';
@override
String get protein => 'प्रोटीन';
@override
String get fat => 'वसा';
@override
String get carbs => 'कार्बोहाइड्रेट';
@override
String get fiber => 'फाइबर';
@override
String get productAddedToShelf => 'पेंट्री में जोड़ा गया';
}

View File

@@ -475,4 +475,68 @@ class AppLocalizationsIt extends AppLocalizations {
@override
String get processingProducts => 'Elaborazione...';
@override
String get clearAllProducts => 'Cancella tutto';
@override
String get clearAllConfirmTitle => 'Cancellare tutti i prodotti?';
@override
String get clearAllConfirmMessage =>
'Tutti i prodotti verranno eliminati definitivamente.';
@override
String get addManually => 'Manualmente';
@override
String get scan => 'Scansiona';
@override
String get addProduct => 'Aggiungi';
@override
String get searchProducts => 'Cerca prodotti';
@override
String get searchProductsHint =>
'Digita il nome del prodotto o aggiungi manualmente';
@override
String noSearchResults(String query) {
return 'Nessun risultato per \"$query\"';
}
@override
String get quantity => 'Quantità';
@override
String get storageDays => 'Giorni di conservazione';
@override
String get addToShelf => 'Aggiungi alla dispensa';
@override
String get errorGeneric => 'Qualcosa è andato storto';
@override
String get nutritionOptional => 'Valori nutrizionali per 100g (opzionale)';
@override
String get calories => 'Calorie';
@override
String get protein => 'Proteine';
@override
String get fat => 'Grassi';
@override
String get carbs => 'Carboidrati';
@override
String get fiber => 'Fibre';
@override
String get productAddedToShelf => 'Aggiunto alla dispensa';
}

View File

@@ -470,4 +470,66 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get processingProducts => '処理中...';
@override
String get clearAllProducts => 'すべてクリア';
@override
String get clearAllConfirmTitle => 'すべての商品をクリアしますか?';
@override
String get clearAllConfirmMessage => 'すべての商品が完全に削除されます。';
@override
String get addManually => '手動';
@override
String get scan => 'スキャン';
@override
String get addProduct => '追加';
@override
String get searchProducts => '製品を検索';
@override
String get searchProductsHint => '製品名を入力するか手動で追加してください';
@override
String noSearchResults(String query) {
return '$query」の検索結果はありません';
}
@override
String get quantity => '数量';
@override
String get storageDays => '保存日数';
@override
String get addToShelf => 'パントリーに追加';
@override
String get errorGeneric => 'エラーが発生しました';
@override
String get nutritionOptional => '100gあたりの栄養素任意';
@override
String get calories => 'カロリー';
@override
String get protein => 'タンパク質';
@override
String get fat => '脂質';
@override
String get carbs => '炭水化物';
@override
String get fiber => '食物繊維';
@override
String get productAddedToShelf => 'パントリーに追加しました';
}

View File

@@ -470,4 +470,66 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get processingProducts => '처리 중...';
@override
String get clearAllProducts => '모두 지우기';
@override
String get clearAllConfirmTitle => '모든 제품을 지울까요?';
@override
String get clearAllConfirmMessage => '모든 제품이 영구적으로 삭제됩니다.';
@override
String get addManually => '수동';
@override
String get scan => '스캔';
@override
String get addProduct => '추가';
@override
String get searchProducts => '제품 검색';
@override
String get searchProductsHint => '제품 이름을 입력하거나 수동으로 추가하세요';
@override
String noSearchResults(String query) {
return '$query」에 대한 결과가 없습니다';
}
@override
String get quantity => '수량';
@override
String get storageDays => '보관 일수';
@override
String get addToShelf => '저장실에 추가';
@override
String get errorGeneric => '오류가 발생했습니다';
@override
String get nutritionOptional => '100g당 영양성분 (선택사항)';
@override
String get calories => '칼로리';
@override
String get protein => '단백질';
@override
String get fat => '지방';
@override
String get carbs => '탄수화물';
@override
String get fiber => '식이섬유';
@override
String get productAddedToShelf => '저장실에 추가되었습니다';
}

View File

@@ -475,4 +475,68 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get processingProducts => 'Processando...';
@override
String get clearAllProducts => 'Limpar tudo';
@override
String get clearAllConfirmTitle => 'Limpar todos os produtos?';
@override
String get clearAllConfirmMessage =>
'Todos os produtos serão excluídos permanentemente.';
@override
String get addManually => 'Manualmente';
@override
String get scan => 'Escanear';
@override
String get addProduct => 'Adicionar';
@override
String get searchProducts => 'Pesquisar produtos';
@override
String get searchProductsHint =>
'Digite o nome do produto ou adicione manualmente';
@override
String noSearchResults(String query) {
return 'Sem resultados para \"$query\"';
}
@override
String get quantity => 'Quantidade';
@override
String get storageDays => 'Dias de armazenamento';
@override
String get addToShelf => 'Adicionar à despensa';
@override
String get errorGeneric => 'Algo deu errado';
@override
String get nutritionOptional => 'Nutrição por 100g (opcional)';
@override
String get calories => 'Calorias';
@override
String get protein => 'Proteína';
@override
String get fat => 'Gorduras';
@override
String get carbs => 'Carboidratos';
@override
String get fiber => 'Fibra';
@override
String get productAddedToShelf => 'Adicionado à despensa';
}

View File

@@ -473,4 +473,69 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get processingProducts => 'Обработка...';
@override
String get clearAllProducts => 'Очистить список';
@override
String get clearAllConfirmTitle => 'Очистить список продуктов?';
@override
String get clearAllConfirmMessage =>
'Все продукты будут удалены без возможности восстановления.';
@override
String get addManually => 'Вручную';
@override
String get scan => 'Сканировать';
@override
String get addProduct => 'Добавить';
@override
String get searchProducts => 'Поиск продуктов';
@override
String get searchProductsHint =>
'Введите название продукта или добавьте вручную';
@override
String noSearchResults(String query) {
return 'Ничего не найдено по запросу \"$query\"';
}
@override
String get quantity => 'Количество';
@override
String get storageDays => 'Дней хранения';
@override
String get addToShelf => 'В холодильник';
@override
String get errorGeneric => 'Что-то пошло не так';
@override
String get nutritionOptional =>
'Питательная ценность на 100г (необязательно)';
@override
String get calories => 'Калории';
@override
String get protein => 'Белки';
@override
String get fat => 'Жиры';
@override
String get carbs => 'Углеводы';
@override
String get fiber => 'Клетчатка';
@override
String get productAddedToShelf => 'Добавлено в холодильник';
}

View File

@@ -469,4 +469,66 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get processingProducts => '处理中...';
@override
String get clearAllProducts => '清空列表';
@override
String get clearAllConfirmTitle => '清空所有产品?';
@override
String get clearAllConfirmMessage => '所有产品将被永久删除。';
@override
String get addManually => '手动';
@override
String get scan => '扫描';
@override
String get addProduct => '添加';
@override
String get searchProducts => '搜索产品';
@override
String get searchProductsHint => '输入产品名称搜索或手动添加';
@override
String noSearchResults(String query) {
return '未找到$query的结果';
}
@override
String get quantity => '数量';
@override
String get storageDays => '保存天数';
@override
String get addToShelf => '添加到储藏室';
@override
String get errorGeneric => '出错了';
@override
String get nutritionOptional => '每100克营养成分可选';
@override
String get calories => '卡路里';
@override
String get protein => '蛋白质';
@override
String get fat => '脂肪';
@override
String get carbs => '碳水化合物';
@override
String get fiber => '膳食纤维';
@override
String get productAddedToShelf => '已添加到储藏室';
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "Recibo",
"jobTypeProducts": "Produtos",
"scanSubmitting": "Enviando...",
"processingProducts": "Processando..."
"processingProducts": "Processando...",
"clearAllProducts": "Limpar tudo",
"clearAllConfirmTitle": "Limpar todos os produtos?",
"clearAllConfirmMessage": "Todos os produtos serão excluídos permanentemente.",
"addManually": "Manualmente",
"scan": "Escanear",
"addProduct": "Adicionar",
"searchProducts": "Pesquisar produtos",
"searchProductsHint": "Digite o nome do produto ou adicione manualmente",
"noSearchResults": "Sem resultados para \"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "Quantidade",
"storageDays": "Dias de armazenamento",
"addToShelf": "Adicionar à despensa",
"errorGeneric": "Algo deu errado",
"nutritionOptional": "Nutrição por 100g (opcional)",
"calories": "Calorias",
"protein": "Proteína",
"fat": "Gorduras",
"carbs": "Carboidratos",
"fiber": "Fibra",
"productAddedToShelf": "Adicionado à despensa"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "Чек",
"jobTypeProducts": "Продукты",
"scanSubmitting": "Отправка...",
"processingProducts": "Обработка..."
"processingProducts": "Обработка...",
"clearAllProducts": "Очистить список",
"clearAllConfirmTitle": "Очистить список продуктов?",
"clearAllConfirmMessage": "Все продукты будут удалены без возможности восстановления.",
"addManually": "Вручную",
"scan": "Сканировать",
"addProduct": "Добавить",
"searchProducts": "Поиск продуктов",
"searchProductsHint": "Введите название продукта или добавьте вручную",
"noSearchResults": "Ничего не найдено по запросу \"{query}\"",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "Количество",
"storageDays": "Дней хранения",
"addToShelf": "В холодильник",
"errorGeneric": "Что-то пошло не так",
"nutritionOptional": "Питательная ценность на 100г (необязательно)",
"calories": "Калории",
"protein": "Белки",
"fat": "Жиры",
"carbs": "Углеводы",
"fiber": "Клетчатка",
"productAddedToShelf": "Добавлено в холодильник"
}

View File

@@ -172,5 +172,32 @@
"jobTypeReceipt": "收据",
"jobTypeProducts": "产品",
"scanSubmitting": "提交中...",
"processingProducts": "处理中..."
"processingProducts": "处理中...",
"clearAllProducts": "清空列表",
"clearAllConfirmTitle": "清空所有产品?",
"clearAllConfirmMessage": "所有产品将被永久删除。",
"addManually": "手动",
"scan": "扫描",
"addProduct": "添加",
"searchProducts": "搜索产品",
"searchProductsHint": "输入产品名称搜索或手动添加",
"noSearchResults": "未找到{query}的结果",
"@noSearchResults": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"quantity": "数量",
"storageDays": "保存天数",
"addToShelf": "添加到储藏室",
"errorGeneric": "出错了",
"nutritionOptional": "每100克营养成分可选",
"calories": "卡路里",
"protein": "蛋白质",
"fat": "脂肪",
"carbs": "碳水化合物",
"fiber": "膳食纤维",
"productAddedToShelf": "已添加到储藏室"
}