feat(i18n): translate hardcoded strings across print, public recipe, and recipe management UI
Wires dozens of components and server pages to next-intl instead of hardcoded English text, and adds a lightweight getMessages/formatMessage helper for server components (print pages, public recipe page, cook metadata) since next-intl/server isn't wired into this app's routing. Backfills missing en/fr message keys that existing code already referenced but fr.json lacked.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Minus, Plus, Sparkles, X } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { scaleQuantity, hasQuantity } from "@/lib/fractions";
|
||||
@@ -35,6 +36,7 @@ export function ServingScaler({
|
||||
recipeId?: string;
|
||||
onAiScale?: (ingredients: ScaledIngredient[] | null) => void;
|
||||
}) {
|
||||
const t = useTranslations("servingScaler");
|
||||
const [servings, setServings] = useState(baseServings);
|
||||
const [aiScaledIngredients, setAiScaledIngredients] = useState<ScaledIngredient[] | null>(null);
|
||||
const [aiScaling, setAiScaling] = useState(false);
|
||||
@@ -67,7 +69,7 @@ export function ServingScaler({
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-3 flex-wrap">
|
||||
<span className="text-sm font-medium text-muted-foreground">Servings</span>
|
||||
<span className="text-sm font-medium text-muted-foreground">{t("servings")}</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -94,7 +96,7 @@ export function ServingScaler({
|
||||
className="text-xs text-muted-foreground hover:text-foreground underline"
|
||||
onClick={() => setServings(baseServings)}
|
||||
>
|
||||
reset
|
||||
{t("reset")}
|
||||
</button>
|
||||
)}
|
||||
{recipeId && servings !== baseServings && (
|
||||
@@ -106,7 +108,7 @@ export function ServingScaler({
|
||||
disabled={aiScaling}
|
||||
>
|
||||
<Sparkles className="h-3 w-3" />
|
||||
{aiScaling ? "Scaling…" : "AI Scale"}
|
||||
{aiScaling ? t("scaling") : t("aiScale")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@@ -114,7 +116,7 @@ export function ServingScaler({
|
||||
{aiScaledIngredients && (
|
||||
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
||||
<Sparkles className="h-3 w-3 shrink-0" />
|
||||
<span>AI-scaled quantities shown below</span>
|
||||
<span>{t("aiScaledNote")}</span>
|
||||
<button
|
||||
className="ml-auto hover:text-foreground"
|
||||
onClick={dismissAiScale}
|
||||
|
||||
Reference in New Issue
Block a user