{ "app": { "name": "EverShelf", "loading": "Loading..." }, "nav": { "title": "EverShelf", "home": "Home", "inventory": "Pantry", "recipes": "Recipes", "shopping": "Shopping", "log": "Log", "settings": "Settings" }, "btn": { "back": "← Back", "save": "πŸ’Ύ Save", "cancel": "βœ• Cancel", "close": "Close", "add": "βœ… Add", "delete": "Delete", "edit": "✏️ Edit", "use": "Use", "edit_item": "Edit", "search": "πŸ” Search", "go": "βœ… Go", "toggle_password": "πŸ‘οΈ Show/Hide", "load_more": "Load more...", "save_config": "πŸ’Ύ Save Configuration", "save_product": "πŸ’Ύ Save Product", "restart": "β†Ί Restart", "reset_default": "β†Ί Reset to default", "save_info": "πŸ’Ύ Save information", "retry": "πŸ”„ Retry", "next": "Next β†’", "yes_short": "Yes", "no_short": "No" }, "form": { "select_placeholder": "-- Select --" }, "locations": { "dispensa": "Pantry", "frigo": "Fridge", "freezer": "Freezer", "altro": "Other" }, "categories": { "latticini": "Dairy", "carne": "Meat", "pesce": "Fish", "frutta": "Fruit", "verdura": "Vegetables", "pasta": "Pasta & Rice", "pane": "Bread & Bakery", "surgelati": "Frozen", "bevande": "Beverages", "condimenti": "Condiments", "snack": "Snacks & Sweets", "conserve": "Canned Goods", "cereali": "Cereals & Legumes", "igiene": "Hygiene", "pulizia": "Household", "altro": "Other", "select": "-- Select --" }, "units": { "pz": "pcs", "conf": "pkg", "g": "g", "ml": "ml", "pieces": "Pieces", "grams": "Grams", "box": "Package", "boxes": "Packages", "millilitres": "Millilitres", "from": "of" }, "shopping_sections": { "frutta_verdura": "Fruits & Vegetables", "carne_pesce": "Meat & Fish", "latticini": "Dairy & Fresh", "pane_dolci": "Bread & Sweets", "pasta": "Pasta & Cereals", "conserve": "Canned & Sauces", "surgelati": "Frozen", "bevande": "Beverages", "pulizia_igiene": "Cleaning & Hygiene", "altro": "Other" }, "dashboard": { "expired_title": "🚫 Expired", "expiring_title": "⏰ Expiring Soon", "stats_period": "πŸ“Š Last 30 days", "opened_title": "πŸ“¦ Opened Products", "review_title": "πŸ” To Review", "review_hint": "Quantities that seem unusual. Confirm if correct or modify.", "quick_recipe": "Quick recipe with expiring products", "banner_review_title": "Anomalous quantity", "banner_review_action_ok": "It's correct", "banner_review_action_finish": "πŸ—‘οΈ All gone", "banner_review_action_edit": "Correct", "banner_review_action_weigh": "Weigh", "banner_review_dismiss": "Dismiss", "banner_prediction_title": "Consumption to review", "banner_prediction_hint": "The consumption estimate adapts to recent data: confirm only if the current quantity is correct.", "banner_prediction_action_confirm": "Confirm {qty} {unit}", "banner_prediction_action_weigh": "Weigh now", "banner_prediction_action_edit": "Update quantity", "banner_expired_title": "Expired product", "banner_expired_today": "Expired today", "banner_expired_days": "Expired {days} days ago", "banner_expired_action_use": "Use anyway", "banner_expired_action_finished": "I finished it!", "banner_expired_action_throw": "I threw it away", "banner_expired_action_edit": "Fix date", "banner_expired_action_modify": "Edit", "banner_expired_action_vacuum": "Put in vacuum seal", "banner_anomaly_action_edit": "Fix inventory", "banner_anomaly_action_dismiss": "Quantity is correct", "banner_no_expiry_title": "Missing expiry: {name}", "banner_no_expiry_detail": "This product has no expiry date. Would you like to add one, or confirm it doesn't expire?", "banner_no_expiry_action_set": "Set expiry date", "banner_no_expiry_action_dismiss": "Doesn't expire βœ“", "banner_no_expiry_toast_dismissed": "Marked as 'no expiry'", "banner_expiring_title": "Expiring soon", "banner_expiring_today": "Expires today!", "banner_expiring_tomorrow": "Expires tomorrow", "banner_expiring_days": "Expires in {days} days", "banner_expiring_action_use": "Use now", "banner_finished_title": "finished?", "banner_finished_detail": "I recorded that {name} reached zero stock. Is it really gone, or do you still have some?", "banner_finished_action_yes": "Yes, it's done", "banner_finished_action_no": "No, I still have some", "banner_review_unusual_pkg_title": "Unusual package size", "banner_review_unusual_pkg_detail": "You set a package of {qty} {unit} β€” the size seems very large. Check if correct or edit.", "banner_review_low_qty_title": "Very low quantity", "banner_review_low_qty_detail": "You only have {qty} in stock β€” seems very little, could be a typo. Confirm if correct.", "banner_review_high_qty_title": "Unusually high quantity", "banner_review_high_qty_detail": "You have {qty} in stock β€” the figure seems very high. Confirm if correct or edit.", "banner_prediction_rate_day": "Average ~{n} {unit}/day", "banner_prediction_rate_week": "Average ~{n} {unit}/week", "banner_prediction_days_ago": "{n} days ago you restocked", "banner_prediction_more": "previous estimate: {expected} {unit}{time}; current quantity: {actual} {unit}.", "banner_prediction_less": "estimate: {expected} {unit}{time}; current quantity: {actual} {unit}. If your usage pace changed, the forecast updates automatically.", "banner_finished_zero": "Inventory shows zero, but recorded movements suggest it shouldn't be empty.", "banner_finished_vanished": "This product no longer appears in inventory, but recorded movements suggest it shouldn't be empty.", "banner_finished_expected": "According to records you should still have {qty} {unit}.", "banner_finished_check": "Can you check?", "banner_finished_action_restore": "Restore {qty} {unit}", "banner_anomaly_phantom_title": "you have more stock than expected", "banner_anomaly_phantom_detail": "Inventory shows {inv_qty} {unit}, but based on records you should only have {expected_qty} {unit}. Did you add stock without recording it?", "banner_anomaly_untracked_title": "stock not recorded as an entry", "banner_anomaly_untracked_detail": "You have {inv_qty} {unit} in inventory, but recorded outflows exceed inflows β€” the initial stock was likely never added as an \"in\" transaction. You can correct the quantity or log the missing entries.", "banner_anomaly_ghost_title": "you have less stock than expected", "banner_anomaly_ghost_detail": "Based on recorded operations you should have {expected_qty} {unit} of {name}, but inventory shows only {inv_qty} {unit}. Did you take stock without recording it?", "banner_dup_loss_title": "Double-consume check: {name}", "banner_dup_loss_detail": "Possible duplicate entry in {location}: two close out events ({qty_pair}) in ~{seconds}s. Please verify and fix if needed.", "banner_dup_loss_action_fix": "Fix quantity", "banner_dup_loss_action_open": "Open product card", "banner_dup_loss_action_done": "Already checked", "banner_dup_loss_toast_done": "Check marked as reviewed", "consumed": "Consumed: {n} ({pct}%)", "wasted": "Wasted: {n} ({pct}%)", "more_opened": "and {n} more opened...", "banner_expired_detail": "{when} Β· you still have {qty}.", "banner_opened_detail": "{when} in {location} Β· you still have {qty}.", "banner_explain_title": "Ask Gemini for an explanation", "banner_explain_btn": "Explain", "banner_analyzing": "πŸ€– Analyzing…", "banner_prediction_confirmed": "βœ… Confirmed β€” forecasts will recalculate from your next entries", "banner_anomaly_explain_fail": "Could not get AI explanation", "banner_anomaly_dismissed": "Anomaly dismissed", "banner_finished_restore_prompt": "How many {unit} of {name} do you still have? (system estimate: {qty})" }, "inventory": { "title": "Pantry", "filter_all": "All", "search_placeholder": "πŸ” Search product...", "recent_title": "πŸ• Recently used", "popular_title": "⭐ Most used", "empty": "No products here.\nScan a product to add it!", "no_items_found": "No inventory items found", "qty_remainder_suffix": "left", "vacuum_badge": "πŸ«™ Vacuum sealed", "opened_badge": "πŸ“­ Opened", "label_expiry": "πŸ“… Expiry", "label_storage": "πŸ«™ Storage", "label_status": "πŸ“­ Status", "opened_since": "Opened since {date}", "label_position": "πŸ“ Location", "label_quantity": "πŸ“¦ Quantity", "label_added": "πŸ“… Added", "empty_text": "No products here.
Scan a product to add it!", "empty_db": "No products in the database.
Scan a product to get started!", "qty_trace": "< 1" }, "scan": { "title": "Scan", "mode_shopping": "πŸ›’ Shopping Mode", "mode_shopping_end": "βœ… End shopping", "spesa_btn": "πŸ›’ Shopping", "spesa_camera_hint": "Point the camera at the barcode. No barcode? Tap Β«Identify with AIΒ» below.", "zoom": "Zoom", "tab_barcode": "Barcode", "tab_name": "Name", "tab_ai": "AI", "recents_label": "Recent", "torch_hint": "Torch", "torch_on": "Torch on", "torch_off": "Torch off", "torch_unavailable": "Torch not available on this device", "flip_hint": "Flip camera", "flip_front": "Front camera", "flip_back": "Rear camera", "num_ocr_btn": "πŸ”’ Read numbers with AI", "num_ocr_searching": "Looking for barcode with AI...", "num_ocr_found": "Code found: {code}", "num_ocr_not_found": "No barcode found in image", "barcode_placeholder": "Enter barcode...", "quick_name_divider": "or type the name", "quick_name_placeholder": "E.g.: Apples, Zucchini, Bread...", "manual_entry": "✏️ Manual Entry", "ai_identify": "πŸ€– Identify with AI", "hint": "Scan the barcode, type the product name, or use AI to identify it", "debug_toggle": "πŸ› Debug Log", "barcode_acquired": "πŸ”– Barcode scanned: {code}", "scan_barcode": "πŸ”– Scan Barcode", "create_named": "Create {name}", "new_without_barcode": "New product without barcode", "stock_in_pantry": "Already in pantry:", "status_ready": "Point camera at barcode", "status_scanning": "Scanning...", "status_partial": "Detected: {code} β€” verifying...", "status_invalid": "Invalid: {code} β€” retrying", "status_confirmed": "Confirmed!", "status_parallel": "Using combined scan methods...", "status_ocr_searching": "Reading the barcode digits...", "status_digit_ocr": "Reading numbers below the barcode...", "status_ai_visual_searching": "Now trying to recognize the product...", "method_ai_ocr": "Gemini OCR", "method_ai_vision": "Gemini Vision", "method_local_ocr": "Digit OCR", "method_zbar": "ZBar", "local_ocr_found": "Code from digits: {code}", "ai_fallback_searching": "AI identifying product...", "ai_fallback_found": "Product identified by AI", "ai_fallback_not_found": "AI: product not recognized", "ai_fallback_exhausted": "AI: product not recognized β€” try scanning the barcode", "ai_overlay_label": "Gemini Vision", "ai_overlay_msg": "Gemini Vision is analyzing the product...", "ai_retry_btn": "Retry with AI", "ai_manual_btn": "πŸ€– Identify with AI", "ai_not_recognized": "AI could not recognize the product. Try again or add manually.", "ai_match_title": "Product recognized by AI", "ai_match_subtitle": "Choose an existing pantry item or add the detected one.", "ai_match_existing": "Currently in pantry", "ai_match_finished": "Finished / depleted", "ai_match_catalog": "In catalog (no stock)", "ai_match_finished_badge": "depleted", "ai_match_finished_hint": "Finished product β€” restock the quantity", "ai_match_merged_existing": "Linked to an existing catalog product", "ai_match_none": "No similar products found β€” you can create a new one.", "ai_match_use_btn": "Use", "ai_match_create_btn": "βž• Create new: {name}", "ai_match_add_btn": "Add {name}", "ai_match_action_hint": "Tap the green button to add this product", "ai_match_or_similar": "Or pick a similar product:", "ai_detected_label": "AI detected", "mode_shopping_activated": "πŸ›’ Shopping mode activated!" }, "action": { "title": "What do you want to do?", "add_btn": "πŸ“₯ ADD", "add_sub": "to pantry/fridge", "use_btn": "USE", "use_sub": "from pantry/fridge", "have_title": "πŸ“¦ Already in stock!", "add_more_sub": "add more", "use_qty_sub": "how much you used", "throw_btn": "πŸ—‘οΈ DISCARD", "throw_sub": "throw away", "edit_sub": "expiry, location…", "create_recipe_btn": "Recipe", "related_stock_title": "Also at home" }, "add": { "title": "Add to Pantry", "location_label": "πŸ“ Where do you put it?", "quantity_label": "πŸ“¦ Quantity", "conf_size_label": "πŸ“¦ Each package contains:", "conf_size_placeholder": "e.g. 300", "vacuum_label": "πŸ«™ Vacuum sealed", "vacuum_hint": "Expiry date will be extended automatically", "submit": "βœ… Add", "purchase_type_label": "πŸ›’ This product is...", "new_btn": "πŸ†• Just bought", "existing_btn": "πŸ“¦ I already had it", "remaining_label": "πŸ“¦ Remaining quantity", "remaining_hint": "Approximately how much is left?", "remaining_full": "🟒 Full", "remaining_half": "🟠 Half", "estimated_expiry": "Estimated expiry:", "suffix_freezer": "(freezer)", "suffix_vacuum": "(vacuum sealed)", "hint_modify": "πŸ“ You can change the date or scan it with the camera", "scan_expiry_title": "πŸ“· Scan Expiry Date", "product_added": "βœ… {name} added!{qty}", "duplicate_recent_confirm": "You just added \"{name}\" ({when}).\n\nQuantity is already {total}.\n\nIncrease it by {qty}?", "suffix_freezer_vacuum": "(freezer + vacuum sealed)", "history_badge_tip": "Average of the last {n} entries β€” updates with each new purchase", "vacuum_question": "Vacuum sealed?", "vacuum_saved": "πŸ”’ Vacuum sealed!" }, "use": { "title": "Use / Consume", "location_label": "πŸ“ From where?", "quantity_label": "How much did you use?", "change": "change", "partial_hint": "Or specify the quantity used:", "partial_piece_hint": "Did you use only a part?", "piece": "piece", "one_whole": "1 whole", "use_all": "πŸ—‘οΈ Used ALL / Finished", "submit": "πŸ“€ Use this quantity", "available": "πŸ“¦ Available:", "opened_badge": "OPENED", "not_in_inventory": "⚠️ Product not in inventory.", "expiry_warning": "⚠️ Use first the one{loc} that expires on {date} β€” {when}!", "expiry_warning_opened": "⚠️ The one{loc} has been open for {when} β€” use it first!", "throw_title": "πŸ—‘οΈ Discard Product", "throw_all": "πŸ—‘οΈ Discard ALL ({qty})", "throw_qty_label": "How much to discard?", "throw_qty_hint": "or enter a quantity:", "throw_partial_btn": "πŸ—‘οΈ Discard this quantity", "when_expired": "expired {n} days ago", "when_today": "expires today", "when_tomorrow": "expires tomorrow", "when_days": "expires in {n} days", "toast_used": "πŸ“€ Used {qty} of {name}", "toast_bring": "πŸ›’ Product finished β†’ added to Bring!", "toast_opened_finished": "πŸ”“ Opened package of {name} finished!", "disambiguation_hint": "What do you mean by \"all done\"?", "disambiguation_one_conf": "Finished 1 package ({qty})", "disambiguation_all": "πŸ—‘οΈ Finish EVERYTHING ({qty})", "toast_one_conf_finished": "πŸ“¦ 1 package of {name} finished!", "error_exceeds_stock": "⚠️ You cannot use more than you have available!", "use_all_confirm_title": "βœ… Finish everything", "use_all_confirm_msg": "Confirm that you have finished the product:", "use_all_confirm_btn": "βœ… Yes, finished", "throw_all_confirm_title": "πŸ—‘οΈ Discard everything", "throw_all_confirm_msg": "Do you really want to throw away the whole product?", "throw_all_confirm_btn": "πŸ—‘οΈ Yes, discard", "locations_short": "places" }, "product": { "title_new": "New Product", "title_edit": "Edit Product", "ai_fill": "πŸ“· Take photo and identify with AI", "ai_fill_hint": "AI will automatically fill in the product fields", "name_label": "🏷️ Product Name *", "name_placeholder": "E.g.: Whole milk, Penne pasta...", "brand_label": "🏒 Brand", "allergens_label": "Allergens:", "ingredients_summary": "πŸ“‹ Ingredients", "brand_placeholder": "E.g.: Barilla, Granarolo, Mutti...", "category_label": "πŸ“‚ Category", "unit_label": "πŸ“ Unit of measure", "default_qty_label": "πŸ”’ Default quantity", "conf_size_label": "πŸ“¦ Each package contains:", "conf_size_placeholder": "e.g. 300", "notes_label": "πŸ“ Notes", "notes_placeholder": "E.g.: lactose free, organic, store in fridge after opening...", "barcode_label": "πŸ”– Barcode", "barcode_placeholder": "Barcode (if available)", "barcode_hint": "⚠️ Add the barcode so next time you just need to scan it!", "submit": "πŸ’Ύ Save Product", "name_required": "Enter the product name", "conf_size_required": "Specify the package content", "expiry_estimated": "Estimated expiry:", "scan_expiry": "Scan expiry date", "expiry_hint": "πŸ“ You can edit the date or scan it with the camera", "add_batch": "πŸ“¦ + Batch with different expiry", "package_info": "πŸ“¦ Package: {info}", "edit_catalog": "βš™οΈ Edit product info (name, brand, category…)", "not_recognized": "⚠️ Product not recognized", "edit_info": "✏️ Edit information", "modify_details": "EDIT\nexpiry, location…", "already_in_pantry": "πŸ“‹ Already in pantry", "no_barcode": "No barcode", "unknown_product": "Unrecognized product", "edit_name_brand": "Edit name/brand", "weight_label": "Weight", "origin_label": "Origin", "labels_label": "Labels", "select_variant": "Select the exact variant or use AI data:", "history_badge": "πŸ“Š history", "from_history": " (last 3 avg)" }, "products": { "title": "πŸ“¦ All Products", "search_placeholder": "πŸ” Search product...", "empty": "No products in database.\nScan a product to get started!", "no_category": "No products in this category" }, "recipes": { "title": "🍳 Recipes", "generate": "✨ Generate new recipe", "archive_empty": "No recipes saved. Generate your first recipe!", "dialog_title": "🍳 Recipe", "dialog_desc": "I will generate a healthy recipe using pantry ingredients, prioritizing expiring items.", "meal_label": "πŸ• Which meal?", "persons_label": "πŸ‘₯ How many people?", "meal_type_label": "🎯 Meal type", "opt_fast": "⚑ Quick meal", "opt_light": "πŸ₯— Light appetite", "opt_expiry": "⏰ Prioritize expiring items", "opt_healthy": "πŸ’š Extra healthy", "opt_opened": "πŸ“¦ Prioritize opened items", "opt_zero_waste": "♻️ Zero waste", "generate_btn": "✨ Generate Recipe", "loading_msg": "Preparing your recipe...", "start_cooking": "πŸ‘¨β€πŸ³ Cooking Mode", "regenerate": "πŸ”„ Generate another one", "regen_choice_title": "What do you want to do with this recipe?", "regen_replace": "πŸ”„ Generate another (discard this one)", "regen_save_new": "πŸ’Ύ Save to archive & generate a new one", "close_btn": "βœ… Close", "ingredients_title": "🧾 Ingredients", "tools_title": "Equipment needed", "steps_title": "πŸ‘¨β€πŸ³ Steps", "no_steps": "No steps available", "generate_error": "Generation error", "stream_interrupted": "Generation interrupted (incomplete server response). Check logs or try again.", "persons_short": "serv.", "use_ingredient_title": "Use ingredient", "recipe_qty_label": "Recipe", "from_where_label": "From where?", "amount_label": "How much", "use_amount_btn": "Use this amount", "use_all_btn": "Use ALL / Finished", "packs_label": "Packs", "quantity_in_total": "Quantity in {unit} (total: {total})", "packs_of_have": "Packs of {size} (you have {count} packs)", "scale_wait_stable": "Wait 10s of stable weight for auto-fill…", "ingredient_scaled_toast": "πŸ“¦ Ingredient deducted from pantry!", "finished_added_bring_toast": "πŸ›’ Finished product β†’ added to Bring!", "load_error": "Loading error", "favorite": "Add to favourites", "unfavorite": "Remove from favourites", "adjust_persons": "Persons", "nutrition_title": "Nutritional values (per serving)", "nutrition_kcal": "Calories", "nutrition_protein": "Protein", "nutrition_carbs": "Carbs", "nutrition_fat": "Fat", "nutrition_per_serving": "Estimated values per serving", "storage_title": "How to store leftovers", "storage_days": "{n} days", "storage_immediately": "Best eaten immediately", "ing_stock_line": "You have {have} Β· {remain} left after use", "ing_use_all_note": "use all (<5% of full package left)" }, "shopping": { "title": "πŸ›’ Shopping List", "bring_loading": "Connecting to Bring!...", "bring_not_configured": "Bring! is not configured. Add your email and password in settings.", "tab_to_buy": "πŸ›οΈ To buy", "tab_forecast": "🧠 Forecast", "total_label": "πŸ’° Estimated total", "section_to_buy": "πŸ›οΈ To buy", "suggestions_title": "πŸ’‘ AI Suggestions", "suggestions_add": "βœ… Add selected to Bring!", "search_prices": "πŸ” Search all prices", "suggest_btn": "Suggest what to buy", "smart_title": "🧠 Smart Predictions", "smart_empty": "No predictions available.
Add products to your pantry to receive smart predictions.", "smart_filter_all": "All", "smart_filter_critical": "πŸ”΄ Urgent", "smart_filter_high": "🟠 Soon", "smart_filter_medium": "🟑 Plan", "smart_filter_low": "🟒 Forecast", "smart_add": "πŸ›’ Add selected to Bring!", "empty": "Shopping list empty!\nUse the button below to generate suggestions.", "already_in_list": "πŸ›’ \"{name}\" is already in the shopping list", "already_in_list_short": "ℹ️ Already in the shopping list", "add_prompt": "Do you want to add it to the shopping list?", "smart_already": "πŸ“Š Smart shopping already predicts {name}", "all_searched": "All products have already been searched. Use πŸ”„ to search individual ones.", "search_complete": "Search complete: {count} products", "removed_sufficient": "🧹 {removed} product(s) with sufficient stock removed from the list", "suggest_buy": "πŸ›’ Buy: {qty} {unit}", "suggest_buy_approx": "πŸ›’ At least: {qty} {unit}", "suggest_buy_tip": "Suggested quantity based on your last 14 days of consumption", "suggest_buy_approx_tip": "Minimum estimate based on consumption (buy the nearest package size)", "bring_badge": "πŸ›’ Already on Bring!", "add_urgent_toast": "πŸ”΄ {n} urgent product(s) automatically added to Bring!", "migration_done": "βœ… {migrated} updated, {skipped} already ok", "added_to_bring": "πŸ›’ {n} products added to Bring!", "added_to_bring_skip": "{n} already present", "all_on_bring": "All products were already on Bring!", "freq_high": "πŸ“ˆ Frequent", "freq_regular": "πŸ“Š Regular", "freq_occasional": "πŸ“‰ Occasional", "out_of_stock": "Out of stock", "scan_toast": "πŸ“· Scan: {name}", "empty_category": "No products in this category", "session_empty": "πŸ›’ No products yet", "urgency_critical": "Urgent", "urgency_high": "Soon", "urgency_medium": "Plan", "urgency_low": "Forecast", "urgency_medium_short": "Medium", "urgency_low_short": "Ok", "tag_urgent": "πŸ”΄ Urgent", "tag_priority": "⭐ Priority", "tag_check": "βœ… Check", "smart_already_predicted": "πŸ“Š Smart shopping already predicts {name}{urgency}.", "item_removed": "βœ… {name} removed from list!", "urgency_spec_critical": "⚑ Urgent", "urgency_spec_high": "🟠 Soon", "urgency_spec_medium": "🟑 Soon", "urgency_spec_low": "πŸ”΅ Forecast", "family_sibling_title": "Similar in {location}", "family_sibling_location": "Location: {location}", "family_sibling_qty": "Quantity: {qty}", "family_sibling_purchased": "Purchased on {date}", "family_sibling_question": "Is the quantity still correct?", "family_sibling_prompt": "You also have {name}: {qty} in stock. Confirm the quantity?", "family_sibling_yes": "Yes, all good", "family_sibling_no": "No, update", "bring_add_n": "Add {n} to Bring!", "bring_add_selected": "Add selected to Bring!", "bring_adding": "Adding...", "bring_added_one": "1 product added to Bring!", "bring_added_many": "{n} products added to Bring!", "bring_skipped": "({n} already in list)", "force_sync": "Force Bring! sync", "scan_target_label": "You are looking for", "scan_target_found": "Found! Remove from list", "bring_add_one": "Add 1 product to Bring!", "bring_add_many": "Add {n} products to Bring!", "syncing": "Syncing…", "sync_done": "Sync completed", "price_searching": "Searching...", "search_action": "Search", "open_action": "Open", "not_found": "Not found", "search_price": "Search price", "tap_to_scan": "Tap to scan", "tag_title": "Tag", "remove_title": "Remove", "found_count": "{found}/{total} products found", "savings_offers": "Β· 🏷️ You save €{amount} with offers", "searching_progress": "Searching {current}/{total}...", "remove_error": "Removal error", "btn_fetch_prices": "Find prices", "price_total_label": "πŸ’° Estimated total:", "price_total_short": "estimated total", "price_loading": "Looking up prices…", "price_not_found": "price n/a", "suggest_loading": "Analyzing...", "suggest_error": "Suggestion generation error", "priority_high": "High", "priority_medium": "Medium", "priority_low": "Low", "smart_last_update": "Updated {time}", "names_already_updated": "All names are already up to date", "pantry_hint": "Already at home: {qty}", "bring_names_migrated": "πŸ”„ {n} names generalized in Bring!" }, "ai": { "title": "πŸ€– AI Identification", "capture": "πŸ“Έ Take Photo", "retake": "πŸ”„ Retake", "hint": "Take a photo of the product and AI will try to identify it", "identifying": "πŸ€– Identifying product...", "no_api_key": "⚠️ Gemini API key not configured.\nAdd GEMINI_API_KEY to the .env file on the server.", "fields_filled": "βœ… Fields filled by AI", "use_data": "βœ… Use AI data", "use_data_no_barcode": "βœ… Use AI data (no barcode)", "conservation_hint": "πŸ€– AI: store in {location}" }, "log": { "title": "πŸ“’ Operations Log", "type_added": "Added", "type_waste": "Discarded", "type_used": "Used", "type_bring": "Added to Bring!", "undone_badge": "Undone", "undo_title": "Undo this operation", "load_error": "Error loading log", "empty": "No operations recorded.", "undo_action_remove": "removal of", "undo_action_restore": "restock of", "undo_confirm": "Undo this operation?\nβ†’ {action} {name}", "undo_success": "↩ Operation undone for {name}", "already_undone": "Operation already undone", "too_old": "Cannot undo operations older than 24 hours", "undo_error": "Error during undo", "recipe_prefix": "Recipe" }, "chat": { "title": "Gemini Chef", "welcome": "Hi! I'm your kitchen assistant", "welcome_desc": "Ask me to make you a juice, a snack, a quick dish... I know your pantry, your appliances and your preferences!", "suggestion_snack": "🍿 Quick snack", "suggestion_juice": "πŸ₯€ Juice/Smoothie", "suggestion_light": "πŸ₯— Something light", "suggestion_expiry": "⏰ Use expiring items", "clear": "New conversation", "placeholder": "Ask something...", "cleared": "Chat cleared", "suggestion_snack_text": "What can I make for a quick snack?", "suggestion_juice_text": "Make me a juice or smoothie with what I have", "suggestion_light_text": "I'm hungry but want something light", "suggestion_expiry_text": "What's about to expire and how can I use it?", "transfer_to_recipes": "Transfer to Recipes", "transferring": "Transferring...", "transferred": "Added to Recipes!", "open_recipe": "Open recipe", "quick_recipe_prompt": "Suggest a quick recipe FOR ONE PERSON using the products that expire first! Ignore freezer items, focus on fridge and pantry." }, "cooking": { "close": "Close", "tts_btn": "Read aloud", "restart": "β†Ί Restart", "replay": "πŸ”Š Replay", "timer": "⏱️ {time} Β· Timer", "prev": "β—€ Previous", "next": "Next β–Ά", "ingredient_used": "βœ”οΈ Deducted", "ingredient_use_btn": "Use", "ingredient_deduct_title": "Deduct from pantry", "timer_expired_tts": "Timer {label} expired!", "timer_warning_tts": "Heads up! {label}: 10 seconds left!", "recipe_done_tts": "Recipe complete! Enjoy your meal!", "expires_chip": "exp. {date}", "finish": "βœ… Finish", "step_fallback": "Step {n}", "zerowaste_label": "♻️ Scrap", "zerowaste_tip_title": "Zero-waste tip" }, "settings": { "title": "βš™οΈ Settings", "tab_api": "API Keys", "tab_bring": "Bring!", "tab_recipe": "Recipes", "tab_mealplan": "Weekly Plan", "tab_appliances": "Appliances", "tab_spesa": "Online Shopping", "tab_camera": "Camera", "tab_security": "Security", "tab_tts": "Voice (TTS)", "tab_language": "Language", "tab_scale": "Smart Scale", "gemini": { "title": "πŸ€– Google Gemini AI", "hint": "API key for product identification, expiry dates and recipes.", "key_label": "Gemini API Key" }, "bring": { "title": "πŸ›’ Bring! Shopping List", "hint": "Credentials for the Bring! shopping list integration.", "email_label": "πŸ“§ Bring! Email", "password_label": "πŸ”’ Bring! Password" }, "price": { "title": "πŸ’° Price Estimation (AI)", "hint": "Show estimated cost per product in the shopping list using AI.", "enabled_label": "Enable price estimation", "country_label": "🌍 Reference country", "currency_label": "πŸ’± Currency", "update_label": "πŸ”„ Refresh prices every", "update_suffix": "months" }, "recipe": { "title": "🍳 Recipe Preferences", "hint": "Configure the default options for recipe generation.", "persons_label": "πŸ‘₯ Default servings", "options_label": "🎯 Default recipe options", "fast": "⚑ Quick Meal", "light": "πŸ₯— Light Meal", "expiry": "⏰ Expiry Priority", "healthy": "πŸ’š Extra Healthy", "opened": "πŸ“¦ Open Items Priority", "zerowaste": "♻️ Zero Waste", "dietary_label": "🚫 Intolerances / Restrictions", "dietary_placeholder": "E.g.: gluten free, lactose free, vegetarian..." }, "mealplan": { "title": "πŸ“… Weekly Meal Plan", "hint": "Set the meal type for each day. It will be used as a guide in recipe generation.", "enabled": "βœ… Enable weekly meal plan", "legend": "🌀️ = Lunch  Β·  πŸŒ™ = Dinner  Β·  Tap a badge to change it.", "types_title": "πŸ“‹ Available types", "reset_btn": "β†Ί Restore defaults" }, "appliances": { "title": "πŸ”Œ Available Appliances", "hint": "Indicate the appliances you have. They will be considered in recipe generation.", "new_placeholder": "E.g.: Bread machine, Thermomix, Air fryer...", "quick_title": "Quick add:", "oven": "πŸ”₯ Oven", "microwave": "πŸ“‘ Microwave", "air_fryer": "🍟 Air fryer", "bread_maker": "🍞 Bread maker", "bimby": "πŸ€– Thermomix/Cookeo", "mixer": "πŸŒ€ Stand mixer", "steamer": "♨️ Steamer", "pressure_cooker": "πŸ«• Pressure cooker", "toaster": "🍞 Toaster", "blender": "🍹 Blender", "empty": "No appliances added" }, "spesa": { "title": "πŸ›οΈ Online Shopping", "hint": "Configure the online shopping provider.", "provider_label": "πŸͺ Provider", "email_label": "πŸ“§ Email", "password_label": "πŸ”’ Password", "login_btn": "πŸ” Login", "ai_prompt_label": "πŸ€– AI product selection prompt", "ai_prompt_placeholder": "Instructions for AI when choosing between multiple products...", "ai_prompt_hint": "AI uses this prompt to choose the most appropriate product from results. Leave empty for default behavior.", "configure_first": "Configure Online Shopping in settings first", "missing_credentials": "Enter email and password", "login_in_progress": "Signing in...", "login_error_prefix": "Error:", "login_network_error_prefix": "Network error:", "login_success_default": "Login successful!", "result_name_label": "Name", "result_card_label": "Card", "result_pickup_label": "Pickup point", "result_points_label": "Loyalty points", "connected_relogin": "βœ… Connected β€” Sign in again", "connected_as": "Connected as {name}" }, "camera": { "title": "πŸ“· Camera", "hint": "Choose which camera to use for barcode scanning and AI identification.", "device_label": "πŸ“Έ Default camera", "back": "πŸ“± Rear (default)", "front": "🀳 Front", "devices_hint": "If you have multiple cameras, you can select a specific one from the list above after granting permissions.", "detect_btn": "πŸ”„ Detect cameras", "ai_fallback_label": "AI visual identification (5s fallback)", "ai_fallback_hint": "If no barcode is read within 5 seconds, a frame is automatically sent to AI to visually identify the product. Requires Gemini configured.", "ai_manual_hint": "If the barcode cannot be read, use the Β«Identify with AIΒ» button below the camera. Requires Gemini configured." }, "security": { "title": "πŸ”’ HTTPS Certificate", "hint": "If the browser shows the error \"Your connection is not private\" (ERR_CERT_AUTHORITY_INVALID), you need to install the CA certificate on the device.", "download_btn": "πŸ“₯ Download CA Certificate", "token_title": "πŸ”‘ Settings Token", "token_label": "Access token", "token_hint": "If `SETTINGS_TOKEN` is configured in the server's `.env`, enter the token here before saving settings. Leave empty if not configured.", "token_placeholder": "(empty = no protection)", "token_required_hint": "πŸ”’ This server requires a token to save settings.", "cert_instructions": "Instructions for Chrome (Android):
1. Download the certificate above
2. Go to Settings → Security & Privacy → More security settings → Install from device storage
3. Select the downloaded EverShelf_CA.crt file
4. Choose \"CA\" and confirm
5. Restart Chrome

Instructions for Chrome (PC):
1. Download the certificate above
2. Go to chrome://settings/certificates (or Settings → Privacy and security → Security → Manage certificates)
3. Tab \"Authorities\" → Import → select the file
4. Check \"Trust this certificate for identifying websites\"
5. Restart Chrome" }, "tts": { "title": "πŸ”Š Voice & TTS", "hint": "Configure text-to-speech via any external REST API. Recipe steps and expired timers will be sent to the configured endpoint.", "enabled": "βœ… Enable TTS", "engine_label": "βš™οΈ TTS Engine", "engine_browser": "πŸ”‡ Browser (offline, no configuration required)", "engine_server": "🌐 External server (Home Assistant, REST API...)", "voice_label": "πŸ—£οΈ Voice", "rate_label": "⚑ Speed", "pitch_label": "🎡 Pitch", "url_label": "🌐 Endpoint URL", "method_label": "πŸ“‘ HTTP Method", "auth_label": "πŸ” Authentication", "auth_bearer": "Bearer Token", "auth_custom": "Custom Header", "auth_none": "None", "token_label": "πŸ”‘ Bearer Token", "custom_header_name": "πŸ“‹ Header name", "custom_header_value": "πŸ“‹ Header value", "content_type_label": "πŸ“„ Content-Type", "payload_key_label": "πŸ—οΈ Text field in payload", "payload_key_hint": "Name of the JSON field that will contain the text to read (e.g.: message, text).", "extra_fields_label": "βž• Extra fields (JSON)", "extra_fields_placeholder": "{\"entity_id\": \"media_player.living_room\"}", "extra_fields_hint": "Additional fields to include in the payload, in JSON format. Leave empty if not needed.", "test_sound_btn": "πŸ”” Run Sound Test", "test_btn": "πŸ”Š Send Test Voice", "voices_loading": "Loading voices…", "voice_not_supported": "Voice not supported by this browser", "voices_none": "No voices available on this device", "voices_hint": "Available voices depend on the OS and browser. On macOS/iOS the Paola (Italian) voice is available. Press β†Ί if the list does not load.", "url_missing": "⚠️ Endpoint URL missing.", "test_sending": "⏳ Sending…", "test_ok": "βœ… Response {code} β€” check that the speaker has spoken.", "heard_question": "Did you hear the voice?", "heard_yes": "Yes, I heard it", "heard_no": "No, I didn't hear it", "test_ok_kiosk": "TTS is working.", "test_fail_steps": "Check: 1) media volume is not 0; 2) Google Text-to-Speech is installed and updated; 3) Italian voice package is downloaded in Android TTS settings." }, "language": { "title": "🌐 Language", "hint": "Select the interface language.", "label": "🌐 Language", "restart_notice": "The page will reload to apply the new language." }, "screensaver": { "label": "Enable screensaver", "card_title": "πŸŒ™ Screensaver", "card_hint": "Shows a clock with useful facts after 5 minutes of inactivity. Disabled by default.", "timeout_1": "1 minute", "timeout_2": "2 minutes", "timeout_5": "5 minutes", "timeout_10": "10 minutes", "timeout_15": "15 minutes", "timeout_30": "30 minutes", "timeout_60": "1 hour", "start_after": "⏱️ Start after" }, "scale": { "title": "βš–οΈ Smart Scale", "hint": "Connect a Bluetooth scale via the Android gateway to automatically read weight.", "tab": "Smart Scale", "enabled": "βœ… Enable smart scale", "url_label": "🌐 WebSocket Gateway URL", "url_placeholder": "ws://192.168.1.x:8765", "url_hint": "URL shown by the Android app (same Wi-Fi network). E.g.:", "test_btn": "πŸ”— Test connection", "download_btn": "πŸ“₯ Download Android Gateway (APK)", "download_hint": "Android app that bridges your BLE scale and EverShelf.", "download_sub": "Source: evershelf-scale-gateway/ in the project root", "live_weight": "real-time weight", "auto_reconnect": "πŸ” Reconnect: automatic", "kiosk_title": "πŸ“‘ BLE Scale integrated in Kiosk", "kiosk_hint": "The scale is directly managed by the internal BLE Gateway of the kiosk. To pair a new device, use the configuration wizard.", "kiosk_reconfigure": "πŸ”„ Reconfigure BLE Scale", "ble_protocols": "

πŸ”Œ Supported BLE protocols:

", "discover_scanning": "πŸ” Scanning local network for scale gateway…", "discover_found": "βœ… Gateway found: {url}{more}", "discover_not_found": "❌ No gateway found on {subnet}. Make sure the Android app is running and on the same Wi-Fi.", "discover_failed": "❌ Discovery failed: {error}", "discover_auto": "πŸ” Auto", "unknown_device": "Unknown device" }, "kiosk": { "hint": "Turn an Android tablet into an always-on EverShelf panel with built-in BLE scale gateway.", "download_btn": "πŸ“₯ Download EverShelf Kiosk (APK)", "download_sub": "Full-screen kiosk mode + integrated scale gateway. Source: evershelf-kiosk/", "native_title": "Kiosk Configuration", "native_hint": "Server URL, BLE scale, screensaver and setup wizard.", "native_btn": "Open kiosk configuration", "native_tap_hint": "Tap the gear button at the top right", "native_update_hint": "Update the kiosk app to use this feature", "update_title": "Kiosk Update", "check_updates_btn": "πŸ” Check for updates", "needs_update": "⚠️ The installed kiosk does not support this feature. Update the kiosk app to enable it." }, "saved": "βœ… Configuration saved!", "saved_local": "βœ… Configuration saved locally", "saved_local_error": "⚠️ Saved locally, server error: {error}", "theme": { "title": "πŸŒ™ Appearance", "hint": "Choose the interface theme.", "label": "πŸŒ™ Theme", "off": "β˜€οΈ Light", "on": "πŸŒ™ Dark", "auto": "πŸ”„ Automatic (time of day)" }, "zerowaste": { "card_title": "♻️ Zero-waste tips", "card_hint": "During cooking, show tips on how to reuse scraps generated in each step (peels, cooking water, etc.). Disabled by default.", "label": "Show tips during cooking" }, "backup": { "tab": "Backup", "local_title": "Local Backup", "local_hint": "Daily database snapshot. Configure how many days of backups to keep.", "enabled": "Enable daily automatic backup", "retention_days": "Retention (days)", "retention_info": "Backups are kept for", "backup_now": "Backup Now", "backing_up": "Backing up…", "backed_up": "Backup complete", "backup_error": "Backup error", "last_backup": "Last backup", "no_backup_yet": "No backup has been created yet", "list_empty": "No backups available", "restore_btn": "Restore", "restore_confirm": "Restore backup", "delete_btn": "Delete", "delete_confirm": "Delete backup", "gdrive_title": "Google Drive", "gdrive_hint": "Automatically back up to Google Drive via OAuth 2.0. No external libraries required.", "gdrive_enabled": "Enable Google Drive backup", "gdrive_folder_id": "Drive Folder ID", "gdrive_folder_id_hint": "Copy the ID from the Drive folder URL: …/folders/ID", "gdrive_retention_days": "Drive retention (days, 0=keep all)", "gdrive_test": "Test Connection", "gdrive_ok": "Connection successful!", "gdrive_error": "Connection failed", "gdrive_push_now": "Upload to Drive Now", "gdrive_pushing": "Uploading…", "gdrive_pushed": "Uploaded to Drive", "gdrive_wizard_hint": "Optional: automatically back up to Google Drive daily via OAuth 2.0.", "gdrive_skip": "Skip β€” configure later in Settings", "gdrive_client_id": "Client ID", "gdrive_client_secret": "Client Secret", "gdrive_redirect_uri_hint": "Add http://localhost as an authorized redirect URI in Google Cloud Console. This works on any server, even without a public domain.", "gdrive_code_title": "Paste the authorization URL or code", "gdrive_code_hint": "After authorizing, the browser will open http://localhost and may show a connection error β€” that is expected. Copy the URL from the address bar (e.g. http://localhost/?code=4%2F0A...) and paste it here.", "gdrive_code_submit": "Submit", "gdrive_code_empty": "Paste the URL or authorization code first", "gdrive_redirect_uri_label": "Redirect URI (add this in Google Cloud Console):", "gdrive_oauth_authorize": "Authorize with Google", "gdrive_oauth_authorized": "Authorized", "gdrive_oauth_not_authorized": "Not authorized yet", "gdrive_oauth_window_opened": "Browser window opened β€” authorize and come back", "gdrive_oauth_how_to": "How to set up OAuth 2.0 (step by step)", "gdrive_oauth_steps": "
  • Go to console.cloud.google.com and select your project
  • Enable the Google Drive API: APIs & Services β†’ Enable APIs β†’ Google Drive API
  • Go to APIs & Services β†’ Credentials β†’ Create Credentials β†’ OAuth client ID
  • Application type: Web application; add http://localhost as an Authorized redirect URI
  • Copy the Client ID and Client Secret into the fields above and save
  • Click Authorize with Google, sign in and grant access
  • The browser will open http://localhost (a connection error is expected): copy the URL from the address bar and paste it in the field that appears below
  • " }, "info": { "tab": "Info", "ai_title": "Gemini AI β€” Token Usage", "ai_hint": "Monthly consumption and estimated cost for the current API key.", "loading": "Loading…", "total_tokens": "Total tokens", "est_cost": "Est. cost", "input_tok": "Input tokens", "output_tok": "Output tokens", "ai_calls": "Calls", "by_action": "Breakdown by function", "by_model": "Breakdown by model", "pricing_note": "Gemini reference pricing: 2.5-flash $0.15/M in Β· $0.60/M out β€” 2.0-flash $0.10/M in Β· $0.40/M out.", "system_title": "System", "db_size": "Database", "log_size": "Logs", "log_level": "Log level", "ai_overview": "AI usage overview, inventory and system status", "calls_unit": "calls", "inv_title": "Inventory", "inv_active": "Active", "inv_products": "Total products", "inv_expiring": "Expiring (7d)", "inv_expired": "Expired", "inv_finished": "Finished", "act_title": "Monthly activity", "act_tx_month": "Movements", "act_restock": "Restocks", "act_use": "Usages", "act_new_products": "New products", "act_tx_year": "Yearly movements", "price_cache": "Price cache", "cache_entries": "products", "last_backup": "Last backup", "bring_days": "token expires in {n} days", "bring_expired": "token expired", "year_label": "Year {year}", "currency_title": "Currency", "currency_hint": "The currency used for all costs and prices in the app." }, "tab_general": "General", "shopping": { "tab": "Shopping list", "title": "Shopping list", "hint": "Configure the built-in shopping list or connect Bring!.", "enable_label": "Enable shopping list", "mode_label": "Provider", "mode_internal": "Built-in (no Bring!)", "mode_bring": "Bring! (external app)", "bring_section_title": "Bring! configuration", "ai_section_title": "AI assistance", "smart_suggestions_label": "AI suggestions", "forecast_label": "Forecast low-stock products", "auto_add_label": "Auto-add to list when", "auto_add_suffix": "remaining in stock (0 = only when empty)" }, "ha": { "tab": "Home Assistant", "title": "Home Assistant", "hint": "Connect EverShelf to Home Assistant for automations, push notifications and REST sensors.", "enabled": "Enable Home Assistant integration", "connection_title": "Connection", "url_label": "Home Assistant URL", "url_placeholder": "http://192.168.1.50:8123", "url_hint": "Base URL of your Home Assistant instance (e.g. http://homeassistant.local:8123).", "token_label": "Long-Lived Access Token", "token_hint": "Generate from HA Profile β†’ Security β†’ Long-Lived Access Tokens.", "token_placeholder": "eyJhbGci...", "token_saved": "Token saved (hidden for security)", "test_btn": "Test connection", "test_ok": "Connected to {version}", "test_fail": "Connection failed: {error}", "test_bad_token": "HA reachable but token is invalid", "testing": "Testing…", "error_no_url": "Please enter the Home Assistant URL first.", "tts_title": "TTS on Smart Speaker", "tts_hint": "Read recipe steps aloud on a Home Assistant media player.", "tts_entity_label": "Media player entity ID", "tts_entity_placeholder": "media_player.living_room", "tts_entity_hint": "Entity ID of the HA media player. Find it in HA: Developer Tools β†’ States.", "tts_platform_label": "TTS platform", "tts_platform_speak": "tts.speak (recommended)", "tts_platform_notify": "notify.* (notification service)", "tts_apply_btn": "Apply HA preset to TTS tab", "tts_apply_hint": "Pre-fills the TTS tab with the Home Assistant URL and token.", "tts_preset_applied": "HA preset applied to TTS tab.", "webhook_title": "Webhook Automations", "webhook_hint": "Send data to Home Assistant when pantry events occur. Create an HA automation with a Webhook trigger and paste the generated ID here.", "webhook_id_label": "Webhook ID", "webhook_id_placeholder": "evershelf_webhook_abc123", "webhook_id_hint": "ID of the webhook created in HA. Copy from: HA β†’ Settings β†’ Automations β†’ Create β†’ Webhook Trigger.", "webhook_events_label": "Notify on these events", "event_expiry": "Expiring products (daily)", "event_shopping": "Item added to shopping list", "event_stock": "Stock level updated", "expiry_days_label": "Expiry lead time (days)", "expiry_days_hint": "Send the expiry alert N days before the expiry date.", "webhook_help": "In HA: Settings β†’ Automations β†’ Create automation β†’ Trigger: Webhook β†’ copy the generated ID above.", "notify_title": "Push Notifications", "notify_hint": "Send push notifications to your phone via a Home Assistant notify service.", "notify_service_label": "Notify service", "notify_service_placeholder": "notify.mobile_app_my_phone", "notify_service_hint": "HA notify service name (e.g. notify.mobile_app_phone). Leave empty to disable.", "sensor_title": "REST Sensors", "sensor_hint": "Add to configuration.yaml to create EverShelf sensors in Home Assistant.", "sensor_copy_btn": "Copy YAML", "sensor_copied": "YAML copied to clipboard!", "save_btn": "Save HA settings", "ha_hint": "If you use Home Assistant, use the Home Assistant tab to configure TTS, webhooks and sensors." }, "kiosk_update_required": "⚠️ Update the kiosk app to use this feature" }, "expiry": { "today": "TODAY", "tomorrow": "Tomorrow", "days": "{days} days", "expired_days": "{days}d ago", "expired_yesterday": "Yesterday", "expired_today": "Today", "badge_today": "⚠️ Expires today!", "badge_tomorrow": "⏰ Tomorrow", "badge_tomorrow_long": "⏰ Expires tomorrow", "badge_days": "⏰ {n} days", "badge_expired_ago": "⚠️ Expired {n}d ago", "badge_expired": "β›” Expired!", "badge_stable": "βœ… Stable", "badge_expiring_short": "⏰ Exp. in {n}d", "badge_ok_still": "βœ… Still {n}d", "badge_expires_red": "πŸ”΄ Exp. in {n}d", "badge_expires_yellow": "🟑 Exp. in {n}d", "badge_expired_bare": "⚠️ Expired", "badge_expires_warn": "⚠️ Exp. in {n}d", "badge_days_left": "⏳ ~{n}d left", "days_approx": "~{n} days", "weeks_approx": "~{n} weeks", "months_approx": "~{n} months", "years_approx": "~{n} years", "expired_today_long": "Expired today", "expired_ago_long": "Expired {n} days ago", "expired_suffix": "β€” Expired!", "expired_suffix_ok": "β€” Expired (still ok)", "expired_suffix_warning": "β€” Expired (check first)", "opened_ago_long": "Opened {n} days ago", "opened_today_long": "Opened today", "opened_suffix": "β€” Opened too long!", "opened_suffix_ok": "β€” Opened (still ok)", "opened_suffix_warning": "β€” Opened (check first)", "days_compact": "{n}d", "badge_check_soon": "Check soon" }, "status": { "ok": "OK", "check": "Check", "discard": "Discard", "tip_freezer_ok": "In freezer: still safe (~{n}d margin)", "tip_freezer_check": "In freezer for a long time, may have lost quality. Consume soon", "tip_freezer_danger": "In freezer too long, risk of freezer burn and degradation", "tip_highRisk_check": "Expired recently, check smell and appearance before consuming", "tip_highRisk_danger": "Perishable product expired: discard for safety", "tip_medRisk_check1": "Check appearance and smell before consuming", "tip_medRisk_check2": "Expired a while ago, check carefully before use", "tip_medRisk_danger": "Too long since expiry, better to discard", "tip_lowRisk_ok": "Long-lasting product, still safe to consume", "tip_lowRisk_check": "Expired over a month ago, check package integrity", "tip_lowRisk_danger": "Expired too long ago, better not to risk it" }, "toast": { "product_saved": "Product saved!", "product_created": "Product created!", "product_updated": "βœ… Product updated!", "product_removed": "Product removed", "updated": "Updated!", "quantity_confirmed": "βœ“ Quantity confirmed", "added_to_inventory": "βœ… {name} added!", "removed_from_list": "βœ… {name} removed from the list!", "removed_from_list_short": "Removed from the list", "added_to_shopping": "πŸ›’ Added to the shopping list!", "removed_from_shopping": "πŸ›’ Removed from the shopping list", "finished_to_bring": "πŸ›’ Product finished β†’ added to Bring!", "thrown_away": "πŸ—‘οΈ {name} thrown away!", "thrown_away_partial": "πŸ—‘οΈ Thrown away {qty} {unit} of {name}", "finished_all": "πŸ“€ {name} finished!", "vacuum_sealed": "{name} saved as vacuum sealed", "product_finished_confirmed": "βœ… Removed β€” add it again when you restock", "ghost_restored": "βœ… {name}: restored {qty} {unit} to inventory", "appliance_added": "Appliance added", "item_added": "{name} added" }, "antiwaste": { "title": "🌱 Anti-Waste Report", "grade_label": "Grade", "you": "You", "avg_label": "Avg", "better": "πŸŽ‰ You lose {diff}% less than the {country}!", "worse": "⚠️ You lose more than the {country}. Room for improvement!", "on_par": "β†’ You're at the {country}. You can do better!", "saved_money": "~{amount}/month saved", "saved_meals": "~{n} meals saved", "saved_co2": "{n} kg COβ‚‚ avoided", "trend_title": "Trend (last 3 months)", "months_ago_2": "-60 days", "months_ago_1": "-30 days", "this_month": "Now", "country_it": "Italian avg", "country_de": "German avg", "country_en": "US average", "source": "Sources: REDUCE, Eurostat, USDA 2021", "live_on": "Live data", "live_off": "Offline", "meals": "meals", "annual_info": "πŸ“… You ~{you} kg/yr Β· avg ~{avg} kg/yr", "badge_rate": "loss rate", "badge_saved_money": "saved vs avg", "badge_wasted": "items lost", "badge_better": "less than avg" }, "error": { "generic": "Error", "network": "Network error", "no_api_key": "Configure the API key in settings", "loading": "Error loading product", "not_found": "Product not found", "not_found_manual": "Product not found. Enter it manually.", "search": "Search error. Try again.", "search_short": "Search error", "save": "Error saving", "connection": "Connection error", "camera": "Cannot access camera", "bring_add": "Error adding to Bring!", "bring_connection": "Bring! connection error", "identification": "Identification error", "ai_quota": "AI quota exhausted. Please try again in a few minutes.", "barcode_empty": "Enter a barcode", "barcode_format": "Barcode must contain only numbers (4-14 digits)", "barcode_checksum": "Invalid EAN checksum β€” please check the barcode digits", "min_chars": "Type at least 2 characters", "not_in_inventory": "Product not in inventory", "appliance_exists": "Appliance already exists", "already_exists": "Already exists", "network_retry": "Connection error. Try again.", "select_items": "Select at least one product", "server_offline": "Server connection lost", "server_restored": "Server connection restored", "server_retry": "Retry", "unknown": "Unknown error", "prefix": "Error", "no_inventory_entry": "No inventory entry found", "offline_title": "No connection", "offline_subtitle": "The app cannot reach the server. Check your Wi-Fi connection.", "offline_checking": "Checking connection…", "offline_restored": "Connection restored!", "offline_continue": "Continue in offline mode", "offline_reading_cache": "Reading from local cache", "offline_ops_pending": "{n} operations pending", "offline_synced": "{n} operations synced", "offline_ai_disabled": "Not available offline", "offline_cache_ready": "Offline β€” {n} items cached", "copy_failed": "Copy to clipboard failed", "invalid_quantity": "Invalid quantity" }, "confirm_placeholder_search": null, "confirm": { "remove_item": "Do you really want to remove this product from inventory?", "kiosk_exit": "Exit kiosk mode?", "cancel": "Cancel", "proceed": "Confirm", "discard_one": "Discard 1 piece" }, "location": { "dispensa": "Pantry", "frigo": "Fridge", "freezer": "Freezer" }, "edit": { "title": "Edit {name}", "unknown_hint": "Enter the product name and information", "label_name": "🏷️ Product name", "choose_location_title": "Which location?", "choose_location_hint": "Choose the location to edit:", "confirm_large_qty": "You are setting the quantity to {qty} {unit}. This seems unusually high. Confirm?" }, "screensaver": { "recipe_btn": "Recipes", "scan_btn": "Scan product" }, "days": { "mon": "Monday", "tue": "Tuesday", "wed": "Wednesday", "thu": "Thursday", "fri": "Friday", "sat": "Saturday", "sun": "Sunday", "mon_short": "Mon", "tue_short": "Tue", "wed_short": "Wed", "thu_short": "Thu", "fri_short": "Fri", "sat_short": "Sat", "sun_short": "Sun" }, "meal_types": { "lunch": "Lunch", "dinner": "Dinner", "colazione": "Breakfast", "merenda": "Snack", "dolce": "Dessert", "succo": "Fruit Juice", "pranzo": "Lunch", "cena": "Dinner" }, "scale": { "status_connected": "Scale connected", "status_searching": "Gateway connected, waiting for scale…", "status_disconnected": "Scale gateway unreachable", "status_error": "Gateway connection error", "not_connected": "Scale gateway not connected", "read_btn": "βš–οΈ Read from scale", "reading_title": "Scale reading", "place_on_scale": "Place the product on the scale…", "waiting_stable": "Weight will be captured automatically once the reading is stable.", "no_url": "Enter the gateway URL", "testing": "⏳ Testing connection…", "connected_ok": "Gateway connection successful!", "timeout": "Timeout: no response from gateway", "error_connect": "Cannot connect to gateway", "tab": "Smart Scale", "low_weight": "Weight < 10 g Β· enter manually\n(auto-reading requires at least 10 g)", "density_hint": "(density {density} g/ml)", "ml_hint": "(will be converted to ml)", "weight_detected": "Weight detected β€” wait 10s for stability…", "weight_too_low": "Weight too low β€” waiting…", "stable": "βœ“ Stable", "auto_confirm": "βœ… {val} {unit} β€” auto-confirm in 5s (tap to cancel)", "cancelled_replace": "Cancelled β€” replace the ingredient on the scale to resume" }, "prediction": { "expected_qty": "Expected: {expected} {unit}", "actual_qty": "Current: {actual} {unit}", "check_suggestion": "Check or weigh the remaining quantity" }, "date": { "today": "πŸ“… Today", "yesterday": "πŸ“… Yesterday" }, "scanner": { "title_barcode": "πŸ”– Scan Barcode", "barcode_hint": "Frame the product barcode", "barcode_manual_placeholder": "Or enter manually...", "barcode_use_btn": "βœ… Use this code", "ai_identifying": "πŸ€– Identifying product...", "ai_analyzing": "πŸ€– AI analysis in progress...", "product_label_hint": "Frame the product label", "expiry_label_hint": "Frame the expiry date printed on the product", "capture_btn": "πŸ“Έ Capture", "capture_photo_btn": "πŸ“Έ Take Photo", "retake_btn": "πŸ”„ Retake", "camera_error_hint": "Ensure you use HTTPS and have granted camera permissions.
    You can enter the barcode manually or use AI identification.", "no_barcode": "No barcode", "save_new_btn": "πŸ†• None of these β€” save as new", "expiry_found": "Date found", "expiry_read_fail": "Cannot read the date.", "expiry_raw_label": "Read" }, "lowstock": { "title": "⚠️ Running low!", "message": "{name} is running low β€” only {qty} remaining.", "question": "Do you want to add it to the shopping list?", "yes": "πŸ›’ Yes, add to Bring!", "no": "No, I'm fine for now" }, "move": { "title": "πŸ“¦ Move the rest?", "question": "Do you want to move the {thing} of {name} to another location?", "question_short": "Do you want to move the {thing} to another location?", "thing_opened": "opened package", "thing_rest": "rest", "stay_btn": "No, stay in {location}", "moved_toast": "πŸ“¦ Opened package moved to {location}", "vacuum_restore": "Restore vacuum sealed", "vacuum_seal_rest": "Vacuum seal the rest", "moved_simple": "πŸ“¦ Moved to {location}" }, "nova": { "1": "Unprocessed", "2": "Culinary ingredient", "3": "Processed", "4": "Ultra-processed" }, "meal_plan_types": { "pasta": "Pasta", "riso": "Rice", "carne": "Meat", "pesce": "Fish", "legumi": "Legumes", "uova": "Eggs", "formaggio": "Cheese", "pizza": "Pizza", "affettati": "Cold Cuts", "verdure": "Veggies", "zuppa": "Soup", "insalata": "Salad", "pane": "Bread/Sandwich", "dolce": "Dessert", "libero": "Free" }, "meal_sub": { "dolce_torta": "Cake", "dolce_crema": "Cream / Pudding", "dolce_crumble": "Crumble / Tart", "dolce_biscotti": "Cookies / Pastries", "dolce_frutta": "Fruit Dessert", "succo_dolce": "Sweet / Fruity", "succo_energizzante": "Energizing", "succo_detox": "Detox / Green", "succo_rinfrescante": "Refreshing", "succo_vitaminico": "Vitamin / Citrus" }, "meal_plan": { "reset_success": "Weekly plan reset", "not_available": "not available in pantry", "suggested_by": "suggested by weekly plan" }, "nutrition": { "title": "πŸ₯— Food Analysis", "score_excellent": "πŸ˜„ Excellent", "score_good": "πŸ™‚ Good", "score_improve": "😬 Improvable", "label_health": "🌿 Health", "label_variety": "🎨 Variety", "label_fresh": "❄️ Fresh", "source": "Based on {n} products in your pantry Β· EverShelf", "products_count": "products", "today_title": "πŸ₯— Your pantry today", "products_n": "{n} products", "macros_title": "Estimated Macronutrients", "macros_proteins": "Proteins", "macros_carbs": "Carbohydrates", "macros_fat": "Fat", "macros_fiber": "Fibre", "macros_source": "Estimate based on {n} pantry products" }, "facts": { "greeting_morning": "Good morning", "greeting_afternoon": "Good afternoon", "greeting_evening": "Good evening", "pantry_waiting": "{greeting}! Your Pantry awaits.", "expired_one": "You have 1 expired product in your pantry. Check it!", "expired_many": "You have {n} expired products in your pantry. Check them!", "expired_list": "Expired products: {names}", "expired_list_more": "and {n} more", "freezer_expired_ok": "{name} is expired, but being in the freezer it may still be fine! Check it.", "freezer_expired_old": "{name} in the freezer has been expired too long. Better to discard it.", "fridge_expired_one": "You have 1 expired product in the fridge!", "fridge_expired_many": "You have {n} expired products in the fridge!", "expiring_today": "{name} expires today! Use it right away.", "expiring_tomorrow": "{name} expires tomorrow. Plan ahead!", "expiring_days": "{name} expires in {days} days.", "expiring_many": "You have {n} products expiring soon.", "expiring_this_week": "{n} products expire this week. Plan your meals accordingly!", "expiring_item_loc": "{name} ({loc}) expires in {days} {dayslabel}.", "expiring_this_month": "{n} products will expire this month.", "shopping_add": "Add to list: {names} πŸ›’", "shopping_more": "and {n} more", "shopping_empty": "Shopping list empty. All stocked up! βœ…", "in_fridge": "In the fridge: {name}.", "in_freezer": "In the freezer: {name}. Don't forget it!", "top_category": "Top category is {icon} {cat} with {n} products.", "cat_meat": "You have {n} meat products. πŸ₯©", "cat_dairy": "You have {n} dairy products at home. πŸ₯›", "cat_veggies": "You have {n} types of vegetables. Great for your health! πŸ₯¬", "cat_fruit": "You have {n} types of fruit. 🍎", "cat_drinks": "You have {n} drinks available. πŸ₯€", "cat_frozen": "You have {n} frozen items. ❄️", "cat_pasta": "You have {n} types of pasta. 🍝 How about a carbonara?", "cat_canned": "You have {n} canned goods in your pantry. πŸ₯«", "cat_snacks": "You have {n} snacks. Resist the temptation! πŸͺ", "cat_condiments": "You have {n} condiments available. πŸ§‚", "item_random": "Did you know? You have {name} in {loc}.", "item_qty": "{name}: you have {qty}.", "no_expiry_count": "{n} products have no expiry date set.", "furthest_expiry": "The product with the furthest expiry is {name}: {months} months.", "high_qty": "You have a great stock of {name}: {qty}!", "low_qty_item": "{name} is running low. Add it to your shopping list?", "low_qty_count": "{n} products are almost out.", "morning_bread": "Good morning! You have bread for breakfast. 🍞", "morning_milk": "Is there milk in the fridge for a cappuccino? β˜•πŸ₯›", "morning_fruit": "Good morning! Some fresh fruit is a great way to start. 🍎", "noon_pasta": "Lunchtime… How about a nice bowl of pasta? 🍝", "noon_salad": "A fresh salad for lunch? You have {n} vegetables! πŸ₯—", "evening_meat": "For dinner you could use the meat you have. πŸ₯©", "evening_fish": "How about fish for dinner? 🐟", "evening_expiring": "You have {n} products expiring this week β€” use them tonight!", "night_reminder": "Good night! Remember to use tomorrow: {names}.", "weekly_balance": "Weekly balance: +{in} added, βˆ’{out} consumed.", "weekly_added": "You added {n} products this week.", "weekly_consumed": "You consumed {n} products this week. Well done!", "tip_freezer": "πŸ’‘ Frozen products last much longer than the expiry date.", "tip_bread": "πŸ’‘ Frozen bread keeps its freshness for weeks.", "tip_fifo": "πŸ’‘ To avoid waste, use products closest to expiry first (FIFO).", "tip_meat": "πŸ’‘ Meat in the freezer can last up to 6 months safely.", "tip_no_refreeze": "πŸ’‘ Never refreeze a thawed product. Cook it right away!", "tip_fridge": "πŸ’‘ A tidy fridge saves you time and money.", "tip_canned": "πŸ’‘ Opened canned goods should go in the fridge and be consumed within a few days.", "top_brand": "The most common brand in your pantry is {brand} with {n} products.", "combo_pasta": "You have pasta and condiments: ready for a first course! 🍝", "combo_sandwich": "Bread and meat: a quick sandwich is always a good idea! πŸ₯ͺ", "combo_balanced": "Vegetables and meat: you have everything for a balanced meal! πŸ₯—πŸ₯©", "pantry_empty": "The pantry is empty! Time to go shopping. πŸ›’", "pantry_empty_scan": "No products registered. Scan something to start!", "location_distribution": "Distribution: {parts}", "day": "day", "days": "days" }, "kiosk_session": { "first_item": "First item: {name}!", "items_two_four": "{n} items β€” warming up πŸš€", "items_five_nine": "{n} items β€” great pace! πŸ’ͺ", "items_ten_twenty": "{n} items β€” almost a record πŸ†", "items_twenty_plus": "{n} items β€” epic shopping! πŸ›’πŸ”₯", "duplicates_one": "1 duplicate (same thing twice)", "duplicates_many": "{n} duplicates (picked multiple times)", "top_category": "Top category: {cat} ({count}Γ—)", "items_fallback": "{n} item{plural} added" }, "kiosk": { "check_btn": "πŸ” Check for updates", "checking": "⏳ Checking…", "error_check": "Error during update check", "error_start_install": "Error starting installation", "version_installed": "Installed: {v}", "update_available": "⬆️ New version available: {latest} (installed: {current})", "up_to_date": "βœ… You are up to date β€” version {v}", "too_old": "⚠️ The installed kiosk is too old for automatic update checking.
    Press the button below to download and install the new version directly.", "manual_install": "⚠️ This kiosk does not support automatic installation.
    Manual procedure:
    1. Exit the kiosk (βœ• button top left)
    2. Uninstall the EverShelf Kiosk app
    3. Download and install the new APK from GitHub:", "starting_download": "⏳ Starting download…", "install_btn": "⬇️ Install update", "exit_title": "Exit kiosk", "refresh_title": "Refresh page" }, "update": { "new_version": "New version", "btn": "Update" }, "gemini": { "chat_title": "Chat with Gemini", "not_configured": "πŸ€– Gemini not configured β€” set GEMINI_API_KEY in settings" }, "appliances": { "empty": "No appliances added" }, "about": { "title": "About", "version": "Version", "report_bug": "Report a Bug", "report_bug_hint": "Something not working? Send us a report directly from the app.", "report_bug_modal_title": "Report a Bug", "report_type_bug": "Bug", "report_type_feature": "Feature", "report_type_question": "Question", "report_field_title": "Title", "report_field_title_ph": "Brief description of the issue", "report_field_desc": "Description", "report_field_desc_ph": "Describe the issue in detail…", "report_field_steps": "Steps to reproduce (optional)", "report_field_steps_ph": "1. Go to…\n2. Tap…\n3. See the error…", "report_auto_info": "Automatically attached: version {version}, language {lang}.", "report_send_btn": "Send report", "report_bug_sending": "Sending…", "report_bug_sent": "Report sent β€” thank you!", "report_bug_error": "Could not send the report. Check your connection.", "changelog": "Changelog", "github": "GitHub Repository" }, "export": { "title": "Export inventory", "hint": "Download the current inventory as CSV or open a print-ready version (PDF).", "btn_csv": "Download CSV", "btn_pdf": "PDF / Print", "btn_title": "Export" }, "startup": { "connecting": "Connecting to server...", "check_php_memory": "PHP memory", "check_php_timeout": "PHP timeout", "check_php_upload": "PHP upload", "check_data_dir": "Data directory", "check_rate_limits": "Rate limits dir", "check_backups": "Backup dir", "check_write_test": "Disk write test", "check_disk_space": "Disk space", "check_db_legacy": "Legacy DB (dispensa.db)", "check_db_connect": "Database connection", "check_db_tables": "Database tables", "check_db_integrity": "Database integrity", "check_db_wal": "WAL mode", "check_db_size": "Database size", "check_db_rows": "Inventory data", "check_env": ".env file", "check_gemini": "Gemini AI key", "check_bring_creds": "Bring! credentials", "check_bring_token": "Bring! token", "check_tts": "Text-to-Speech URL", "check_scale": "Scale gateway", "check_curl_ssl": "cURL SSL", "check_internet": "Internet connection", "fresh_install": "fresh install", "warnings_found": "warnings found", "all_ok": "System OK", "critical_error_short": "Critical error", "critical_error": "Critical error: the app cannot start. Check your server logs.", "critical_error_intro": "The app cannot start due to the following issues:", "error_network": "Cannot reach the server.", "error_network_detail": "The browser cannot reach the PHP server.\n\nPossible causes:\nβ€’ Apache/PHP server is not running\nβ€’ Network or firewall issue\nβ€’ Incorrect app URL\n\nMake sure the server is started and try again.", "retry": "Retry", "syncing_local": "Syncing local data...", "sync_done": "Local data synced", "token_required": "API token required", "token_autoconfig": "Configuring access...", "token_prompt_title": "πŸ”’ API Token", "token_prompt_hint": "Enter the API_TOKEN value from the server .env file.", "token_prompt_btn": "Continue" }, "stats_monthly": { "title": "Monthly Stats", "consumed": "products used", "trend_up": "+{pct}% vs {prev}", "trend_down": "-{pct}% vs {prev}", "trend_same": "same pace as last month", "added": "added", "wasted": "wasted", "top_used": "top used", "top_cats": "Top categories", "source": "Transaction history Β· current month" }, "time": { "just_now": "just now", "seconds_ago": "{n}s ago", "minutes_ago": "{n} min ago", "hours_ago": "{n} h ago", "days_ago": "{n} d ago" } }