feat: improved receipt recognition, batch product add, and scan UX

- Rewrite receipt OCR prompt: completes truncated names, preserves fat%
  and flavour attributes, extracts weight/volume from line, infers
  typical package sizes for solid goods with quantity_confidence field
- Add quantity_confidence to RecognizedItem, EnrichedItem, and
  ProductJobResultItem; propagate through item enricher and worker
- Replace per-item create loop with single POST /user-products/batch call
  from RecognitionConfirmScreen
- Rebuild RecognitionConfirmScreen: amber qty border for low
  quantity_confidence, tappable product name → catalog picker,
  sort items by confidence, full L10n (no hardcoded strings)
- Add timestamps (HH:mm / d MMM HH:mm) to recent scan chips
- Show close-app hint on ProductJobWatchScreen (queued + processing)
- Refresh recentProductJobsProvider on watch screen init so new job
  appears without a manual pull-to-refresh
- App-level WidgetsBindingObserver refreshes product and dish job lists
  on resume, fixing stale lists after background/foreground transitions
- Add 9 new L10n keys across all 12 locales

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
dbastrikin
2026-03-26 23:09:57 +02:00
parent b2bdcbae6f
commit 5c5ed25e5b
38 changed files with 1221 additions and 115 deletions

View File

@@ -201,5 +201,35 @@
"fat": "دهون",
"carbs": "كربوهيدرات",
"fiber": "ألياف",
"productAddedToShelf": "تمت الإضافة إلى المخزن"
"productAddedToShelf": "تمت الإضافة إلى المخزن",
"recognitionFoundProducts": "تم العثور على {count} منتجات",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "إضافة الكل",
"recognitionAddToStock": "إضافة إلى المخزن",
"recognitionAdded": "تمت إضافة {count} منتجات",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "فشل إضافة المنتجات",
"recognitionEmpty": "لم يتم العثور على منتجات",
"recognitionConfidence": "{percent}% ثقة",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "استبدال المنتج",
"scanJobCloseHint": "يمكنك إغلاق التطبيق — سيظهر هذا المسح في عمليات المسح الأخيرة في شاشة المنتجات"
}

View File

@@ -201,5 +201,35 @@
"fat": "Fett",
"carbs": "Kohlenhydrate",
"fiber": "Ballaststoffe",
"productAddedToShelf": "Zum Vorrat hinzugefügt"
"productAddedToShelf": "Zum Vorrat hinzugefügt",
"recognitionFoundProducts": "{count} Produkte gefunden",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "Alle hinzufügen",
"recognitionAddToStock": "In Vorrat",
"recognitionAdded": "{count} Produkte hinzugefügt",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "Hinzufügen fehlgeschlagen",
"recognitionEmpty": "Keine Produkte gefunden",
"recognitionConfidence": "{percent}% Sicherheit",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "Produkt ersetzen",
"scanJobCloseHint": "Du kannst die App schließen — dieser Scan erscheint in Letzte Scans auf dem Produktbildschirm"
}

View File

@@ -201,5 +201,35 @@
"fat": "Fat",
"carbs": "Carbohydrates",
"fiber": "Fiber",
"productAddedToShelf": "Added to pantry"
"productAddedToShelf": "Added to pantry",
"recognitionFoundProducts": "Found {count} products",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "Add all",
"recognitionAddToStock": "Add to pantry",
"recognitionAdded": "Added {count} products",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "Failed to add products",
"recognitionEmpty": "No products found",
"recognitionConfidence": "{percent}% confidence",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "Replace product",
"scanJobCloseHint": "You can close the app — this scan will appear in Recent Scans on the Products screen"
}

View File

@@ -201,5 +201,35 @@
"fat": "Grasas",
"carbs": "Carbohidratos",
"fiber": "Fibra",
"productAddedToShelf": "Agregado a la despensa"
"productAddedToShelf": "Agregado a la despensa",
"recognitionFoundProducts": "Se encontraron {count} productos",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "Agregar todo",
"recognitionAddToStock": "Agregar al almacén",
"recognitionAdded": "Se agregaron {count} productos",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "Error al agregar productos",
"recognitionEmpty": "No se encontraron productos",
"recognitionConfidence": "{percent}% de confianza",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "Reemplazar producto",
"scanJobCloseHint": "Puedes cerrar la app — este escaneo aparecerá en Escaneos recientes en la pantalla de Productos"
}

View File

