diff --git a/CHANGELOG.md b/CHANGELOG.md index 977d30b..bf91442 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to Epicure are documented here. This file is mirrored in-app at `/changelog` (and in the admin dashboard) via `apps/web/lib/changelog.ts` — update both together. +## 0.27.2 — 2026-07-14 13:20 + +### Fixed +- Dietary tag chips, the recipe tag-adding form, the "Edit recipe" title, and the meal-plan nutrition-goals bar were all hardcoded in English regardless of app language — now translated. + ## 0.27.1 — 2026-07-14 12:05 ### Fixed diff --git a/apps/web/app/(app)/recipes/[id]/edit/page.tsx b/apps/web/app/(app)/recipes/[id]/edit/page.tsx index 12416c6..98e5e5e 100644 --- a/apps/web/app/(app)/recipes/[id]/edit/page.tsx +++ b/apps/web/app/(app)/recipes/[id]/edit/page.tsx @@ -6,6 +6,7 @@ import { db, recipes } from "@epicure/db"; import { and, eq } from "@epicure/db"; import { RecipeForm } from "@/components/recipe/recipe-form"; import { getPublicUrl } from "@/lib/storage"; +import { getMessages } from "@/lib/i18n/server"; type Params = { params: Promise<{ id: string }> }; @@ -28,6 +29,8 @@ export default async function EditRecipePage({ params }: Params) { if (!recipe) notFound(); + const m = getMessages((session.user as { locale?: string }).locale); + const defaultValues = { title: recipe.title, description: recipe.description ?? undefined, @@ -71,7 +74,7 @@ export default async function EditRecipePage({ params }: Params) { return (
-

Edit recipe

+

{m.recipes.editTitle}

{recipe.title}

