Files
food-ai/client/lib/l10n/app_en.arb
dbastrikin 5c5ed25e5b 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>
2026-03-26 23:09:57 +02:00

236 lines
7.5 KiB
Plaintext

{
"@@locale": "en",
"appTitle": "FoodAI",
"greetingMorning": "Good morning",
"greetingAfternoon": "Good afternoon",
"greetingEvening": "Good evening",
"caloriesUnit": "kcal",
"gramsUnit": "g",
"goalLabel": "goal:",
"consumed": "Consumed",
"remaining": "Remaining",
"exceeded": "Exceeded",
"proteinLabel": "Protein",
"fatLabel": "Fat",
"carbsLabel": "Carbs",
"today": "Today",
"yesterday": "Yesterday",
"mealsSection": "Meals",
"addDish": "Add dish",
"scanDish": "Scan",
"menu": "Menu",
"dishHistory": "Dish history",
"recommendCook": "We recommend cooking",
"camera": "Camera",
"gallery": "Gallery",
"analyzingPhoto": "Analyzing photo...",
"inQueue": "You are in queue",
"queuePosition": "Position {position}",
"@queuePosition": {
"placeholders": {
"position": {
"type": "int"
}
}
},
"processing": "Processing...",
"upgradePrompt": "Skip the queue? Upgrade →",
"recognitionFailed": "Recognition failed. Try again.",
"dishRecognition": "Dish recognition",
"all": "All",
"dishRecognized": "Dish recognized",
"recognizing": "Recognizing…",
"recognitionError": "Recognition error",
"dishResultTitle": "Dish recognized",
"selectDish": "Select dish",
"dishNotRecognized": "Dish not recognized",
"tryAgain": "Try again",
"nutritionApproximate": "Nutrition is approximate — estimated from photo.",
"portion": "Portion",
"mealType": "Meal type",
"dateLabel": "Date",
"addToJournal": "Add to journal",
"addFailed": "Failed to add. Try again.",
"historyTitle": "Recognition history",
"historyLoadError": "Failed to load history",
"retry": "Retry",
"noHistory": "No recognitions yet",
"profileTitle": "Profile",
"edit": "Edit",
"bodyParams": "BODY PARAMS",
"goalActivity": "GOAL & ACTIVITY",
"nutrition": "NUTRITION",
"settings": "SETTINGS",
"height": "Height",
"weight": "Weight",
"age": "Age",
"gender": "Gender",
"genderMale": "Male",
"genderFemale": "Female",
"goalLoss": "Weight loss",
"goalMaintain": "Maintenance",
"goalGain": "Muscle gain",
"activityLow": "Low",
"activityMedium": "Medium",
"activityHigh": "High",
"calorieGoal": "Calorie goal",
"mealTypes": "Meal types",
"formulaNote": "Calculated using the Mifflin-St Jeor formula",
"language": "Language",
"notSet": "Not set",
"calorieHint": "Enter body params to calculate calorie goal",
"logout": "Log out",
"editProfile": "Edit profile",
"cancel": "Cancel",
"save": "Save",
"nameLabel": "Name",
"heightCm": "Height (cm)",
"weightKg": "Weight (kg)",
"birthDate": "Date of birth",
"nameRequired": "Enter name",
"profileUpdated": "Profile updated",
"profileSaveFailed": "Failed to save",
"mealTypeBreakfast": "Breakfast",
"mealTypeSecondBreakfast": "Second breakfast",
"mealTypeLunch": "Lunch",
"mealTypeAfternoonSnack": "Afternoon snack",
"mealTypeDinner": "Dinner",
"mealTypeSnack": "Snack",
"navHome": "Home",
"navProducts": "Products",
"navRecipes": "Recipes",
"addFromReceiptOrPhoto": "Add from receipt or photo",
"scanScreenTitle": "Scan & Recognize",
"barcodeScanSubtitle": "Find a product by its barcode",
"chooseMethod": "Choose method",
"photoReceipt": "Photo of receipt",
"photoReceiptSubtitle": "Recognize all items from a receipt",
"photoProducts": "Photo of products",
"photoProductsSubtitle": "Fridge, table, shelf — up to 3 photos",
"addPackagedFood": "Add packaged food",
"scanBarcode": "Scan barcode",
"portionWeightG": "Portion weight (g)",
"productNotFound": "Product not found",
"enterManually": "Enter manually",
"perHundredG": "per 100 g",
"searchFoodHint": "Search products and dishes...",
"recentlyUsedLabel": "Recently used",
"productsSection": "Products",
"dishesSection": "Dishes",
"noResultsForQuery": "Nothing found for \"{query}\"",
"@noResultsForQuery": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"servingsLabel": "Servings",
"addToDiary": "Add to diary",
"scanDishPhoto": "Scan photo",
"planningForDate": "Planning for {date}",
"@planningForDate": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"markAsEaten": "Mark as eaten",
"plannedMealLabel": "Planned",
"generateWeekLabel": "Plan the week",
"generateWeekSubtitle": "AI will create a menu with breakfast, lunch and dinner for the whole week",
"generatingMenu": "Generating menu...",
"dayPlannedLabel": "Day planned",
"planMenuButton": "Plan meals",
"planMenuTitle": "What to plan?",
"planOptionSingleMeal": "Single meal",
"planOptionSingleMealDesc": "Choose a day and meal type",
"planOptionDay": "One day",
"planOptionDayDesc": "All meals for one day",
"planOptionDays": "Several days",
"planOptionDaysDesc": "Custom date range",
"planOptionWeek": "A week",
"planOptionWeekDesc": "7 days at once",
"planSelectDate": "Select date",
"planSelectMealType": "Meal type",
"planSelectRange": "Select period",
"planGenerateButton": "Plan",
"planGenerating": "Generating plan…",
"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 — 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",
"recentScans": "Recent scans",
"seeAllScans": "See all",
"productJobHistoryTitle": "Scan history",
"jobTypeReceipt": "Receipt",
"jobTypeProducts": "Products",
"scanSubmitting": "Submitting...",
"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",
"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"
}