@@ -201,5 +201,35 @@
"fat": "Graisses",
"carbs": "Glucides",
"fiber": "Fibres",
"productAddedToShelf": "Ajouté au garde-manger"
"productAddedToShelf": "Ajouté au garde-manger",
"recognitionFoundProducts": "{count} produits trouvés",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "Tout ajouter",
"recognitionAddToStock": "Ajouter au garde-manger",
"recognitionAdded": "{count} produits ajoutés",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "Échec de l'ajout des produits",
"recognitionEmpty": "Aucun produit trouvé",
"recognitionConfidence": "{percent}% de confiance",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "Remplacer le produit",
"scanJobCloseHint": "Vous pouvez fermer l'app — ce scan apparaîtra dans Scans récents sur l'écran Produits"
}

View File

@@ -201,5 +201,35 @@
"fat": "वसा",
"carbs": "कार्बोहाइड्रेट",
"fiber": "फाइबर",
"productAddedToShelf": "पेंट्री में जोड़ा गया"
"productAddedToShelf": "पेंट्री में जोड़ा गया",
"recognitionFoundProducts": "{count} उत्पाद मिले",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "सब जोड़ें",
"recognitionAddToStock": "पेंट्री में जोड़ें",
"recognitionAdded": "{count} उत्पाद जोड़े गए",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "उत्पाद जोड़ने में विफल",
"recognitionEmpty": "कोई उत्पाद नहीं मिला",
"recognitionConfidence": "{percent}% विश्वसनीयता",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "उत्पाद बदलें",
"scanJobCloseHint": "आप ऐप बंद कर सकते हैं — यह स्कैन उत्पाद स्क्रीन पर हाल के स्कैन में दिखाई देगा"
}

View File

@@ -201,5 +201,35 @@
"fat": "Grassi",
"carbs": "Carboidrati",
"fiber": "Fibre",
"productAddedToShelf": "Aggiunto alla dispensa"
"productAddedToShelf": "Aggiunto alla dispensa",
"recognitionFoundProducts": "Trovati {count} prodotti",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "Aggiungi tutto",
"recognitionAddToStock": "Aggiungi alla dispensa",
"recognitionAdded": "Aggiunti {count} prodotti",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "Impossibile aggiungere i prodotti",
"recognitionEmpty": "Nessun prodotto trovato",
"recognitionConfidence": "{percent}% di certezza",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "Sostituisci prodotto",
"scanJobCloseHint": "Puoi chiudere l'app — questa scansione apparirà in Scansioni recenti nella schermata Prodotti"
}

View File

@@ -201,5 +201,35 @@
"fat": "脂質",
"carbs": "炭水化物",
"fiber": "食物繊維",
"productAddedToShelf": "パントリーに追加しました"
"productAddedToShelf": "パントリーに追加しました",
"recognitionFoundProducts": "{count}個の商品が見つかりました",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "すべて追加",
"recognitionAddToStock": "パントリーに追加",
"recognitionAdded": "{count}個の商品を追加しました",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "商品の追加に失敗しました",
"recognitionEmpty": "商品が見つかりません",
"recognitionConfidence": "{percent}%の信頼度",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "商品を置き換える",
"scanJobCloseHint": "アプリを閉じても大丈夫です — このスキャンは製品画面の最近のスキャンに表示されます"
}

View File

@@ -201,5 +201,35 @@
"fat": "지방",
"carbs": "탄수화물",
"fiber": "식이섬유",
"productAddedToShelf": "저장실에 추가되었습니다"
"productAddedToShelf": "저장실에 추가되었습니다",
"recognitionFoundProducts": "{count}개 제품 찾음",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "모두 추가",
"recognitionAddToStock": "저장실에 추가",
"recognitionAdded": "{count}개 제품 추가됨",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "제품 추가 실패",
"recognitionEmpty": "제품을 찾을 수 없습니다",
"recognitionConfidence": "{percent}% 신뢰도",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "제품 교체",
"scanJobCloseHint": "앱을 닫아도 됩니다 — 이 스캔은 제품 화면의 최근 스캔에 표시됩니다"
}

View File

