feat(web): Next.js 15 app shell, auth, i18n, base UI
App Router setup with next-intl (en/fr), Better Auth wiring, shadcn/ui components, Tailwind, AES-256-GCM encrypt util, Redis rate limiter, tier limit checker, site_settings helper for runtime .env overrides.
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
{
|
||||
"nav": {
|
||||
"recipes": "Recipes",
|
||||
"explore": "Explore",
|
||||
"search": "Search",
|
||||
"feed": "Feed",
|
||||
"collections": "Collections",
|
||||
"mealPlan": "Meal Plan",
|
||||
"pantry": "Pantry",
|
||||
"shopping": "Shopping",
|
||||
"settings": "Settings",
|
||||
"admin": "Admin",
|
||||
"signOut": "Sign out",
|
||||
"apiKeys": "API keys",
|
||||
"webhooks": "Webhooks",
|
||||
"language": "Language"
|
||||
},
|
||||
"recipe": {
|
||||
"ingredients": "Ingredients",
|
||||
"instructions": "Instructions",
|
||||
"photos": "Photos",
|
||||
"servings": "{count} servings",
|
||||
"prep": "{mins}m prep",
|
||||
"cook": "{mins}m cook",
|
||||
"total": "{mins}m total",
|
||||
"edit": "Edit",
|
||||
"variations": "Variations",
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete",
|
||||
"visibility": {
|
||||
"private": "Private",
|
||||
"unlisted": "Unlisted",
|
||||
"public": "Public"
|
||||
},
|
||||
"difficulty": {
|
||||
"easy": "Easy",
|
||||
"medium": "Medium",
|
||||
"hard": "Hard"
|
||||
},
|
||||
"dietary": {
|
||||
"vegan": "Vegan",
|
||||
"vegetarian": "Vegetarian",
|
||||
"glutenFree": "Gluten-free",
|
||||
"dairyFree": "Dairy-free",
|
||||
"nutFree": "Nut-free",
|
||||
"halal": "Halal",
|
||||
"kosher": "Kosher"
|
||||
}
|
||||
},
|
||||
"ai": {
|
||||
"generate": {
|
||||
"title": "Generate recipe with AI",
|
||||
"description": "Describe what you want to cook and AI will create a complete recipe.",
|
||||
"prompt": "What do you want to cook?",
|
||||
"placeholder": "e.g. A creamy mushroom risotto with parmesan, serves 4, easy difficulty",
|
||||
"language": "Language",
|
||||
"button": "Generate",
|
||||
"generating": "Generating…",
|
||||
"success": "Recipe generated! Review and edit before publishing.",
|
||||
"error": "Failed to generate recipe",
|
||||
"saveError": "Failed to save generated recipe"
|
||||
},
|
||||
"variations": {
|
||||
"title": "AI Recipe Variations",
|
||||
"description": "Generate creative variations of this recipe — dietary adaptations, flavor twists, technique changes.",
|
||||
"generate": "Generate 3 variations",
|
||||
"generating": "Generating variations…",
|
||||
"regenerate": "Regenerate",
|
||||
"apply": "Apply",
|
||||
"applying": "Applying…",
|
||||
"ingredientChanges": "Ingredient changes",
|
||||
"stepChanges": "Step changes",
|
||||
"success": "Variation created — review and edit before publishing.",
|
||||
"error": "Failed to generate variations",
|
||||
"saveError": "Failed to save variation",
|
||||
"wait": "This may take 20–30 seconds"
|
||||
},
|
||||
"translate": {
|
||||
"title": "Translate Recipe",
|
||||
"description": "Translate this recipe's title, description, ingredients, and steps into another language.",
|
||||
"targetLanguage": "Target language",
|
||||
"button": "Translate",
|
||||
"translating": "Translating…",
|
||||
"success": "Translation saved as new draft recipe.",
|
||||
"error": "Failed to translate recipe",
|
||||
"saveError": "Failed to save translated recipe",
|
||||
"wait": "This may take 20–30 seconds"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"profile": "Profile",
|
||||
"language": "Language",
|
||||
"units": "Units",
|
||||
"metric": "Metric",
|
||||
"imperial": "Imperial"
|
||||
},
|
||||
"common": {
|
||||
"loading": "Loading…",
|
||||
"error": "Something went wrong",
|
||||
"save": "Save",
|
||||
"saved": "Saved",
|
||||
"saveFailed": "Failed to save",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete",
|
||||
"confirm": "Confirm",
|
||||
"back": "Back"
|
||||
},
|
||||
"auth": {
|
||||
"signIn": "Sign in",
|
||||
"signInTitle": "Sign in to your recipe library",
|
||||
"signInLoading": "Signing in…",
|
||||
"signUp": "Sign up",
|
||||
"signUpTitle": "Create account",
|
||||
"signUpSubtitle": "Start building your recipe library",
|
||||
"signUpLoading": "Creating account…",
|
||||
"continueWithGoogle": "Continue with Google",
|
||||
"email": "Email",
|
||||
"emailPlaceholder": "you@example.com",
|
||||
"password": "Password",
|
||||
"name": "Name",
|
||||
"namePlaceholder": "Your name",
|
||||
"forgotPassword": "Forgot password?",
|
||||
"forgotPasswordTitle": "Forgot password",
|
||||
"forgotPasswordSent": "Check your inbox",
|
||||
"forgotPasswordDescription": "Enter your email and we'll send you a reset link.",
|
||||
"forgotPasswordSentDescription": "If an account exists for that email, you'll receive a reset link shortly.",
|
||||
"sendResetLink": "Send reset link",
|
||||
"sendingLink": "Sending…",
|
||||
"resetPasswordTitle": "Reset password",
|
||||
"resetPasswordDescription": "Enter a new password for your account.",
|
||||
"newPassword": "New password",
|
||||
"confirmPassword": "Confirm password",
|
||||
"updatePassword": "Update password",
|
||||
"updatingPassword": "Updating…",
|
||||
"invalidToken": "Invalid or missing reset token.",
|
||||
"noAccount": "No account? Sign up",
|
||||
"alreadyHaveAccount": "Already have an account? Sign in",
|
||||
"backToSignIn": "Back to sign in",
|
||||
"emailNotVerified": "Email not verified",
|
||||
"checkInboxVerification": "Check your inbox for a verification email.",
|
||||
"resendVerification": "Resend verification email",
|
||||
"resendingSending": "Sending…",
|
||||
"or": "or"
|
||||
},
|
||||
"recipes": {
|
||||
"title": "Recipes",
|
||||
"subtitle": "Your personal recipe library",
|
||||
"new": "New recipe",
|
||||
"newTitle": "New recipe",
|
||||
"newSubtitle": "Build your recipe from scratch",
|
||||
"importUrl": "Import URL",
|
||||
"generate": "Generate",
|
||||
"search": "Search recipes…",
|
||||
"noRecipes": "No recipes yet",
|
||||
"noMatch": "No recipes match",
|
||||
"clearSearch": "Clear search",
|
||||
"createFirst": "Create your first recipe",
|
||||
"resultSingular": "result",
|
||||
"resultPlural": "results",
|
||||
"for": "for"
|
||||
},
|
||||
"recipeForm": {
|
||||
"titleLabel": "Title *",
|
||||
"titleRequired": "Title is required",
|
||||
"titlePlaceholder": "My amazing recipe",
|
||||
"descriptionLabel": "Description",
|
||||
"descriptionPlaceholder": "What makes this recipe special…",
|
||||
"servings": "Servings",
|
||||
"prepMins": "Prep (min)",
|
||||
"cookMins": "Cook (min)",
|
||||
"difficulty": "Difficulty",
|
||||
"visibility": "Visibility",
|
||||
"dietaryTags": "Dietary tags",
|
||||
"photos": "Photos",
|
||||
"ingredients": "Ingredients",
|
||||
"amount": "Amount",
|
||||
"unit": "Unit",
|
||||
"ingredient": "Ingredient",
|
||||
"note": "Note",
|
||||
"addIngredient": "Add ingredient",
|
||||
"steps": "Steps",
|
||||
"stepPlaceholder": "Step {n}…",
|
||||
"timerSeconds": "Timer (s)",
|
||||
"addStep": "Add step",
|
||||
"saving": "Saving…",
|
||||
"saveChanges": "Save changes",
|
||||
"createRecipe": "Create recipe",
|
||||
"updateSuccess": "Recipe updated",
|
||||
"createSuccess": "Recipe created",
|
||||
"saveError": "Failed to save recipe"
|
||||
},
|
||||
"canCook": {
|
||||
"title": "What can I cook?",
|
||||
"subtitle": "Recipes you can make with your pantry",
|
||||
"emptyPantry": "Your pantry is empty",
|
||||
"addPantryItems": "Add pantry items",
|
||||
"readyToCook": "Ready to cook",
|
||||
"almostThere": "Almost there (70–99%)",
|
||||
"partialMatches": "Partial matches",
|
||||
"noMatches": "No strong matches found",
|
||||
"missing": "Missing",
|
||||
"ingredientProgress": "{matched}/{total} ingredients"
|
||||
},
|
||||
"mealPlan": {
|
||||
"title": "Meal Plan",
|
||||
"shoppingLists": "Shopping lists",
|
||||
"addTo": "Add to {day} – {meal}",
|
||||
"searchRecipes": "Search recipes…",
|
||||
"servings": "Servings",
|
||||
"noRecipes": "No recipes found",
|
||||
"days": {
|
||||
"mon": "Mon",
|
||||
"tue": "Tue",
|
||||
"wed": "Wed",
|
||||
"thu": "Thu",
|
||||
"fri": "Fri",
|
||||
"sat": "Sat",
|
||||
"sun": "Sun"
|
||||
},
|
||||
"meals": {
|
||||
"breakfast": "Breakfast",
|
||||
"lunch": "Lunch",
|
||||
"dinner": "Dinner",
|
||||
"snack": "Snack"
|
||||
},
|
||||
"generateWithAi": "Generate with AI",
|
||||
"aiModalDescription": "AI will generate a full week of meals and create draft recipes for you.",
|
||||
"dietaryPrefs": "Dietary preferences",
|
||||
"dietaryPrefsPlaceholder": "e.g. vegetarian, gluten-free, low-carb…",
|
||||
"aiPantryNote": "Your pantry items will be considered when available.",
|
||||
"generating": "Generating…",
|
||||
"generate": "Generate",
|
||||
"cancel": "Cancel",
|
||||
"aiGenerated": "Meal plan generated!",
|
||||
"includePantryItems": "Include pantry items",
|
||||
"pantryMode": "Pantry mode — maximize use of what you have",
|
||||
"pantryModeDescription": "Prefer meals that use multiple pantry ingredients and minimize extra shopping."
|
||||
},
|
||||
"pantry": {
|
||||
"title": "Pantry",
|
||||
"subtitle": "Track what you have on hand",
|
||||
"canCook": "What can I cook?"
|
||||
},
|
||||
"feed": {
|
||||
"title": "Feed",
|
||||
"followEmpty": "Follow chefs to see their recipes here.",
|
||||
"noNew": "No new recipes from people you follow.",
|
||||
"following": "Following",
|
||||
"trending": "Trending",
|
||||
"trendingEmpty": "No trending recipes this week.",
|
||||
"loading": "Loading…"
|
||||
},
|
||||
"shoppingLists": {
|
||||
"title": "Shopping Lists",
|
||||
"subtitle": "Plan your grocery runs",
|
||||
"empty": "No shopping lists yet",
|
||||
"listEmpty": "Empty",
|
||||
"generated": "Generated",
|
||||
"items": "{checked}/{total} items"
|
||||
},
|
||||
"collections": {
|
||||
"title": "Collections",
|
||||
"subtitle": "Curate your favorite recipes into collections",
|
||||
"empty": "No collections yet",
|
||||
"public": "Public",
|
||||
"recipeCount": "{count} recipe",
|
||||
"recipeCountPlural": "{count} recipes"
|
||||
},
|
||||
"cookingMode": {
|
||||
"cooking": "Cooking",
|
||||
"stepOf": "Step {current} of {total}",
|
||||
"ingredients": "Ingredients",
|
||||
"startTimer": "Start timer",
|
||||
"timerDone": "Done",
|
||||
"pause": "Pause",
|
||||
"reset": "Reset",
|
||||
"previous": "Previous",
|
||||
"next": "Next",
|
||||
"finish": "Done!",
|
||||
"voiceNotSupported": "Voice not supported in this browser",
|
||||
"voiceError": "Voice error — try again",
|
||||
"enableVoice": "Enable voice control",
|
||||
"stopVoice": "Stop voice",
|
||||
"toggleIngredients": "Toggle ingredients",
|
||||
"shortcutsTitle": "Shortcuts & commands",
|
||||
"keyboardSection": "Keyboard",
|
||||
"voiceSection": "Voice commands",
|
||||
"enableMicFirst": "Enable voice via the mic button first.",
|
||||
"stepRepeatPrefix": "Step {n}: ",
|
||||
"shortcuts": {
|
||||
"nextStep": "Next step",
|
||||
"prevStep": "Previous step",
|
||||
"startTimer": "Start timer",
|
||||
"toggleHelp": "Toggle this panel",
|
||||
"exitMode": "Exit cook mode"
|
||||
},
|
||||
"voiceLabels": {
|
||||
"nextCmd": "next / continue",
|
||||
"prevCmd": "previous / back",
|
||||
"timerCmd": "timer / start",
|
||||
"stopCmd": "stop / pause",
|
||||
"resetCmd": "reset",
|
||||
"repeatCmd": "repeat / again",
|
||||
"nextLabel": "Next step",
|
||||
"prevLabel": "Previous step",
|
||||
"timerLabel": "Start timer",
|
||||
"stopLabel": "Pause timer",
|
||||
"resetLabel": "Reset timer",
|
||||
"repeatLabel": "Re-read step"
|
||||
}
|
||||
},
|
||||
"settingsForm": {
|
||||
"profile": "Profile",
|
||||
"displayName": "Display name",
|
||||
"email": "Email",
|
||||
"emailReadOnly": "Email cannot be changed here.",
|
||||
"saving": "Saving…",
|
||||
"title": "Settings",
|
||||
"subtitle": "Manage your account and preferences",
|
||||
"language": "Language",
|
||||
"languageDescription": "Choose your preferred language for the app and AI-generated content.",
|
||||
"changeEmail": "Change email",
|
||||
"newEmail": "New email address",
|
||||
"changeEmailDescription": "A verification link will be sent to your new address before it takes effect.",
|
||||
"sendVerification": "Send verification",
|
||||
"sendingVerification": "Sending…",
|
||||
"emailChangeSent": "Verification email sent. Check your inbox.",
|
||||
"emailChangeFailed": "Failed to send verification email.",
|
||||
"changePassword": "Change password",
|
||||
"currentPassword": "Current password",
|
||||
"newPassword": "New password",
|
||||
"confirmPassword": "Confirm new password",
|
||||
"passwordMismatch": "Passwords don't match.",
|
||||
"changingPassword": "Changing…",
|
||||
"changePasswordButton": "Change password",
|
||||
"passwordChanged": "Password changed successfully.",
|
||||
"passwordChangeFailed": "Failed to change password."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
{
|
||||
"nav": {
|
||||
"recipes": "Recettes",
|
||||
"explore": "Explorer",
|
||||
"search": "Rechercher",
|
||||
"feed": "Fil d'actualité",
|
||||
"collections": "Collections",
|
||||
"mealPlan": "Planning repas",
|
||||
"pantry": "Garde-manger",
|
||||
"shopping": "Courses",
|
||||
"settings": "Paramètres",
|
||||
"admin": "Admin",
|
||||
"signOut": "Se déconnecter",
|
||||
"apiKeys": "Clés API",
|
||||
"webhooks": "Webhooks",
|
||||
"language": "Langue"
|
||||
},
|
||||
"recipe": {
|
||||
"ingredients": "Ingrédients",
|
||||
"instructions": "Instructions",
|
||||
"photos": "Photos",
|
||||
"servings": "{count} portions",
|
||||
"prep": "{mins}m prép.",
|
||||
"cook": "{mins}m cuisson",
|
||||
"total": "{mins}m total",
|
||||
"edit": "Modifier",
|
||||
"variations": "Variations",
|
||||
"save": "Enregistrer",
|
||||
"cancel": "Annuler",
|
||||
"delete": "Supprimer",
|
||||
"visibility": {
|
||||
"private": "Privée",
|
||||
"unlisted": "Non répertoriée",
|
||||
"public": "Publique"
|
||||
},
|
||||
"difficulty": {
|
||||
"easy": "Facile",
|
||||
"medium": "Moyen",
|
||||
"hard": "Difficile"
|
||||
},
|
||||
"dietary": {
|
||||
"vegan": "Végétalien",
|
||||
"vegetarian": "Végétarien",
|
||||
"glutenFree": "Sans gluten",
|
||||
"dairyFree": "Sans lactose",
|
||||
"nutFree": "Sans noix",
|
||||
"halal": "Halal",
|
||||
"kosher": "Casher"
|
||||
}
|
||||
},
|
||||
"ai": {
|
||||
"generate": {
|
||||
"title": "Générer une recette avec l'IA",
|
||||
"description": "Décrivez ce que vous voulez cuisiner et l'IA créera une recette complète.",
|
||||
"prompt": "Que voulez-vous cuisiner ?",
|
||||
"placeholder": "ex. Un risotto crémeux aux champignons et parmesan, 4 portions, niveau facile",
|
||||
"language": "Langue",
|
||||
"button": "Générer",
|
||||
"generating": "Génération en cours…",
|
||||
"success": "Recette générée ! Vérifiez et modifiez avant de publier.",
|
||||
"error": "Échec de la génération de la recette",
|
||||
"saveError": "Échec de l'enregistrement de la recette générée"
|
||||
},
|
||||
"variations": {
|
||||
"title": "Variations de recette par IA",
|
||||
"description": "Générez des variations créatives de cette recette — adaptations diététiques, profils de saveurs, changements de techniques.",
|
||||
"generate": "Générer 3 variations",
|
||||
"generating": "Génération des variations…",
|
||||
"regenerate": "Régénérer",
|
||||
"apply": "Appliquer",
|
||||
"applying": "Application…",
|
||||
"ingredientChanges": "Changements d'ingrédients",
|
||||
"stepChanges": "Changements d'étapes",
|
||||
"success": "Variation créée — vérifiez et modifiez avant de publier.",
|
||||
"error": "Échec de la génération des variations",
|
||||
"saveError": "Échec de l'enregistrement de la variation",
|
||||
"wait": "Cela peut prendre 20 à 30 secondes"
|
||||
},
|
||||
"translate": {
|
||||
"title": "Traduire la recette",
|
||||
"description": "Traduisez le titre, la description, les ingrédients et les étapes de cette recette dans une autre langue.",
|
||||
"targetLanguage": "Langue cible",
|
||||
"button": "Traduire",
|
||||
"translating": "Traduction en cours…",
|
||||
"success": "Traduction enregistrée comme nouveau brouillon.",
|
||||
"error": "Échec de la traduction de la recette",
|
||||
"saveError": "Échec de l'enregistrement de la recette traduite",
|
||||
"wait": "Cela peut prendre 20 à 30 secondes"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Paramètres",
|
||||
"profile": "Profil",
|
||||
"language": "Langue",
|
||||
"units": "Unités",
|
||||
"metric": "Métrique",
|
||||
"imperial": "Impérial"
|
||||
},
|
||||
"common": {
|
||||
"loading": "Chargement…",
|
||||
"error": "Une erreur s'est produite",
|
||||
"save": "Enregistrer",
|
||||
"saved": "Enregistré",
|
||||
"saveFailed": "Échec de l'enregistrement",
|
||||
"cancel": "Annuler",
|
||||
"delete": "Supprimer",
|
||||
"confirm": "Confirmer",
|
||||
"back": "Retour"
|
||||
},
|
||||
"auth": {
|
||||
"signIn": "Se connecter",
|
||||
"signInTitle": "Connectez-vous à votre bibliothèque de recettes",
|
||||
"signInLoading": "Connexion en cours…",
|
||||
"signUp": "S'inscrire",
|
||||
"signUpTitle": "Créer un compte",
|
||||
"signUpSubtitle": "Commencez à construire votre bibliothèque de recettes",
|
||||
"signUpLoading": "Création du compte…",
|
||||
"continueWithGoogle": "Continuer avec Google",
|
||||
"email": "E-mail",
|
||||
"emailPlaceholder": "vous@exemple.fr",
|
||||
"password": "Mot de passe",
|
||||
"name": "Nom",
|
||||
"namePlaceholder": "Votre nom",
|
||||
"forgotPassword": "Mot de passe oublié ?",
|
||||
"forgotPasswordTitle": "Mot de passe oublié",
|
||||
"forgotPasswordSent": "Vérifiez vos e-mails",
|
||||
"forgotPasswordDescription": "Saisissez votre e-mail et nous vous enverrons un lien de réinitialisation.",
|
||||
"forgotPasswordSentDescription": "Si un compte existe pour cet e-mail, vous recevrez un lien sous peu.",
|
||||
"sendResetLink": "Envoyer le lien",
|
||||
"sendingLink": "Envoi en cours…",
|
||||
"resetPasswordTitle": "Réinitialiser le mot de passe",
|
||||
"resetPasswordDescription": "Saisissez un nouveau mot de passe pour votre compte.",
|
||||
"newPassword": "Nouveau mot de passe",
|
||||
"confirmPassword": "Confirmer le mot de passe",
|
||||
"updatePassword": "Mettre à jour le mot de passe",
|
||||
"updatingPassword": "Mise à jour…",
|
||||
"invalidToken": "Jeton de réinitialisation invalide ou manquant.",
|
||||
"noAccount": "Pas de compte ? S'inscrire",
|
||||
"alreadyHaveAccount": "Déjà un compte ? Se connecter",
|
||||
"backToSignIn": "Retour à la connexion",
|
||||
"emailNotVerified": "E-mail non vérifié",
|
||||
"checkInboxVerification": "Vérifiez votre boîte de réception pour l'e-mail de vérification.",
|
||||
"resendVerification": "Renvoyer l'e-mail de vérification",
|
||||
"resendingSending": "Envoi en cours…",
|
||||
"or": "ou"
|
||||
},
|
||||
"recipes": {
|
||||
"title": "Recettes",
|
||||
"subtitle": "Votre bibliothèque personnelle de recettes",
|
||||
"new": "Nouvelle recette",
|
||||
"newTitle": "Nouvelle recette",
|
||||
"newSubtitle": "Créez votre recette depuis zéro",
|
||||
"importUrl": "Importer une URL",
|
||||
"generate": "Générer",
|
||||
"search": "Rechercher des recettes…",
|
||||
"noRecipes": "Aucune recette pour l'instant",
|
||||
"noMatch": "Aucune recette ne correspond",
|
||||
"clearSearch": "Effacer la recherche",
|
||||
"createFirst": "Créer votre première recette",
|
||||
"resultSingular": "résultat",
|
||||
"resultPlural": "résultats",
|
||||
"for": "pour"
|
||||
},
|
||||
"recipeForm": {
|
||||
"titleLabel": "Titre *",
|
||||
"titleRequired": "Le titre est requis",
|
||||
"titlePlaceholder": "Ma super recette",
|
||||
"descriptionLabel": "Description",
|
||||
"descriptionPlaceholder": "Ce qui rend cette recette spéciale…",
|
||||
"servings": "Portions",
|
||||
"prepMins": "Prép. (min)",
|
||||
"cookMins": "Cuisson (min)",
|
||||
"difficulty": "Difficulté",
|
||||
"visibility": "Visibilité",
|
||||
"dietaryTags": "Tags alimentaires",
|
||||
"photos": "Photos",
|
||||
"ingredients": "Ingrédients",
|
||||
"amount": "Quantité",
|
||||
"unit": "Unité",
|
||||
"ingredient": "Ingrédient",
|
||||
"note": "Note",
|
||||
"addIngredient": "Ajouter un ingrédient",
|
||||
"steps": "Étapes",
|
||||
"stepPlaceholder": "Étape {n}…",
|
||||
"timerSeconds": "Minuteur (s)",
|
||||
"addStep": "Ajouter une étape",
|
||||
"saving": "Enregistrement…",
|
||||
"saveChanges": "Enregistrer les modifications",
|
||||
"createRecipe": "Créer la recette",
|
||||
"updateSuccess": "Recette mise à jour",
|
||||
"createSuccess": "Recette créée",
|
||||
"saveError": "Échec de l'enregistrement de la recette"
|
||||
},
|
||||
"canCook": {
|
||||
"title": "Que puis-je cuisiner ?",
|
||||
"subtitle": "Recettes réalisables avec votre garde-manger",
|
||||
"emptyPantry": "Votre garde-manger est vide",
|
||||
"addPantryItems": "Ajouter des articles",
|
||||
"readyToCook": "Prêt à cuisiner",
|
||||
"almostThere": "Presque là (70–99 %)",
|
||||
"partialMatches": "Correspondances partielles",
|
||||
"noMatches": "Aucune correspondance trouvée",
|
||||
"missing": "Manquant",
|
||||
"ingredientProgress": "{matched}/{total} ingrédients"
|
||||
},
|
||||
"mealPlan": {
|
||||
"title": "Planning repas",
|
||||
"shoppingLists": "Listes de courses",
|
||||
"addTo": "Ajouter à {day} – {meal}",
|
||||
"searchRecipes": "Rechercher des recettes…",
|
||||
"servings": "Portions",
|
||||
"noRecipes": "Aucune recette trouvée",
|
||||
"days": {
|
||||
"mon": "Lun",
|
||||
"tue": "Mar",
|
||||
"wed": "Mer",
|
||||
"thu": "Jeu",
|
||||
"fri": "Ven",
|
||||
"sat": "Sam",
|
||||
"sun": "Dim"
|
||||
},
|
||||
"meals": {
|
||||
"breakfast": "Petit-déjeuner",
|
||||
"lunch": "Déjeuner",
|
||||
"dinner": "Dîner",
|
||||
"snack": "Collation"
|
||||
},
|
||||
"generateWithAi": "Générer avec l'IA",
|
||||
"aiModalDescription": "L'IA va générer une semaine complète de repas et créer des recettes brouillons.",
|
||||
"dietaryPrefs": "Préférences alimentaires",
|
||||
"dietaryPrefsPlaceholder": "ex. végétarien, sans gluten, low-carb…",
|
||||
"aiPantryNote": "Les articles de votre garde-manger seront pris en compte.",
|
||||
"generating": "Génération…",
|
||||
"generate": "Générer",
|
||||
"cancel": "Annuler",
|
||||
"aiGenerated": "Plan de repas généré !",
|
||||
"includePantryItems": "Inclure les articles du garde-manger",
|
||||
"pantryMode": "Mode garde-manger — maximiser ce que vous avez",
|
||||
"pantryModeDescription": "Préférer les repas utilisant plusieurs ingrédients du garde-manger et limiter les achats supplémentaires."
|
||||
},
|
||||
"pantry": {
|
||||
"title": "Garde-manger",
|
||||
"subtitle": "Suivez ce que vous avez en stock",
|
||||
"canCook": "Que puis-je cuisiner ?"
|
||||
},
|
||||
"feed": {
|
||||
"title": "Fil d'actualité",
|
||||
"followEmpty": "Suivez des chefs pour voir leurs recettes ici.",
|
||||
"noNew": "Aucune nouvelle recette de vos abonnements.",
|
||||
"following": "Abonnements",
|
||||
"trending": "Tendances",
|
||||
"trendingEmpty": "Aucune recette tendance cette semaine.",
|
||||
"loading": "Chargement…"
|
||||
},
|
||||
"shoppingLists": {
|
||||
"title": "Listes de courses",
|
||||
"subtitle": "Planifiez vos courses",
|
||||
"empty": "Aucune liste de courses",
|
||||
"listEmpty": "Vide",
|
||||
"generated": "Générée",
|
||||
"items": "{checked}/{total} articles"
|
||||
},
|
||||
"collections": {
|
||||
"title": "Collections",
|
||||
"subtitle": "Organisez vos recettes favorites en collections",
|
||||
"empty": "Aucune collection pour l'instant",
|
||||
"public": "Publique",
|
||||
"recipeCount": "{count} recette",
|
||||
"recipeCountPlural": "{count} recettes"
|
||||
},
|
||||
"cookingMode": {
|
||||
"cooking": "En cuisine",
|
||||
"stepOf": "Étape {current} sur {total}",
|
||||
"ingredients": "Ingrédients",
|
||||
"startTimer": "Démarrer le minuteur",
|
||||
"timerDone": "Terminé",
|
||||
"pause": "Pause",
|
||||
"reset": "Réinitialiser",
|
||||
"previous": "Précédent",
|
||||
"next": "Suivant",
|
||||
"finish": "Terminé !",
|
||||
"voiceNotSupported": "Commandes vocales non supportées dans ce navigateur",
|
||||
"voiceError": "Erreur vocale — réessayez",
|
||||
"enableVoice": "Activer les commandes vocales",
|
||||
"stopVoice": "Désactiver les commandes vocales",
|
||||
"toggleIngredients": "Afficher les ingrédients",
|
||||
"shortcutsTitle": "Raccourcis et commandes",
|
||||
"keyboardSection": "Clavier",
|
||||
"voiceSection": "Commandes vocales",
|
||||
"enableMicFirst": "Activez le micro via le bouton micro d'abord.",
|
||||
"stepRepeatPrefix": "Étape {n} : ",
|
||||
"shortcuts": {
|
||||
"nextStep": "Étape suivante",
|
||||
"prevStep": "Étape précédente",
|
||||
"startTimer": "Démarrer le minuteur",
|
||||
"toggleHelp": "Afficher/masquer ce panneau",
|
||||
"exitMode": "Quitter le mode cuisine"
|
||||
},
|
||||
"voiceLabels": {
|
||||
"nextCmd": "suivant / continuer",
|
||||
"prevCmd": "précédent / retour",
|
||||
"timerCmd": "minuteur / démarrer",
|
||||
"stopCmd": "arrêter / pause",
|
||||
"resetCmd": "réinitialiser",
|
||||
"repeatCmd": "répéter / encore",
|
||||
"nextLabel": "Étape suivante",
|
||||
"prevLabel": "Étape précédente",
|
||||
"timerLabel": "Démarrer le minuteur",
|
||||
"stopLabel": "Mettre en pause",
|
||||
"resetLabel": "Réinitialiser le minuteur",
|
||||
"repeatLabel": "Relire l'étape"
|
||||
}
|
||||
},
|
||||
"settingsForm": {
|
||||
"profile": "Profil",
|
||||
"displayName": "Nom d'affichage",
|
||||
"email": "E-mail",
|
||||
"emailReadOnly": "L'e-mail ne peut pas être modifié ici.",
|
||||
"saving": "Enregistrement…",
|
||||
"title": "Paramètres",
|
||||
"subtitle": "Gérez votre compte et vos préférences",
|
||||
"language": "Langue",
|
||||
"languageDescription": "Choisissez la langue de l'application et du contenu généré par l'IA.",
|
||||
"changeEmail": "Changer l'e-mail",
|
||||
"newEmail": "Nouvelle adresse e-mail",
|
||||
"changeEmailDescription": "Un lien de vérification sera envoyé à votre nouvelle adresse avant que la modification soit prise en compte.",
|
||||
"sendVerification": "Envoyer la vérification",
|
||||
"sendingVerification": "Envoi…",
|
||||
"emailChangeSent": "E-mail de vérification envoyé. Vérifiez votre boîte de réception.",
|
||||
"emailChangeFailed": "Échec de l'envoi de l'e-mail de vérification.",
|
||||
"changePassword": "Changer le mot de passe",
|
||||
"currentPassword": "Mot de passe actuel",
|
||||
"newPassword": "Nouveau mot de passe",
|
||||
"confirmPassword": "Confirmer le nouveau mot de passe",
|
||||
"passwordMismatch": "Les mots de passe ne correspondent pas.",
|
||||
"changingPassword": "Modification…",
|
||||
"changePasswordButton": "Changer le mot de passe",
|
||||
"passwordChanged": "Mot de passe modifié avec succès.",
|
||||
"passwordChangeFailed": "Échec de la modification du mot de passe."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user