696a9c6d11
- Always-on 2x hardware zoom (CSS scale fallback) - Torch button with toggle + visual feedback - Camera flip (front/back) with settings persistence - 3-tab input panel: Barcode / Name / AI - Recent products chips (last 6 scanned, from localStorage) - Live barcode code overlay during partial detection - Confirm overlay (checkmark + name) on successful scan - AI number OCR (Gemini reads barcode digits from image, shown after 4s) - Guide corners frame in viewport - PHP: gemini_number_ocr action + rate-limited - Translations: new scan.* keys in it/en/de
1086 lines
47 KiB
JSON
1086 lines
47 KiB
JSON
{
|
||
"app": {
|
||
"name": "EverShelf",
|
||
"loading": "Loading..."
|
||
},
|
||
"nav": {
|
||
"title": "EverShelf",
|
||
"home": "Home",
|
||
"inventory": "Pantry",
|
||
"recipes": "Recipes",
|
||
"shopping": "Shopping",
|
||
"log": "Log"
|
||
},
|
||
"btn": {
|
||
"back": "← Back",
|
||
"save": "💾 Save",
|
||
"cancel": "✕ Cancel",
|
||
"close": "Close",
|
||
"add": "✅ Add",
|
||
"delete": "Delete",
|
||
"edit": "✏️ 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"
|
||
},
|
||
"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"
|
||
},
|
||
"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": "Anomalous consumption",
|
||
"banner_prediction_hint": "Based on predictions, this quantity doesn't match expected consumption.",
|
||
"banner_prediction_action_confirm": "Confirm {qty} {unit} is correct",
|
||
"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_throw": "I threw it away",
|
||
"banner_expired_action_edit": "Fix date",
|
||
"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": "I expected {expected} {unit}{time}, but you have {actual} {unit}. Did you add stock without recording it?",
|
||
"banner_prediction_less": "I expected {expected} {unit}{time}, but you only have {actual} {unit}. Did you use more than usual?",
|
||
"banner_finished_zero": "Inventory shows zero, 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_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 <strong>{inv_qty} {unit}</strong> 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?",
|
||
"consumed": "Consumed: {n} ({pct}%)",
|
||
"wasted": "Wasted: {n} ({pct}%)",
|
||
"more_opened": "and {n} more opened...",
|
||
"banner_expired_detail": "{when} · you still have <strong>{qty}</strong>.",
|
||
"banner_opened_detail": "{when} in {location} · you still have <strong>{qty}</strong>.",
|
||
"banner_explain_title": "Ask Gemini for an explanation",
|
||
"banner_explain_btn": "Explain",
|
||
"banner_analyzing": "🤖 Analyzing…"
|
||
},
|
||
"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.<br>Scan a product to add it!",
|
||
"empty_db": "No products in the database.<br>Scan a product to get started!",
|
||
"qty_trace": "< 1"
|
||
},
|
||
"scan": {
|
||
"title": "Scan",
|
||
"mode_shopping": "🛒 Shopping Mode",
|
||
"mode_shopping_end": "✅ End shopping",
|
||
"spesa_btn": "🛒 Shopping",
|
||
"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"
|
||
},
|
||
"action": {
|
||
"title": "What do you want to do?",
|
||
"add_btn": "📥 ADD",
|
||
"add_sub": "to pantry/fridge",
|
||
"use_btn": "📤 USE / CONSUME",
|
||
"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": "Create a recipe with this"
|
||
},
|
||
"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}",
|
||
"suffix_freezer_vacuum": "(freezer + vacuum sealed)",
|
||
"history_badge_tip": "Average from {n} previous entries"
|
||
},
|
||
"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}!",
|
||
"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 <strong>today</strong>",
|
||
"when_tomorrow": "expires <strong>tomorrow</strong>",
|
||
"when_days": "expires in <strong>{n} days</strong>",
|
||
"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_all": "🗑️ Finish EVERYTHING ({qty})",
|
||
"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"
|
||
},
|
||
"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",
|
||
"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"
|
||
},
|
||
"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",
|
||
"close_btn": "✅ Close",
|
||
"ingredients_title": "🧾 Ingredients",
|
||
"steps_title": "👨🍳 Steps",
|
||
"no_steps": "No steps available",
|
||
"generate_error": "Generation error",
|
||
"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"
|
||
},
|
||
"shopping": {
|
||
"title": "🛒 Shopping List",
|
||
"bring_loading": "Connecting to Bring!...",
|
||
"bring_not_configured": "Bring! is not configured. Add your email and password in <a href='#' onclick=\"showPage('settings');return false;\">settings</a>.",
|
||
"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.<br>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 <strong>{name}</strong>{urgency}.",
|
||
"item_removed": "✅ {name} removed from list!",
|
||
"urgency_spec_critical": "⚡ Urgent",
|
||
"urgency_spec_high": "🟠 Soon",
|
||
"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_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"
|
||
},
|
||
"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.\n<small>Add GEMINI_API_KEY to the .env file on the server.</small>",
|
||
"fields_filled": "✅ Fields filled by AI",
|
||
"use_data": "✅ Use AI data",
|
||
"use_data_no_barcode": "✅ Use AI data (no barcode)"
|
||
},
|
||
"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"
|
||
},
|
||
"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"
|
||
},
|
||
"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"
|
||
},
|
||
"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"
|
||
},
|
||
"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"
|
||
},
|
||
"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"
|
||
},
|
||
"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",
|
||
"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_btn": "🔊 Send Test Voice"
|
||
},
|
||
"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."
|
||
},
|
||
"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"
|
||
},
|
||
"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/"
|
||
},
|
||
"saved": "✅ Configuration saved!",
|
||
"saved_local": "✅ Configuration saved locally",
|
||
"saved_local_error": "⚠️ Saved locally, server error: {error}"
|
||
},
|
||
"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"
|
||
},
|
||
"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}",
|
||
"product_finished_confirmed": "✅ Removed — add it again when you restock",
|
||
"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)",
|
||
"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"
|
||
},
|
||
"confirm": {
|
||
"remove_item": "Do you really want to remove this product from inventory?",
|
||
"kiosk_exit": "Exit kiosk mode?",
|
||
"cancel": "Cancel",
|
||
"proceed": "Confirm"
|
||
},
|
||
"location": {
|
||
"dispensa": "Pantry",
|
||
"frigo": "Fridge",
|
||
"freezer": "Freezer"
|
||
},
|
||
"edit": {
|
||
"title": "Edit {name}",
|
||
"unknown_hint": "Enter the product name and information",
|
||
"label_name": "🏷️ Product name"
|
||
},
|
||
"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.<br>You can enter the barcode manually or use AI identification.",
|
||
"no_barcode": "No barcode",
|
||
"save_new_btn": "🆕 None of these — save as new"
|
||
},
|
||
"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"
|
||
},
|
||
"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"
|
||
},
|
||
"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: <strong>{latest}</strong> (installed: {current})",
|
||
"up_to_date": "✅ You are up to date — version <strong>{v}</strong>",
|
||
"too_old": "⚠️ The installed kiosk is too old for automatic update checking.<br>Press the button below to download and install the new version directly.",
|
||
"manual_install": "⚠️ This kiosk does not support automatic installation.<br><strong>Manual procedure:</strong><br>1. Exit the kiosk (✕ button top left)<br>2. Uninstall the EverShelf Kiosk app<br>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"
|
||
}
|
||
} |