@@ -1161,6 +1161,60 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Added to pantry'**
String get productAddedToShelf;
/// No description provided for @recognitionFoundProducts.
///
/// In en, this message translates to:
/// **'Found {count} products'**
String recognitionFoundProducts(int count);
/// No description provided for @recognitionAddAll.
///
/// In en, this message translates to:
/// **'Add all'**
String get recognitionAddAll;
/// No description provided for @recognitionAddToStock.
///
/// In en, this message translates to:
/// **'Add to pantry'**
String get recognitionAddToStock;
/// No description provided for @recognitionAdded.
///
/// In en, this message translates to:
/// **'Added {count} products'**
String recognitionAdded(int count);
/// No description provided for @recognitionProductsFailed.
///
/// In en, this message translates to:
/// **'Failed to add products'**
String get recognitionProductsFailed;
/// No description provided for @recognitionEmpty.
///
/// In en, this message translates to:
/// **'No products found'**
String get recognitionEmpty;
/// No description provided for @recognitionConfidence.
///
/// In en, this message translates to:
/// **'{percent}% confidence'**
String recognitionConfidence(int percent);
/// No description provided for @recognitionReplaceProduct.
///
/// In en, this message translates to:
/// **'Replace product'**
String get recognitionReplaceProduct;
/// No description provided for @scanJobCloseHint.
///
/// In en, this message translates to:
/// **'You can close the app — this scan will appear in Recent Scans on the Products screen'**
String get scanJobCloseHint;
}
class _AppLocalizationsDelegate

View File

@@ -541,4 +541,38 @@ class AppLocalizationsAr extends AppLocalizations {
@override
String get productAddedToShelf => 'تمت الإضافة إلى المخزن';
@override
String recognitionFoundProducts(int count) {
return 'تم العثور على $count منتجات';
}
@override
String get recognitionAddAll => 'إضافة الكل';
@override
String get recognitionAddToStock => 'إضافة إلى المخزن';
@override
String recognitionAdded(int count) {
return 'تمت إضافة $count منتجات';
}
@override
String get recognitionProductsFailed => 'فشل إضافة المنتجات';
@override
String get recognitionEmpty => 'لم يتم العثور على منتجات';
@override
String recognitionConfidence(int percent) {
return '$percent% ثقة';
}
@override
String get recognitionReplaceProduct => 'استبدال المنتج';
@override
String get scanJobCloseHint =>
'يمكنك إغلاق التطبيق — سيظهر هذا المسح في عمليات المسح الأخيرة في شاشة المنتجات';
}

View File

@@ -545,4 +545,38 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get productAddedToShelf => 'Zum Vorrat hinzugefügt';
@override
String recognitionFoundProducts(int count) {
return '$count Produkte gefunden';
}
@override
String get recognitionAddAll => 'Alle hinzufügen';
@override
String get recognitionAddToStock => 'In Vorrat';
@override
String recognitionAdded(int count) {
return '$count Produkte hinzugefügt';
}
@override
String get recognitionProductsFailed => 'Hinzufügen fehlgeschlagen';
@override
String get recognitionEmpty => 'Keine Produkte gefunden';
@override
String recognitionConfidence(int percent) {
return '$percent% Sicherheit';
}
@override
String get recognitionReplaceProduct => 'Produkt ersetzen';
@override
String get scanJobCloseHint =>
'Du kannst die App schließen — dieser Scan erscheint in Letzte Scans auf dem Produktbildschirm';
}

View File

@@ -543,4 +543,38 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get productAddedToShelf => 'Added to pantry';
@override
String recognitionFoundProducts(int count) {
return 'Found $count products';
}
@override
String get recognitionAddAll => 'Add all';
@override
String get recognitionAddToStock => 'Add to pantry';
@override
String recognitionAdded(int count) {
return 'Added $count products';
}
@override
String get recognitionProductsFailed => 'Failed to add products';
@override
String get recognitionEmpty => 'No products found';
@override
String recognitionConfidence(int percent) {
return '$percent% confidence';
}
@override
String get recognitionReplaceProduct => 'Replace product';
@override
String get scanJobCloseHint =>
'You can close the app — this scan will appear in Recent Scans on the Products screen';
}

View File

@@ -546,4 +546,38 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get productAddedToShelf => 'Agregado a la despensa';
@override
String recognitionFoundProducts(int count) {
return 'Se encontraron $count productos';
}
@override
String get recognitionAddAll => 'Agregar todo';
@override
String get recognitionAddToStock => 'Agregar al almacén';
@override
String recognitionAdded(int count) {
return 'Se agregaron $count productos';
}
@override
String get recognitionProductsFailed => 'Error al agregar productos';
@override
String get recognitionEmpty => 'No se encontraron productos';
@override
String recognitionConfidence(int percent) {
return '$percent% de confianza';
}
@override
String get recognitionReplaceProduct => 'Reemplazar producto';
@override
String get scanJobCloseHint =>
'Puedes cerrar la app — este escaneo aparecerá en Escaneos recientes en la pantalla de Productos';
}

View File

