f46b12e3ad
- #124: star toggle on recipe view + favorites shown first in archive with gold border - #123: +/- persons buttons on recipe to scale ingredient quantities - #117: wasted value in EUR displayed in monthly stats section - #118: macronutrient breakdown panel (P/C/F/fiber bars) with 4th insight rotation phase - DB: is_favorite column on recipes, nutriments_json on products (auto-migrated) - OFF API: nutriments fields fetched and stored per product - Translations: it/en/de/fr/es updated with new keys
1392 lines
77 KiB
JSON
1392 lines
77 KiB
JSON
{
|
||
"app": {
|
||
"name": "EverShelf",
|
||
"loading": "Chargement..."
|
||
},
|
||
"nav": {
|
||
"title": "EverShelf",
|
||
"home": "Accueil",
|
||
"inventory": "Garde-manger",
|
||
"recipes": "Recettes",
|
||
"shopping": "Courses",
|
||
"log": "Journal",
|
||
"settings": "Paramètres"
|
||
},
|
||
"btn": {
|
||
"back": "← Retour",
|
||
"save": "💾 Enregistrer",
|
||
"cancel": "✕ Annuler",
|
||
"close": "Fermer",
|
||
"add": "✅ Ajouter",
|
||
"delete": "Supprimer",
|
||
"edit": "✏️ Modifier",
|
||
"use": "Utiliser",
|
||
"edit_item": "Modifier",
|
||
"search": "🔍 Rechercher",
|
||
"go": "✅ Valider",
|
||
"toggle_password": "👁️ Afficher/Masquer",
|
||
"load_more": "Charger plus...",
|
||
"save_config": "💾 Enregistrer la configuration",
|
||
"save_product": "💾 Enregistrer le produit",
|
||
"restart": "↺ Redémarrer",
|
||
"reset_default": "↺ Rétablir les valeurs par défaut",
|
||
"save_info": "💾 Enregistrer les informations",
|
||
"retry": "🔄 Réessayer",
|
||
"yes_short": "Oui",
|
||
"no_short": "Non"
|
||
},
|
||
"form": {
|
||
"select_placeholder": "-- Sélectionner --"
|
||
},
|
||
"locations": {
|
||
"dispensa": "Garde-manger",
|
||
"frigo": "Réfrigérateur",
|
||
"freezer": "Congélateur",
|
||
"altro": "Autre"
|
||
},
|
||
"categories": {
|
||
"latticini": "Produits laitiers",
|
||
"carne": "Viande",
|
||
"pesce": "Poisson",
|
||
"frutta": "Fruits",
|
||
"verdura": "Légumes",
|
||
"pasta": "Pâtes & Riz",
|
||
"pane": "Pain & Boulangerie",
|
||
"surgelati": "Surgelés",
|
||
"bevande": "Boissons",
|
||
"condimenti": "Condiments",
|
||
"snack": "Snacks & Sucreries",
|
||
"conserve": "Conserves",
|
||
"cereali": "Céréales & Légumineuses",
|
||
"igiene": "Hygiène",
|
||
"pulizia": "Entretien",
|
||
"altro": "Autre",
|
||
"select": "-- Sélectionner --"
|
||
},
|
||
"units": {
|
||
"pz": "pcs",
|
||
"conf": "pkg",
|
||
"g": "g",
|
||
"ml": "ml",
|
||
"pieces": "Pièces",
|
||
"grams": "Grammes",
|
||
"box": "Paquet",
|
||
"boxes": "Paquets",
|
||
"millilitres": "Millilitres",
|
||
"from": "de"
|
||
},
|
||
"shopping_sections": {
|
||
"frutta_verdura": "Fruits & Légumes",
|
||
"carne_pesce": "Viande & Poisson",
|
||
"latticini": "Produits laitiers & Frais",
|
||
"pane_dolci": "Pain & Pâtisseries",
|
||
"pasta": "Pâtes & Céréales",
|
||
"conserve": "Conserves & Sauces",
|
||
"surgelati": "Surgelés",
|
||
"bevande": "Boissons",
|
||
"pulizia_igiene": "Nettoyage & Hygiène",
|
||
"altro": "Autre"
|
||
},
|
||
"dashboard": {
|
||
"expired_title": "🚫 Périmé",
|
||
"expiring_title": "⏰ Expire bientôt",
|
||
"stats_period": "📊 30 derniers jours",
|
||
"opened_title": "📦 Produits ouverts",
|
||
"review_title": "🔍 À vérifier",
|
||
"review_hint": "Quantités inhabituelles. Confirmez si elles sont correctes ou modifiez-les.",
|
||
"quick_recipe": "Recette rapide avec les produits qui expirent",
|
||
"banner_review_title": "Quantité anormale",
|
||
"banner_review_action_ok": "C'est correct",
|
||
"banner_review_action_finish": "🗑️ Tout fini",
|
||
"banner_review_action_edit": "Corriger",
|
||
"banner_review_action_weigh": "Peser",
|
||
"banner_review_dismiss": "Ignorer",
|
||
"banner_prediction_title": "Consommation à vérifier",
|
||
"banner_prediction_hint": "L'estimation de consommation s'adapte aux données récentes : confirmez uniquement si la quantité actuelle est correcte.",
|
||
"banner_prediction_action_confirm": "Confirmer {qty} {unit}",
|
||
"banner_prediction_action_weigh": "Peser maintenant",
|
||
"banner_prediction_action_edit": "Mettre à jour la quantité",
|
||
"banner_expired_title": "Produit périmé",
|
||
"banner_expired_today": "Périmé aujourd'hui",
|
||
"banner_expired_days": "Périmé il y a {days} jours",
|
||
"banner_expired_action_use": "Utiliser quand même",
|
||
"banner_expired_action_finished": "Je l'ai terminé !",
|
||
"banner_expired_action_throw": "Je l'ai jeté",
|
||
"banner_expired_action_edit": "Corriger la date",
|
||
"banner_anomaly_action_edit": "Corriger l'inventaire",
|
||
"banner_anomaly_action_dismiss": "La quantité est correcte",
|
||
"banner_no_expiry_title": "Date manquante : {name}",
|
||
"banner_no_expiry_detail": "Ce produit n'a pas de date de péremption. Voulez-vous en ajouter une ou confirmer qu'il ne périme pas ?",
|
||
"banner_no_expiry_action_set": "Définir une date de péremption",
|
||
"banner_no_expiry_action_dismiss": "Ne périme pas ✓",
|
||
"banner_no_expiry_toast_dismissed": "Marqué comme « sans date limite »",
|
||
"banner_expiring_title": "Expire bientôt",
|
||
"banner_expiring_today": "Expire aujourd'hui !",
|
||
"banner_expiring_tomorrow": "Expire demain",
|
||
"banner_expiring_days": "Expire dans {days} jours",
|
||
"banner_expiring_action_use": "Utiliser maintenant",
|
||
"banner_finished_title": "terminé ?",
|
||
"banner_finished_detail": "J'ai enregistré que {name} a atteint zéro stock. Est-il vraiment épuisé ou en avez-vous encore ?",
|
||
"banner_finished_action_yes": "Oui, c'est fini",
|
||
"banner_finished_action_no": "Non, j'en ai encore",
|
||
"banner_review_unusual_pkg_title": "Taille de paquet inhabituelle",
|
||
"banner_review_unusual_pkg_detail": "Vous avez défini un paquet de {qty} {unit} — la taille semble très grande. Vérifiez si c'est correct ou modifiez.",
|
||
"banner_review_low_qty_title": "Quantité très faible",
|
||
"banner_review_low_qty_detail": "Vous n'avez que {qty} en stock — cela semble très peu, peut-être une erreur de saisie. Confirmez si c'est correct.",
|
||
"banner_review_high_qty_title": "Quantité inhabituellement élevée",
|
||
"banner_review_high_qty_detail": "Vous avez {qty} en stock — le chiffre semble très élevé. Confirmez si c'est correct ou modifiez.",
|
||
"banner_prediction_rate_day": "Moyenne ~{n} {unit}/jour",
|
||
"banner_prediction_rate_week": "Moyenne ~{n} {unit}/semaine",
|
||
"banner_prediction_days_ago": "Il y a {n} jours vous avez réapprovisionné",
|
||
"banner_prediction_more": "estimation précédente : {expected} {unit}{time} ; quantité actuelle : {actual} {unit}.",
|
||
"banner_prediction_less": "estimation : {expected} {unit}{time} ; quantité actuelle : {actual} {unit}. Si votre rythme d'utilisation a changé, la prévision se met à jour automatiquement.",
|
||
"banner_finished_zero": "L'inventaire indique zéro, mais les mouvements enregistrés suggèrent qu'il ne devrait pas être vide.",
|
||
"banner_finished_expected": "D'après les enregistrements vous devriez avoir encore {qty} {unit}.",
|
||
"banner_finished_check": "Pouvez-vous vérifier ?",
|
||
"banner_anomaly_phantom_title": "vous avez plus de stock que prévu",
|
||
"banner_anomaly_phantom_detail": "L'inventaire indique {inv_qty} {unit}, mais selon les enregistrements vous ne devriez avoir que {expected_qty} {unit}. Avez-vous ajouté du stock sans l'enregistrer ?",
|
||
"banner_anomaly_untracked_title": "stock non enregistré comme entrée",
|
||
"banner_anomaly_untracked_detail": "Vous avez <strong>{inv_qty} {unit}</strong> en inventaire, mais les sorties enregistrées dépassent les entrées — le stock initial n'a probablement jamais été ajouté comme transaction « entrée ». Vous pouvez corriger la quantité ou saisir les entrées manquantes.",
|
||
"banner_anomaly_ghost_title": "vous avez moins de stock que prévu",
|
||
"banner_anomaly_ghost_detail": "D'après les opérations enregistrées vous devriez avoir {expected_qty} {unit} de {name}, mais l'inventaire n'en montre que {inv_qty} {unit}. Avez-vous pris du stock sans l'enregistrer ?",
|
||
"consumed": "Consommé : {n} ({pct}%)",
|
||
"wasted": "Gaspillé : {n} ({pct}%)",
|
||
"more_opened": "et {n} autres ouverts...",
|
||
"banner_expired_detail": "{when} · il vous reste encore <strong>{qty}</strong>.",
|
||
"banner_opened_detail": "{when} dans {location} · il vous reste encore <strong>{qty}</strong>.",
|
||
"banner_explain_title": "Demander une explication à Gemini",
|
||
"banner_explain_btn": "Expliquer",
|
||
"banner_analyzing": "🤖 Analyse en cours…"
|
||
},
|
||
"inventory": {
|
||
"title": "Garde-manger",
|
||
"filter_all": "Tout",
|
||
"search_placeholder": "🔍 Rechercher un produit...",
|
||
"recent_title": "🕐 Utilisés récemment",
|
||
"popular_title": "⭐ Les plus utilisés",
|
||
"empty": "Aucun produit ici.\nScannez un produit pour l'ajouter !",
|
||
"no_items_found": "Aucun article trouvé",
|
||
"qty_remainder_suffix": "restant",
|
||
"vacuum_badge": "🫙 Sous vide",
|
||
"opened_badge": "📭 Ouvert",
|
||
"label_expiry": "📅 Péremption",
|
||
"label_storage": "🫙 Conservation",
|
||
"label_status": "📭 État",
|
||
"opened_since": "Ouvert depuis le {date}",
|
||
"label_position": "📍 Emplacement",
|
||
"label_quantity": "📦 Quantité",
|
||
"label_added": "📅 Ajouté",
|
||
"empty_text": "Aucun produit ici.<br>Scannez un produit pour l'ajouter !",
|
||
"empty_db": "Aucun produit dans la base de données.<br>Scannez un produit pour commencer !",
|
||
"qty_trace": "< 1"
|
||
},
|
||
"scan": {
|
||
"title": "Scanner",
|
||
"mode_shopping": "🛒 Mode courses",
|
||
"mode_shopping_end": "✅ Terminer les courses",
|
||
"spesa_btn": "🛒 Courses",
|
||
"zoom": "Zoom",
|
||
"tab_barcode": "Code-barres",
|
||
"tab_name": "Nom",
|
||
"tab_ai": "IA",
|
||
"recents_label": "Récents",
|
||
"torch_hint": "Torche",
|
||
"torch_on": "Torche activée",
|
||
"torch_off": "Torche désactivée",
|
||
"torch_unavailable": "Torche non disponible sur cet appareil",
|
||
"flip_hint": "Retourner la caméra",
|
||
"flip_front": "Caméra frontale",
|
||
"flip_back": "Caméra arrière",
|
||
"num_ocr_btn": "🔢 Lire les chiffres avec l'IA",
|
||
"num_ocr_searching": "Recherche du code-barres avec l'IA...",
|
||
"num_ocr_found": "Code trouvé : {code}",
|
||
"num_ocr_not_found": "Aucun code-barres trouvé dans l'image",
|
||
"barcode_placeholder": "Entrez le code-barres...",
|
||
"quick_name_divider": "ou tapez le nom",
|
||
"quick_name_placeholder": "Ex. : Pommes, Courgettes, Pain...",
|
||
"manual_entry": "✏️ Saisie manuelle",
|
||
"ai_identify": "🤖 Identifier avec l'IA",
|
||
"hint": "Scannez le code-barres, tapez le nom du produit ou utilisez l'IA pour l'identifier",
|
||
"debug_toggle": "🐛 Journal de débogage",
|
||
"barcode_acquired": "🔖 Code-barres scanné : {code}",
|
||
"scan_barcode": "🔖 Scanner le code-barres",
|
||
"create_named": "Créer {name}",
|
||
"new_without_barcode": "Nouveau produit sans code-barres"
|
||
},
|
||
"action": {
|
||
"title": "Que voulez-vous faire ?",
|
||
"add_btn": "📥 AJOUTER",
|
||
"add_sub": "au garde-manger/réfrigérateur",
|
||
"use_btn": "📤 UTILISER / CONSOMMER",
|
||
"use_sub": "depuis le garde-manger/réfrigérateur",
|
||
"have_title": "📦 Déjà en stock !",
|
||
"add_more_sub": "en ajouter",
|
||
"use_qty_sub": "combien vous avez utilisé",
|
||
"throw_btn": "🗑️ JETER",
|
||
"throw_sub": "jeter",
|
||
"edit_sub": "péremption, emplacement…",
|
||
"create_recipe_btn": "Recette"
|
||
},
|
||
"add": {
|
||
"title": "Ajouter au garde-manger",
|
||
"location_label": "📍 Où le rangez-vous ?",
|
||
"quantity_label": "📦 Quantité",
|
||
"conf_size_label": "📦 Chaque paquet contient :",
|
||
"conf_size_placeholder": "ex. 300",
|
||
"vacuum_label": "🫙 Sous vide",
|
||
"vacuum_hint": "La date de péremption sera automatiquement prolongée",
|
||
"submit": "✅ Ajouter",
|
||
"purchase_type_label": "🛒 Ce produit est...",
|
||
"new_btn": "🆕 Vient d'être acheté",
|
||
"existing_btn": "📦 Je l'avais déjà",
|
||
"remaining_label": "📦 Quantité restante",
|
||
"remaining_hint": "Approximativement combien en reste-t-il ?",
|
||
"remaining_full": "🟢 Plein",
|
||
"remaining_half": "🟠 À moitié",
|
||
"estimated_expiry": "Date de péremption estimée :",
|
||
"suffix_freezer": "(congélateur)",
|
||
"suffix_vacuum": "(sous vide)",
|
||
"hint_modify": "📝 Vous pouvez modifier la date ou la scanner avec la caméra",
|
||
"scan_expiry_title": "📷 Scanner la date de péremption",
|
||
"product_added": "✅ {name} ajouté !{qty}",
|
||
"suffix_freezer_vacuum": "(congélateur + sous vide)",
|
||
"history_badge_tip": "Moyenne de {n} entrées précédentes",
|
||
"vacuum_question": "Sous vide ?",
|
||
"vacuum_saved": "🔒 Sous vide !"
|
||
},
|
||
"use": {
|
||
"title": "Utiliser / Consommer",
|
||
"location_label": "📍 Depuis où ?",
|
||
"quantity_label": "Combien avez-vous utilisé ?",
|
||
"change": "modifier",
|
||
"partial_hint": "Ou précisez la quantité utilisée :",
|
||
"partial_piece_hint": "Avez-vous utilisé seulement une partie ?",
|
||
"piece": "pièce",
|
||
"one_whole": "1 entier",
|
||
"use_all": "🗑️ Tout utilisé / Terminé",
|
||
"submit": "📤 Utiliser cette quantité",
|
||
"available": "📦 Disponible :",
|
||
"opened_badge": "OUVERT",
|
||
"not_in_inventory": "⚠️ Produit absent de l'inventaire.",
|
||
"expiry_warning": "⚠️ Utilisez en premier celui{loc} qui expire le {date} — {when} !",
|
||
"expiry_warning_opened": "⚠️ Celui{loc} est ouvert depuis {when} — utilisez-le en premier !",
|
||
"throw_title": "🗑️ Jeter le produit",
|
||
"throw_all": "🗑️ Tout jeter ({qty})",
|
||
"throw_qty_label": "Quelle quantité jeter ?",
|
||
"throw_qty_hint": "ou entrez une quantité :",
|
||
"throw_partial_btn": "🗑️ Jeter cette quantité",
|
||
"when_expired": "périmé il y a {n} jours",
|
||
"when_today": "expire <strong>aujourd'hui</strong>",
|
||
"when_tomorrow": "expire <strong>demain</strong>",
|
||
"when_days": "expire dans <strong>{n} jours</strong>",
|
||
"toast_used": "📤 {qty} de {name} utilisé",
|
||
"toast_bring": "🛒 Produit terminé → ajouté à Bring !",
|
||
"toast_opened_finished": "🔓 Emballage ouvert de {name} terminé !",
|
||
"disambiguation_hint": "Que voulez-vous dire par « tout fini » ?",
|
||
"disambiguation_all": "🗑️ Tout finir ({qty})",
|
||
"error_exceeds_stock": "⚠️ Vous ne pouvez pas utiliser plus que ce que vous avez disponible !",
|
||
"use_all_confirm_title": "✅ Tout terminer",
|
||
"use_all_confirm_msg": "Confirmez que vous avez terminé le produit :",
|
||
"use_all_confirm_btn": "✅ Oui, terminé",
|
||
"throw_all_confirm_title": "🗑️ Tout jeter",
|
||
"throw_all_confirm_msg": "Voulez-vous vraiment jeter tout le produit ?",
|
||
"throw_all_confirm_btn": "🗑️ Oui, jeter"
|
||
},
|
||
"product": {
|
||
"title_new": "Nouveau produit",
|
||
"title_edit": "Modifier le produit",
|
||
"ai_fill": "📷 Prendre une photo et identifier avec l'IA",
|
||
"ai_fill_hint": "L'IA remplira automatiquement les champs du produit",
|
||
"name_label": "🏷️ Nom du produit *",
|
||
"name_placeholder": "Ex. : Lait entier, Pâtes penne...",
|
||
"brand_label": "🏢 Marque",
|
||
"brand_placeholder": "Ex. : Barilla, Danone, Heinz...",
|
||
"category_label": "📂 Catégorie",
|
||
"unit_label": "📏 Unité de mesure",
|
||
"default_qty_label": "🔢 Quantité par défaut",
|
||
"conf_size_label": "📦 Chaque paquet contient :",
|
||
"conf_size_placeholder": "ex. 300",
|
||
"notes_label": "📝 Notes",
|
||
"notes_placeholder": "Ex. : sans lactose, biologique, conserver au réfrigérateur après ouverture...",
|
||
"barcode_label": "🔖 Code-barres",
|
||
"barcode_placeholder": "Code-barres (si disponible)",
|
||
"barcode_hint": "⚠️ Ajoutez le code-barres pour la prochaine fois, il suffira de scanner !",
|
||
"submit": "💾 Enregistrer le produit",
|
||
"name_required": "Entrez le nom du produit",
|
||
"conf_size_required": "Précisez le contenu du paquet",
|
||
"expiry_estimated": "Date de péremption estimée :",
|
||
"scan_expiry": "Scanner la date de péremption",
|
||
"expiry_hint": "📝 Vous pouvez modifier la date ou la scanner avec la caméra",
|
||
"add_batch": "📦 + Lot avec une date différente",
|
||
"package_info": "📦 Paquet : {info}",
|
||
"edit_catalog": "⚙️ Modifier les infos produit (nom, marque, catégorie…)",
|
||
"not_recognized": "⚠️ Produit non reconnu",
|
||
"edit_info": "✏️ Modifier les informations",
|
||
"modify_details": "MODIFIER\npéremption, emplacement…",
|
||
"already_in_pantry": "📋 Déjà dans le garde-manger",
|
||
"no_barcode": "Pas de code-barres",
|
||
"unknown_product": "Produit non reconnu",
|
||
"edit_name_brand": "Modifier nom/marque",
|
||
"weight_label": "Poids",
|
||
"origin_label": "Origine",
|
||
"labels_label": "Labels",
|
||
"select_variant": "Sélectionnez la variante exacte ou utilisez les données IA :"
|
||
},
|
||
"products": {
|
||
"title": "📦 Tous les produits",
|
||
"search_placeholder": "🔍 Rechercher un produit...",
|
||
"empty": "Aucun produit dans la base de données.\nScannez un produit pour commencer !",
|
||
"no_category": "Aucun produit dans cette catégorie"
|
||
},
|
||
"recipes": {
|
||
"title": "🍳 Recettes",
|
||
"generate": "✨ Générer une nouvelle recette",
|
||
"archive_empty": "Aucune recette enregistrée. Générez votre première recette !",
|
||
"dialog_title": "🍳 Recette",
|
||
"dialog_desc": "Je vais générer une recette saine en utilisant les ingrédients du garde-manger, en priorisant les produits qui expirent.",
|
||
"meal_label": "🕐 Quel repas ?",
|
||
"persons_label": "👥 Pour combien de personnes ?",
|
||
"meal_type_label": "🎯 Type de repas",
|
||
"opt_fast": "⚡ Repas rapide",
|
||
"opt_light": "🥗 Appétit léger",
|
||
"opt_expiry": "⏰ Prioriser les produits qui expirent",
|
||
"opt_healthy": "💚 Extra sain",
|
||
"opt_opened": "📦 Prioriser les produits ouverts",
|
||
"opt_zero_waste": "♻️ Zéro déchet",
|
||
"generate_btn": "✨ Générer la recette",
|
||
"loading_msg": "Préparation de votre recette...",
|
||
"start_cooking": "👨🍳 Mode cuisine",
|
||
"regenerate": "🔄 En générer une autre",
|
||
"regen_choice_title": "Que veux-tu faire de cette recette ?",
|
||
"regen_replace": "🔄 En générer une autre (ignorer celle-ci)",
|
||
"regen_save_new": "💾 Sauvegarder dans l'archive et en générer une nouvelle",
|
||
"close_btn": "✅ Fermer",
|
||
"ingredients_title": "🧾 Ingrédients",
|
||
"tools_title": "Matériel nécessaire",
|
||
"steps_title": "👨🍳 Étapes",
|
||
"no_steps": "Aucune étape disponible",
|
||
"generate_error": "Erreur de génération",
|
||
"persons_short": "pers.",
|
||
"use_ingredient_title": "Utiliser l'ingrédient",
|
||
"recipe_qty_label": "Recette",
|
||
"from_where_label": "Depuis où ?",
|
||
"amount_label": "Combien",
|
||
"use_amount_btn": "Utiliser cette quantité",
|
||
"use_all_btn": "Tout utiliser / Terminé",
|
||
"packs_label": "Paquets",
|
||
"quantity_in_total": "Quantité en {unit} (total : {total})",
|
||
"packs_of_have": "Paquets de {size} (vous en avez {count})",
|
||
"scale_wait_stable": "Attendez 10s de poids stable pour le remplissage automatique…",
|
||
"ingredient_scaled_toast": "📦 Ingrédient déduit du garde-manger !",
|
||
"finished_added_bring_toast": "🛒 Produit terminé → ajouté à Bring !",
|
||
"load_error": "Erreur de chargement",
|
||
"favorite": "Ajouter aux favoris",
|
||
"unfavorite": "Retirer des favoris",
|
||
"adjust_persons": "Personnes"
|
||
},
|
||
"shopping": {
|
||
"title": "🛒 Liste de courses",
|
||
"bring_loading": "Connexion à Bring !...",
|
||
"bring_not_configured": "Bring ! n'est pas configuré. Ajoutez votre e-mail et mot de passe dans les <a href='#' onclick=\"showPage('settings');return false;\">paramètres</a>.",
|
||
"tab_to_buy": "🛍️ À acheter",
|
||
"tab_forecast": "🧠 Prévision",
|
||
"total_label": "💰 Total estimé",
|
||
"section_to_buy": "🛍️ À acheter",
|
||
"suggestions_title": "💡 Suggestions IA",
|
||
"suggestions_add": "✅ Ajouter la sélection à Bring !",
|
||
"search_prices": "🔍 Rechercher tous les prix",
|
||
"suggest_btn": "Suggérer des achats",
|
||
"smart_title": "🧠 Prévisions intelligentes",
|
||
"smart_empty": "Aucune prévision disponible.<br>Ajoutez des produits à votre garde-manger pour recevoir des prévisions intelligentes.",
|
||
"smart_filter_all": "Tout",
|
||
"smart_filter_critical": "🔴 Urgent",
|
||
"smart_filter_high": "🟠 Bientôt",
|
||
"smart_filter_medium": "🟡 Planifier",
|
||
"smart_filter_low": "🟢 Prévision",
|
||
"smart_add": "🛒 Ajouter la sélection à Bring !",
|
||
"empty": "Liste de courses vide !\nUtilisez le bouton ci-dessous pour générer des suggestions.",
|
||
"already_in_list": "🛒 \"{name}\" est déjà dans la liste de courses",
|
||
"already_in_list_short": "ℹ️ Déjà dans la liste de courses",
|
||
"add_prompt": "Voulez-vous l'ajouter à la liste de courses ?",
|
||
"smart_already": "📊 Les prévisions achats prédisent déjà {name}",
|
||
"all_searched": "Tous les produits ont déjà été recherchés. Utilisez 🔄 pour rechercher individuellement.",
|
||
"search_complete": "Recherche terminée : {count} produits",
|
||
"removed_sufficient": "🧹 {removed} produit(s) avec stock suffisant retiré(s) de la liste",
|
||
"suggest_buy": "🛒 Acheter : {qty} {unit}",
|
||
"suggest_buy_approx": "🛒 Au minimum : {qty} {unit}",
|
||
"suggest_buy_tip": "Quantité suggérée basée sur vos 14 derniers jours de consommation",
|
||
"suggest_buy_approx_tip": "Estimation minimale basée sur la consommation (achetez le format le plus proche)",
|
||
"bring_badge": "🛒 Déjà sur Bring !",
|
||
"add_urgent_toast": "🔴 {n} produit(s) urgent(s) automatiquement ajouté(s) à Bring !",
|
||
"migration_done": "✅ {migrated} mis à jour, {skipped} déjà ok",
|
||
"added_to_bring": "🛒 {n} produits ajoutés à Bring !",
|
||
"added_to_bring_skip": "{n} déjà présents",
|
||
"all_on_bring": "Tous les produits étaient déjà sur Bring !",
|
||
"freq_high": "📈 Fréquent",
|
||
"freq_regular": "📊 Régulier",
|
||
"freq_occasional": "📉 Occasionnel",
|
||
"out_of_stock": "Rupture de stock",
|
||
"scan_toast": "📷 Scanner : {name}",
|
||
"empty_category": "Aucun produit dans cette catégorie",
|
||
"session_empty": "🛒 Aucun produit encore",
|
||
"urgency_critical": "Urgent",
|
||
"urgency_high": "Bientôt",
|
||
"urgency_medium": "Planifier",
|
||
"urgency_low": "Prévision",
|
||
"urgency_medium_short": "Moyen",
|
||
"urgency_low_short": "Ok",
|
||
"tag_urgent": "🔴 Urgent",
|
||
"tag_priority": "⭐ Priorité",
|
||
"tag_check": "✅ Vérifier",
|
||
"smart_already_predicted": "📊 Les prévisions achats prédisent déjà <strong>{name}</strong>{urgency}.",
|
||
"item_removed": "✅ {name} retiré de la liste !",
|
||
"urgency_spec_critical": "⚡ Urgent",
|
||
"urgency_spec_high": "🟠 Bientôt",
|
||
"bring_add_n": "Ajouter {n} à Bring !",
|
||
"bring_add_selected": "Ajouter la sélection à Bring !",
|
||
"bring_adding": "Ajout en cours...",
|
||
"bring_added_one": "1 produit ajouté à Bring !",
|
||
"bring_added_many": "{n} produits ajoutés à Bring !",
|
||
"bring_skipped": "({n} déjà dans la liste)",
|
||
"force_sync": "Forcer la synchronisation Bring !",
|
||
"scan_target_label": "Vous cherchez",
|
||
"scan_target_found": "Trouvé ! Retirer de la liste",
|
||
"bring_add_one": "Ajouter 1 produit à Bring !",
|
||
"bring_add_many": "Ajouter {n} produits à Bring !",
|
||
"syncing": "Synchronisation…",
|
||
"sync_done": "Synchronisation terminée",
|
||
"price_searching": "Recherche en cours...",
|
||
"search_action": "Rechercher",
|
||
"open_action": "Ouvrir",
|
||
"not_found": "Non trouvé",
|
||
"search_price": "Rechercher le prix",
|
||
"tap_to_scan": "Appuyez pour scanner",
|
||
"tag_title": "Tag",
|
||
"remove_title": "Retirer",
|
||
"found_count": "{found}/{total} produits trouvés",
|
||
"savings_offers": "· 🏷️ Vous économisez {amount}€ avec les offres",
|
||
"searching_progress": "Recherche {current}/{total}...",
|
||
"remove_error": "Erreur de suppression",
|
||
"btn_fetch_prices": "Trouver les prix",
|
||
"price_total_label": "💰 Total estimé :",
|
||
"price_loading": "Recherche des prix…",
|
||
"price_not_found": "prix n/d",
|
||
"suggest_loading": "Analyse en cours...",
|
||
"suggest_error": "Erreur de génération des suggestions",
|
||
"priority_high": "Élevée",
|
||
"priority_medium": "Moyenne",
|
||
"priority_low": "Faible",
|
||
"smart_last_update": "Mis à jour {time}",
|
||
"names_already_updated": "Tous les noms sont déjà à jour"
|
||
},
|
||
"ai": {
|
||
"title": "🤖 Identification IA",
|
||
"capture": "📸 Prendre une photo",
|
||
"retake": "🔄 Reprendre",
|
||
"hint": "Prenez une photo du produit et l'IA essaiera de l'identifier",
|
||
"identifying": "🤖 Identification du produit...",
|
||
"no_api_key": "⚠️ Clé API Gemini non configurée.\n<small>Ajoutez GEMINI_API_KEY au fichier .env sur le serveur.</small>",
|
||
"fields_filled": "✅ Champs remplis par l'IA",
|
||
"use_data": "✅ Utiliser les données IA",
|
||
"use_data_no_barcode": "✅ Utiliser les données IA (sans code-barres)"
|
||
},
|
||
"log": {
|
||
"title": "📒 Journal des opérations",
|
||
"type_added": "Ajouté",
|
||
"type_waste": "Jeté",
|
||
"type_used": "Utilisé",
|
||
"type_bring": "Ajouté à Bring !",
|
||
"undone_badge": "Annulé",
|
||
"undo_title": "Annuler cette opération",
|
||
"load_error": "Erreur de chargement du journal",
|
||
"empty": "Aucune opération enregistrée.",
|
||
"undo_action_remove": "suppression de",
|
||
"undo_action_restore": "réapprovisionnement de",
|
||
"undo_confirm": "Annuler cette opération ?\n→ {action} {name}",
|
||
"undo_success": "↩ Opération annulée pour {name}",
|
||
"already_undone": "Opération déjà annulée",
|
||
"too_old": "Impossible d'annuler des opérations de plus de 24 heures",
|
||
"undo_error": "Erreur lors de l'annulation",
|
||
"recipe_prefix": "Recette"
|
||
},
|
||
"chat": {
|
||
"title": "Chef Gemini",
|
||
"welcome": "Bonjour ! Je suis votre assistant cuisine",
|
||
"welcome_desc": "Demandez-moi de préparer un jus, un snack, un plat rapide… Je connais votre garde-manger, vos appareils et vos préférences !",
|
||
"suggestion_snack": "🍿 Snack rapide",
|
||
"suggestion_juice": "🥤 Jus/Smoothie",
|
||
"suggestion_light": "🥗 Quelque chose de léger",
|
||
"suggestion_expiry": "⏰ Utiliser les produits qui expirent",
|
||
"clear": "Nouvelle conversation",
|
||
"placeholder": "Demandez quelque chose...",
|
||
"cleared": "Chat effacé",
|
||
"suggestion_snack_text": "Que puis-je préparer comme snack rapide ?",
|
||
"suggestion_juice_text": "Faites-moi un jus ou un smoothie avec ce que j'ai",
|
||
"suggestion_light_text": "J'ai faim mais je veux quelque chose de léger",
|
||
"suggestion_expiry_text": "Qu'est-ce qui va bientôt expirer et comment l'utiliser ?",
|
||
"transfer_to_recipes": "Transférer aux recettes",
|
||
"transferring": "Transfert en cours...",
|
||
"transferred": "Ajouté aux recettes !",
|
||
"open_recipe": "Ouvrir la recette",
|
||
"quick_recipe_prompt": "Suggérez une recette rapide POUR UNE PERSONNE en utilisant les produits qui expirent en premier ! Ignorez les congélateurs, concentrez-vous sur le réfrigérateur et le garde-manger."
|
||
},
|
||
"cooking": {
|
||
"close": "Fermer",
|
||
"tts_btn": "Lire à voix haute",
|
||
"restart": "↺ Recommencer",
|
||
"replay": "🔊 Rejouer",
|
||
"timer": "⏱️ {time} · Minuterie",
|
||
"prev": "◀ Précédent",
|
||
"next": "Suivant ▶",
|
||
"ingredient_used": "✔️ Déduit",
|
||
"ingredient_use_btn": "📦 Utiliser",
|
||
"ingredient_deduct_title": "Déduire du garde-manger",
|
||
"timer_expired_tts": "Minuterie {label} terminée !",
|
||
"timer_warning_tts": "Attention ! {label} : 10 secondes restantes !",
|
||
"recipe_done_tts": "Recette terminée ! Bon appétit !",
|
||
"expires_chip": "exp. {date}",
|
||
"finish": "✅ Terminer",
|
||
"step_fallback": "Étape {n}",
|
||
"zerowaste_label": "♻️ Déchet",
|
||
"zerowaste_tip_title": "Conseil zéro déchet"
|
||
},
|
||
"settings": {
|
||
"title": "⚙️ Paramètres",
|
||
"tab_api": "Clés API",
|
||
"tab_bring": "Bring !",
|
||
"tab_recipe": "Recettes",
|
||
"tab_mealplan": "Plan hebdomadaire",
|
||
"tab_appliances": "Appareils",
|
||
"tab_spesa": "Courses en ligne",
|
||
"tab_camera": "Caméra",
|
||
"tab_security": "Sécurité",
|
||
"tab_tts": "Voix (TTS)",
|
||
"tab_language": "Langue",
|
||
"tab_scale": "Balance connectée",
|
||
"gemini": {
|
||
"title": "🤖 Google Gemini IA",
|
||
"hint": "Clé API pour l'identification des produits, les dates de péremption et les recettes.",
|
||
"key_label": "Clé API Gemini"
|
||
},
|
||
"bring": {
|
||
"title": "🛒 Liste de courses Bring !",
|
||
"hint": "Identifiants pour l'intégration de la liste de courses Bring !",
|
||
"email_label": "📧 E-mail Bring !",
|
||
"password_label": "🔒 Mot de passe Bring !"
|
||
},
|
||
"price": {
|
||
"title": "💰 Estimation des prix (IA)",
|
||
"hint": "Afficher le coût estimé par produit dans la liste de courses à l'aide de l'IA.",
|
||
"enabled_label": "Activer l'estimation des prix",
|
||
"country_label": "🌍 Pays de référence",
|
||
"currency_label": "💱 Devise",
|
||
"update_label": "🔄 Actualiser les prix tous les",
|
||
"update_suffix": "mois"
|
||
},
|
||
"recipe": {
|
||
"title": "🍳 Préférences de recettes",
|
||
"hint": "Configurez les options par défaut pour la génération de recettes.",
|
||
"persons_label": "👥 Portions par défaut",
|
||
"options_label": "🎯 Options de recette par défaut",
|
||
"fast": "⚡ Repas rapide",
|
||
"light": "🥗 Repas léger",
|
||
"expiry": "⏰ Priorité péremption",
|
||
"healthy": "💚 Extra sain",
|
||
"opened": "📦 Priorité produits ouverts",
|
||
"zerowaste": "♻️ Zéro déchet",
|
||
"dietary_label": "🚫 Intolérances / Restrictions",
|
||
"dietary_placeholder": "Ex. : sans gluten, sans lactose, végétarien..."
|
||
},
|
||
"mealplan": {
|
||
"title": "📅 Plan de repas hebdomadaire",
|
||
"hint": "Définissez le type de repas pour chaque jour. Il sera utilisé comme guide pour la génération de recettes.",
|
||
"enabled": "✅ Activer le plan hebdomadaire",
|
||
"legend": "🌤️ = Déjeuner · 🌙 = Dîner · Appuyez sur un badge pour le modifier.",
|
||
"types_title": "📋 Types disponibles",
|
||
"reset_btn": "↺ Restaurer les valeurs par défaut"
|
||
},
|
||
"appliances": {
|
||
"title": "🔌 Appareils disponibles",
|
||
"hint": "Indiquez les appareils que vous possédez. Ils seront pris en compte lors de la génération de recettes.",
|
||
"new_placeholder": "Ex. : Machine à pain, Thermomix, Friteuse à air...",
|
||
"quick_title": "Ajout rapide :",
|
||
"oven": "🔥 Four",
|
||
"microwave": "📡 Micro-ondes",
|
||
"air_fryer": "🍟 Friteuse à air",
|
||
"bread_maker": "🍞 Machine à pain",
|
||
"bimby": "🤖 Thermomix/Cookeo",
|
||
"mixer": "🌀 Robot pâtissier",
|
||
"steamer": "♨️ Cuiseur vapeur",
|
||
"pressure_cooker": "🫕 Cocotte-minute",
|
||
"toaster": "🍞 Grille-pain",
|
||
"blender": "🍹 Mixeur",
|
||
"empty": "Aucun appareil ajouté"
|
||
},
|
||
"spesa": {
|
||
"title": "🛍️ Courses en ligne",
|
||
"hint": "Configurez le fournisseur de courses en ligne.",
|
||
"provider_label": "🏪 Fournisseur",
|
||
"email_label": "📧 E-mail",
|
||
"password_label": "🔒 Mot de passe",
|
||
"login_btn": "🔐 Connexion",
|
||
"ai_prompt_label": "🤖 Prompt IA de sélection de produit",
|
||
"ai_prompt_placeholder": "Instructions pour l'IA lors du choix entre plusieurs produits...",
|
||
"ai_prompt_hint": "L'IA utilise ce prompt pour choisir le produit le plus approprié parmi les résultats. Laissez vide pour le comportement par défaut.",
|
||
"configure_first": "Configurez d'abord les courses en ligne dans les paramètres",
|
||
"missing_credentials": "Entrez l'e-mail et le mot de passe",
|
||
"login_in_progress": "Connexion en cours...",
|
||
"login_error_prefix": "Erreur :",
|
||
"login_network_error_prefix": "Erreur réseau :",
|
||
"login_success_default": "Connexion réussie !",
|
||
"result_name_label": "Nom",
|
||
"result_card_label": "Carte",
|
||
"result_pickup_label": "Point de retrait",
|
||
"result_points_label": "Points fidélité",
|
||
"connected_relogin": "✅ Connecté — Se reconnecter",
|
||
"connected_as": "Connecté en tant que {name}"
|
||
},
|
||
"camera": {
|
||
"title": "📷 Caméra",
|
||
"hint": "Choisissez la caméra à utiliser pour le scan de code-barres et l'identification IA.",
|
||
"device_label": "📸 Caméra par défaut",
|
||
"back": "📱 Arrière (par défaut)",
|
||
"front": "🤳 Frontale",
|
||
"devices_hint": "Si vous avez plusieurs caméras, vous pouvez en sélectionner une dans la liste ci-dessus après avoir accordé les permissions.",
|
||
"detect_btn": "🔄 Détecter les caméras"
|
||
},
|
||
"security": {
|
||
"title": "🔒 Certificat HTTPS",
|
||
"hint": "Si le navigateur affiche l'erreur « Votre connexion n'est pas privée » (ERR_CERT_AUTHORITY_INVALID), vous devez installer le certificat CA sur l'appareil.",
|
||
"download_btn": "📥 Télécharger le certificat CA",
|
||
"token_title": "🔑 Token de paramètres",
|
||
"token_label": "Token d'accès",
|
||
"token_hint": "Si `SETTINGS_TOKEN` est configuré dans le `.env` du serveur, entrez le token ici avant de sauvegarder les paramètres. Laissez vide si non configuré.",
|
||
"token_placeholder": "(vide = pas de protection)",
|
||
"token_required_hint": "🔒 Ce serveur nécessite un token pour sauvegarder les paramètres.",
|
||
"cert_instructions": "<strong>Instructions pour Chrome (Android) :</strong><br>1. Téléchargez le certificat ci-dessus<br>2. Allez dans <em>Paramètres → Sécurité & Confidentialité → Plus de paramètres de sécurité → Installer depuis le stockage</em><br>3. Sélectionnez le fichier <em>EverShelf_CA.crt</em> téléchargé<br>4. Choisissez « CA » et confirmez<br>5. Redémarrez Chrome<br><br><strong>Instructions pour Chrome (PC) :</strong><br>1. Téléchargez le certificat ci-dessus<br>2. Allez dans <em>chrome://settings/certificates</em><br>3. Onglet « Autorités » → Importer → sélectionnez le fichier<br>4. Cochez « Approuver ce certificat pour identifier les sites web »<br>5. Redémarrez Chrome"
|
||
},
|
||
"tts": {
|
||
"title": "🔊 Voix & TTS",
|
||
"hint": "Configurez la synthèse vocale via une API REST externe. Les étapes de recette et les minuteries expirées seront envoyées à l'endpoint configuré.",
|
||
"enabled": "✅ Activer la TTS",
|
||
"engine_label": "⚙️ Moteur TTS",
|
||
"engine_browser": "🔇 Navigateur (hors ligne, aucune configuration requise)",
|
||
"engine_server": "🌐 Serveur externe (Home Assistant, API REST...)",
|
||
"voice_label": "🗣️ Voix",
|
||
"rate_label": "⚡ Vitesse",
|
||
"pitch_label": "🎵 Tonalité",
|
||
"url_label": "🌐 URL de l'endpoint",
|
||
"method_label": "📡 Méthode HTTP",
|
||
"auth_label": "🔐 Authentification",
|
||
"auth_bearer": "Bearer Token",
|
||
"auth_custom": "En-tête personnalisé",
|
||
"auth_none": "Aucune",
|
||
"token_label": "🔑 Bearer Token",
|
||
"custom_header_name": "📋 Nom de l'en-tête",
|
||
"custom_header_value": "📋 Valeur de l'en-tête",
|
||
"content_type_label": "📄 Content-Type",
|
||
"payload_key_label": "🗝️ Champ texte dans le payload",
|
||
"payload_key_hint": "Nom du champ JSON qui contiendra le texte à lire (ex. : message, text).",
|
||
"extra_fields_label": "➕ Champs supplémentaires (JSON)",
|
||
"extra_fields_placeholder": "{\"entity_id\": \"media_player.salon\"}",
|
||
"extra_fields_hint": "Champs supplémentaires à inclure dans le payload, en format JSON. Laissez vide si non nécessaire.",
|
||
"test_btn": "🔊 Envoyer une voix de test",
|
||
"voices_loading": "Chargement des voix…",
|
||
"voice_not_supported": "Voix non supportée par ce navigateur",
|
||
"voices_none": "Aucune voix disponible sur cet appareil",
|
||
"voices_hint": "Les voix disponibles dépendent du système d'exploitation et du navigateur. Appuyez sur ↺ si la liste ne se charge pas.",
|
||
"url_missing": "⚠️ URL de l'endpoint manquante.",
|
||
"test_sending": "⏳ Envoi…",
|
||
"test_ok": "✅ Réponse {code} — vérifiez que le haut-parleur a parlé.",
|
||
"heard_question": "Avez-vous entendu la voix ?",
|
||
"heard_yes": "Oui, je l'ai entendu",
|
||
"heard_no": "Non, je n'ai rien entendu",
|
||
"test_ok_kiosk": "TTS fonctionne.",
|
||
"test_fail_steps": "Vérifiez : 1) le volume média n'est pas 0 ; 2) Google Text-to-Speech est installé et mis à jour ; 3) le pack vocal français est téléchargé dans les paramètres TTS Android."
|
||
},
|
||
"language": {
|
||
"title": "🌐 Langue",
|
||
"hint": "Sélectionnez la langue de l'interface.",
|
||
"label": "🌐 Langue",
|
||
"restart_notice": "La page sera rechargée pour appliquer la nouvelle langue."
|
||
},
|
||
"screensaver": {
|
||
"label": "Activer l'économiseur d'écran",
|
||
"card_title": "🌙 Économiseur d'écran",
|
||
"card_hint": "Affiche une horloge avec des informations utiles après 5 minutes d'inactivité. Désactivé par défaut.",
|
||
"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 heure",
|
||
"start_after": "⏱️ Démarrer après"
|
||
},
|
||
"scale": {
|
||
"title": "⚖️ Balance connectée",
|
||
"hint": "Connectez une balance Bluetooth via la passerelle Android pour lire automatiquement le poids.",
|
||
"tab": "Balance connectée",
|
||
"enabled": "✅ Activer la balance connectée",
|
||
"url_label": "🌐 URL de la passerelle WebSocket",
|
||
"url_placeholder": "ws://192.168.1.x:8765",
|
||
"url_hint": "URL affichée par l'application Android (même réseau Wi-Fi). Ex. :",
|
||
"test_btn": "🔗 Tester la connexion",
|
||
"download_btn": "📥 Télécharger la passerelle Android (APK)",
|
||
"download_hint": "Application Android qui connecte votre balance BLE et EverShelf.",
|
||
"download_sub": "Source : evershelf-scale-gateway/ dans la racine du projet",
|
||
"live_weight": "poids en temps réel",
|
||
"auto_reconnect": "🔁 Reconnexion : automatique",
|
||
"kiosk_title": "📡 Balance BLE intégrée dans le kiosque",
|
||
"kiosk_hint": "La balance est directement gérée par la passerelle BLE interne du kiosque. Pour associer un nouvel appareil, utilisez l'assistant de configuration.",
|
||
"kiosk_reconfigure": "🔄 Reconfigurer la balance BLE",
|
||
"ble_protocols": "<p style=\"margin:0 0 6px;font-weight:600\">🔌 Protocoles BLE supportés :</p><ul style=\"margin:0 0 0 16px;padding:0;font-size:0.8rem\"><li>Bluetooth SIG Weight Scale (0x181D)</li><li>Bluetooth SIG Body Composition (0x181B) — poids, graisse, IMC</li><li>Xiaomi Mi Body Composition Scale 2</li><li>Générique — heuristique automatique pour 100+ modèles</li></ul>"
|
||
},
|
||
"kiosk": {
|
||
"hint": "Transformez une tablette Android en panneau EverShelf permanent avec passerelle BLE intégrée.",
|
||
"download_btn": "📥 Télécharger EverShelf Kiosk (APK)",
|
||
"download_sub": "Mode kiosque plein écran + passerelle de balance intégrée. Source : evershelf-kiosk/",
|
||
"native_title": "Configuration du kiosque",
|
||
"native_hint": "URL du serveur, balance BLE, économiseur d'écran et assistant de configuration.",
|
||
"native_btn": "Ouvrir la configuration du kiosque",
|
||
"native_tap_hint": "Appuyez sur le bouton engrenage en haut à droite",
|
||
"native_update_hint": "Mettez à jour l'application kiosque pour utiliser cette fonctionnalité",
|
||
"update_title": "Mise à jour du kiosque",
|
||
"check_updates_btn": "🔍 Vérifier les mises à jour",
|
||
"needs_update": "⚠️ Le kiosque installé ne supporte pas cette fonctionnalité. Mettez à jour l'application kiosque pour l'activer."
|
||
},
|
||
"saved": "✅ Configuration enregistrée !",
|
||
"saved_local": "✅ Configuration enregistrée localement",
|
||
"saved_local_error": "⚠️ Enregistré localement, erreur serveur : {error}",
|
||
"theme": {
|
||
"title": "🌙 Apparence",
|
||
"hint": "Choisissez le thème de l'interface.",
|
||
"label": "🌙 Thème",
|
||
"off": "☀️ Clair",
|
||
"on": "🌙 Sombre",
|
||
"auto": "🔄 Automatique (système)"
|
||
},
|
||
"zerowaste": {
|
||
"card_title": "♻️ Conseils zéro déchet",
|
||
"card_hint": "Pendant la cuisson, affichez des conseils pour réutiliser les déchets produits à chaque étape (épluchures, eau de cuisson, etc.). Désactivé par défaut.",
|
||
"label": "Afficher les conseils pendant la cuisson"
|
||
},
|
||
"backup": {
|
||
"tab": "Sauvegarde",
|
||
"local_title": "Sauvegarde locale",
|
||
"local_hint": "Instantané quotidien de la base de données. Configurez le nombre de jours de rétention.",
|
||
"enabled": "Activer la sauvegarde automatique quotidienne",
|
||
"retention_days": "Rétention (jours)",
|
||
"retention_info": "Les sauvegardes sont conservées pendant",
|
||
"backup_now": "Sauvegarder maintenant",
|
||
"backing_up": "Sauvegarde en cours…",
|
||
"backed_up": "Sauvegarde terminée",
|
||
"backup_error": "Erreur de sauvegarde",
|
||
"last_backup": "Dernière sauvegarde",
|
||
"no_backup_yet": "Aucune sauvegarde créée",
|
||
"list_empty": "Aucune sauvegarde disponible",
|
||
"restore_btn": "Restaurer",
|
||
"restore_confirm": "Restaurer la sauvegarde",
|
||
"delete_btn": "Supprimer",
|
||
"delete_confirm": "Supprimer la sauvegarde",
|
||
"gdrive_title": "Google Drive",
|
||
"gdrive_hint": "Sauvegardez automatiquement sur Google Drive via OAuth 2.0. Aucune bibliothèque externe requise.",
|
||
"gdrive_enabled": "Activer la sauvegarde Google Drive",
|
||
"gdrive_folder_id": "ID du dossier Drive",
|
||
"gdrive_folder_id_hint": "Copiez l'ID depuis l'URL du dossier Drive : …/folders/<strong>ID</strong>",
|
||
"gdrive_retention_days": "Rétention Drive (jours, 0=tout garder)",
|
||
"gdrive_test": "Tester la connexion",
|
||
"gdrive_ok": "Connexion réussie !",
|
||
"gdrive_error": "Échec de la connexion",
|
||
"gdrive_push_now": "Téléverser sur Drive maintenant",
|
||
"gdrive_pushing": "Téléversement en cours…",
|
||
"gdrive_pushed": "Téléversé sur Drive",
|
||
"gdrive_wizard_hint": "Optionnel : sauvegarde quotidienne automatique sur Google Drive via OAuth 2.0.",
|
||
"gdrive_skip": "Passer — configurer plus tard dans Paramètres",
|
||
"gdrive_client_id": "Client ID",
|
||
"gdrive_client_secret": "Client Secret",
|
||
"gdrive_redirect_uri_hint": "Ajoute <strong>http://localhost</strong> comme URI de redirection autorisé dans la Google Cloud Console. Fonctionne sur n'importe quel serveur, même sans domaine public.",
|
||
"gdrive_code_title": "Coller l'URL ou le code d'autorisation",
|
||
"gdrive_code_hint": "Après autorisation, le navigateur ouvre http://localhost et peut afficher une erreur de connexion — c'est normal. Copie l'URL dans la barre d'adresse (ex. <code>http://localhost/?code=4%2F0A...</code>) et colle-la ici.",
|
||
"gdrive_code_submit": "Confirmer",
|
||
"gdrive_code_empty": "Coller d'abord l'URL ou le code d'autorisation",
|
||
"gdrive_redirect_uri_label": "URI de redirection (ajouter dans Google Cloud Console) :",
|
||
"gdrive_oauth_authorize": "Autoriser avec Google",
|
||
"gdrive_oauth_authorized": "Autorisé",
|
||
"gdrive_oauth_not_authorized": "Pas encore autorisé",
|
||
"gdrive_oauth_window_opened": "Fenêtre ouverte — autorisez et revenez ici",
|
||
"gdrive_oauth_how_to": "Configurer OAuth 2.0 (étape par étape)",
|
||
"gdrive_oauth_steps": "<li>Allez sur <a href='https://console.cloud.google.com/' target='_blank' rel='noopener'>console.cloud.google.com</a> et sélectionnez votre projet</li><li>Activez l’<strong>API Google Drive</strong> : <em>API et services → Activer les API → Google Drive API</em></li><li>Allez dans <em>API et services → Identifiants → Créer des identifiants → ID client OAuth</em></li><li>Type d’application : <strong>Application Web</strong> ; ajoutez l’URL affichée ci-dessous comme <em>URI de redirection autorisé</em></li><li>Copiez le <strong>Client ID</strong> et le <strong>Client Secret</strong> dans les champs ci-dessus et enregistrez</li><li>Cliquez sur <strong>Autoriser avec Google</strong> : connectez-vous et accordez l’accès</li><li>La fenêtre se ferme automatiquement une fois terminé et les sauvegardes sont prêtes</li>"
|
||
},
|
||
"shopping": {
|
||
"tab": "Liste de courses",
|
||
"title": "Liste de courses",
|
||
"hint": "Configurez la liste de courses intégrée ou connectez Bring!.",
|
||
"enable_label": "Activer la liste de courses",
|
||
"mode_label": "Fournisseur",
|
||
"mode_internal": "Intégré (sans Bring!)",
|
||
"mode_bring": "Bring! (application externe)",
|
||
"bring_section_title": "Configuration Bring!",
|
||
"ai_section_title": "Assistance IA",
|
||
"smart_suggestions_label": "Suggestions IA",
|
||
"forecast_label": "Prévision des produits bientôt épuisés",
|
||
"auto_add_label": "Ajouter automatiquement quand",
|
||
"auto_add_suffix": "restant en stock (0 = seulement quand épuisé)"
|
||
},
|
||
"ha": {
|
||
"tab": "Home Assistant",
|
||
"title": "Home Assistant",
|
||
"hint": "Connectez EverShelf à Home Assistant pour les automations, les notifications push et les capteurs REST.",
|
||
"enabled": "Activer l'intégration Home Assistant",
|
||
"connection_title": "Connexion",
|
||
"url_label": "URL Home Assistant",
|
||
"url_placeholder": "http://192.168.1.50:8123",
|
||
"url_hint": "URL de base de votre instance Home Assistant.",
|
||
"token_label": "Jeton d'accès longue durée",
|
||
"token_hint": "Générez depuis Profil HA → Sécurité → Jetons d'accès longue durée.",
|
||
"token_placeholder": "eyJhbGci...",
|
||
"token_saved": "Jeton enregistré (masqué pour des raisons de sécurité)",
|
||
"test_btn": "Tester la connexion",
|
||
"test_ok": "Connecté à {version}",
|
||
"test_fail": "Connexion échouée : {error}",
|
||
"test_bad_token": "HA accessible mais le jeton est invalide",
|
||
"testing": "Test en cours…",
|
||
"error_no_url": "Veuillez d'abord saisir l'URL de Home Assistant.",
|
||
"tts_title": "TTS sur enceinte connectée",
|
||
"tts_hint": "Lisez les étapes de recette sur un media player Home Assistant.",
|
||
"tts_entity_label": "Entity ID du lecteur multimédia",
|
||
"tts_entity_placeholder": "media_player.salon",
|
||
"tts_entity_hint": "Entity ID du lecteur multimédia HA. Disponible dans HA : Outils développeur → États.",
|
||
"tts_platform_label": "Plateforme TTS",
|
||
"tts_platform_speak": "tts.speak (recommandé)",
|
||
"tts_platform_notify": "notify.* (service de notification)",
|
||
"tts_apply_btn": "Appliquer le preset HA à l'onglet TTS",
|
||
"tts_apply_hint": "Pré-remplit l'onglet TTS avec l'URL et le jeton de Home Assistant.",
|
||
"tts_preset_applied": "Preset HA appliqué à l'onglet TTS.",
|
||
"webhook_title": "Automations Webhook",
|
||
"webhook_hint": "Envoyez des données à Home Assistant lors d'événements dans le garde-manger.",
|
||
"webhook_id_label": "ID Webhook",
|
||
"webhook_id_placeholder": "evershelf_webhook_abc123",
|
||
"webhook_id_hint": "ID du webhook créé dans HA. Copiez depuis : HA → Paramètres → Automations → Créer → Déclencheur Webhook.",
|
||
"webhook_events_label": "Notifier pour ces événements",
|
||
"event_expiry": "Produits expirant bientôt (quotidien)",
|
||
"event_shopping": "Article ajouté à la liste de courses",
|
||
"event_stock": "Niveau de stock mis à jour",
|
||
"expiry_days_label": "Préavis d'expiration (jours)",
|
||
"expiry_days_hint": "Envoyer l'alerte d'expiration N jours avant la date d'expiration.",
|
||
"webhook_help": "Dans HA : Paramètres → Automations → Créer → Déclencheur : Webhook → copier l'ID généré.",
|
||
"notify_title": "Notifications push",
|
||
"notify_hint": "Envoyez des notifications push sur votre téléphone via un service notify de Home Assistant.",
|
||
"notify_service_label": "Service notify",
|
||
"notify_service_placeholder": "notify.mobile_app_mon_telephone",
|
||
"notify_service_hint": "Nom du service notify HA. Laissez vide pour désactiver.",
|
||
"sensor_title": "Capteurs REST",
|
||
"sensor_hint": "Ajoutez à configuration.yaml pour créer des capteurs EverShelf dans Home Assistant.",
|
||
"sensor_copy_btn": "Copier le YAML",
|
||
"sensor_copied": "YAML copié dans le presse-papiers !",
|
||
"save_btn": "Enregistrer les paramètres HA",
|
||
"ha_hint": "Si vous utilisez Home Assistant, utilisez l'onglet Home Assistant pour configurer TTS, webhooks et capteurs."
|
||
}
|
||
},
|
||
"expiry": {
|
||
"today": "AUJOURD'HUI",
|
||
"tomorrow": "Demain",
|
||
"days": "{days} jours",
|
||
"expired_days": "il y a {days}j",
|
||
"expired_yesterday": "Hier",
|
||
"expired_today": "Aujourd'hui",
|
||
"badge_today": "⚠️ Expire aujourd'hui !",
|
||
"badge_tomorrow": "⏰ Demain",
|
||
"badge_tomorrow_long": "⏰ Expire demain",
|
||
"badge_days": "⏰ {n} jours",
|
||
"badge_expired_ago": "⚠️ Périmé il y a {n}j",
|
||
"badge_expired": "⛔ Périmé !",
|
||
"badge_stable": "✅ Stable",
|
||
"badge_expiring_short": "⏰ Exp. dans {n}j",
|
||
"badge_ok_still": "✅ Encore {n}j",
|
||
"badge_expires_red": "🔴 Exp. dans {n}j",
|
||
"badge_expires_yellow": "🟡 Exp. dans {n}j",
|
||
"badge_expired_bare": "⚠️ Périmé",
|
||
"badge_expires_warn": "⚠️ Exp. dans {n}j",
|
||
"badge_days_left": "⏳ ~{n}j restants",
|
||
"days_approx": "~{n} jours",
|
||
"weeks_approx": "~{n} semaines",
|
||
"months_approx": "~{n} mois",
|
||
"years_approx": "~{n} ans",
|
||
"expired_today_long": "Périmé aujourd'hui",
|
||
"expired_ago_long": "Périmé il y a {n} jours",
|
||
"expired_suffix": "— Périmé !",
|
||
"expired_suffix_ok": "— Périmé (encore ok)",
|
||
"expired_suffix_warning": "— Périmé (vérifier d'abord)",
|
||
"opened_ago_long": "Ouvert il y a {n} jours",
|
||
"opened_today_long": "Ouvert aujourd'hui",
|
||
"opened_suffix": "— Ouvert depuis trop longtemps !",
|
||
"opened_suffix_ok": "— Ouvert (encore ok)",
|
||
"opened_suffix_warning": "— Ouvert (vérifier d'abord)",
|
||
"days_compact": "{n}j",
|
||
"badge_check_soon": "Vérifier prochainement"
|
||
},
|
||
"status": {
|
||
"ok": "OK",
|
||
"check": "Vérifier",
|
||
"discard": "Jeter",
|
||
"tip_freezer_ok": "Au congélateur : encore sûr (~{n}j de marge)",
|
||
"tip_freezer_check": "Au congélateur depuis longtemps, peut avoir perdu en qualité. Consommer rapidement",
|
||
"tip_freezer_danger": "Au congélateur trop longtemps, risque de brûlure de congélation et de dégradation",
|
||
"tip_highRisk_check": "Périmé récemment, vérifiez l'odeur et l'aspect avant de consommer",
|
||
"tip_highRisk_danger": "Produit périssable périmé : jeter pour la sécurité",
|
||
"tip_medRisk_check1": "Vérifiez l'aspect et l'odeur avant de consommer",
|
||
"tip_medRisk_check2": "Périmé depuis un moment, vérifiez soigneusement avant utilisation",
|
||
"tip_medRisk_danger": "Trop longtemps depuis la péremption, mieux vaut jeter",
|
||
"tip_lowRisk_ok": "Produit longue conservation, encore sûr à consommer",
|
||
"tip_lowRisk_check": "Périmé depuis plus d'un mois, vérifiez l'intégrité de l'emballage",
|
||
"tip_lowRisk_danger": "Périmé depuis trop longtemps, mieux vaut ne pas risquer"
|
||
},
|
||
"toast": {
|
||
"product_saved": "Produit enregistré !",
|
||
"product_created": "Produit créé !",
|
||
"product_updated": "✅ Produit mis à jour !",
|
||
"product_removed": "Produit supprimé",
|
||
"updated": "Mis à jour !",
|
||
"quantity_confirmed": "✓ Quantité confirmée",
|
||
"added_to_inventory": "✅ {name} ajouté !",
|
||
"removed_from_list": "✅ {name} retiré de la liste !",
|
||
"removed_from_list_short": "Retiré de la liste",
|
||
"added_to_shopping": "🛒 Ajouté à la liste de courses !",
|
||
"removed_from_shopping": "🛒 Retiré de la liste de courses",
|
||
"finished_to_bring": "🛒 Produit terminé → ajouté à Bring !",
|
||
"thrown_away": "🗑️ {name} jeté !",
|
||
"thrown_away_partial": "🗑️ {qty} {unit} de {name} jeté(s)",
|
||
"finished_all": "📤 {name} terminé !",
|
||
"product_finished_confirmed": "✅ Supprimé — ajoutez-le à nouveau lors du réapprovisionnement",
|
||
"appliance_added": "Appareil ajouté",
|
||
"item_added": "{name} ajouté"
|
||
},
|
||
"antiwaste": {
|
||
"title": "🌱 Rapport anti-gaspi",
|
||
"grade_label": "Note",
|
||
"you": "Vous",
|
||
"avg_label": "Moy.",
|
||
"better": "🎉 Vous gaspillez {diff}% de moins que la moyenne {country} !",
|
||
"worse": "⚠️ Vous gaspillez plus que la moyenne {country}. Des progrès sont possibles !",
|
||
"on_par": "→ Vous êtes dans la moyenne {country}. Vous pouvez faire mieux !",
|
||
"saved_money": "~{amount}/mois économisé",
|
||
"saved_meals": "~{n} repas sauvés",
|
||
"saved_co2": "{n} kg CO₂ évités",
|
||
"trend_title": "Tendance (3 derniers mois)",
|
||
"months_ago_2": "-60 jours",
|
||
"months_ago_1": "-30 jours",
|
||
"this_month": "Maintenant",
|
||
"country_it": "Moy. italienne",
|
||
"country_de": "Moy. allemande",
|
||
"country_en": "Moy. américaine",
|
||
"source": "Sources : REDUCE, Eurostat, USDA 2021",
|
||
"live_on": "Données en direct",
|
||
"live_off": "Hors ligne",
|
||
"meals": "repas",
|
||
"annual_info": "📅 Vous ~{you} kg/an · moy. ~{avg} kg/an",
|
||
"badge_rate": "taux de perte",
|
||
"badge_saved_money": "économisé vs moy.",
|
||
"badge_wasted": "articles perdus",
|
||
"badge_better": "moins que la moy."
|
||
},
|
||
"error": {
|
||
"generic": "Erreur",
|
||
"network": "Erreur réseau",
|
||
"no_api_key": "Configurez la clé API dans les paramètres",
|
||
"loading": "Erreur de chargement du produit",
|
||
"not_found": "Produit introuvable",
|
||
"not_found_manual": "Produit introuvable. Entrez-le manuellement.",
|
||
"search": "Erreur de recherche. Réessayez.",
|
||
"search_short": "Erreur de recherche",
|
||
"save": "Erreur d'enregistrement",
|
||
"connection": "Erreur de connexion",
|
||
"camera": "Impossible d'accéder à la caméra",
|
||
"bring_add": "Erreur d'ajout à Bring !",
|
||
"bring_connection": "Erreur de connexion à Bring !",
|
||
"identification": "Erreur d'identification",
|
||
"ai_quota": "Quota IA épuisé. Réessayez dans quelques minutes.",
|
||
"barcode_empty": "Entrez un code-barres",
|
||
"barcode_format": "Le code-barres ne doit contenir que des chiffres (4-14 chiffres)",
|
||
"min_chars": "Tapez au moins 2 caractères",
|
||
"not_in_inventory": "Produit absent de l'inventaire",
|
||
"appliance_exists": "L'appareil existe déjà",
|
||
"already_exists": "Existe déjà",
|
||
"network_retry": "Erreur de connexion. Réessayez.",
|
||
"select_items": "Sélectionnez au moins un produit",
|
||
"server_offline": "Connexion au serveur perdue",
|
||
"server_restored": "Connexion au serveur rétablie",
|
||
"server_retry": "Réessayer",
|
||
"unknown": "Erreur inconnue",
|
||
"prefix": "Erreur",
|
||
"no_inventory_entry": "Aucune entrée d'inventaire trouvée",
|
||
"offline_title": "Aucune connexion",
|
||
"offline_subtitle": "L'app ne peut pas atteindre le serveur. Vérifiez votre connexion Wi-Fi.",
|
||
"offline_checking": "Vérification de la connexion…",
|
||
"offline_restored": "Connexion rétablie !",
|
||
"offline_continue": "Continuer en mode hors ligne",
|
||
"offline_reading_cache": "Lecture depuis le cache local",
|
||
"offline_ops_pending": "{n} opérations en attente",
|
||
"offline_synced": "{n} opérations synchronisées",
|
||
"offline_ai_disabled": "Indisponible hors ligne",
|
||
"offline_cache_ready": "Offline — {n} produits en cache"
|
||
},
|
||
"confirm": {
|
||
"remove_item": "Voulez-vous vraiment supprimer ce produit de l'inventaire ?",
|
||
"kiosk_exit": "Quitter le mode kiosque ?",
|
||
"cancel": "Annuler",
|
||
"proceed": "Confirmer"
|
||
},
|
||
"location": {
|
||
"dispensa": "Garde-manger",
|
||
"frigo": "Réfrigérateur",
|
||
"freezer": "Congélateur"
|
||
},
|
||
"edit": {
|
||
"title": "Modifier {name}",
|
||
"unknown_hint": "Entrez le nom du produit et les informations",
|
||
"label_name": "🏷️ Nom du produit",
|
||
"choose_location_title": "Quel emplacement ?",
|
||
"choose_location_hint": "Choisissez l'emplacement à modifier :"
|
||
},
|
||
"screensaver": {
|
||
"recipe_btn": "Recettes",
|
||
"scan_btn": "Scanner un produit"
|
||
},
|
||
"days": {
|
||
"mon": "Lundi",
|
||
"tue": "Mardi",
|
||
"wed": "Mercredi",
|
||
"thu": "Jeudi",
|
||
"fri": "Vendredi",
|
||
"sat": "Samedi",
|
||
"sun": "Dimanche",
|
||
"mon_short": "Lun",
|
||
"tue_short": "Mar",
|
||
"wed_short": "Mer",
|
||
"thu_short": "Jeu",
|
||
"fri_short": "Ven",
|
||
"sat_short": "Sam",
|
||
"sun_short": "Dim"
|
||
},
|
||
"meal_types": {
|
||
"lunch": "Déjeuner",
|
||
"dinner": "Dîner",
|
||
"colazione": "Petit-déjeuner",
|
||
"merenda": "Goûter",
|
||
"dolce": "Dessert",
|
||
"succo": "Jus de fruits",
|
||
"pranzo": "Déjeuner",
|
||
"cena": "Dîner"
|
||
},
|
||
"scale": {
|
||
"status_connected": "Balance connectée",
|
||
"status_searching": "Passerelle connectée, attente de la balance…",
|
||
"status_disconnected": "Passerelle de balance inaccessible",
|
||
"status_error": "Erreur de connexion à la passerelle",
|
||
"not_connected": "Passerelle de balance non connectée",
|
||
"read_btn": "⚖️ Lire depuis la balance",
|
||
"reading_title": "Lecture de la balance",
|
||
"place_on_scale": "Posez le produit sur la balance…",
|
||
"waiting_stable": "Le poids sera capturé automatiquement une fois la lecture stable.",
|
||
"no_url": "Entrez l'URL de la passerelle",
|
||
"testing": "⏳ Test de connexion…",
|
||
"connected_ok": "Connexion à la passerelle réussie !",
|
||
"timeout": "Délai dépassé : pas de réponse de la passerelle",
|
||
"error_connect": "Impossible de se connecter à la passerelle",
|
||
"tab": "Balance connectée",
|
||
"low_weight": "Poids < 10 g · entrez manuellement\n(la lecture automatique nécessite au moins 10 g)",
|
||
"density_hint": "(densité {density} g/ml)",
|
||
"ml_hint": "(sera converti en ml)",
|
||
"weight_detected": "Poids détecté — attendez 10s de stabilité…",
|
||
"weight_too_low": "Poids trop faible — attente…",
|
||
"stable": "✓ Stable",
|
||
"auto_confirm": "✅ {val} {unit} — confirmation automatique dans 5s (appuyez pour annuler)",
|
||
"cancelled_replace": "Annulé — replacez l'ingrédient sur la balance pour reprendre"
|
||
},
|
||
"prediction": {
|
||
"expected_qty": "Attendu : {expected} {unit}",
|
||
"actual_qty": "Actuel : {actual} {unit}",
|
||
"check_suggestion": "Vérifiez ou pesez la quantité restante"
|
||
},
|
||
"date": {
|
||
"today": "📅 Aujourd'hui",
|
||
"yesterday": "📅 Hier"
|
||
},
|
||
"scanner": {
|
||
"title_barcode": "🔖 Scanner le code-barres",
|
||
"barcode_hint": "Cadrez le code-barres du produit",
|
||
"barcode_manual_placeholder": "Ou entrez manuellement...",
|
||
"barcode_use_btn": "✅ Utiliser ce code",
|
||
"ai_identifying": "🤖 Identification du produit...",
|
||
"ai_analyzing": "🤖 Analyse IA en cours...",
|
||
"product_label_hint": "Cadrez l'étiquette du produit",
|
||
"expiry_label_hint": "Cadrez la date de péremption imprimée sur le produit",
|
||
"capture_btn": "📸 Capturer",
|
||
"capture_photo_btn": "📸 Prendre une photo",
|
||
"retake_btn": "🔄 Reprendre",
|
||
"camera_error_hint": "Assurez-vous d'utiliser HTTPS et d'avoir accordé les permissions caméra.<br>Vous pouvez entrer le code-barres manuellement ou utiliser l'identification IA.",
|
||
"no_barcode": "Pas de code-barres",
|
||
"save_new_btn": "🆕 Aucun de ceux-ci — enregistrer comme nouveau"
|
||
},
|
||
"lowstock": {
|
||
"title": "⚠️ Stock faible !",
|
||
"message": "{name} est presque épuisé — il ne reste que {qty}.",
|
||
"question": "Voulez-vous l'ajouter à la liste de courses ?",
|
||
"yes": "🛒 Oui, ajouter à Bring !",
|
||
"no": "Non, pour l'instant ça va"
|
||
},
|
||
"move": {
|
||
"title": "📦 Déplacer le reste ?",
|
||
"question": "Voulez-vous déplacer {thing} de {name} vers un autre emplacement ?",
|
||
"question_short": "Voulez-vous déplacer {thing} vers un autre emplacement ?",
|
||
"thing_opened": "l'emballage ouvert",
|
||
"thing_rest": "le reste",
|
||
"stay_btn": "Non, rester dans {location}",
|
||
"moved_toast": "📦 Emballage ouvert déplacé vers {location}",
|
||
"vacuum_restore": "🫙 Restaurer sous vide",
|
||
"vacuum_seal_rest": "🔒 Mettre le reste sous vide"
|
||
},
|
||
"nova": {
|
||
"1": "Non transformé",
|
||
"2": "Ingrédient culinaire",
|
||
"3": "Transformé",
|
||
"4": "Ultra-transformé"
|
||
},
|
||
"meal_plan_types": {
|
||
"pasta": "Pâtes",
|
||
"riso": "Riz",
|
||
"carne": "Viande",
|
||
"pesce": "Poisson",
|
||
"legumi": "Légumineuses",
|
||
"uova": "Œufs",
|
||
"formaggio": "Fromage",
|
||
"pizza": "Pizza",
|
||
"affettati": "Charcuterie",
|
||
"verdure": "Légumes",
|
||
"zuppa": "Soupe",
|
||
"insalata": "Salade",
|
||
"pane": "Pain/Sandwich",
|
||
"dolce": "Dessert",
|
||
"libero": "Libre"
|
||
},
|
||
"meal_sub": {
|
||
"dolce_torta": "Gâteau",
|
||
"dolce_crema": "Crème / Pudding",
|
||
"dolce_crumble": "Crumble / Tarte",
|
||
"dolce_biscotti": "Biscuits / Pâtisseries",
|
||
"dolce_frutta": "Dessert aux fruits",
|
||
"succo_dolce": "Sucré / Fruité",
|
||
"succo_energizzante": "Énergisant",
|
||
"succo_detox": "Détox / Vert",
|
||
"succo_rinfrescante": "Rafraîchissant",
|
||
"succo_vitaminico": "Vitaminé / Agrumes"
|
||
},
|
||
"meal_plan": {
|
||
"reset_success": "Plan hebdomadaire réinitialisé",
|
||
"not_available": "non disponible dans le garde-manger",
|
||
"suggested_by": "suggéré par le plan hebdomadaire"
|
||
},
|
||
"nutrition": {
|
||
"title": "🥗 Analyse alimentaire",
|
||
"score_excellent": "😄 Excellent",
|
||
"score_good": "🙂 Bien",
|
||
"score_improve": "😬 Améliorable",
|
||
"label_health": "🌿 Santé",
|
||
"label_variety": "🎨 Variété",
|
||
"label_fresh": "❄️ Frais",
|
||
"source": "Basé sur {n} produits dans votre garde-manger · EverShelf",
|
||
"products_count": "produits",
|
||
"today_title": "🥗 Votre garde-manger aujourd'hui",
|
||
"products_n": "{n} produits",
|
||
"macros_title": "Macronutriments estimés",
|
||
"macros_proteins": "Protéines",
|
||
"macros_carbs": "Glucides",
|
||
"macros_fat": "Lipides",
|
||
"macros_fiber": "Fibres",
|
||
"macros_source": "Estimation basée sur {n} produits en stock"
|
||
},
|
||
"facts": {
|
||
"greeting_morning": "Bonjour",
|
||
"greeting_afternoon": "Bon après-midi",
|
||
"greeting_evening": "Bonsoir",
|
||
"pantry_waiting": "{greeting} ! Votre garde-manger vous attend.",
|
||
"expired_one": "Vous avez 1 produit périmé dans votre garde-manger. Vérifiez-le !",
|
||
"expired_many": "Vous avez {n} produits périmés dans votre garde-manger. Vérifiez-les !",
|
||
"expired_list": "Produits périmés : {names}",
|
||
"expired_list_more": "et {n} autres",
|
||
"freezer_expired_ok": "{name} est périmé, mais étant au congélateur il peut encore être bon ! Vérifiez.",
|
||
"freezer_expired_old": "{name} au congélateur est périmé depuis trop longtemps. Mieux vaut le jeter.",
|
||
"fridge_expired_one": "Vous avez 1 produit périmé dans le réfrigérateur !",
|
||
"fridge_expired_many": "Vous avez {n} produits périmés dans le réfrigérateur !",
|
||
"expiring_today": "{name} expire aujourd'hui ! Utilisez-le immédiatement.",
|
||
"expiring_tomorrow": "{name} expire demain. Planifiez !",
|
||
"expiring_days": "{name} expire dans {days} jours.",
|
||
"expiring_many": "Vous avez {n} produits qui expirent bientôt.",
|
||
"expiring_this_week": "{n} produits expirent cette semaine. Planifiez vos repas en conséquence !",
|
||
"expiring_item_loc": "{name} ({loc}) expire dans {days} {dayslabel}.",
|
||
"expiring_this_month": "{n} produits expireront ce mois-ci.",
|
||
"shopping_add": "Ajouter à la liste : {names} 🛒",
|
||
"shopping_more": "et {n} autres",
|
||
"shopping_empty": "Liste de courses vide. Tout est en stock ! ✅",
|
||
"in_fridge": "Dans le réfrigérateur : {name}.",
|
||
"in_freezer": "Dans le congélateur : {name}. N'oubliez pas !",
|
||
"top_category": "Catégorie principale : {icon} {cat} avec {n} produits.",
|
||
"cat_meat": "Vous avez {n} produits carnés. 🥩",
|
||
"cat_dairy": "Vous avez {n} produits laitiers chez vous. 🥛",
|
||
"cat_veggies": "Vous avez {n} types de légumes. Super pour la santé ! 🥬",
|
||
"cat_fruit": "Vous avez {n} types de fruits. 🍎",
|
||
"cat_drinks": "Vous avez {n} boissons disponibles. 🥤",
|
||
"cat_frozen": "Vous avez {n} articles surgelés. ❄️",
|
||
"cat_pasta": "Vous avez {n} types de pâtes. 🍝 Et si on faisait une carbonara ?",
|
||
"cat_canned": "Vous avez {n} conserves dans le garde-manger. 🥫",
|
||
"cat_snacks": "Vous avez {n} snacks. Résistez à la tentation ! 🍪",
|
||
"cat_condiments": "Vous avez {n} condiments disponibles. 🧂",
|
||
"item_random": "Le saviez-vous ? Vous avez {name} dans {loc}.",
|
||
"item_qty": "{name} : vous en avez {qty}.",
|
||
"no_expiry_count": "{n} produits n'ont pas de date de péremption.",
|
||
"furthest_expiry": "Le produit avec la date de péremption la plus lointaine est {name} : {months} mois.",
|
||
"high_qty": "Vous avez un beau stock de {name} : {qty} !",
|
||
"low_qty_item": "{name} est presque épuisé. L'ajouter à votre liste de courses ?",
|
||
"low_qty_count": "{n} produits sont presque épuisés.",
|
||
"morning_bread": "Bonjour ! Vous avez du pain pour le petit-déjeuner. 🍞",
|
||
"morning_milk": "Y a-t-il du lait dans le réfrigérateur pour un cappuccino ? ☕🥛",
|
||
"morning_fruit": "Bonjour ! Des fruits frais sont un excellent début de journée. 🍎",
|
||
"noon_pasta": "C'est l'heure du déjeuner… Et si on faisait un bon bol de pâtes ? 🍝",
|
||
"noon_salad": "Une salade fraîche pour le déjeuner ? Vous avez {n} légumes ! 🥗",
|
||
"evening_meat": "Pour le dîner, vous pourriez utiliser la viande que vous avez. 🥩",
|
||
"evening_fish": "Et si on mangeait du poisson ce soir ? 🐟",
|
||
"evening_expiring": "Vous avez {n} produits qui expirent cette semaine — utilisez-les ce soir !",
|
||
"night_reminder": "Bonne nuit ! N'oubliez pas d'utiliser demain : {names}.",
|
||
"weekly_balance": "Bilan hebdomadaire : +{in} ajoutés, −{out} consommés.",
|
||
"weekly_added": "Vous avez ajouté {n} produits cette semaine.",
|
||
"weekly_consumed": "Vous avez consommé {n} produits cette semaine. Bravo !",
|
||
"tip_freezer": "💡 Les produits surgelés durent bien plus longtemps que la date de péremption.",
|
||
"tip_bread": "💡 Le pain congelé garde sa fraîcheur pendant des semaines.",
|
||
"tip_fifo": "💡 Pour éviter le gaspillage, utilisez en premier les produits les plus proches de la péremption (FIFO).",
|
||
"tip_meat": "💡 La viande au congélateur peut se conserver jusqu'à 6 mois en toute sécurité.",
|
||
"tip_no_refreeze": "💡 Ne jamais recongeler un produit décongelé. Cuisinez-le immédiatement !",
|
||
"tip_fridge": "💡 Un réfrigérateur bien rangé vous fait gagner du temps et de l'argent.",
|
||
"tip_canned": "💡 Les conserves ouvertes doivent aller au réfrigérateur et être consommées en quelques jours.",
|
||
"top_brand": "La marque la plus courante dans votre garde-manger est {brand} avec {n} produits.",
|
||
"combo_pasta": "Vous avez des pâtes et des condiments : prêt pour un premier plat ! 🍝",
|
||
"combo_sandwich": "Pain et viande : un sandwich rapide est toujours une bonne idée ! 🥪",
|
||
"combo_balanced": "Légumes et viande : vous avez tout pour un repas équilibré ! 🥗🥩",
|
||
"pantry_empty": "Le garde-manger est vide ! Il est temps de faire les courses. 🛒",
|
||
"pantry_empty_scan": "Aucun produit enregistré. Scannez quelque chose pour commencer !",
|
||
"location_distribution": "Distribution : {parts}",
|
||
"day": "jour",
|
||
"days": "jours"
|
||
},
|
||
"kiosk_session": {
|
||
"first_item": "Premier article : {name} !",
|
||
"items_two_four": "{n} articles — on démarre 🚀",
|
||
"items_five_nine": "{n} articles — bon rythme ! 💪",
|
||
"items_ten_twenty": "{n} articles — presque un record 🏆",
|
||
"items_twenty_plus": "{n} articles — courses épiques ! 🛒🔥",
|
||
"duplicates_one": "1 doublon (même article deux fois)",
|
||
"duplicates_many": "{n} doublons (pris plusieurs fois)",
|
||
"top_category": "Catégorie principale : {cat} ({count}×)",
|
||
"items_fallback": "{n} article{plural} ajouté{plural}"
|
||
},
|
||
"kiosk": {
|
||
"check_btn": "🔍 Vérifier les mises à jour",
|
||
"checking": "⏳ Vérification…",
|
||
"error_check": "Erreur lors de la vérification des mises à jour",
|
||
"error_start_install": "Erreur au démarrage de l'installation",
|
||
"version_installed": "Installé : {v}",
|
||
"update_available": "⬆️ Nouvelle version disponible : <strong>{latest}</strong> (installée : {current})",
|
||
"up_to_date": "✅ Vous êtes à jour — version <strong>{v}</strong>",
|
||
"too_old": "⚠️ Le kiosque installé est trop ancien pour la vérification automatique des mises à jour.<br>Appuyez sur le bouton ci-dessous pour télécharger et installer la nouvelle version directement.",
|
||
"manual_install": "⚠️ Ce kiosque ne supporte pas l'installation automatique.<br><strong>Procédure manuelle :</strong><br>1. Quittez le kiosque (bouton ✕ en haut à gauche)<br>2. Désinstallez l'application EverShelf Kiosk<br>3. Téléchargez et installez le nouvel APK depuis GitHub :",
|
||
"starting_download": "⏳ Démarrage du téléchargement…",
|
||
"install_btn": "⬇️ Installer la mise à jour",
|
||
"exit_title": "Quitter le kiosque",
|
||
"refresh_title": "Actualiser la page"
|
||
},
|
||
"update": {
|
||
"new_version": "Nouvelle version",
|
||
"btn": "Mettre à jour"
|
||
},
|
||
"gemini": {
|
||
"chat_title": "Discussion avec Gemini",
|
||
"not_configured": "🤖 Gemini non configuré — définissez GEMINI_API_KEY dans les paramètres"
|
||
},
|
||
"appliances": {
|
||
"empty": "Aucun appareil ajouté"
|
||
},
|
||
"about": {
|
||
"title": "À propos",
|
||
"version": "Version",
|
||
"report_bug": "Signaler un bug",
|
||
"report_bug_hint": "Quelque chose ne fonctionne pas ? Envoyez-nous un rapport directement depuis l'application.",
|
||
"report_bug_modal_title": "Signaler un bug",
|
||
"report_type_bug": "Bug",
|
||
"report_type_feature": "Fonctionnalité",
|
||
"report_type_question": "Question",
|
||
"report_field_title": "Titre",
|
||
"report_field_title_ph": "Brève description du problème",
|
||
"report_field_desc": "Description",
|
||
"report_field_desc_ph": "Décrivez le problème en détail…",
|
||
"report_field_steps": "Étapes pour reproduire (optionnel)",
|
||
"report_field_steps_ph": "1. Aller à…\n2. Appuyer sur…\n3. Voir l'erreur…",
|
||
"report_auto_info": "Joint automatiquement : version {version}, langue {lang}.",
|
||
"report_send_btn": "Envoyer le rapport",
|
||
"report_bug_sending": "Envoi…",
|
||
"report_bug_sent": "Rapport envoyé — merci !",
|
||
"report_bug_error": "Impossible d'envoyer le rapport. Vérifiez votre connexion.",
|
||
"changelog": "Journal des modifications",
|
||
"github": "Dépôt GitHub"
|
||
},
|
||
"export": {
|
||
"title": "Exporter l'inventaire",
|
||
"hint": "Téléchargez l'inventaire actuel en CSV ou ouvrez la version imprimable (PDF).",
|
||
"btn_csv": "Télécharger CSV",
|
||
"btn_pdf": "PDF / Imprimer",
|
||
"btn_title": "Exporter"
|
||
},
|
||
"startup": {
|
||
"connecting": "Connexion au serveur...",
|
||
"check_php_memory": "Mémoire PHP",
|
||
"check_php_timeout": "Délai PHP",
|
||
"check_php_upload": "Upload PHP",
|
||
"check_data_dir": "Dossier de données",
|
||
"check_rate_limits": "Dossier rate limits",
|
||
"check_backups": "Dossier sauvegardes",
|
||
"check_write_test": "Test d'écriture disque",
|
||
"check_disk_space": "Espace disque",
|
||
"check_db_connect": "Connexion base de données",
|
||
"check_db_tables": "Tables de la BDD",
|
||
"check_db_integrity": "Intégrité BDD",
|
||
"check_db_wal": "Mode WAL",
|
||
"check_db_size": "Taille de la BDD",
|
||
"check_db_rows": "Données inventaire",
|
||
"check_env": "Fichier .env",
|
||
"check_gemini": "Clé Gemini AI",
|
||
"check_bring_creds": "Identifiants Bring!",
|
||
"check_bring_token": "Token Bring!",
|
||
"check_curl_ssl": "cURL SSL",
|
||
"check_internet": "Connexion internet",
|
||
"fresh_install": "nouvelle installation",
|
||
"warnings_found": "avertissements détectés",
|
||
"all_ok": "Système OK",
|
||
"critical_error_short": "Erreur critique",
|
||
"critical_error": "Erreur critique : l'application ne peut pas démarrer. Vérifiez les logs.",
|
||
"error_network": "Impossible de contacter le serveur. Vérifiez votre connexion réseau.",
|
||
"retry": "Réessayer",
|
||
"syncing_local": "Synchronisation des données locales...",
|
||
"sync_done": "Données locales synchronisées"
|
||
},
|
||
"stats_monthly": {
|
||
"title": "Statistiques Mensuelles",
|
||
"consumed": "produits utilisés",
|
||
"trend_up": "+{pct}% vs {prev}",
|
||
"trend_down": "-{pct}% vs {prev}",
|
||
"trend_same": "même rythme que le mois dernier",
|
||
"added": "ajoutés",
|
||
"wasted": "gaspillés",
|
||
"top_used": "le plus utilisé",
|
||
"top_cats": "Catégories principales",
|
||
"source": "Historique des transactions · mois en cours"
|
||
}
|
||
} |