i18n(hemskärm): översätt rekommendationstitlar + ingrediensnamn + hårdkodade strängar
- what-to-eat översätter nu recepttitlar (resolveRecipeTitles, batch) + ⏳/saknas- ingrediensnamn (via allIngredients-id-karta + resolveIngredientNames) - index.tsx använder rec.title/item.name; hårdkodat -> t(): sökfält, Rekommenderat, Toppval, Menade du, Baka (kategori), tomma-lägen - 7 nya nycklar (wte.searchPlaceholder/recommended/topPick/didYouMean/emptySearch/ emptyHoliday, cat.baking) i alla 12 språk - KVAR (separat): whySv-prosan (kräver strukturerade skäl), säsongsval (region), meal-box-titlar Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ import { DEFAULT_TARGETS, computeDailyTargets, summarizeDay } from "@app/nutriti
|
||||
import { parse } from "../lib/errors.js";
|
||||
import { getActiveHouseholdId, todayIso } from "../lib/helpers.js";
|
||||
import { loadLocalePreferences } from "../lib/localeContext.js";
|
||||
import { resolveIngredientNames, resolveRecipeTitles } from "../lib/contentLanguage.js";
|
||||
|
||||
/**
|
||||
* "Vad ska vi äta?" (spec §18) – appens viktigaste endpoint.
|
||||
@@ -604,6 +605,27 @@ export async function recommendationRoutes(app: FastifyInstance) {
|
||||
? await computeSearchSuggestion(app, q.search)
|
||||
: null;
|
||||
|
||||
// --- i18n: översätt titlar + ingrediensnamn till användarens språk (svensk källa = fallback) ---
|
||||
const languageTag = localePrefs.languageTag;
|
||||
const titleByRecipe = await resolveRecipeTitles(
|
||||
app.db,
|
||||
recommendations.map((r) => r.recipeId),
|
||||
languageTag,
|
||||
);
|
||||
const localizedById = await resolveIngredientNames(
|
||||
app.db,
|
||||
allIngredients
|
||||
.map((i) => i.canonicalIngredientId)
|
||||
.filter((id): id is string => id != null),
|
||||
languageTag,
|
||||
);
|
||||
const svToLocalized = new Map<string, string>();
|
||||
for (const i of allIngredients) {
|
||||
const loc = i.canonicalIngredientId ? localizedById.get(i.canonicalIngredientId) : undefined;
|
||||
if (loc) svToLocalized.set(i.displayNameSv, loc);
|
||||
}
|
||||
const localizeName = (n: string): string => svToLocalized.get(n) ?? n;
|
||||
|
||||
return {
|
||||
mealType: q.mealType,
|
||||
context: {
|
||||
@@ -622,6 +644,9 @@ export async function recommendationRoutes(app: FastifyInstance) {
|
||||
mealBoxSuggestions,
|
||||
recommendations: recommendations.map((r) => ({
|
||||
...r,
|
||||
title: titleByRecipe.get(r.recipeId) ?? r.titleSv,
|
||||
usesExpiring: r.usesExpiring.map((u) => ({ ...u, name: localizeName(u.nameSv) })),
|
||||
missingIngredients: r.missingIngredients.map(localizeName),
|
||||
ratingAverage: ratingByRecipe.get(r.recipeId)?.average ?? null,
|
||||
ratingCount: ratingByRecipe.get(r.recipeId)?.count ?? 0,
|
||||
})),
|
||||
|
||||
Reference in New Issue
Block a user