@@ -546,4 +546,38 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get productAddedToShelf => 'Ajouté au garde-manger';
@override
String recognitionFoundProducts(int count) {
return '$count produits trouvés';
}
@override
String get recognitionAddAll => 'Tout ajouter';
@override
String get recognitionAddToStock => 'Ajouter au garde-manger';
@override
String recognitionAdded(int count) {
return '$count produits ajoutés';
}
@override
String get recognitionProductsFailed => 'Échec de l\'ajout des produits';
@override
String get recognitionEmpty => 'Aucun produit trouvé';
@override
String recognitionConfidence(int percent) {
return '$percent% de confiance';
}
@override
String get recognitionReplaceProduct => 'Remplacer le produit';
@override
String get scanJobCloseHint =>
'Vous pouvez fermer l\'app — ce scan apparaîtra dans Scans récents sur l\'écran Produits';
}

View File

@@ -544,4 +544,38 @@ class AppLocalizationsHi extends AppLocalizations {
@override
String get productAddedToShelf => 'पेंट्री में जोड़ा गया';
@override
String recognitionFoundProducts(int count) {
return '$count उत्पाद मिले';
}
@override
String get recognitionAddAll => 'सब जोड़ें';
@override
String get recognitionAddToStock => 'पेंट्री में जोड़ें';
@override
String recognitionAdded(int count) {
return '$count उत्पाद जोड़े गए';
}
@override
String get recognitionProductsFailed => 'उत्पाद जोड़ने में विफल';
@override
String get recognitionEmpty => 'कोई उत्पाद नहीं मिला';
@override
String recognitionConfidence(int percent) {
return '$percent% विश्वसनीयता';
}
@override
String get recognitionReplaceProduct => 'उत्पाद बदलें';
@override
String get scanJobCloseHint =>
'आप ऐप बंद कर सकते हैं — यह स्कैन उत्पाद स्क्रीन पर हाल के स्कैन में दिखाई देगा';
}

View File

@@ -546,4 +546,38 @@ class AppLocalizationsIt extends AppLocalizations {
@override
String get productAddedToShelf => 'Aggiunto alla dispensa';
@override
String recognitionFoundProducts(int count) {
return 'Trovati $count prodotti';
}
@override
String get recognitionAddAll => 'Aggiungi tutto';
@override
String get recognitionAddToStock => 'Aggiungi alla dispensa';
@override
String recognitionAdded(int count) {
return 'Aggiunti $count prodotti';
}
@override
String get recognitionProductsFailed => 'Impossibile aggiungere i prodotti';
@override
String get recognitionEmpty => 'Nessun prodotto trovato';
@override
String recognitionConfidence(int percent) {
return '$percent% di certezza';
}
@override
String get recognitionReplaceProduct => 'Sostituisci prodotto';
@override
String get scanJobCloseHint =>
'Puoi chiudere l\'app — questa scansione apparirà in Scansioni recenti nella schermata Prodotti';
}

View File

@@ -538,4 +538,37 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get productAddedToShelf => 'パントリーに追加しました';
@override
String recognitionFoundProducts(int count) {
return '$count個の商品が見つかりました';
}
@override
String get recognitionAddAll => 'すべて追加';
@override
String get recognitionAddToStock => 'パントリーに追加';
@override
String recognitionAdded(int count) {
return '$count個の商品を追加しました';
}
@override
String get recognitionProductsFailed => '商品の追加に失敗しました';
@override
String get recognitionEmpty => '商品が見つかりません';
@override
String recognitionConfidence(int percent) {
return '$percent%の信頼度';
}
@override
String get recognitionReplaceProduct => '商品を置き換える';
@override
String get scanJobCloseHint => 'アプリを閉じても大丈夫です — このスキャンは製品画面の最近のスキャンに表示されます';
}

View File

@@ -538,4 +538,37 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get productAddedToShelf => '저장실에 추가되었습니다';
@override
String recognitionFoundProducts(int count) {
return '$count개 제품 찾음';
}
@override
String get recognitionAddAll => '모두 추가';
@override
String get recognitionAddToStock => '저장실에 추가';
@override
String recognitionAdded(int count) {
return '$count개 제품 추가됨';
}
@override
String get recognitionProductsFailed => '제품 추가 실패';
@override
String get recognitionEmpty => '제품을 찾을 수 없습니다';
@override
String recognitionConfidence(int percent) {
return '$percent% 신뢰도';
}
@override
String get recognitionReplaceProduct => '제품 교체';
@override
String get scanJobCloseHint => '앱을 닫아도 됩니다 — 이 스캔은 제품 화면의 최근 스캔에 표시됩니다';
}

View File

