{
"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 {inv_qty} {unit} 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 {qty}.",
"banner_opened_detail": "{when} dans {location} · il vous reste encore {qty}.",
"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.
Scannez un produit pour l'ajouter !",
"empty_db": "Aucun produit dans la base de données.
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",
"status_ready": "Pointez la caméra sur le code-barres",
"status_scanning": "Scan en cours...",
"status_partial": "Lu : {code} — vérification...",
"status_invalid": "Invalide : {code} — nouvel essai",
"status_confirmed": "Confirmé !",
"status_parallel": "Scan combiné actif...",
"ai_fallback_searching": "Identification IA en cours...",
"ai_fallback_found": "Produit identifié par l'IA",
"ai_fallback_not_found": "IA : produit non reconnu"
},
"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 aujourd'hui",
"when_tomorrow": "expire demain",
"when_days": "expire dans {n} jours",
"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 paramètres.",
"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.
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à {name}{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.\nAjoutez GEMINI_API_KEY au fichier .env sur le serveur.",
"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",
"ai_fallback_label": "Identification visuelle IA (repli 5s)",
"ai_fallback_hint": "Si aucun code-barres n'est lu en 5 secondes, une image est automatiquement envoyée à l'IA pour identifier visuellement le produit. Nécessite Gemini configuré."
},
"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": "Instructions pour Chrome (Android) :
1. Téléchargez le certificat ci-dessus
2. Allez dans Paramètres → Sécurité & Confidentialité → Plus de paramètres de sécurité → Installer depuis le stockage
3. Sélectionnez le fichier EverShelf_CA.crt téléchargé
4. Choisissez « CA » et confirmez
5. Redémarrez Chrome
Instructions pour Chrome (PC) :
1. Téléchargez le certificat ci-dessus
2. Allez dans chrome://settings/certificates
3. Onglet « Autorités » → Importer → sélectionnez le fichier
4. Cochez « Approuver ce certificat pour identifier les sites web »
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": "
🔌 Protocoles BLE supportés :
http://localhost/?code=4%2F0A...) 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": "