diff --git a/apps/web/components/nutrition/weekly-nutrition-bar.tsx b/apps/web/components/nutrition/weekly-nutrition-bar.tsx index 91df563..9ed824b 100644 --- a/apps/web/components/nutrition/weekly-nutrition-bar.tsx +++ b/apps/web/components/nutrition/weekly-nutrition-bar.tsx @@ -1,6 +1,7 @@ "use client"; import { useEffect, useState } from "react"; +import { useTranslations } from "next-intl"; type NutritionTotals = { calories: number; @@ -45,6 +46,7 @@ type BarItem = { }; export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { + const t = useTranslations("mealPlan.nutritionBar"); const [data, setData] = useState(null); useEffect(() => { @@ -60,7 +62,7 @@ export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { const bars: BarItem[] = [ { - label: "Calories", + label: t("calories"), value: dailyAverage.calories, goal: goals.caloriesKcal, unit: "kcal", @@ -68,7 +70,7 @@ export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { colorClass: "bg-orange-500", }, { - label: "Protein", + label: t("protein"), value: dailyAverage.protein, goal: goals.proteinG, unit: "g", @@ -76,7 +78,7 @@ export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { colorClass: "bg-blue-500", }, { - label: "Carbs", + label: t("carbs"), value: dailyAverage.carbs, goal: goals.carbsG, unit: "g", @@ -84,7 +86,7 @@ export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { colorClass: "bg-green-500", }, { - label: "Fat", + label: t("fat"), value: dailyAverage.fat, goal: goals.fatG, unit: "g", @@ -95,7 +97,7 @@ export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { return (
-

Daily average vs. your goals

+

{t("dailyAverageVsGoals")}

{bars.map((bar) => { if (bar.goal == null) return null; const width = Math.min(bar.percentage, 100); @@ -118,7 +120,7 @@ export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { })} {unknownCount > 0 && (

- {unknownCount} planned {unknownCount === 1 ? "meal" : "meals"} missing nutrition data — estimate it from the recipe page for a more accurate picture. + {t(unknownCount === 1 ? "missingDataSingular" : "missingDataPlural", { count: unknownCount })}

)}
diff --git a/apps/web/components/recipe/dietary-tag-picker.tsx b/apps/web/components/recipe/dietary-tag-picker.tsx index c46dd69..a29648a 100644 --- a/apps/web/components/recipe/dietary-tag-picker.tsx +++ b/apps/web/components/recipe/dietary-tag-picker.tsx @@ -1,5 +1,7 @@ "use client"; +import { useTranslations } from "next-intl"; + type DietaryTags = { vegan?: boolean; vegetarian?: boolean; @@ -10,15 +12,7 @@ type DietaryTags = { kosher?: boolean; }; -const TAG_LABELS: Record = { - vegan: "Vegan", - vegetarian: "Vegetarian", - glutenFree: "Gluten-free", - dairyFree: "Dairy-free", - nutFree: "Nut-free", - halal: "Halal", - kosher: "Kosher", -}; +const TAG_KEYS: (keyof DietaryTags)[] = ["vegan", "vegetarian", "glutenFree", "dairyFree", "nutFree", "halal", "kosher"]; export function DietaryTagPicker({ value, @@ -27,9 +21,11 @@ export function DietaryTagPicker({ value: DietaryTags; onChange: (tags: DietaryTags) => void; }) { + const t = useTranslations("recipe.dietary"); return (
- {(Object.entries(TAG_LABELS) as [keyof DietaryTags, string][]).map(([key, label]) => { + {TAG_KEYS.map((key) => { + const label = t(key); const active = !!value[key]; return ( @@ -460,12 +460,12 @@ export function RecipeForm({ recipeId, defaultValues }: RecipeFormProps) { onChange={(e) => setTagInput(e.target.value)} onKeyDown={handleTagKeyDown} onBlur={() => { if (tagInput.trim()) addTag(tagInput); }} - placeholder={tags.length === 0 ? "Add tags… (press Enter)" : ""} + placeholder={tags.length === 0 ? t("tagsPlaceholder") : ""} className="flex-1 min-w-[120px] bg-transparent text-sm outline-none placeholder:text-muted-foreground" /> )}
-

Press Enter to add · Backspace to remove last · max 20 tags

+

{t("tagsHelp")}

diff --git a/apps/web/lib/changelog.ts b/apps/web/lib/changelog.ts index 7d92397..2e0869d 100644 --- a/apps/web/lib/changelog.ts +++ b/apps/web/lib/changelog.ts @@ -1,5 +1,5 @@ // Mirrors CHANGELOG.md at the repo root — update both together. -export const APP_VERSION = "0.27.1"; +export const APP_VERSION = "0.27.2"; export type ChangelogEntry = { version: string; @@ -11,6 +11,13 @@ export type ChangelogEntry = { }; export const CHANGELOG: ChangelogEntry[] = [ + { + version: "0.27.2", + date: "2026-07-14 13:20", + fixed: [ + "Dietary tag chips, the recipe tag-adding form, the \"Edit recipe\" title, and the meal-plan nutrition-goals bar were all hardcoded in English regardless of app language — now translated.", + ], + }, { version: "0.27.1", date: "2026-07-14 12:05", diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index b4f4665..90d90ea 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -633,6 +633,7 @@ "new": "New recipe", "newTitle": "New recipe", "newSubtitle": "Build your recipe from scratch", + "editTitle": "Edit recipe", "importUrl": "Import URL", "generate": "Generate", "batchCooking": "Batch cooking", @@ -695,6 +696,7 @@ "tags": "Tags", "tagsHelp": "Press Enter to add · Backspace to remove last · max 20 tags", "tagsPlaceholder": "Add tags… (press Enter)", + "removeTagAriaLabel": "Remove tag {tag}", "dietaryTags": "Dietary tags", "photos": "Photos", "ingredients": "Ingredients", @@ -752,6 +754,15 @@ }, "mealPlan": { "title": "Meal Plan", + "nutritionBar": { + "dailyAverageVsGoals": "Daily average vs. your goals", + "calories": "Calories", + "protein": "Protein", + "carbs": "Carbs", + "fat": "Fat", + "missingDataSingular": "{count} planned meal missing nutrition data — estimate it from the recipe page for a more accurate picture.", + "missingDataPlural": "{count} planned meals missing nutrition data — estimate it from the recipe page for a more accurate picture." + }, "shoppingLists": "Shopping lists", "print": "Print", "shareTitle": "Share this week's plan", diff --git a/apps/web/messages/fr.json b/apps/web/messages/fr.json index 3852864..fd50bfd 100644 --- a/apps/web/messages/fr.json +++ b/apps/web/messages/fr.json @@ -624,6 +624,7 @@ "new": "Nouvelle recette", "newTitle": "Nouvelle recette", "newSubtitle": "Créez votre recette depuis zéro", + "editTitle": "Modifier la recette", "importUrl": "Importer une URL", "generate": "Générer", "batchCooking": "Batch cooking", @@ -683,6 +684,10 @@ "cookMins": "Cuisson (min)", "difficulty": "Difficulté", "visibilityMenuLabel": "Visibilité", + "tags": "Tags", + "tagsHelp": "Appuyez sur Entrée pour ajouter · Retour arrière pour supprimer le dernier · 20 tags max", + "tagsPlaceholder": "Ajouter des tags… (Entrée)", + "removeTagAriaLabel": "Supprimer le tag {tag}", "dietaryTags": "Tags alimentaires", "photos": "Photos", "ingredients": "Ingrédients", @@ -740,6 +745,15 @@ }, "mealPlan": { "title": "Planning repas", + "nutritionBar": { + "dailyAverageVsGoals": "Moyenne quotidienne vs vos objectifs", + "calories": "Calories", + "protein": "Protéines", + "carbs": "Glucides", + "fat": "Lipides", + "missingDataSingular": "{count} repas planifié manque de données nutritionnelles — estimez-les depuis la page de la recette pour un résultat plus précis.", + "missingDataPlural": "{count} repas planifiés manquent de données nutritionnelles — estimez-les depuis la page de la recette pour un résultat plus précis." + }, "shoppingLists": "Listes de courses", "print": "Imprimer", "shareTitle": "Partager le planning de cette semaine", diff --git a/apps/web/package.json b/apps/web/package.json index f98663f..b6e808b 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@epicure/web", - "version": "0.27.1", + "version": "0.27.2", "private": true, "scripts": { "dev": "next dev", diff --git a/package.json b/package.json index 45b1d63..d88f389 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "epicure", - "version": "0.27.1", + "version": "0.27.2", "private": true, "scripts": { "dev": "pnpm --filter web dev",