@@ -545,4 +545,38 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get productAddedToShelf => 'Adicionado à despensa';
@override
String recognitionFoundProducts(int count) {
return 'Encontrado $count produtos';
}
@override
String get recognitionAddAll => 'Adicionar tudo';
@override
String get recognitionAddToStock => 'Adicionar ao estoque';
@override
String recognitionAdded(int count) {
return 'Adicionado $count produtos';
}
@override
String get recognitionProductsFailed => 'Falha ao adicionar produtos';
@override
String get recognitionEmpty => 'Nenhum produto encontrado';
@override
String recognitionConfidence(int percent) {
return '$percent% de confiança';
}
@override
String get recognitionReplaceProduct => 'Substituir produto';
@override
String get scanJobCloseHint =>
'Você pode fechar o app — este scan aparecerá em Scans recentes na tela de Produtos';
}

View File

@@ -544,4 +544,38 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get productAddedToShelf => 'Добавлено в холодильник';
@override
String recognitionFoundProducts(int count) {
return 'Найдено $count продуктов';
}
@override
String get recognitionAddAll => 'Добавить всё';
@override
String get recognitionAddToStock => 'В запасы';
@override
String recognitionAdded(int count) {
return 'Добавлено $count продуктов';
}
@override
String get recognitionProductsFailed => 'Не удалось добавить продукты';
@override
String get recognitionEmpty => 'Продукты не найдены';
@override
String recognitionConfidence(int percent) {
return '$percent% уверенность';
}
@override
String get recognitionReplaceProduct => 'Заменить продукт';
@override
String get scanJobCloseHint =>
'Можно закрыть приложение — скан появится в последних сканированиях на экране продуктов';
}

View File

@@ -537,4 +537,37 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get productAddedToShelf => '已添加到储藏室';
@override
String recognitionFoundProducts(int count) {
return '找到 $count 个产品';
}
@override
String get recognitionAddAll => '全部添加';
@override
String get recognitionAddToStock => '加入储藏室';
@override
String recognitionAdded(int count) {
return '已添加 $count 个产品';
}
@override
String get recognitionProductsFailed => '添加产品失败';
@override
String get recognitionEmpty => '未找到产品';
@override
String recognitionConfidence(int percent) {
return '$percent% 置信度';
}
@override
String get recognitionReplaceProduct => '替换产品';
@override
String get scanJobCloseHint => '您可以关闭应用 — 此扫描将显示在产品页面的最近扫描中';
}

View File

@@ -201,5 +201,35 @@
"fat": "Gorduras",
"carbs": "Carboidratos",
"fiber": "Fibra",
"productAddedToShelf": "Adicionado à despensa"
"productAddedToShelf": "Adicionado à despensa",
"recognitionFoundProducts": "Encontrado {count} produtos",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "Adicionar tudo",
"recognitionAddToStock": "Adicionar ao estoque",
"recognitionAdded": "Adicionado {count} produtos",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "Falha ao adicionar produtos",
"recognitionEmpty": "Nenhum produto encontrado",
"recognitionConfidence": "{percent}% de confiança",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "Substituir produto",
"scanJobCloseHint": "Você pode fechar o app — este scan aparecerá em Scans recentes na tela de Produtos"
}

View File

@@ -201,5 +201,35 @@
"fat": "Жиры",
"carbs": "Углеводы",
"fiber": "Клетчатка",
"productAddedToShelf": "Добавлено в холодильник"
"productAddedToShelf": "Добавлено в холодильник",
"recognitionFoundProducts": "Найдено {count} продуктов",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "Добавить всё",
"recognitionAddToStock": "В запасы",
"recognitionAdded": "Добавлено {count} продуктов",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "Не удалось добавить продукты",
"recognitionEmpty": "Продукты не найдены",
"recognitionConfidence": "{percent}% уверенность",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "Заменить продукт",
"scanJobCloseHint": "Можно закрыть приложение — скан появится в последних сканированиях на экране продуктов"
}

View File

@@ -201,5 +201,35 @@
"fat": "脂肪",
"carbs": "碳水化合物",
"fiber": "膳食纤维",
"productAddedToShelf": "已添加到储藏室"
"productAddedToShelf": "已添加到储藏室",
"recognitionFoundProducts": "找到 {count} 个产品",
"@recognitionFoundProducts": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionAddAll": "全部添加",
"recognitionAddToStock": "加入储藏室",
"recognitionAdded": "已添加 {count} 个产品",
"@recognitionAdded": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"recognitionProductsFailed": "添加产品失败",
"recognitionEmpty": "未找到产品",
"recognitionConfidence": "{percent}% 置信度",
"@recognitionConfidence": {
"placeholders": {
"percent": {
"type": "int"
}
}
},
"recognitionReplaceProduct": "替换产品",
"scanJobCloseHint": "您可以关闭应用 — 此扫描将显示在产品页面的最近扫描中"
}